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"] + "<span style='color:gray'>#" + g["_id"] + "</span>");
 | 
						|
            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 = encodeURIComponent(document.getElementById("report_filter").value.trim());
 | 
						|
    let groups = encodeURIComponent(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);
 | 
						|
// }
 |