SpreadQuiz/class/Task.php
2025-10-11 18:39:30 +02:00

260 lines
6.5 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;
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" => "str_replace",
"replace_field" => function($field, $replacement, $str) {
return [ str_replace("{{" . $field . "}}", $replacement, $str) ];
}
]);
}
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->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 = $mark;
}
function getMark(): float
{
return $this->mark;
}
private function luaCheck(): void {
$this->luaCall("check");
}
protected function staticCheck(): void {
return;
}
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,
];
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;
}
private function luaRandomize(): void {
$this->luaCall("randomize");
}
function randomize(): void
{
if ($this->lua_script !== "") {
$this->luaRandomize();
}
return;
}
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();
}
}
}