compile_log = $a["compile_log"] ?? ""; $this->test_bench_fn = $a["test_bench_fn"] ?? ""; $this->error_score = $a["error_score"] ?? -1.0; } private function verifyCode(): bool { // check that no $function calls are in the code if (str_contains($this->player_answer, "$")) { $this->compile_log .= "A kód nem tartalmazhat \$függvényhívásokat!\n"; return false; } return true; } private function executeTest(): int { // store the user's answer $module_code_fn = tempnam(sys_get_temp_dir(), "verilogtask_user_module_"); file_put_contents($module_code_fn, $this->getPlayerAnswer()); // modify the test bench and save into a separate file $test_bench_fn = tempnam(sys_get_temp_dir(), "verilogtask_test_bench_"); $include_line = "`include \"$module_code_fn\"\n\n"; $tb = $include_line . file_get_contents($this->getGameDir() . DIRECTORY_SEPARATOR . $this->test_bench_fn); file_put_contents($test_bench_fn, $tb); // run the simulation $output_fn = sys_get_temp_dir() . DIRECTORY_SEPARATOR . uniqid("verilogtask_output_"); $iverilog_cmd = "iverilog $test_bench_fn -o $output_fn -g2012 2>&1"; $compilation_log = shell_exec($iverilog_cmd); $failed_count = 0; if (!is_null($compilation_log)) { $compilation_log = str_replace([$module_code_fn, $test_bench_fn], ["[kód]", "[tesztkörnyezet]"], $compilation_log); $this->compile_log .= "Fordítási hiba:\n\n" . (string)($compilation_log); $failed_count = PHP_INT_MAX; goto cleanup; } if (file_exists($output_fn)) { $tb_output = shell_exec("$output_fn"); $tb_output_lines = array_map(fn($line) => trim($line), explode("\n", $tb_output)); $failed_trimlen = strlen(self::FAILED_MARK); foreach ($tb_output_lines as $line) { if (str_starts_with($line, self::FAILED_MARK)) { $this->compile_log .= substr($line, $failed_trimlen) . "\n"; $failed_count++; } } if ($failed_count == 0) { $this->compile_log .= "Minden rendben! :)"; } else { $this->compile_log = "$failed_count db hiba:\n\n" . $this->compile_log; } } cleanup: // remove the temporary files @unlink($module_code_fn); @unlink($test_bench_fn); @unlink($output_fn); return $failed_count; } public function setErrorScore(float $error_score): void { $this->error_score = $error_score; } public function getErrorScore(): float { return $this->error_score; } public function staticCheck(): void { $this->compile_log = ""; // verify code $mark = 0.0; if ($this->verifyCode()) { // run the simulation $failed_count = $this->executeTest(); if ($failed_count != PHP_INT_MAX) { $mark = $this->getMaxMark() + $failed_count * $this->error_score; } } $this->setMark($mark); } public function toArray(string $mode = "all"): array { $a = parent::toArray($mode); $a["compile_log"] = $this->compile_log; if ($mode == "all") { $a["test_bench_fn"] = $this->test_bench_fn; $a["error_score"] = $this->error_score; } return $a; } }