diff --git a/interface.php b/interface.php
index b6aa0de..68c34a9 100644
--- a/interface.php
+++ b/interface.php
@@ -112,9 +112,9 @@ switch ($action) {
}
// test-related queries
-if ((($testid = trim($_REQUEST["testid"] ?: "")) !== "") &&
+if (isset($_REQUEST["testid"]) && (($testid = trim($_REQUEST["testid"])) !== "") &&
((count($test_data = get_test($testid))) > 0) &&
- ($test_data["nickname"] === $nickname)) {
+ (($test_data["nickname"] === $nickname) || $is_quizmaster)) {
// update the test if timed
update_timed_tests([$test_data]);
@@ -141,6 +141,9 @@ if ((($testid = trim($_REQUEST["testid"] ?: "")) !== "") &&
}
}
break;
+ }
+
+ switch ($action) {
case "save_answer":
{
$chidx = $_REQUEST["challenge_index"];
@@ -313,12 +316,21 @@ switch ($action) {
{
$gameid = trim($_REQUEST["gameid"] ?: "");
$filter = trim($_REQUEST["filter"] ?: "");
+ $ordering = trim($_REQUEST["orderby"] ?: "");
if (($gameid !== "") && (is_user_contributor_to_game($gameid, $nickname) || $is_quizmaster)) {
- $game_results = get_results_by_gameid($gameid, $filter);
+ $game_results = get_results_by_gameid($gameid, $filter, $ordering, true);
$result = json_encode($game_results);
}
}
break;
+ case "generate_detailed_stats":
+ {
+ $testids = json_decode(trim($_REQUEST["testids"] ?: "[]"), true);
+ $gameid = trim($_REQUEST["gameid"] ?: "");
+ $stats = generate_detailed_stats($gameid, $testids);
+ $result = json_encode($stats);
+ }
+ break;
}
// quizmaster actions
diff --git a/js/common.js b/js/common.js
index 768b367..a00c4b6 100644
--- a/js/common.js
+++ b/js/common.js
@@ -30,4 +30,19 @@ function time_to_seconds(t) {
}
}
return s;
+}
+
+function preprocess_inserts(str) {
+ let code_delim = '`';
+ let parts = str.split(code_delim);
+ let res = "";
+ for (let i = 0; i < parts.length; i++) {
+ res += parts[i];
+ if (i % 2 === 0) {
+ res += "";
+ } else {
+ res += "
";
+ }
+ }
+ return res;
}
\ No newline at end of file
diff --git a/js/gamemgr.js b/js/gamemgr.js
index 44f2667..798a6e0 100644
--- a/js/gamemgr.js
+++ b/js/gamemgr.js
@@ -339,6 +339,10 @@ function list_results_by_game(game) {
}
}
+ test_summary_record.addEventListener("click", () => {
+ window.open(`testground.php?testid=${record["_id"]}&view_only=true`, "_blank");
+ });
+
test_group_box.appendChild(test_summary_record);
n--;
diff --git a/js/result_analyzer.js b/js/result_analyzer.js
index b63695b..b34efab 100644
--- a/js/result_analyzer.js
+++ b/js/result_analyzer.js
@@ -1,4 +1,4 @@
-function create_cell(content) {
+function create_cell(content = "") {
let cell = document.createElement("td");
cell.innerHTML = content;
return cell;
@@ -7,8 +7,14 @@ function create_cell(content) {
function fetch_results() {
let filterF = document.getElementById("filter");
+ let orderbyF = document.getElementById("orderby");
- let req = {action: "get_results_by_gameid", gameid: GAMEID, filter: filterF.value.trim()};
+ let req = {
+ action: "get_results_by_gameid",
+ gameid: GAMEID,
+ filter: filterF.value.trim(),
+ orderby: orderbyF.value.trim()
+ };
request(req).then(resp => {
let rd = document.getElementById("results_display");
@@ -28,8 +34,9 @@ function fetch_results() {
// is the game concluded
let concluded = record["state"] === "concluded";
- let percentage = "-";
- let timestamp = "-";
+ let percentage = "";
+ let start_timestamp = unix_time_to_human_readable(record["start_time"]);
+ let end_timestamp = "";
// replace some fields if game was concluded
if (concluded) {
@@ -39,16 +46,31 @@ function fetch_results() {
percentage = `${r}%`;
// finish timestamp
- timestamp = unix_time_to_human_readable(record["end_time"]);
+ end_timestamp = unix_time_to_human_readable(record["end_time"]);
}
// create cells
- let empty_cell = create_cell("");
+ let selectChk = document.createElement("input");
+ selectChk.type = "checkbox";
+ selectChk.name = "game_select";
+ selectChk.record = record;
+
+ let selection_cell = create_cell();
+ selection_cell.append(selectChk);
+
+ let id_cell = create_cell(record["_id"]);
+
+ let inspect_link = `🔎`
+ let inspect_cell = create_cell(inspect_link);
let name_cell = create_cell(record.nickname)
let percentage_cell = create_cell(percentage)
- let timestamp_cell = create_cell(timestamp);
+ let start_timestamp_cell = create_cell(start_timestamp);
+ let end_timestamp_cell = create_cell(end_timestamp);
- row.append(empty_cell, name_cell, percentage_cell, timestamp_cell);
+ row.append(selection_cell, id_cell, inspect_cell, name_cell, percentage_cell, start_timestamp_cell, end_timestamp_cell);
+
+ // save record data into the row object
+ row.record = record;
// append row
rd.appendChild(row);
@@ -56,3 +78,91 @@ function fetch_results() {
});
}
+
+function generate_report() {
+ let testids = [];
+ let game_selectChks = document.getElementsByName("game_select");
+ game_selectChks.forEach((chk) => {
+ if (chk.checked) {
+ testids.push(chk.record["_id"]);
+ }
+ });
+
+ let req = {
+ action: "generate_detailed_stats",
+ gameid: GAMEID,
+ testids: JSON.stringify(testids)
+ };
+
+ request(req).then((resp) => {
+ let stats = JSON.parse(resp);
+ let statsTab = window.open("report.html", "_blank");
+
+ statsTab.addEventListener("load", () => {
+ let report_display = statsTab.document.getElementById("report_display");
+ report_display.innerHTML = "";
+
+ stats.forEach((challenge) => {
+ let challenge_box = document.createElement("section");
+ challenge_box.classList.add("challenge");
+ challenge_box.style.width = "100%";
+
+ let img_url = challenge["image_url"];
+ if (img_url !== "") {
+ let fig = document.createElement("img");
+ fig.src = img_url;
+ fig.classList.add("question-image");
+ challenge_box.append(fig);
+ }
+
+ let question = document.createElement("span");
+ question.classList.add("question");
+ question.innerHTML = preprocess_inserts(challenge["question"]);
+ let answer_container = document.createElement("section");
+ answer_container.classList.add("answer-container");
+ challenge_box.append(question, answer_container);
+
+ let n = challenge["answer_count"];
+ for (let i = 0; i < n; i++) {
+ let answer = challenge["answers"][i];
+ let correct_answer = answer === challenge["correct_answer"];
+
+ let answer_section = document.createElement("section");
+ answer_section.classList.add("answer");
+
+ let progress_bar_container = document.createElement("section");
+ progress_bar_container.classList.add("pb-container")
+ let progress_bar_indicator = document.createElement("section");
+ progress_bar_indicator.classList.add("pb-indicator")
+
+ let percentage = challenge["answer_ratio"][i] * 100;
+ progress_bar_indicator.style.width = `${percentage}%`;
+ progress_bar_indicator.innerText = Math.round(percentage * 100.0) / 100.0 + "%";
+ progress_bar_indicator.setAttribute("correct", correct_answer ? "true" : "false");
+
+ progress_bar_container.append(progress_bar_indicator);
+
+ let answer_text = document.createElement("span");
+ answer_text.classList.add("answer");
+ answer_text.innerHTML = preprocess_inserts(answer);
+ answer_text.setAttribute("correct", correct_answer ? "true" : "false");
+
+ answer_section.append(progress_bar_container, answer_text);
+
+ answer_container.append(answer_section);
+ }
+
+ report_display.append(challenge_box);
+ });
+
+ statsTab.MathJax.typeset();
+ });
+ });
+}
+
+function toggle_test_selection() {
+ let game_selectChks = document.getElementsByName("game_select");
+ game_selectChks.forEach((chk) => {
+ chk.checked = !chk.checked;
+ });
+}
\ No newline at end of file
diff --git a/js/testground.js b/js/testground.js
index be54e84..061e687 100644
--- a/js/testground.js
+++ b/js/testground.js
@@ -1,7 +1,7 @@
let TEST_DATA = {}
let INTERVAL_HANDLE = null;
-function populate_infobox(test_data) {
+function populate_infobox(test_data, view_only) {
if (INTERVAL_HANDLE !== null) {
clearInterval(INTERVAL_HANDLE);
}
@@ -12,6 +12,9 @@ function populate_infobox(test_data) {
let durationS = document.getElementById("duration");
let percentageS = document.getElementById("percentage");
+ let submitBtn = document.getElementById("submit_btn");
+ submitBtn.hidden = view_only;
+
game_nameS.innerHTML = test_data["gamename"];
if (test_concluded) {
@@ -28,19 +31,27 @@ function populate_infobox(test_data) {
hide("ongoing-info");
show("concluded-info");
} else {
+ let timerS = document.getElementById("timer");
+ let time_left_s = Number(test_data["end_limit_time"]) - Number(test_data["current_time"]);
+
+ let print_timer = () => {
+ timerS.innerHTML = seconds_to_time(time_left_s);
+ };
+
if (test_data["time_limited"]) {
- let timerS = document.getElementById("timer");
- let time_left_s = Number(test_data["end_limit_time"]) - Number(test_data["current_time"]);
- seconds_to_time(time_left_s);
- INTERVAL_HANDLE = setInterval(() => {
- time_left_s--;
- timerS.innerHTML = seconds_to_time(time_left_s);
- if (time_left_s <= 0) {
- populate_all(test_data["_id"]);
- clearInterval(INTERVAL_HANDLE);
- INTERVAL_HANDLE = null;
- }
- }, 1000);
+ print_timer()
+
+ if (!view_only) {
+ INTERVAL_HANDLE = setInterval(() => {
+ time_left_s--;
+ print_timer();
+ if (time_left_s <= 0) {
+ populate_all(test_data["_id"]);
+ clearInterval(INTERVAL_HANDLE);
+ INTERVAL_HANDLE = null;
+ }
+ }, 1000);
+ }
show("time-info");
} else {
hide("time-info");
@@ -59,7 +70,7 @@ function populate_infobox(test_data) {
}
}
-function populate_challenges(test_data) {
+function populate_challenges(test_data, view_only = false) {
let test_display = document.getElementById("test_display");
test_display.innerHTML = "";
@@ -99,7 +110,7 @@ function populate_challenges(test_data) {
answer_radio.type = "radio";
answer_radio.id = `${challenge_N}_${answer_N}`;
answer_radio.name = `challenge_${challenge_N}`;
- answer_radio.disabled = test_concluded;
+ answer_radio.disabled = test_concluded || view_only;
let answer_N_snapshot = answer_N;
answer_radio.addEventListener("input", () => {
save_answer(challenge_N_snapshot, answer_N_snapshot);
@@ -132,15 +143,16 @@ function populate_challenges(test_data) {
MathJax.typeset();
}
-function populate_all(test_id) {
+function populate_all(test_id, view_only) {
let req = {
action: "get_test",
+ view_only: view_only,
testid: test_id
}
request(req).then(resp => {
TEST_DATA = JSON.parse(resp);
- populate_challenges(TEST_DATA);
- populate_infobox(TEST_DATA);
+ populate_challenges(TEST_DATA, view_only);
+ populate_infobox(TEST_DATA, view_only);
});
}
@@ -154,21 +166,6 @@ function save_answer(chidx, aidx) {
request(req);
}
-function preprocess_inserts(str) {
- let code_delim = '`';
- let parts = str.split(code_delim);
- let res = "";
- for (let i = 0; i < parts.length; i++) {
- res += parts[i];
- if (i % 2 === 0) {
- res += "";
- } else {
- res += "
";
- }
- }
- return res;
-}
-
function submit_test() {
let req = {
action: "submit_test",
diff --git a/report.html b/report.html
new file mode 100644
index 0000000..141615b
--- /dev/null
+++ b/report.html
@@ -0,0 +1,20 @@
+
+
+
+ + | +# +
+ [_id]
+
+ |
Felhasználónév @@ -60,11 +70,17 @@ if (!is_user_contributor_to_game($game_id, $user_data["nickname"]) && ($user_dat [result] |
- Időbélyeg + | Kezdés ideje
- [timestamp]
+ [start_time]
|
+ Befejezés ideje +
+ [end_time]
+
+ |
+
---|