diff --git a/class/Game.php b/class/Game.php
index 16141bb..f8535b2 100644
--- a/class/Game.php
+++ b/class/Game.php
@@ -362,9 +362,18 @@ class Game extends AutoStoring
         $columns = Game::getTableColumnIndices($header); // fetch column names
 
         // start iterating over tasks
+        $count = 0;
         for ($i = 1; $i < $n; $i++) {
             $row = &$table[$i]; // fetch row
 
+            $flags = Game::explodeFlags($row[0] ?? ""); // get flags
+            if (in_array("hidden", $flags)) { // skip hidden tasks
+                continue;
+            }
+
+            // count in this task
+            $count++;
+
             // prepare a function that looks up the fields referenced by their labels
             $select_fn = function (array $cols) use (&$row, &$columns) {
                 for ($i = 0; $i < count($cols); $i++) {
@@ -382,7 +391,7 @@ class Game extends AutoStoring
 
             // fetch generic fields
             $a = [
-                "flags" => Game::explodeFlags($row[0] ?? ""),
+                "flags" => $flags,
                 "type" => strtolower($select_fn(["Típus", "Type"])),
                 "image_data" => $select_fn(["Kép", "Image"]),
                 "question" => $select_fn(["Kérdés", "Question"]),
@@ -403,6 +412,7 @@ class Game extends AutoStoring
                     $a["instruction"] = $row[$fuc];
                     break;
                 case "truthtable":
+                case "logicfunction":
                     $a["input_variables"] = Utils::str2a($row[$fuc]);
                     $a["output_variable"] = $row[$fuc + 1];
                     $a["expression"] = $row[$fuc + 2];
@@ -426,9 +436,18 @@ class Game extends AutoStoring
 
             // generate the task
             $this->tasks[] = TaskFactory::fromArray($a, $this);
+
+            // assign scoring strategy
+            $sct = $select_fn(["Pontozás", "Scoring"]);
+            if ($sct !== "") {
+                $sct_fields = Utils::str2kv($sct);
+                foreach ($sct_fields as $key => $value) {
+                    $sct_fields[$key] = $value;
+                }
+            }
         }
 
-        $result["n"] = $n - 1;
+        $result["n"] = $count;
         return $result;
     }
 
diff --git a/class/LogicFunction.php b/class/LogicFunction.php
index ed8eea5..417734a 100644
--- a/class/LogicFunction.php
+++ b/class/LogicFunction.php
@@ -51,11 +51,12 @@ class LogicFunction implements JsonSerializable
 //                printf("%d ", $vars[$this->input_vars[$k]]);
             }
             $out = self::$EXP_LANG->evaluate($expression, $vars);
+            $out_str = $out ? "1" : "0";
 //            printf("%d\n", $out);
-            $tt[] = $out;
+            $tt[] = $out_str;
         }
 
-        return join("", array_map(fn($r) => ($r === True) ? 1 : 0, $tt));
+        return join("", $tt);
     }
 
     public static function genRandom(array $input_vars, int $min_depth = 2, int $max_depth = 3): LogicFunction
@@ -93,7 +94,7 @@ class LogicFunction implements JsonSerializable
         return new LogicFunction($term, $input_vars);
     }
 
