diff --git a/gamemgr.php b/gamemgr.php
index d6e49bd..ec4ad6a 100644
--- a/gamemgr.php
+++ b/gamemgr.php
@@ -27,7 +27,7 @@ function create_game(string $name, string $owner, string $description = "", arra
// prepare game context
$id = $game_data["_id"];
- $current_game_media_dir = GAMEMEDIA_DIR . DIRECTORY_SEPARATOR . $id;
+ $current_game_media_dir = get_game_dir_by_gameid($id);
mkdir($current_game_media_dir);
save_challenges($id, []);
return true;
@@ -92,6 +92,7 @@ const CSV_ENCODINGS = ["Windows-1252", "UTF-8"];
function import_challenges_from_csv(string $csv_path, string $gameid): array
{
$game_data = get_game($gameid);
+ $game_dir = get_game_dir_by_gameid($gameid);
if (count($game_data) === []) {
return ["n" => 0, "encoding" => ""];
}
@@ -125,14 +126,31 @@ function import_challenges_from_csv(string $csv_path, string $gameid): array
continue;
}
if (count($csvline) >= 3) {
+ // construct challenge record
$ch = [
- "question" => $csvline[0],
- "image_url" => $csvline[1],
- "correct_answer" => $csvline[2],
+ "question" => trim($csvline[0]),
+ "image_url" => trim($csvline[1]),
+ "correct_answer" => trim($csvline[2]),
"answers" => array_filter(array_slice($csvline, 2), function ($v) {
return trim($v) !== "";
})
];
+
+ // if image is attached to the challenge, then give a random name to the image
+ if ($ch["image_url"] !== "") {
+ $old_img_name = $ch["image_url"];
+ $ext = pathinfo($old_img_name, PATHINFO_EXTENSION);
+ $ext = ($ext !== "") ? ("." . $ext) : $ext;
+ $new_img_name = uniqid("img_", true) . $ext;
+ $ch["image_url"] = $new_img_name;
+
+ // rename the actual file
+ $old_img_path = $game_dir . DIRECTORY_SEPARATOR . $old_img_name;
+ $new_img_path = $game_dir . DIRECTORY_SEPARATOR . $new_img_name;
+ rename($old_img_path, $new_img_path);
+ }
+
+ // store the challenge
$challenges[] = $ch;
}
}
@@ -207,4 +225,9 @@ function get_contributors(string $gameid): array
function get_game_file_by_gameid(string $gameid)
{
return GAMEMEDIA_DIR . DIRECTORY_SEPARATOR . $gameid . DIRECTORY_SEPARATOR . GAME_FILE;
+}
+
+function get_game_dir_by_gameid(string $gameid)
+{
+ return GAMEMEDIA_DIR . DIRECTORY_SEPARATOR . $gameid;
}
\ No newline at end of file
diff --git a/interface.php b/interface.php
index 0076d14..2457a06 100644
--- a/interface.php
+++ b/interface.php
@@ -126,6 +126,20 @@ if ((($testid = trim($_REQUEST["testid"] ?: "")) !== "") &&
$result = json_encode($test_data_with_current_time);
}
break;
+ case "get_image":
+ {
+ $img_url = trim($_REQUEST["image_url"] ?: "");
+ if ($img_url !== "") {
+ $gameid = $test_data["gameid"];
+ $game_dir = get_game_dir_by_gameid($gameid);
+ $image_fetch_url = $game_dir . DIRECTORY_SEPARATOR . $img_url;
+
+ $img_fp = fopen($image_fetch_url, "r");
+ fpassthru($img_fp);
+ fclose($img_fp);
+ }
+ }
+ break;
case "save_answer":
{
$chidx = $_REQUEST["challenge_index"];
@@ -174,8 +188,8 @@ switch ($action) {
$groupids_with_editor_access[] = $groupid;
}
}
- $groupids_with_editor_access = $groupid;
+ // create or update
if (!$update) {
create_game($name, $owner, $description);
} else if (is_user_contributor_to_game($gameid, $nickname)) {
@@ -209,7 +223,35 @@ switch ($action) {
// update game file if supplied
if (isset($_FILES["game_file"])) {
- $challenge_import_status = import_challenges_from_csv($_FILES["game_file"]["tmp_name"], $data["_id"]);
+ // decide weather it's a package or a plain table
+ $file = $_FILES["game_file"];
+ $file_type = $file["type"];
+ $challenge_import_status = [];
+ if ($file_type === "application/zip") { // a package was uploaded
+ $zip = new ZipArchive;
+ if ($zip->open($file["tmp_name"])) {
+
+ $game_dir = get_game_dir_by_gameid($gameid); // get game directory
+ $game_files = glob($game_dir); // get list of existing game files
+ // remove former files recursively
+ $dir_iter = new RecursiveDirectoryIterator($game_dir, FilesystemIterator::SKIP_DOTS);
+ foreach ($dir_iter as $dir_item) {
+ $item_path = $dir_item->getPathname();
+ $dir_item->isDir() ? rmdir($item_path) : unlink($item_path);
+ }
+
+ // extract package contents to the game directory
+ $zip->extractTo($game_dir . DIRECTORY_SEPARATOR);
+
+ // search for the CSV table file
+ $csv_files = glob($game_dir . DIRECTORY_SEPARATOR . "*.csv") ?: [];
+ if (count($csv_files)) {
+ $challenge_import_status = import_challenges_from_csv($csv_files[0], $gameid);
+ }
+ }
+ } else if ($file_type === "text/csv") { // a plain table was uploaded
+ $challenge_import_status = import_challenges_from_csv($file["tmp_name"], $gameid);
+ }
$result = json_encode($challenge_import_status);
}
}
diff --git a/js/testground.js b/js/testground.js
index 10182e3..be54e84 100644
--- a/js/testground.js
+++ b/js/testground.js
@@ -41,8 +41,19 @@ function populate_infobox(test_data) {
INTERVAL_HANDLE = null;
}
}, 1000);
+ show("time-info");
+ } else {
+ hide("time-info");
}
+ // fill further info
+ let further_info_box = document.getElementById("further-info");
+ let further_info = "";
+ if (!test_data["repeatable"]) {
+ further_info += "A teszt nem megismételhető!
";
+ }
+ further_info_box.innerHTML = further_info;
+
show("ongoing-info");
hide("concluded-info");
}
@@ -66,6 +77,18 @@ function populate_challenges(test_data) {
answer_container.classList.add("answer-container");
challenge_box.append(question, answer_container);
+ if (challenge["image_url"] !== "") {
+ let qimg = document.createElement("img");
+ qimg.src = `interface.php?action=get_image&testid=${test_data["_id"]}&image_url=${challenge["image_url"]}`;
+ qimg.classList.add("question-image")
+ challenge_box.insertBefore(qimg, answer_container);
+ }
+
+ let seq_num_section = document.createElement("section");
+ seq_num_section.innerText = String(challenge_N + 1) + "."
+ seq_num_section.classList.add("seq-num");
+ challenge_box.append(seq_num_section);
+
let answer_N = 0;
let player_answer = challenge["player_answer"];
player_answer = (player_answer !== "") ? Number(player_answer) : -1;
@@ -90,6 +113,10 @@ function populate_challenges(test_data) {
answer_text.setAttribute("for", answer_radio.id);
if (test_concluded && (challenge["correct_answer"] === answer_N)) {
answer_text.classList.add("correct-answer")
+
+ if (player_answer !== challenge["correct_answer"]) {
+ challenge_box.classList.add("bad-answer");
+ }
}
answer_section.append(answer_radio, answer_text);
diff --git a/style/spreadquiz.css b/style/spreadquiz.css
index fa1a37e..4e6cd08 100644
--- a/style/spreadquiz.css
+++ b/style/spreadquiz.css
@@ -229,6 +229,7 @@ section#test_area {
section.challenge {
display: block;
+ position: relative;
margin: 0 auto;
width: 40em;
/*border: 1px solid black;*/
@@ -361,4 +362,34 @@ section.test-summary-record {
code {
font-family: 'Monaco', monospace;
+}
+
+img.question-image {
+ display: block;
+ position: relative;
+ margin: 1em auto;
+ border-radius: 0.3em;
+ max-width: 100%;
+}
+
+section.seq-num {
+ 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;
+}
+
+section.bad-answer {
+ background-color: #e5d8d3;
+}
+
+section#further-info {
+ font-size: 0.8em;
+ padding: 0.4em 0;
}
\ No newline at end of file
diff --git a/testground.php b/testground.php
index 176bcb7..eedc021 100644
--- a/testground.php
+++ b/testground.php
@@ -36,8 +36,13 @@ if ($testid === "") {