getJoinedMembersByUniqueNames($groups); $groupFilter = ["nickname", "IN", $nicknames]; // get IDs $tests = $testMgr->getResultsByGameId($gameid, $filter, "", true, $bestOnly, $groupFilter); $ids = array_map(fn($test) => $test["_id"], $tests); // generate stats return $testMgr->generateDetailedStats($gameid, $ids); } } class TeXUtils { static public function processCodeInserts(string $str) : string { $parts = explode("`", $str); $output = ""; for ($i = 0; $i < count($parts); $i++) { $output .= $parts[$i]; if ($i < count($parts) - 1) { if (($i % 2) === 0) { $output .= "\\texttt{"; } else { $output .= "}"; } } } return $output; } static public function escape(string $str) : string { return preg_replace("/([$#%&_~^])/", "\\\\$1", $str); } } class Answer { const CORRECT = "Correct"; const INCORRECT = "Incorrect"; private string $text; // Answer's text private string $type; // Answer's type private float $ratio; // Answer's ratio public function __construct(string $type, string $text, float $ratio) { $this->type = $type; $this->text = $text; $this->ratio = $ratio; } // Convert answer into TeX format. public function genTeX(): string { return "\\answer" . $this->type . "{" . $this->ratio . "}{" . $this->text . "}\n"; } // Get answer ratio. public function getRatio(): float { return $this->ratio; } } class Challenge { private string $question; private array $answers; private int $fillCount; private int $skipCount; // Sort answers by ratio. private function sortAnswers() : void { usort($this->answers, function($a, $b) {return $a->getRatio() < $b->getRatio();}); } function __construct(array $data) { $this->question = $data["question"]; // store question for ($i = 0; $i < count($data["answers"]); $i++) { $answer = $data["answers"][$i]; $ratio = $data["answer_ratio"][$i]; $type = $answer === $data["correct_answer"] ? Answer::CORRECT : Answer::INCORRECT; $this->answers[] = new Answer($type, $answer, $ratio); } $this->fillCount = array_sum($data["player_answers"]); // get fill count $this->skipCount = $data["skipped"]; $this->sortAnswers(); // sort answers by fill ratio } public function getQuestion(): string { return $this->question; } public function getAnswers(): array { return $this->answers; } public function getFillCount(): int { return $this->fillCount; } public function getSkipCount(): int { return $this->skipCount; } public function getSubmissionCount() : int { return $this->fillCount + $this->skipCount; } // Generate TeX representation. public function genTeX(): string { $tex = "\\begin{question}{" . $this->question . "}{" . $this->fillCount . "}\n"; foreach ($this->answers as &$answer) { $tex .= $answer->genTeX(); } $tex .= "\\end{question}\n"; return $tex; } } class ReportSection { private string $title; private array $challenges; private function getNumberOfSubmissions() : int { return count($this->challenges) > 0 ? $this->challenges[0]->getSubmissionCount() : 0; } function __construct(string $title, array $challenges) { $this->title = $title; $this->challenges = array_map(fn($ch) => new Challenge($ch), $challenges); } function getChallenges(): array { return $this->challenges; } function getTitle(): string { return $this->title; } // Generate TeX representation of this report. function genTeX(): string { $tex = "\\begin{quiz}{" . $this->title . "}{" . $this->getMaxFillingCount() . "}\n"; foreach ($this->challenges as $challenge) { $tex .= $challenge->genTeX(); } $tex .= "\\end{quiz}\n"; return $tex; } } class Report { private string $title; private array $sections; function __construct(string $title) { $this->title = $title; $this->sections = []; } // Add a new section to the report. function addSection(ReportSection &$section): void { $this->sections[] = $section; } // Generate TeX representation. function genTeX(): string { $tex = ""; foreach ($this->sections as $section) { $tex .= $section->genTeX() . "\n\n"; } $tex = TeXUtils::processCodeInserts($tex); $tex = TeXUtils::escape($tex); return $tex; } const CONTENT_FILE = "content.tex"; const TITLE_FILE = "title.tex"; // Save TeX representation. function saveTeX(string $dir): void { file_put_contents($dir . DIRECTORY_SEPARATOR . self::CONTENT_FILE, $this->genTeX()); file_put_contents($dir . DIRECTORY_SEPARATOR . self::TITLE_FILE, $this->title); } }