188 lines
		
	
	
		
			4.6 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			188 lines
		
	
	
		
			4.6 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
<?php
 | 
						|
 | 
						|
require_once "GroupMgr.php";
 | 
						|
require_once "TestMgr.php";
 | 
						|
 | 
						|
require_once "common_func.php";
 | 
						|
 | 
						|
class ReportBuilder
 | 
						|
{
 | 
						|
    static public function getStatsByFilters(int $gameid, string $filter, string $groups, string $ordering)
 | 
						|
    {
 | 
						|
        $groupMgr = new GroupMgr();
 | 
						|
        $testMgr = new TestMgr();
 | 
						|
 | 
						|
        // get nicknames
 | 
						|
        $groups = explode_list($groups);
 | 
						|
        $nicknames = $groupMgr->getJoinedMembersByUniqueNames($groups);
 | 
						|
        $groupFilter = ["nickname", "IN", $nicknames];
 | 
						|
 | 
						|
        // get IDs
 | 
						|
        $tests = $testMgr->getResultsByGameId($gameid, $filter, $ordering, true, $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";
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
class Challenge
 | 
						|
{
 | 
						|
    private string $question;
 | 
						|
    private array $answers;
 | 
						|
 | 
						|
    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);
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    public function getQuestion(): string
 | 
						|
    {
 | 
						|
        return $this->question;
 | 
						|
    }
 | 
						|
 | 
						|
    public function getAnswers(): array
 | 
						|
    {
 | 
						|
        return $this->answers;
 | 
						|
    }
 | 
						|
 | 
						|
    // Generate TeX representation.
 | 
						|
    public function genTeX(): string
 | 
						|
    {
 | 
						|
        $tex = "\\begin{question}{" . $this->question . "}\n";
 | 
						|
        foreach ($this->answers as &$answer) {
 | 
						|
            $tex .= $answer->genTeX();
 | 
						|
        }
 | 
						|
        $tex .= "\\end{question}\n";
 | 
						|
        return $tex;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
class ReportSection
 | 
						|
{
 | 
						|
    private string $title;
 | 
						|
    private array $challenges;
 | 
						|
 | 
						|
    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 . "}\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);
 | 
						|
    }
 | 
						|
}
 | 
						|
 |