-    public static function genRandomDF($input_vars): LogicFunction
+    public static function genRandomDNF($input_vars): LogicFunction
     {
         $N = count($input_vars);
         $states = pow(2, $N);
@@ -101,7 +102,7 @@ class LogicFunction implements JsonSerializable
         $verilog_term = "";
         for ($i = 0; $i < $states; $i++) {
             $inside = "";
-            $omit = random_int(0, 1); // omit the variable or not?
+            $omit = random_int(0, 1); // omit the term or not?
             if (!$omit) {
                 for ($j = 0; $j < $N; $j++) {
                     $neg = !($i & (1 << $j)); // is it an inverted variable?
diff --git a/class/LuaUtils.php b/class/LuaUtils.php
new file mode 100644
index 0000000..3854111
--- /dev/null
+++ b/class/LuaUtils.php
@@ -0,0 +1,34 @@
+registerLibrary("logic", [
+            "extend" => fn() => [ call_user_func(array(LogicUtils::class, "extend"), ...func_get_args()) ],
+            "complement" => fn() => [ call_user_func(array(LogicUtils::class, "complement"), ...func_get_args()) ],
+            "changeRepresentation" => fn() => [ call_user_func(array(LogicUtils::class, "changeRepresentation"), ...func_get_args()) ],
+            "genRandomLogicFunction" => fn($iv, $mind, $maxd) => [ call_user_func(array(LogicFunction::class, "genRandom"), self::l2pA($iv), $mind, $maxd)->getExpression() ],
+            "genRandomLogicFunctionDNF" => fn($iv) => [ call_user_func(array(LogicFunction::class, "genRandomDNF"), self::l2pA($iv))->getExpression() ],
+            "isLogicFunctionValid" => fn($expr) => [ (new LogicFunction($expr))->isValid() ],
+            "isLogicFunctionADNF" => fn($iv, $expr) => [ call_user_func(array(LogicFunction::class, "isCorrectDNF"), self::l2pA($iv), $expr) ],
+            "collectVariablesFromLogicFunction" => fn($expr) => call_user_func(array(LogicFunction::class, "collectVariables"), $expr),
+            "convertLogicFunctionToTruthTable" => fn($expr, $iv) => [ (new LogicFunction($expr, self::l2pA($iv)))->getTruthTable() ],
+            "drawLogicFunction" => fn($expr, $iv, $ov) => [ (new LogicFunction($expr, self::l2pA($iv)))->drawNetwork($ov) ],
+        ]);
+    }
+}
\ No newline at end of file
diff --git a/class/Task.php b/class/Task.php
index 3e245df..7da929b 100644
--- a/class/Task.php
+++ b/class/Task.php
@@ -37,6 +37,8 @@ class Task implements JsonSerializable
                 return [ str_replace("{{" . $field . "}}", $replacement, $str) ];
             }
         ]);
+
+        LuaUtils::registerLuaLibs($this->lua_sandbox);
     }
     private function createLuaSandbox(): void {
         if ($this->lua_sandbox === null) {
@@ -116,7 +118,7 @@ class Task implements JsonSerializable
     }
 
     function setMark(float $mark): void {
-        $this->mark = $mark;
+        $this->mark = max($mark, 0.0);
     }
 
     function getMark(): float
@@ -129,7 +131,7 @@ class Task implements JsonSerializable
     }
 
     protected function staticCheck(): void {
-        return;
+        $this->mark = $this->max_mark;
     }
 
     function autoCheck(): void {
@@ -249,7 +251,6 @@ class Task implements JsonSerializable
         if ($this->lua_script !== "") {
             $this->luaRandomize();
         }
-        return;
     }
 
     function setGovernor(Game|Test|null &$governor): void {
diff --git a/class/TaskFactory.php b/class/TaskFactory.php
index aca9126..3e7a71f 100644
--- a/class/TaskFactory.php
+++ b/class/TaskFactory.php
@@ -10,6 +10,8 @@ require_once "Tasks/TruthTableTask.php";
 
 require_once "Tasks/VerilogTask.php";
 
+require_once "Tasks/LogicFunctionTask.php";
+
 class TaskFactory
 {
     static function fromArray(array $a, Game|Test|null &$governor = null): Task|null
@@ -28,6 +30,9 @@ class TaskFactory
             case "truthtable":
                 $task = new TruthTableTask($a);
                 break;
+            case "logicfunction":
+                $task = new LogicFunctionTask($a);
+                break;
             case "verilog":
                 $task = new VerilogTask($a);
                 break;
diff --git a/class/Tasks/LogicFunctionTask.php b/class/Tasks/LogicFunctionTask.php
new file mode 100644
index 0000000..701a16c
--- /dev/null
+++ b/class/Tasks/LogicFunctionTask.php
@@ -0,0 +1,59 @@
+missing_minterm_score = $a["missing_minterm_score"] ?? -1.0;
+
+        if (!$this->hasFlag("dnf")) {
+            $this->setCorrectAnswer($this->getLogicFunction()->getExpression());
+        } else {
+            $this->setCorrectAnswer($this->getLogicFunction()->toDNF());
+        }
+    }
+
+    public function toArray(string $mode = "all"): array
+    {
+        $a = parent::toArray($mode);
+
+        if ($this->hasFlag("attachtruthtable")) {
+            $a["truthtable"] = $this->getTruthtable();
+        }
+
+        if ($mode == "all") {
+            $a["missing_minterm_score"] = $this->missing_minterm_score;
+        }
+
+        return $a;
+    }
+
+    public function getMissingMintermScore(): float
+    {
+        return $this->missing_minterm_score;
+    }
+
+    public function setMissingMintermScore(float $missing_minterm_score): void
+    {
+        $this->missing_minterm_score = $missing_minterm_score;
+    }
+
+    protected function staticCheck(): void
+    {
+        $mark = 0.0;
+        $pa = $this->player_answer ?? "";
+        $iv = $this->getLogicFunction()->getInputVars();
+        $palf = new LogicFunction($pa, $iv);
+        if ($palf->isValid() && ((!$this->hasFlag("dnf")) || LogicFunction::isCorrectDNF($iv, $pa))) { // if the function is valid AND (if enabled) it is a correct DNF
+            $patt = $palf->getTruthTable();
+            $errs = $this->getTTDiffCntToCA($patt);
+            $mark = $this->getMaxMark() + $errs * $this->getMissingMintermScore();
+        }
+        $this->setMark($mark);
+    }
+}
\ No newline at end of file
diff --git a/class/Tasks/LogicTaskBase.php b/class/Tasks/LogicTaskBase.php
new file mode 100644
index 0000000..3317a4a
--- /dev/null
+++ b/class/Tasks/LogicTaskBase.php
@@ -0,0 +1,111 @@
+lf = LogicFunction::fromArray($a["function"]);
+        } else if (isset($a["expression"], $a["input_variables"])) { // building from the scratch
+            $this->lf = new LogicFunction($a["expression"], $a["input_variables"]);
+        } else {
+            $this->lf = new LogicFunction();
+        }
+
+        $this->output_variable = $a["output_variable"] ?? "f";
+    }
+
+    public function setOutputVariable(string $ovar): void {
+        $this->output_variable = $ovar;
+    }
+
+    public function getOutputVariable(): string {
+        return $this->output_variable;
+    }
+
+    public function setLogicFunction(LogicFunction $lf): void {
+        $this->lf = $lf;
+    }
+
+    public function getLogicFunction(): LogicFunction {
+        return $this->lf;
+    }
+
+    protected function getTTDiffCntToCA(string $ott): int {
+        $cans_tt = $this->getTruthTable();
+        $errs = 0;
+        for ($i = 0; $i < $this->getLogicFunction()->getNStates(); $i++) {
+            if (($ott[$i] ?? " ") != $cans_tt[$i]) {
+                $errs++;
+            }
+        }
+        return $errs;
+    }
+
+    public function toArray(string $mode = "all"): array
+    {
+        $a = parent::toArray($mode);
+
+        if ($mode === "all") {
+            $a["function"] = $this->lf->toArray();
+        }
+
+        $a["output_variable"] = $this->output_variable;
+        $a["input_variables"] = $this->lf->getInputVars();
+
+        return $a;
+    }
+
+    public function randomize(): void
+    {
+        parent::randomize();
+
+        if ($this->hasFlag("drawnetwork")) {
+            $this->setImageData($this->lf->drawNetwork($this->output_variable));
+            $this->setImageType("html");
+        }
+    }
+
+    // ---- Lua specific ----
+
+    public function generateRandomFunction(array $input_vars, int $min_depth, int $max_depth): void {
+        $this->lf = LogicFunction::genRandom(LuaUtils::l2pA($input_vars), $min_depth, $max_depth);
+    }
+
+    public function generateRandomDF(array $input_vars): void {
+        $this->lf = LogicFunction::genRandomDNF(LuaUtils::l2pA($input_vars));
+    }
+
+    public function getFunctionAsDNF(): string {
+        return $this->lf->toDNF();
+    }
+
+    public function setLogicFunctionExpr(string $expr, array $input_vars = []): void {
+        $this->lf = new LogicFunction($expr, LuaUtils::l2pA($input_vars));
+    }
+
+    public function getLogicFunctionExpr(string $fmt = "verilog_bitwise"): string {
+        return $this->lf->getExpression($fmt);
+    }
+
+    public function getLogicFunctionDNF(): string {
+        return $this->lf->toDNF();
+    }
+
+    public function getTruthTable(): string {
+        return $this->lf->getTruthTable();
+    }
+}
\ No newline at end of file
diff --git a/class/Tasks/NumberConversionTask.php b/class/Tasks/NumberConversionTask.php
index 21bc9e0..8afc0c8 100644
--- a/class/Tasks/NumberConversionTask.php
+++ b/class/Tasks/NumberConversionTask.php
@@ -106,9 +106,9 @@ class NumberConversionTask extends OpenEndedTask
     {
         $mark = 0.0;
         if ($this->hasFlag("acceptwithoutleadingzeros")) {
-            $mark = (ltrim($this->player_answer, " 0") === ltrim($this->correct_answer, "0")) ? 1.0 : 0.0;
+            $mark = (ltrim($this->player_answer, " 0") === ltrim($this->correct_answer, "0")) ? $this->getMaxMark() : 0.0;
         } else {
-            $mark = (trim($this->player_answer) === trim($this->correct_answer)) ? 1.0 : 0.0;
+            $mark = (trim($this->player_answer) === trim($this->correct_answer)) ? $this->getMaxMark() : 0.0;
         }
         $this->setMark($mark);
     }
diff --git a/class/Tasks/OpenEndedTask.php b/class/Tasks/OpenEndedTask.php
index ff83c8e..9276f80 100644
--- a/class/Tasks/OpenEndedTask.php
+++ b/class/Tasks/OpenEndedTask.php
@@ -48,7 +48,7 @@ class OpenEndedTask extends PicturedTask
 
     public function staticCheck(): void
     {
-        $mark = in_array($this->player_answer, $this->correct_answer) ? 1.0 : 0.0;
+        $mark = in_array($this->player_answer, $this->correct_answer) ? $this->getMaxMark() : 0.0;
         $this->setMark($mark);
     }
 
diff --git a/class/Tasks/PicturedTask.php b/class/Tasks/PicturedTask.php
index ddab455..e572e76 100644
--- a/class/Tasks/PicturedTask.php
+++ b/class/Tasks/PicturedTask.php
@@ -32,6 +32,16 @@ class PicturedTask extends Task
         return $this->image_type;
     }
 
+    function setUrlData(string $url_data): void {
+        $this->setImageData($url_data);
+        $this->setImageType("url");
+    }
+
+    function setHtmlData(string $svg_data): void {
+        $this->setImageData($svg_data);
+        $this->setImageType("html");
+    }
+
     function toArray(string $mode = "all"): array
     {
         $a = parent::toArray($mode);
diff --git a/class/Tasks/SingleChoiceTask.php b/class/Tasks/SingleChoiceTask.php
index 16f01c0..c915b9d 100644
--- a/class/Tasks/SingleChoiceTask.php
+++ b/class/Tasks/SingleChoiceTask.php
@@ -55,7 +55,7 @@ class SingleChoiceTask extends PicturedTask
 
     function staticCheck(): void
     {
-        $mark = ($this->player_answer == $this->correct_answer) ? 1.0 : 0.0;
+        $mark = ($this->player_answer == $this->correct_answer) ? $this->getMaxMark() : 0.0;
         $this->setMark($mark);
     }
 
diff --git a/class/Tasks/TruthTableTask.php b/class/Tasks/TruthTableTask.php
index 75676fc..40f3751 100644
--- a/class/Tasks/TruthTableTask.php
+++ b/class/Tasks/TruthTableTask.php
@@ -1,119 +1,42 @@
 lf = LogicFunction::fromArray($a["function"]);
-        } else if (isset($a["expression"], $a["input_variables"])) { // building from the scratch
-            $this->lf = new LogicFunction($a["expression"], $a["input_variables"]);
-        } else {
-            $this->lf = new LogicFunction();
-        }
+        $this->bad_line_score = $a["bad_line_score"] ?? -1.0;
+    }
 
