402 lines
14 KiB
JavaScript
402 lines
14 KiB
JavaScript
function fetch_game_groups(gameid, cb) {
|
|
let req = {
|
|
action: "get_game_groups",
|
|
gameid: gameid
|
|
};
|
|
request(req).then(resp => {
|
|
let groups = JSON.parse(resp);
|
|
let groupsJoined = groups.join(", ");
|
|
cb(groupsJoined);
|
|
});
|
|
}
|
|
|
|
function list_all_games() {
|
|
let req = {action: "get_all_game_headers"};
|
|
let tbody = document.getElementById("game_manager_table");
|
|
tbody.innerHTML = "";
|
|
request(req).then(resp => {
|
|
let games = JSON.parse(resp);
|
|
for (let i = 0; i < games.length; i++) {
|
|
let g = games[i];
|
|
let row = document.createElement("tr");
|
|
let chkbox = document.createElement("input");
|
|
chkbox.type = "checkbox";
|
|
chkbox.name = "game_chkbox";
|
|
chkbox.game = g;
|
|
let tdChkBox = document.createElement("td");
|
|
tdChkBox.appendChild(chkbox);
|
|
tdChkBox.classList.add("checkbox");
|
|
let tdGameName = create_table_cell(g["name"]);
|
|
let tdGameDescription = create_table_cell(g["description"]);
|
|
let tdOwner = create_table_cell(g["owner"]);
|
|
row.append(tdChkBox, tdGameName, tdGameDescription, tdOwner);
|
|
tbody.appendChild(row);
|
|
|
|
let edit_group_action = () => {
|
|
create_edit_game(g);
|
|
};
|
|
|
|
tdGameName.addEventListener("click", edit_group_action);
|
|
tdGameDescription.addEventListener("click", edit_group_action);
|
|
tdOwner.addEventListener("click", edit_group_action);
|
|
}
|
|
});
|
|
}
|
|
|
|
function get_full_hostname() {
|
|
return window.location.origin + window.location.pathname;
|
|
}
|
|
|
|
var EDITED_GAME = null;
|
|
|
|
function create_edit_game(game = null) {
|
|
EDITED_GAME = game;
|
|
let updating = game !== null;
|
|
|
|
let nameF = document.getElementById("game_name");
|
|
let descriptionF = document.getElementById("game_description");
|
|
let submit_btn = document.getElementById("game_editor_submit_btn");
|
|
let ownerF = document.getElementById("game_owner");
|
|
let contributorsF = document.getElementById("game_contributors");
|
|
let gameFileF = document.getElementById("game_file");
|
|
let download_challenges_btn = document.getElementById("download_challenges_btn");
|
|
let show_game_file_upload_btn = document.getElementById("show_game_file_upload");
|
|
let cancel_game_file_upload_btn = document.getElementById("cancel_game_file_upload");
|
|
let edit_challenges_btn = document.getElementById("edit_challenges_btn");
|
|
let groupF = document.getElementById("game_groups");
|
|
let time_limitedChk = document.getElementById("time_limited");
|
|
let time_limitF = document.getElementById("time_limit");
|
|
let repeatableChk = document.getElementById("repeatable");
|
|
let publicChk = document.getElementById("public");
|
|
let publicUrlF = document.getElementById("public_url");
|
|
|
|
let hide_public_url_field = () => {
|
|
publicUrlF.hidden = !publicChk.checked;
|
|
}
|
|
|
|
let hide_public_option = () => {
|
|
let hide = (!repeatableChk.checked) || (time_limitedChk.checked);
|
|
if (hide) {
|
|
publicChk.checked = false;
|
|
}
|
|
publicChk.disabled = hide;
|
|
|
|
hide_public_url_field();
|
|
}
|
|
|
|
if (!updating) { // creating a new game
|
|
nameF.value = "";
|
|
descriptionF.value = "";
|
|
submit_btn.value = "Létrehozás"
|
|
ownerF.value = USERDATA["nickname"];
|
|
ownerF.readOnly = true;
|
|
contributorsF.value = "";
|
|
groupF.value = "";
|
|
time_limitedChk.checked = false;
|
|
repeatableChk.checked = true;
|
|
publicChk.checked = false;
|
|
publicUrlF.value = "";
|
|
|
|
// hide additional controls
|
|
hide("additional_controls");
|
|
} else { // editing an existing one
|
|
nameF.value = game["name"];
|
|
descriptionF.value = game["description"];
|
|
submit_btn.value = "Mentés"
|
|
ownerF.value = game["owner"];
|
|
ownerF.readOnly = false;
|
|
contributorsF.value = game["contributors"].join(", ");
|
|
|
|
fetch_game_groups(game["_id"], (groups) => {
|
|
groupF.value = groups;
|
|
});
|
|
|
|
publicChk.addEventListener("change", hide_public_url_field);
|
|
publicChk.checked = game["public"];
|
|
publicUrlF.hidden = !publicChk.checked;
|
|
publicUrlF.value = game["public_id"];
|
|
|
|
let props = game["properties"];
|
|
let time_limit = Math.max(Number(props["time_limit"]), 0);
|
|
time_limitF.value = seconds_to_time(time_limit);
|
|
time_limitedChk.checked = time_limit > 0;
|
|
time_limitedChk.addEventListener("change", hide_public_option);
|
|
handle_time_limit_chkbox();
|
|
|
|
repeatableChk.checked = props["repeatable"];
|
|
repeatableChk.addEventListener("change", hide_public_option);
|
|
|
|
hide_public_option();
|
|
|
|
// show additional controls
|
|
show("additional_controls");
|
|
|
|
}
|
|
gameFileF.value = "";
|
|
|
|
let game_file_present = updating && game["game_file_present"];
|
|
if (game_file_present) {
|
|
show(download_challenges_btn);
|
|
show(edit_challenges_btn);
|
|
edit_challenges_btn.onclick = () => {
|
|
edit_challenges(game);
|
|
};
|
|
} else {
|
|
hide(download_challenges_btn);
|
|
hide(edit_challenges_btn);
|
|
}
|
|
show_hide_gamefile_upload(false);
|
|
|
|
submit_btn.onclick = () => {
|
|
let game_name = document.getElementById("game_name").value.trim();
|
|
if (updating && time_limitedChk.checked && time_limitF.validity.patternMismatch) {
|
|
alert("Hibás időformátum!")
|
|
return;
|
|
}
|
|
if (game_name !== "") {
|
|
let reqData = {
|
|
name: game_name,
|
|
description: descriptionF.value.trim(),
|
|
owner: updating ? ownerF.value.trim() : USERDATA["nickname"],
|
|
contributors: contributorsF.value.trim(),
|
|
groups: groupF.value.trim(),
|
|
public: publicChk.checked,
|
|
properties: {
|
|
time_limit: updating ? (time_limitedChk.checked ? time_to_seconds(time_limitF.value) : 0) : 0,
|
|
repeatable: updating ? repeatableChk.checked : false
|
|
}
|
|
};
|
|
if (updating) {
|
|
reqData["_id"] = game["_id"];
|
|
}
|
|
let req = {
|
|
action: updating ? "update_game" : "create_game",
|
|
data: JSON.stringify(reqData)
|
|
};
|
|
let uploading_game_file = gameFileF.files.length > 0;
|
|
if (uploading_game_file) { // append game file if selected
|
|
req["game_file"] = gameFileF.files[0];
|
|
}
|
|
request(req).then(resp => {
|
|
if (uploading_game_file) {
|
|
let file_upload_status = JSON.parse(resp);
|
|
alert(`Importálás eredménye:\n${file_upload_status["n"]} kérdés, ${file_upload_status["encoding"]} szövegkódolással`);
|
|
}
|
|
list_all_games();
|
|
});
|
|
hide("game_editor_window");
|
|
}
|
|
};
|
|
|
|
show("game_editor_window");
|
|
}
|
|
|
|
function show_hide_gamefile_upload(en) {
|
|
if (en) {
|
|
// hide("download_challenges_btn");
|
|
hide("show_game_file_upload");
|
|
show("game_file");
|
|
show("cancel_game_file_upload");
|
|
} else {
|
|
// show("download_challenges_btn");
|
|
show("show_game_file_upload");
|
|
hide("game_file");
|
|
hide("cancel_game_file_upload");
|
|
document.getElementById("game_file").value = "";
|
|
}
|
|
}
|
|
|
|
function download_challenges() {
|
|
let action = "export_game_file_csv";
|
|
let gameid = EDITED_GAME["_id"];
|
|
window.open(`interface.php?action=${action}&gameid=${gameid}`, "_blank");
|
|
}
|
|
|
|
function get_selected_games() {
|
|
let selected_chkboxes = document.getElementsByName("game_chkbox");
|
|
let selected_games = [];
|
|
selected_chkboxes.forEach((chkbox) => {
|
|
if (chkbox.checked) {
|
|
selected_games.push(chkbox.game);
|
|
}
|
|
});
|
|
return selected_games;
|
|
}
|
|
|
|
function delete_games() {
|
|
let games = get_selected_games();
|
|
if (games.length === 0) {
|
|
return;
|
|
}
|
|
|
|
let game_names = [];
|
|
let game_ids = [];
|
|
games.forEach((g) => {
|
|
game_names.push(g["name"]);
|
|
game_ids.push(g["_id"]);
|
|
});
|
|
let msg = "Biztosan törölni kívánja a következő játéko(ka)t?\n\n" + game_names.join(", ") + "\n\n"
|
|
+ "A törlés nem vonható vissza!";
|
|
if (confirm(msg)) {
|
|
let req = {action: "delete_games", ids: game_ids.join(",")};
|
|
request(req).then(resp => {
|
|
list_all_games();
|
|
});
|
|
}
|
|
}
|
|
|
|
function handle_time_limit_chkbox() {
|
|
let time_limitedChk = document.getElementById("time_limited");
|
|
let time_limitF = document.getElementById("time_limit");
|
|
time_limitF.disabled = !time_limitedChk.checked;
|
|
}
|
|
|
|
function edit_challenges(game) {
|
|
let req = {action: "get_challenges", gameid: game["_id"]};
|
|
request(req).then(resp => {
|
|
console.log(JSON.parse(resp));
|
|
});
|
|
}
|
|
|
|
function list_results_by_game(game) {
|
|
let req = {action: "get_results_by_gameid", gameid: game["_id"]};
|
|
request(req).then(resp => {
|
|
let rd = document.getElementById("results_display");
|
|
let results = JSON.parse(resp);
|
|
if (results.length === 0) {
|
|
return;
|
|
}
|
|
|
|
rd.innerHTML = "";
|
|
let n = results.length;
|
|
|
|
results.sort((a, b) => {
|
|
return Number(b["_id"]) - Number(a["_id"])
|
|
}); // sort records by ID
|
|
|
|
let results_by_nickname = {};
|
|
results.forEach((record) => {
|
|
let nickname = record["nickname"];
|
|
if (!results_by_nickname.hasOwnProperty(nickname)) {
|
|
results_by_nickname[nickname] = [];
|
|
}
|
|
results_by_nickname[nickname].push(record);
|
|
});
|
|
|
|
let nicknames = Object.keys(results_by_nickname);
|
|
|
|
// mark best of the results
|
|
nicknames.forEach((nickname) => {
|
|
let result_group = results_by_nickname[nickname];
|
|
let best_entry = null;
|
|
let best_percentage = -1.0;
|
|
result_group.forEach((result) => {
|
|
result["best"] = false;
|
|
if (result["state"] === "concluded") {
|
|
let percentage = result["summary"]["correct_answer_n"] / result["summary"]["challenge_n"];
|
|
if ((best_entry === null) || (percentage >= best_percentage)) {
|
|
best_percentage = percentage;
|
|
best_entry = result;
|
|
}
|
|
}
|
|
});
|
|
if (best_entry !== null) {
|
|
best_entry["best"] = true;
|
|
}
|
|
});
|
|
|
|
// print the grouped results
|
|
nicknames.forEach((nickname) => {
|
|
let result_group = results_by_nickname[nickname];
|
|
|
|
let test_group_box = document.createElement("section");
|
|
test_group_box.classList.add("summary-group")
|
|
|
|
let nickname_box = document.createElement("section");
|
|
nickname_box.classList.add("summary-nickname-box");
|
|
nickname_box.innerText = nickname;
|
|
|
|
test_group_box.append(nickname_box);
|
|
|
|
result_group.forEach((record) => {
|
|
let concluded = record["state"] === "concluded";
|
|
|
|
let test_summary_record = document.createElement("section");
|
|
test_summary_record.classList.add("test-summary-record");
|
|
|
|
// let sequence_number_sec = document.createElement("section");
|
|
// sequence_number_sec.classList.add("summary-name-id-block");
|
|
// sequence_number_sec.innerText = record["nickname"] + "#" + n;
|
|
let duration_sec = document.createElement("section");
|
|
duration_sec.classList.add("summary-duration");
|
|
let start_time = unix_time_to_human_readable(record["start_time"]);
|
|
duration_sec.innerHTML = `${start_time}-`
|
|
test_summary_record.append(duration_sec);
|
|
|
|
if (concluded) {
|
|
let end_time = unix_time_to_human_readable(record["end_time"]);
|
|
|
|
let summary = record["summary"];
|
|
duration_sec.innerHTML += `<br>${end_time}<br>${summary["correct_answer_n"]}/${summary["challenge_n"]}`;
|
|
|
|
let percentage = document.createElement("section");
|
|
percentage.classList.add("summary-percentage");
|
|
let r = Math.floor((summary["correct_answer_n"] / summary["challenge_n"]) * 100);
|
|
percentage.innerHTML = `${r}%`;
|
|
|
|
test_summary_record.append(percentage);
|
|
|
|
if (record["best"]) {
|
|
let best_badge = document.createElement("section");
|
|
best_badge.classList.add("summary-best-badge");
|
|
best_badge.innerText = "LEGJOBB";
|
|
test_summary_record.append(best_badge);
|
|
}
|
|
}
|
|
|
|
test_summary_record.addEventListener("click", () => {
|
|
window.open(`testground.php?testid=${record["_id"]}&view_only=true`, "_blank");
|
|
});
|
|
|
|
test_group_box.appendChild(test_summary_record);
|
|
|
|
n--;
|
|
|
|
});
|
|
|
|
rd.append(test_group_box);
|
|
|
|
});
|
|
show("results_viewer_window");
|
|
});
|
|
}
|
|
|
|
function generate_game_report_by_groups() {
|
|
let gameid = EDITED_GAME["_id"];
|
|
let filter = document.getElementById("report_filter").value.trim();
|
|
let groups = document.getElementById("report_groups").value.trim();
|
|
let best_only = document.getElementById("best_only").checked ? "true" : "false";
|
|
let outtype = document.getElementById("report_output_type").value;
|
|
|
|
let report_url = `interface.php?action=generate_report_by_groups&gameid=${gameid}&groups=${groups}&filter=${filter}&outtype=${outtype}&best_only=${best_only}`;
|
|
report_url = report_url.replaceAll("#", "%23");
|
|
window.open(report_url, "_blank");
|
|
}
|
|
|
|
// function hint_all_groups(target_element_id) {
|
|
// const hintbox_insert_fn = (record) => {
|
|
// let targetF = document.getElementById(target_element_id);
|
|
// let groups = explode_sanitize_string_list(targetF.value);
|
|
// groups.pop();
|
|
// groups.push(record);
|
|
// targetF.value = groups.join(", ");
|
|
// close_hintbox(true);
|
|
// }
|
|
//
|
|
// let req = {
|
|
// action: "search_groups",
|
|
// }
|
|
//
|
|
// open_hintbox_at(target_element_id, req, print_group_name, hintbox_insert_fn);
|
|
// }
|