📄 manage_test.cpp
字号:
/* * $File: manage_test.cpp * $Author: Jiakai -- gy_jk@126.com * $Date: Thu Mar 26 20:30:31 2009*//*Copyright (C) (2008) (Jiakai) <gy_jk@126.com>This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or any later version.This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with this program; if not, write to the Free SoftwareFoundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.*/#include "manage_test.h"#include "auto_add_points.h"#define NEED_LIST_DIR#include "../common.h"#include "../conf.h"#include "manage_test_func2.h"#include "../judge.h"#include "interface.h"using namespace ncurses;#include <sys/types.h>#include <unistd.h>#include <errno.h>#include <cstring>#include <cstdio>#include <vector>#include <iostream>#include <sstream>#include <iomanip>#include <algorithm>using namespace std;#define DEFAULT_DATA_DIR "data"#define DEFAULT_DATA_DIR_S "data/%s/"typedef void (*Func_t) (const char *);typedef vector<string> Str_array;struct Test_point{ int time; double score; char input[STRING_MAX_LEN + 1], output[STRING_MAX_LEN + 1]; Test_point& operator = (const Test_point &a) { time = a.time; score = a.score; strcpy(input, a.input); strcpy(output, a.output); }};typedef vector<Test_point> Test_point_array;struct Contest_option{ Str_array compiler_ext, compiler_command; char source_path[STRING_MAX_LEN + 1], contest_name[STRING_MAX_LEN + 1]; Contest_option(const Conf &conf); void write_conf(Conf &conf);};struct Problem_conf{ char name[STRING_MAX_LEN + 1], input[STRING_MAX_LEN + 1], output[STRING_MAX_LEN + 1], source[STRING_MAX_LEN + 1]; Test_point_array points; Problem_conf(const Conf &conf, int prob_num); Problem_conf(const char *probname); void write_conf(Conf &conf);};struct Contestant_result{ string name; double total_score; unsigned long total_time; typedef vector<Judge_result> Jr_array; Jr_array result; vector<bool> judged;};bool operator < (const Contestant_result &n1, const Contestant_result &n2);typedef vector<Contestant_result> Conr_array;//----------------------Function Statements-----------------------------------static void func1(const char *path);static void func3(const char *path);static void create_problem(Conf &conf);static void delete_problem(Conf &conf, int prob);static void modify_problem(Conf &conf, int prob);static void add_new_test_points(Test_point_array &tpa, const char *probname);static void modify_test_point(Test_point &tp);static void modify_contest_opt(Contest_option &co);static void init_contestant_result(Str_array &probnames, Conr_array &conr, const Conf &conf, const char *conf_path);static void show_contestant_detail(const Str_array &probnames, const Contestant_result &cre);static void output_problem_detail(ostream &outstr, const Judge_result &result);static bool save_html(const char *path, const Conr_array &result, const Conf &conf, const Str_array &probnames);static void auto_conf_prob(Conf &conf);static bool auto_add_prob_points(Problem_conf &conf, const char *conf_path);//----------------------------------------------------------------------------Contest_option::Contest_option(const Conf &conf){ int ncp; if (!conf.read("compiler", "num", ncp)) { compiler_ext.push_back("cpp"); compiler_command.push_back("g++ %s.cpp -O2 -o %s"); compiler_ext.push_back("c"); compiler_command.push_back("gcc %s.c -O2 -o %s"); compiler_ext.push_back("pas"); compiler_command.push_back("fpc %s.pas"); } else { for (int i = 0; i < ncp; i ++) { char tmp[STRING_MAX_LEN + 1], conf_item[STRING_MAX_LEN]; sprintf(conf_item, "%d.ext", i); if (!conf.read("compiler", conf_item, tmp, STRING_MAX_LEN)) report_err("Fail to read @%d.ext .\n", __PRETTY_FUNCTION__, __LINE__); compiler_ext.push_back(tmp); sprintf(conf_item, "%d.command", i); if (!conf.read("compiler", conf_item, tmp, STRING_MAX_LEN)) report_err("Fail to read @%d.command .\n", __PRETTY_FUNCTION__, __LINE__); compiler_command.push_back(tmp); } } if (!conf.read("general", "src", source_path, STRING_MAX_LEN)) strcpy(source_path, "src/"); if (!conf.read("general", "name", contest_name, STRING_MAX_LEN)) read_input("Please enter the name of contest: ", contest_name, "Contest");}void Contest_option::write_conf(Conf &conf){ conf.delsection("compiler"); conf.delsection("compiler.command"); if (compiler_ext.size() != compiler_command.size()) report_err("An strange error occurred...\n", __PRETTY_FUNCTION__, __LINE__); else { conf.write("compiler", "num", int(compiler_ext.size())); for (vector<string>::size_type i = 0; i < compiler_ext.size(); i ++) { char conf_item[STRING_MAX_LEN]; sprintf(conf_item, "%d.ext", i); conf.write("compiler", conf_item, compiler_ext[i].c_str()); sprintf(conf_item, "%d.command", i); conf.write("compiler", conf_item, compiler_command[i].c_str()); conf.write("compiler.command", compiler_ext[i].c_str(), compiler_command[i].c_str()); } } conf.delitem("general", "src"); conf.delitem("general", "name"); conf.write("general", "src", source_path); conf.write("general", "name", contest_name);}void manage_test(const char *path){ if (seteuid(getuid()) != 0 || setegid(getuid()) != 0) { perror("manage_test : seteuid || setegid "); return; } do { string tmp(path); int pos = tmp.length() - 1; while (pos >= 0 && tmp[pos] != '/') pos --; if (pos < 0) break; if (chdir(tmp.substr(0, pos + 1).c_str())) { perror("manage_test : chdir "); return; } path += pos + 1; } while(0); char tmp[STRING_MAX_LEN]; sprintf(tmp, "Welcome to %s .\nPlease use UP and DOWN keys to select a task and press ENTER to start it.\nThe current configuration file is: %s \n", VERSION_INF, path); static const char * const menu_items[] = {"Modify the contest", "OK, judge now!", "View Reports", "Exit", NULL}; static const int key_allowable[] = {ENTER, 0}; init(); Window main_win; Menu menu; menu.set_arg(main_win, menu_items, key_allowable, tmp, 6, 30); try { while (true) { menu.wait_key(); int ch = menu.get_choice(); static const Func_t func[] = {&func1, &func2, &func3}; if (ch != 3) func[ch](path); else break; } } catch (Error err) { menu.free(); end(); cerr << "An error occurred: \n" << err.msg << endl; delete []err.msg; return; } menu.free(); end();}void func1(const char *path){ Conf conf(path); const char * OPERATION_REMINDER = "Press 'c' to create a new problem, 'd' to delete a subsistent problem, ENTER to modify a subsistent problem or general options, 'a' to automatically configure the problems, or 'r' to return to the main menu.\n"; Contest_option conopt(conf); static const int key_allowable[] = {'c', 'd', ENTER, 'a', 'r', 0}; int nproblems = 0; char **probnames = NULL;#define FREE_PROBNAMES() \ do \ { \ if (probnames == NULL) \ break; \ for (int i = 0; i < nproblems + 2; i ++) \ delete []probnames[i]; \ delete []probnames; \ probnames = NULL; \ } \ while (false) Window main_win; Menu menu; bool changed = true; while (true) { if (changed) { FREE_PROBNAMES(); if (!conf.read("general", "problems_num", nproblems)) nproblems = 0; probnames = new char *[nproblems + 2]; probnames[0] = new char[STRING_MAX_LEN]; strcpy(probnames[0], "general options"); for (int i = 1; i <= nproblems; i ++) { char str[STRING_MAX_LEN]; sprintf(str, "problem_%d_name", i - 1); probnames[i] = new char[STRING_MAX_LEN + 1]; if (!conf.read("general", str, probnames[i], STRING_MAX_LEN)) report_err("Fail to read @prbname.\n", __PRETTY_FUNCTION__, __LINE__); } probnames[nproblems + 1] = NULL; menu.set_arg(main_win, probnames, key_allowable, OPERATION_REMINDER); changed = false; } int key_pressed = menu.wait_key(); if (key_pressed == 'r') break; int choice = menu.get_choice(); switch (key_pressed) { case 'c' : create_problem(conf); changed = true; break; case 'd' : delete_problem(conf, choice - 1); changed = true; break; case ENTER : if (choice == 0) modify_contest_opt(conopt); else modify_problem(conf, choice - 1); break; case 'a': auto_conf_prob(conf); changed = true; break; } } menu.free(); FREE_PROBNAMES();#undef FREE_PROBNAME conopt.write_conf(conf); if (!conf.save()) report_err("Fail to save the configuration file.\n", __PRETTY_FUNCTION__, __LINE__);}void create_problem(Conf &conf){ int np; if (!conf.read("general", "problems_num", np)) np = 0; np ++; conf.write("general", "problems_num", np); char problem_name[STRING_MAX_LEN]; problem_name[0] = 0; while (problem_name[0] == 0) read_input("Please enter the name of the problem(you can not modify it later unless you modify the configuration file manually): ", problem_name); char conf_item[STRING_MAX_LEN]; while (true) { for (int i = 0; i < np - 1; i ++) { sprintf(conf_item, "problem_%d_name", i); char tmp[STRING_MAX_LEN + 1]; if (conf.read("general", conf_item, tmp, STRING_MAX_LEN) && strcmp(tmp, problem_name) == 0) { read_input("The name of the problem has already existed, please choose another: ", problem_name); i = -1; } } break; } sprintf(conf_item, "problem_%d_name", np - 1); conf.write("general", conf_item, problem_name); modify_problem(conf, np - 1);}void delete_problem(Conf &conf, int prob){ if (prob < 0) { message_box("Oh, you can not do so..."); return; } char conf_item[STRING_MAX_LEN]; sprintf(conf_item, "problem_%d_name", prob); char probname[STRING_MAX_LEN + 1]; if (!conf.read("general", conf_item, probname, STRING_MAX_LEN)) { report_err("Fail to read @probname.\n", __PRETTY_FUNCTION__, __LINE__); return; } char msg[STRING_MAX_LEN]; sprintf(msg, "Are you sure to delete problem \"%s\" ? All information and judge results about this problem will be deleted. (y/n)", probname);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -