309 lines
		
	
	
		
			7.7 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			309 lines
		
	
	
		
			7.7 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
<?php
 | 
						|
 | 
						|
class Task implements JsonSerializable
 | 
						|
{
 | 
						|
    private string $type; // task type
 | 
						|
    private string $question; // the task title
 | 
						|
    protected mixed $player_answer; // answer given by the player
 | 
						|
    protected mixed $correct_answer; // correct answer
 | 
						|
    private string $comment; // solution_explanation
 | 
						|
    private float $max_mark; // maximum points that can be collected at this task
 | 
						|
    private float $mark; // earned points
 | 
						|
    private bool $is_template; // this task is a template
 | 
						|
    private array $flags; // task flags
 | 
						|
    private string $lua_script; // path to the corresponding Lua script
 | 
						|
    private Game|Test|null $governor; // object that governs this task
 | 
						|
    private LuaSandbox|null $lua_sandbox; // Lua sandbox, initially NULL
 | 
						|
    private array $lua_params; // Lua script parameters
 | 
						|
 | 
						|
    // -------------
 | 
						|
 | 
						|
    protected function addLuaLibraries(): void
 | 
						|
    {
 | 
						|
        // register member methods
 | 
						|
        $method_names = get_class_methods($this);
 | 
						|
        $methods = [];
 | 
						|
        foreach ($method_names as $method_name) {
 | 
						|
            $methods[$method_name] = fn() => [call_user_func(array(&$this, $method_name), ...func_get_args())];
 | 
						|
        }
 | 
						|
        $this->lua_sandbox->registerLibrary("task", $methods);
 | 
						|
 | 
						|
        // register generic functionality
 | 
						|
        $this->lua_sandbox->registerLibrary("php", [
 | 
						|
            "print" => function ($str) {
 | 
						|
                printf("%s\n", $str);
 | 
						|
            },
 | 
						|
            "replace" => function ($search, $replace, $str) {
 | 
						|
                return [str_replace(LuaUtils::l2pA($search), LuaUtils::l2pA($replace), $str)];
 | 
						|
            },
 | 
						|
            "replace_field" => function ($field, $replacement, $str) {
 | 
						|
                return [str_replace("{{" . $field . "}}", $replacement, $str)];
 | 
						|
            },
 | 
						|
            "trim" => function ($str, $chars = " \n\r\t\v\0") {
 | 
						|
                return [trim($str, $chars)];
 | 
						|
            },
 | 
						|
            "ltrim" => function ($str, $chars = " \n\r\t\v\0") {
 | 
						|
                return [ltrim($str, $chars)];
 | 
						|
            },
 | 
						|
            "rtrim" => function ($str, $chars = " \n\r\t\v\0") {
 | 
						|
                return [rtrim($str, $chars)];
 | 
						|
            },
 | 
						|
            "starts_with" => function ($str, $start) {
 | 
						|
                return [str_starts_with($str, $start)];
 | 
						|
            },
 | 
						|
        ]);
 | 
						|
 | 
						|
        LuaUtils::registerLuaLibs($this->lua_sandbox);
 | 
						|
    }
 | 
						|
 | 
						|
    private function createLuaSandbox(): void
 | 
						|
    {
 | 
						|
        if ($this->lua_sandbox === null) {
 | 
						|
            $this->lua_sandbox = new LuaSandbox;
 | 
						|
            $this->addLuaLibraries();
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    private function luaCall(string $lua_function): void
 | 
						|
    {
 | 
						|
        $this->createLuaSandbox();
 | 
						|
        $implementation = file_get_contents($this->getGameDir() . DIRECTORY_SEPARATOR . $this->lua_script);
 | 
						|
        $function_call = "$lua_function()";
 | 
						|
        $joined_code = $implementation . "\n\n" . $function_call;
 | 
						|
        $fn = $this->lua_sandbox->loadString($joined_code);
 | 
						|
        $fn->call();
 | 
						|
    }
 | 
						|
 | 
						|
    function __construct(string $type, array &$a = null)
 | 
						|
    {
 | 
						|
        $this->type = $type;
 | 
						|
        $this->is_template = $a["is_template"] ?? false;
 | 
						|
        $this->max_mark = $a["max_mark"] ?? 1.0;
 | 
						|
        $this->mark = $a["mark"] ?? -1;
 | 
						|
        $this->question = $a["question"] ?? "";
 | 
						|
        $this->flags = $a["flags"] ?? [];
 | 
						|
        $this->player_answer = $a["player_answer"] ?? null;
 | 
						|
        $this->correct_answer = $a["correct_answer"] ?? null;
 | 
						|
        $this->comment = $a["comment"] ?? "";
 | 
						|
        $this->lua_script = $a["lua_script"] ?? "";
 | 
						|
        $this->lua_params = $a["lua_params"] ?? [];
 | 
						|
 | 
						|
        $this->governor = null;
 | 
						|
        $this->lua_sandbox = null;
 | 
						|
    }
 | 
						|
 | 
						|
    function setQuestion(string $question): void
 | 
						|
    {
 | 
						|
        $this->question = $question;
 | 
						|
    }
 | 
						|
 | 
						|
    function getQuestion(): string
 | 
						|
    {
 | 
						|
        return $this->question;
 | 
						|
    }
 | 
						|
 | 
						|
    // save answer
 | 
						|
    function saveAnswer(mixed $ans): bool
 | 
						|
    {
 | 
						|
        $this->player_answer = $ans;
 | 
						|
        return true;
 | 
						|
    }
 | 
						|
 | 
						|
    // clear answer
 | 
						|
    function clearAnswer(): void
 | 
						|
    {
 | 
						|
        $this->player_answer = "";
 | 
						|
    }
 | 
						|
 | 
						|
    // set task type
 | 
						|
    function setType(string $type): void
 | 
						|
    {
 | 
						|
        $this->type = $type;
 | 
						|
    }
 | 
						|
 | 
						|
    // get task type
 | 
						|
    function getType(): string
 | 
						|
    {
 | 
						|
        return $this->type;
 | 
						|
    }
 | 
						|
 | 
						|
    function setMaxMark(float $max_mark): void
 | 
						|
    {
 | 
						|
        $this->max_mark = $max_mark;
 | 
						|
    }
 | 
						|
 | 
						|
    function getMaxMark(): float
 | 
						|
    {
 | 
						|
        return $this->max_mark;
 | 
						|
    }
 | 
						|
 | 
						|
    function setMark(float $mark): void
 | 
						|
    {
 | 
						|
        $this->mark = max($mark, 0.0);
 | 
						|
    }
 | 
						|
 | 
						|
    function getMark(): float
 | 
						|
    {
 | 
						|
        return $this->mark;
 | 
						|
    }
 | 
						|
 | 
						|
    private function luaCheck(): void
 | 
						|
    {
 | 
						|
        $this->luaCall("check");
 | 
						|
    }
 | 
						|
 | 
						|
    protected function staticCheck(): void
 | 
						|
    {
 | 
						|
        $this->mark = $this->max_mark;
 | 
						|
    }
 | 
						|
 | 
						|
    function autoCheck(): void
 | 
						|
    {
 | 
						|
        if ($this->lua_script !== "") {
 | 
						|
            $this->luaCheck();
 | 
						|
        } else {
 | 
						|
            $this->staticCheck();
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    function toArray(string $mode = "all"): array
 | 
						|
    {
 | 
						|
        $a = [
 | 
						|
            "type" => $this->type,
 | 
						|
            "question" => $this->question,
 | 
						|
            "max_mark" => $this->max_mark,
 | 
						|
            "mark" => $this->mark,
 | 
						|
            "correct_answer" => $this->correct_answer,
 | 
						|
            "comment" => $this->comment,
 | 
						|
        ];
 | 
						|
 | 
						|
        if ($mode === "all") {
 | 
						|
            $a["is_template"] = $this->is_template;
 | 
						|
            $a["flags"] = $this->flags;
 | 
						|
            $a["lua_script"] = $this->lua_script;
 | 
						|
            $a["lua_params"] = $this->lua_params;
 | 
						|
        }
 | 
						|
 | 
						|
        if (!$this->isTemplate()) {
 | 
						|
            $a["player_answer"] = $this->player_answer;
 | 
						|
        }
 | 
						|
 | 
						|
        return $a;
 | 
						|
    }
 | 
						|
 | 
						|
    function jsonSerialize(): mixed
 | 
						|
    {
 | 
						|
        return $this->toArray();
 | 
						|
    }
 | 
						|
 | 
						|
    function setTemplate(bool $is_template): void
 | 
						|
    {
 | 
						|
        $this->is_template = $is_template;
 | 
						|
    }
 | 
						|
 | 
						|
    function isTemplate(): bool
 | 
						|
    {
 | 
						|
        return $this->is_template;
 | 
						|
    }
 | 
						|
 | 
						|
    function getFlags(): array
 | 
						|
    {
 | 
						|
        return $this->flags;
 | 
						|
    }
 | 
						|
 | 
						|
    function setFlags(array $flags): void
 | 
						|
    {
 | 
						|
        $this->flags = $flags;
 | 
						|
    }
 | 
						|
 | 
						|
    function hasFlag(string $flag): bool
 | 
						|
    {
 | 
						|
        return in_array($flag, $this->flags);
 | 
						|
    }
 | 
						|
 | 
						|
    function setLuaScript(string $lua_script): void
 | 
						|
    {
 | 
						|
        $this->lua_script = $lua_script;
 | 
						|
    }
 | 
						|
 | 
						|
    public function getLuaScript(): string
 | 
						|
    {
 | 
						|
        return $this->lua_script;
 | 
						|
    }
 | 
						|
 | 
						|
    public function getLuaParams(): array
 | 
						|
    {
 | 
						|
        return $this->lua_params;
 | 
						|
    }
 | 
						|
 | 
						|
    public function setLuaParams(array $lua_params): void
 | 
						|
    {
 | 
						|
        $this->lua_params = $lua_params;
 | 
						|
    }
 | 
						|
 | 
						|
    function getPlayerAnswer(): mixed
 | 
						|
    {
 | 
						|
        return $this->player_answer;
 | 
						|
    }
 | 
						|
 | 
						|
//    /* FIXME: ez ugyanaz, mint a saveAnswer() */
 | 
						|
//    function setPlayerAnswer(mixed $player_answer): void {
 | 
						|
//        $this->player_answer = $player_answer;
 | 
						|
//    }
 | 
						|
 | 
						|
    function setCorrectAnswer(mixed $correct_answer): void
 | 
						|
    {
 | 
						|
        $this->correct_answer = $correct_answer;
 | 
						|
    }
 | 
						|
 | 
						|
    function getCorrectAnswer(): mixed
 | 
						|
    {
 | 
						|
        return $this->correct_answer;
 | 
						|
    }
 | 
						|
 | 
						|
    function setComment(string $comment): void
 | 
						|
    {
 | 
						|
        $this->comment = $comment;
 | 
						|
    }
 | 
						|
 | 
						|
    function addCommentLine(string $cmtl): void {
 | 
						|
        $this->comment .= $cmtl . "<br>";
 | 
						|
    }
 | 
						|
 | 
						|
    function getComment(): string
 | 
						|
    {
 | 
						|
        return $this->comment;
 | 
						|
    }
 | 
						|
 | 
						|
    private function luaRandomize(): void
 | 
						|
    {
 | 
						|
        $this->luaCall("randomize");
 | 
						|
    }
 | 
						|
 | 
						|
    function randomize(): void
 | 
						|
    {
 | 
						|
        if ($this->lua_script !== "") {
 | 
						|
            $this->luaRandomize();
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    function setGovernor(Game|Test|null &$governor): void
 | 
						|
    {
 | 
						|
        $this->governor =  &$governor;
 | 
						|
    }
 | 
						|
 | 
						|
    function &getGovernor(): Game|Test|null
 | 
						|
    {
 | 
						|
        return $this->governor;
 | 
						|
    }
 | 
						|
 | 
						|
    function getGameDir(): string
 | 
						|
    {
 | 
						|
        $gov = $this->getGovernor();
 | 
						|
        if ($gov == null) {
 | 
						|
            return "";
 | 
						|
        } else {
 | 
						|
            return $gov->getGameDir();
 | 
						|
        }
 | 
						|
    }
 | 
						|
} |