-        $this->setOutputVariable($a["output_variable"] ?? "f");
+    function setBadLineScore(float $bad_line_score): void {
+        $this->bad_line_score = $bad_line_score;
+    }
+
+    function getBadLineScore(): float {
+        return $this->bad_line_score;
     }
 
     public function staticCheck(): void
     {
-        $ans_tt = $this->player_answer;
-        $cans_tt = $this->lf->getTruthTable();
-        $errs = 0;
-        for ($i = 0; $i < $this->lf->getNStates(); $i++) {
-            if (($ans_tt[$i] ?? " ") != $cans_tt[$i]) {
-                $errs++;
-            }
-        }
-        $mark = ($errs === 0) ? 1.0 : 0.0;
+        $errs = $this->getTTDiffCntToCA($this->player_answer ?? "");
+        $mark = $this->getMaxMark() + $errs * $this->getBadLineScore();
         $this->setMark($mark);
     }
 
-    public function setOutputVariable(string $ovar): void {
-        $this->output_variable = $ovar;
-    }
-
-    public function getOutputVariable(): string {
-        return $this->output_variable;
-    }
-
-    public function setLogicFunction(LogicFunction $lf): void {
-        $this->lf = $lf;
-    }
-
-    public function getLogicFunction(): LogicFunction {
-        return $this->lf;
-    }
-
-    public static function sanitizeIndices(array $a): array {
-        $r = [];
-        $i = 0;
-        foreach ($a as $v) {
-            $r[$i++] = $v;
-        }
-        return $r;
-    }
-
-    public function generateRandomFunction(array $input_vars, int $min_depth, int $max_depth): void {
-        $this->lf = LogicFunction::genRandom(self::sanitizeIndices($input_vars), $min_depth, $max_depth);
-    }
-
-    public function generateRandomDF(array $input_vars): void {
-        $this->lf = LogicFunction::genRandomDF(self::sanitizeIndices($input_vars));
-    }
-
-    public function getFunctionAsDNF(): string {
-        return $this->lf->toDNF();
-    }
-
-    public function isValidDNF(): bool {
-        return LogicFunction::isCorrectDNF($this->lf->getInputVars(), $this->lf->getExpression());
-    }
-
-    public function setLogicFunctionExpr(string $expr, array $input_vars = []): void {
-        $this->lf = new LogicFunction($expr, self::sanitizeIndices($input_vars));
-    }
-
-    public function getLogicFunctionExpr(string $fmt = "verilog_bitwise"): string {
-        return $this->lf->getExpression($fmt);
-    }
-
-    public function getLogicFunctionDNF(): string {
-        return $this->lf->toDNF();
-    }
-
     public function toArray(string $mode = "all"): array
     {
         $a = parent::toArray($mode);
 
         if ($mode === "all") {
-            $a["function"] = $this->lf->toArray();
+            $a["bad_line_score"] = $this->bad_line_score;
         }
 
-        $a["correct_answer"] = $this->lf->getTruthTable();
-        $a["input_variables"] = $this->lf->getInputVars();
-        $a["output_variable"] = $this->output_variable;
+        $a["correct_answer"] = $this->getLogicFunction()->getTruthTable();
 
         return $a;
     }
-
-    public function randomize(): void
-    {
-        parent::randomize();
-
-        if ($this->hasFlag("drawnetwork")) {
-            $this->setImageData($this->lf->drawNetwork($this->output_variable));
-            $this->setImageType("svg");
-        }
-    }
 }
\ No newline at end of file
diff --git a/class/Tasks/VerilogTask.php b/class/Tasks/VerilogTask.php
index 405e200..42ff210 100644
--- a/class/Tasks/VerilogTask.php
+++ b/class/Tasks/VerilogTask.php
@@ -6,6 +6,7 @@ class VerilogTask extends PicturedTask
 {
     private string $test_bench_fn; // test bench file name
     private string $compile_log; // short explanation for the marking
+    private float $error_score; // points received for an error
     private const FAILED_MARK = "[FAILED]"; // mark at the beginning of testbench results indicating a failed combination
 
     public function __construct(array &$a = null)
@@ -14,6 +15,7 @@ class VerilogTask extends PicturedTask
 
         $this->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
@@ -26,7 +28,7 @@ class VerilogTask extends PicturedTask
         return true;
     }
 
