false]); const DEFAULT_GAME_PROPERTIES = [ "forward_only" => false, // player may traverse back and forth between challenges "time_limit" => 0, // no time limit; otherwise, this field indicates time limit in seconds "repeatable" => false // this test can be taken multiple times ]; function create_game(string $name, string $owner, string $description = "", array $properties = DEFAULT_GAME_PROPERTIES, array $contributors = [], array $challenges = []): bool { global $gamedb; $game_data = [ "name" => $name, "owner" => $owner, "contributors" => $contributors, "description" => $description, "game_file_present" => false, "properties" => $properties, "groups" => [], "public" => false, "public_id" => uniqid("p"), ]; $game_data = $gamedb->insert($game_data); // prepare game context $id = $game_data["_id"]; $current_game_media_dir = get_game_dir_by_gameid($id); mkdir($current_game_media_dir); save_challenges($id, []); return true; } function get_game(string $gameid): array { global $gamedb; return $gamedb->findById($gameid); } function update_game(array $game_data) { global $gamedb; $gamedb->update($game_data); } function delete_game(string $gameid) { global $gamedb; $game_data = get_game($gameid); if (count($game_data) != 0) { foreach ($game_data["groups"] as $groupid) { change_group_game_assignments($groupid, null, $gameid); } $gamedb->deleteById($gameid); } } function change_game_group_assignments(string $gid, $groupname_add, $groupname_remove) { $game_data = get_game($gid); if (count($game_data) != 0) { alter_array_contents($game_data["groups"], $groupname_add, $groupname_remove); update_game($game_data); // update user } } function get_all_games() { global $gamedb; return $gamedb->findAll(); } function get_all_game_data_by_contributor_nickname(string $nickname): array { global $gamedb; $game_headers = []; if ($nickname !== "*") { $game_data_array = $gamedb->findBy([["owner", "=", $nickname], "OR", ["contributors", "CONTAINS", $nickname]]); } else { $game_data_array = $gamedb->findAll(); } foreach ($game_data_array as $game_data) { $game_headers[] = $game_data; } return $game_headers; } const CSV_ENCODINGS = ["UTF-8", "Windows-1252"]; 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" => ""]; } // convert text encoding into UTF-8 $data = file_get_contents($csv_path); $encoding = "UNKNOWN"; foreach (CSV_ENCODINGS as $enc) { // detect encoding if (mb_check_encoding($data, $enc)) { $encoding = $enc; break; } } if ($encoding !== "UNKNOWN") { // if encoding has been detected successfully $data = mb_convert_encoding($data, "UTF-8", $encoding); file_put_contents($csv_path, $data); } // load challenges $challenges = []; // load filled CSV file $f = fopen($csv_path, "r"); if (!$f) { // failed to open file return ["n" => 0, "encoding" => $encoding]; } while ($csvline = fgetcsv($f)) { // skip empty lines if (trim(implode("", $csvline)) === "") { continue; } if (count($csvline) >= 3) { // construct challenge record $ch = [ "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; } } fclose($f); // save challenges save_challenges($gameid, $challenges); // update game with game file present $game_data["game_file_present"] = true; update_game($game_data); return ["n" => count($challenges), "encoding" => $encoding]; } function is_user_contributor_to_game(string $gameid, string $nickname): bool { $game_data = get_game($gameid); if (count($game_data) === 0) { return false; } return in_array($nickname, $game_data["contributors"]) || ($game_data["owner"] === $nickname); } function is_user_owner_of_the_game(string $gameid, string $nickname): bool { $game_data = get_game($gameid); if (count($game_data) === 0) { return false; } return $game_data["owner"] === $nickname; } function save_challenges(string $gameid, array $challenges) { file_put_contents(get_game_file_by_gameid($gameid), json_encode($challenges)); // store challenges in JSON-format } function load_challenges(string $gameid) { return json_decode(file_get_contents(get_game_file_by_gameid($gameid)), true); } function export_challenges_to_csv($f, string $gameid) { $game_data = get_game($gameid); if ((count($game_data) === []) || (!$game_data["game_file_present"])) { return; } // load challenges $challenges = load_challenges($gameid); // populate CSV file foreach ($challenges as $ch) { $csvline = [ $ch["question"], $ch["image_url"], ]; $csvline = array_merge($csvline, $ch["answers"]); fputcsv($f, $csvline); } } function get_contributors(string $gameid): array { $game_data = get_game($gameid); return $game_data["contributors"]; } 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; }