assertNotNull($sheet, $code); $parsed = TrackScoringSheet::parseAndValidateConfig($sheet); $this->assertTrue($parsed['ok'], $code.': '.($parsed['message'] ?? '')); $this->assertSame(100.0, $parsed['sheet']['full_score']); } } public function test_default_ai_track_sheet_sums_to_100(): void { $sheet = DefaultTrackScoringSheets::forTrackCode('xiaofei_ai', '消费+人工智能'); $this->assertNotNull($sheet); $parsed = TrackScoringSheet::parseAndValidateConfig($sheet); $this->assertTrue($parsed['ok']); $this->assertSame(100.0, $parsed['sheet']['full_score']); $this->assertCount(8, $parsed['sheet']['items']); } public function test_config_rejects_sum_not_100(): void { $parsed = TrackScoringSheet::parseAndValidateConfig([ 'version' => 1, 'title' => 't', 'items' => [ [ 'key' => 'a', 'sort' => 1, 'category' => '通用指标', 'title' => 'A', 'criteria' => '', 'max_score' => 40, ], ], ]); $this->assertFalse($parsed['ok']); $this->assertStringContainsString('100', $parsed['message']); } public function test_submit_sums_item_scores_and_rejects_invalid_items(): void { $parsed = TrackScoringSheet::parseAndValidateConfig($this->twoItemSheet()); $this->assertTrue($parsed['ok']); $sheet = $parsed['sheet']; $ok = TrackScoringSheet::normalizeSubmitPayload($sheet, [ 'scores' => ['a' => 10.5, 'b' => 20], ]); $this->assertTrue($ok['ok']); $this->assertSame(30.5, $ok['line_total']); $this->assertSame(10.5, $ok['scores']['a']); $this->assertSame(20.0, $ok['scores']['b']); $this->assertSame(30.5, $ok['payload']['line_total']); $zero = TrackScoringSheet::normalizeSubmitPayload($sheet, [ 'scores' => ['a' => 0, 'b' => 0], ]); $this->assertTrue($zero['ok']); $this->assertSame(0.0, $zero['line_total']); $full = TrackScoringSheet::normalizeSubmitPayload($sheet, [ 'scores' => ['a' => 40, 'b' => 60], ]); $this->assertTrue($full['ok']); $this->assertSame(100.0, $full['line_total']); $missing = TrackScoringSheet::normalizeSubmitPayload($sheet, ['line_total' => 88]); $this->assertFalse($missing['ok']); $this->assertStringContainsString('每一项', $missing['message']); $overItem = TrackScoringSheet::normalizeSubmitPayload($sheet, [ 'scores' => ['a' => 40.01, 'b' => 0], ]); $this->assertFalse($overItem['ok']); $this->assertStringContainsString('不能高于该项分值', $overItem['message']); $neg = TrackScoringSheet::normalizeSubmitPayload($sheet, [ 'scores' => ['a' => -0.01, 'b' => 0], ]); $this->assertFalse($neg['ok']); $this->assertStringContainsString('不能小于 0', $neg['message']); $tooManyDecimals = TrackScoringSheet::normalizeSubmitPayload($sheet, [ 'scores' => ['a' => '10.001', 'b' => 0], ]); $this->assertFalse($tooManyDecimals['ok']); $this->assertStringContainsString('两位小数', $tooManyDecimals['message']); } /** * @return array */ private function twoItemSheet(): array { return [ 'version' => 1, 'title' => 't', 'items' => [ [ 'key' => 'a', 'sort' => 1, 'category' => '通用指标', 'title' => 'A', 'criteria' => '', 'max_score' => 40, ], [ 'key' => 'b', 'sort' => 2, 'category' => '通用指标', 'title' => 'B', 'criteria' => '', 'max_score' => 60, ], ], ]; } }