-    private function executeTest(): bool
+    private function executeTest(): int
     {
         // store the user's answer
         $module_code_fn = tempnam(sys_get_temp_dir(), "verilogtask_user_module_");
@@ -74,7 +76,17 @@ class VerilogTask extends PicturedTask
         @unlink($test_bench_fn);
         @unlink($output_fn);
 
-        return $failed_count == 0;
+        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
@@ -85,10 +97,12 @@ class VerilogTask extends PicturedTask
         $mark = 0.0;
         if ($this->verifyCode()) {
             // run the simulation
-            $test_ok = $this->executeTest();
-
-            $mark = $test_ok ? 1.0 : 0.0;  // FIXME
+            $failed_count = $this->executeTest();
+            if ($failed_count != PHP_INT_MAX) {
+                $mark = $this->getMaxMark() + $failed_count * $this->error_score;
+            }
         }
+
         $this->setMark($mark);
     }
 
@@ -100,6 +114,7 @@ class VerilogTask extends PicturedTask
 
         if ($mode == "all") {
             $a["test_bench_fn"] = $this->test_bench_fn;
+            $a["error_score"] = $this->error_score;
         }
 
         return $a;
diff --git a/class/Utils.php b/class/Utils.php
index f494eb8..2abc6f5 100644
--- a/class/Utils.php
+++ b/class/Utils.php
@@ -7,7 +7,22 @@ class Utils
     public static function str2kv(string $str): array
     {
         preg_match_all("/([^,= ]+)=([^,= ]+)/", $str, $r);
-        return array_combine($r[1], $r[2]);
+        $a = array_combine($r[1], $r[2]);
+
+        foreach ($a as &$v) {
+            if (is_numeric($v)) { // is it a numeric value?
+                if (((int)$v) == ((double)$v)) { // is it an integer?
+                    $v = (int)$v;
+                } else { // is it a float?
+                    $v = (double)$v;
+                }
+            } else if (in_array(strtolower($v), ["true", "false"]) ) { // it's a boolean
+                $v = $v === "true";
+            } else if (str_starts_with($v, '"') && str_ends_with($v, '"')) { // it's a string
+                $v = substr($v, 1, strlen($v) - 2); // strip leading and trailing quotes
+            }
+        }
+        return $a;
     }
 
     public static function str2a(string $str): array {
diff --git a/js/tasks.js b/js/tasks.js
index 316763b..7e780cf 100644
--- a/js/tasks.js
+++ b/js/tasks.js
@@ -36,19 +36,26 @@ class Task extends HTMLElement {
                 margin-bottom: 0.5em;
                 border-radius: 0.3em;
             }
-            section.seq-num {
+            section.seq-num, section.mark {
                 display: block;
                 position: absolute;
                 right: 0;
                 padding: 0.5em;
-                bottom: 0;
                 background-color: #176767;
                 color: whitesmoke;
-                border-bottom-right-radius: 0.3em;
-                border-top-left-radius: 0.3em;
                 width: 2em;
                 z-index: 10;
             }
+            section.seq-num {
+                bottom: 0;
+                border-bottom-right-radius: 0.3em;
+                border-top-left-radius: 0.3em;
+            }
+            section.mark {
+                top: 0;
+                border-top-right-radius: 0.3em;
+                border-bottom-left-radius: 0.3em;
+            }
             section.answer-container {
                 /* (empty) */
             }
@@ -56,7 +63,7 @@ class Task extends HTMLElement {
                 background-color: #e5d8d3;
             }
             code {
-                font-family: 'Monaco', monospace;
+                font-family: 'Source Code Pro', monospace;
             }
             
             section#correct-answer {
@@ -96,6 +103,8 @@ class Task extends HTMLElement {
         question_span.classList.add("question");
         let answer_container = document.createElement("section");
         answer_container.classList.add("answer-container");
+        let mark_section = document.createElement("section");
+        mark_section.classList.add("mark");
         let seq_num_section = document.createElement("section");
         seq_num_section.classList.add("seq-num");
         seq_num_section.innerText = `${this.sequence_number + 1}.`;
@@ -106,6 +115,7 @@ class Task extends HTMLElement {
 
         task_box.append(question_span);
         task_box.append(answer_container);
+        task_box.append(mark_section);
         task_box.append(seq_num_section);
         task_box.append(ca_section);
         task_box.append(comment_sec);
@@ -115,6 +125,7 @@ class Task extends HTMLElement {
         this.task_box = task_box;
         this.question_span = question_span;
         this.answer_container = answer_container;
+        this.mark_section = mark_section;
         this.seq_num_section = seq_num_section;
         this.ca_section = ca_section;
         this.comment_sec = comment_sec;
@@ -198,10 +209,21 @@ class Task extends HTMLElement {
 
     }
 
+    displayMarking() {
+        if (this.isConcluded) {
+            this.mark_section.innerText = `${this.mark}/${this.max_mark}`;
+        } else {
+            this.mark_section.innerText = `${this.max_mark}`;
+        }
+        this.mark_section.innerHTML += `p`
+    }
+
     fromArray(a) {
         this.setQuestion(a["question"]);
         this.playerAnswer = a["player_answer"];
         this.correctAnswer = a["correct_answer"];
+        this.max_mark = a["max_mark"];
+        this.mark = a["mark"];
 
         let comment = a["comment"];
         if ((comment !== undefined) && (comment !== null) && (comment !== "")) {
@@ -217,6 +239,8 @@ class Task extends HTMLElement {
         if (this.isConcluded) {
             this.displayCorrectAnswer();
         }
+
+        this.displayMarking();
     }
 }
 
@@ -258,7 +282,7 @@ class PicturedTask extends Task {
                 this.img.src = data.trim();
             }
             break;
-            case "svg":
+            case "html":
             {
                 this.img = document.createElement("section");
                 this.img.classList.add("question-image");
@@ -393,6 +417,8 @@ class SingleChoiceTask extends PicturedTask {
 class OpenEndedTask extends PicturedTask {
     constructor() {
         super("openended");
+
+        this.ca_prefix = "Lehetséges megoldások:";
     }
 
     createStyle() {
@@ -400,7 +426,7 @@ class OpenEndedTask extends PicturedTask {
 
         this.css.innerHTML += `
             input[type="text"] {
-                font-family: 'Monaco', monospaced;
+                font-family: 'Source Code Pro', monospace;
                 border-width: 0 0 2.2pt 0;
                 background-color: transparent;
                 width: calc(100% - 4em);
@@ -434,7 +460,9 @@ class OpenEndedTask extends PicturedTask {
     }
 
     displayCorrectAnswer() {
-        this.ca_section.innerHTML = "Lehetséges megoldások:
" + this.correctAnswer.join(", VAGY
");
+        if (this.correctAnswer !== null) {
+            this.ca_section.innerHTML = this.ca_prefix + "
" + this.correctAnswer.join(", VAGY
");
+        }
     }
 
     fromArray(a) {
@@ -442,12 +470,15 @@ class OpenEndedTask extends PicturedTask {
     }
 
     set playerAnswer(player_answer) {
+        if (player_answer === null) {
+            player_answer = "";
+        }
         super.playerAnswer = player_answer;
-        this.answer_tf.value = player_answer;
+        this.answer_tf.value = this.playerAnswer;
     }
 
     get playerAnswer() {
-        return this.player_answer;
+        return super.playerAnswer;
     }
 
     updateAnswerFieldState() {
@@ -489,7 +520,7 @@ class NumberConversionTask extends OpenEndedTask {
             section#src, section#dst {
                 position: relative;
                 display: inline-block;
-                font-family: 'Monaco', monospace;
+                font-family: 'Source Code Pro', monospace;
                 color: #176767;
             }
             section#src {
@@ -574,7 +605,7 @@ class Switch extends HTMLElement {
                 display: inline-block;
                 padding: 0.2em 0.5em;
                 cursor: pointer;
-                font-family: 'Monaco', monospace;
+                font-family: 'Source Code Pro', monospace;
             }
             section.button[disabled="false"]:hover {
                 background-color: #408d8d;
@@ -651,6 +682,28 @@ class Switch extends HTMLElement {
     }
 }
 
+var truth_table_css = `
+    table#tt {
+        border: 1.5pt solid #176767;
+        margin: 0.5em auto;
+        border-spacing: 0;
+        font-family: 'Source Code Pro', monospace;
+    }
+    table#tt tr:not(:last-child) td {
+        border-bottom: 1.2pt solid black;
+    }
+    table#tt th {
+        border-bottom: 1.5pt dotted black
+    }
+    table#tt td, table#tt th {
+        min-width: 3ch;
+        text-align: center;
+    }
+    table#tt td:last-child, table#tt th:last-child {
+        border-left: 1.5pt dashed black;
+    }
+`;
+
 class TruthTableTask extends PicturedTask {
     constructor() {
         super("truthtable");
@@ -663,27 +716,7 @@ class TruthTableTask extends PicturedTask {
     createStyle() {
         super.createStyle();
 
-        this.css.innerHTML += `
-            table#tt {
-                border: 1.5pt solid #176767;
-                margin: 0.5em auto;
-                border-spacing: 0;
-                font-family: 'Monaco', monospace;
-            }
-            table#tt tr:not(:last-child) td {
-                border-bottom: 1.2pt solid black;
-            }
-            table#tt th {
-                border-bottom: 1.5pt dotted black
-            }
-            table#tt td, table#tt th {
-                min-width: 3ch;
-                text-align: center;
-            }
-            table#tt td:last-child, table#tt th:last-child {
-                border-left: 1.5pt dashed black;
-            }
-        `;
+        this.css.innerHTML += truth_table_css;
     }
 
     createElements() {
@@ -775,6 +808,91 @@ class TruthTableTask extends PicturedTask {
     }
 }
 
+class LogicFunctionTask extends OpenEndedTask {
+    constructor() {
+        super();
+        this.type = "logicfunction";
+    }
+
+    createStyle() {
+        super.createStyle();
+
+        this.css.innerHTML += truth_table_css;
+        this.css.innerHTML += `
+            section#assignment-sec {
+                position: relative;
+                display: inline-block;
+                font-family: 'Source Code Pro', monospace;
+                color: #176767;
+                margin-right: 1ch;
+            }
+            input[type="text"] {
+                min-width: 5em;
+                width: 85%;
+                font-family: 'Source Code Pro', monospace;
+            }
+        `;
+    }
+
+    createElements() {
+        super.createElements();
+
+        let assignment_sec = document.createElement("section");
+        assignment_sec.id = "assignment-sec";
+
+        this.answer_container.insertBefore(assignment_sec, this.answer_tf);
+
+        this.assignment_sec = assignment_sec;
+    }
+
+    drawTruthTable() {
+        let N = this.input_variables.length;
+        let M = (1 << N);
+
+        let table = "
| " + this.input_variables[i] + " | "; + } + table += "" + this.output_variable + " | "; + table += "
|---|---|
| " + ((i >> (N - j - 1)) & 1).toString() + " | "; + } + table += "" + this.truth_table.charAt(i) + " | " + table += "
" + correct_answer + "" ];
+    }
+
+    get correctAnswer() {
+        return super.correctAnswer;
+    }
+}
+
 class VerilogTask extends PicturedTask {
     //static observedAttributes = ["language"]
     constructor() {
@@ -920,7 +1038,9 @@ class VerilogTask extends PicturedTask {
 customElements.define('singlechoice-task', SingleChoiceTask);
 customElements.define('openended-task', OpenEndedTask);
 customElements.define('numberconversion-task', NumberConversionTask);
-customElements.define('truthtable-task', TruthTableTask);
 customElements.define('slide-switch', Switch);
+customElements.define('truthtable-task', TruthTableTask);
+customElements.define('logicfunction-task', LogicFunctionTask);
 customElements.define('verilog-task', VerilogTask);
 
+
diff --git a/maintenance.html b/maintenance.html
index f97b79a..5eb4d15 100644
--- a/maintenance.html
+++ b/maintenance.html
@@ -7,7 +7,7 @@
 
 
-