diff --git a/MyScripts/Account_Generator.cpp b/MyScripts/Account_Generator.cpp index 0040b25..5365148 100644 --- a/MyScripts/Account_Generator.cpp +++ b/MyScripts/Account_Generator.cpp @@ -1,56 +1,109 @@ #include using namespace std; -#define all(a) begin(a), end(a) -#define pb push_back -#define pii pair -#define F first -#define S second -#define mp make_pair - -const char chr[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + +// *Important* Check if the same team name exist for different teams. + +#define AUTO_GENERATE_ACCOUNT +#define AUTO_GENERATE_TEAMNAME + +#if defined(AUTO_GENERATE_ACCOUNT) && defined(AUTO_GENERATE_TEAMNAME) + #define ACCOUNT_NUMBER 10 +#endif + +#define AccountPrefix "account" +#define TeamnamePrefix "team" + +#define PASSWORD_LENTH 6 +const char chr[] = {'2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', - 'H', 'I', 'J', 'K', 'L', 'M', 'N', - 'O', 'P', 'Q', 'R', 'S', 'T', + 'H', 'J', 'K', 'L', 'M', 'N', + 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', - 'h', 'i', 'j', 'k', 'l', 'm', 'n', - 'o', 'p', 'q', 'r', 's', 't', + 'h', 'i', 'j', 'k', 'm', 'n', + 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'}; -string genPass() { +string Generate_Password() { string password; - for (int i = 0; i < 6; i++) { - int idx = rand() % 62; - password.pb(chr[idx]); + int sz = sizeof(chr); + for (int i = 0; i < PASSWORD_LENTH; i++) { + int idx = rand() % sz; + password += chr[idx]; } return password; } +string Generate_Account(int idx) { + stringstream account; + account << AccountPrefix << setw(3) << setfill('0') << idx; + return account.str(); +} + +string Generate_Teamname(int idx) { + stringstream teamname; + teamname << TeamnamePrefix << setw(3) << setfill('0') << idx; + return teamname.str(); +} + int main() { - srand(time(NULL)); - /* - users: - - username: "team1" - password: "dssinsdnds" - first_name: "TeamName" - */ - ifstream TeamnameFile("teamname.txt"); + srand(time(0)); + map > team; ofstream PasswordFile("password.txt"); - ofstream SettingFile("context.yaml"); + ofstream SettingFile("contest.user.yaml"); +#ifdef AUTO_GENERATE_ACCOUNT + ofstream AccountFile("account.txt"); +#else + ifstream AccountFile("account.txt"); +#endif +#ifdef AUTO_GENERATE_TEAMNAME + ofstream TeamnameFile("teamname.txt"); +#else + ifstream TeamnameFile("teamname.txt"); +#endif - for (int i = 1; i <= 200; i++) { - string password = genPass(); - string teamname; - getline(TeamnameFile,teamname); + string teamname, account, password; + int Account_Idx = 1; - PasswordFile << password << '\n'; - SettingFile << " - username: \"team" << setw(3) << setfill('0') << i << "\"\n"; +#if defined(AUTO_GENERATE_TEAMNAME) && defined(AUTO_GENERATE_ACCOUNT) + while(Account_Idx <= ACCOUNT_NUMBER){ + teamname = Generate_Teamname(Account_Idx); + account = Generate_Account(Account_Idx); +#elif !defined(AUTO_GENERATE_ACCOUNT) && !defined(AUTO_GENERATE_TEAMNAME) + while (getline(AccountFile, account)) { + getline(TeamnameFile, teamname); +#elif defined(AUTO_GENERATE_ACCOUNT) && !defined(AUTO_GENERATE_TEAMNAME) + while (getline(TeamnameFile, teamname)) { + account = Generate_Account(Account_Idx); +#elif !defined(AUTO_GENERATE_ACCOUNT) && defined(AUTO_GENERATE_TEAMNAME) + while (getline(AccountFile, account)) { + teamname = Generate_Teamname(Account_Idx); +#endif + + password = Generate_Password(); + + SettingFile << " - username: \"" << account << "\"\n"; SettingFile << " password: \"" << password << "\"\n"; SettingFile << " first_name: \"" << teamname << "\"\n"; + +#ifdef AUTO_GENERATE_ACCOUNT + AccountFile << account << "\n"; +#endif +#ifdef AUTO_GENERATE_TEAMNAME + TeamnameFile << teamname << "\n"; +#endif + PasswordFile << password << "\n"; + + Account_Idx++; } TeamnameFile.close(); PasswordFile.close(); + AccountFile.close(); SettingFile.close(); } -// g++ gen.cpp && ./a.out && rm a.out +/* + cms username: account + cms password: password + cms first_name: teamname +*/ diff --git a/MyScripts/Add_Problem_Id_To_File_Name.cpp b/MyScripts/Add_Problem_Id_To_File_Name.cpp deleted file mode 100644 index f9e65e3..0000000 --- a/MyScripts/Add_Problem_Id_To_File_Name.cpp +++ /dev/null @@ -1,28 +0,0 @@ -#include -using namespace std; -#define TEAM_NUMBER 200 -#define MIN_PROBLEM_ID 'A' -#define MAX_PROBLEM_ID 'H' -int main() { - for (int i = 1; i <= TEAM_NUMBER; i++) { - string foldername1 = "team" + string(3 - to_string(i).length(), '0') + to_string(i); - for (const auto& entry1 : filesystem::directory_iterator(foldername1)) { - ifstream file(entry1.path()); - string s, line; - - for (int i = 0; i < 5; i++) { - getline(file, line); - s += line; - } - - if (s.find(".%l") == string::npos) { - cout << "fail on " << entry1.path() << '\n'; - return 1; - } - file.close(); - char p = s[s.find(".%l") - 1]; - rename(entry1.path(), string(entry1.path()) + "_p" + string(1, p)); - } - } - cout << "Successful\n"; -} diff --git a/MyScripts/Groups_Submissions_By_Problem_Name.sh b/MyScripts/Groups_Submissions_By_Problem_Name.sh new file mode 100644 index 0000000..b5477a8 --- /dev/null +++ b/MyScripts/Groups_Submissions_By_Problem_Name.sh @@ -0,0 +1,31 @@ +#! /usr/bin/bash + +# 1. first copy all submissions from /var/local/lib/cms/submissions to ~ +# 2. run this script +# 3. you will get a folder named Problem_Submissions, which groups submissions by problem name + +rm -rf Problem_Submissions +IFS=$'\n' + +getProblemName(){ + ProblemName=$(head -n 3 $1 | tr -d '\r\n' | tr -cd '[:alnum:]-_}.%' | sed 's/\.%l.*//' | awk -F '}' '{print $NF}') + echo $ProblemName +} + +for team in $(ls submissions); do + for submission in $(ls submissions/$team); do + problem=$(getProblemName "submissions/$team/$submission") + time=$(echo $submission | awk -F '.' '{print $1}') + + if [ ! -d "$problem" ]; then + mkdir -p "Problem_Submissions/$problem" + fi + cp "submissions/$team/$submission" "Problem_Submissions/$problem/$team" + echo -e "\n$time" >> "Problem_Submissions/$problem/$team" + done + echo "$team done!" +done + +for problem in $(ls Problem_Submissions); do + python moss.py $problem +done diff --git a/MyScripts/Moss.py b/MyScripts/Moss.py deleted file mode 100644 index e300519..0000000 --- a/MyScripts/Moss.py +++ /dev/null @@ -1,12 +0,0 @@ -import mosspy - -userid = 61861013 - -m = mosspy.Moss(userid, "python") - - -m.addFilesByWildcard("pH/*") - -url = m.send() # Submission Report URL - -print ("Report Url: " + url) diff --git a/MyScripts/Sort_Submissions_By_Problem_ID.cpp b/MyScripts/Sort_Submissions_By_Problem_ID.cpp deleted file mode 100644 index 1fc7c9b..0000000 --- a/MyScripts/Sort_Submissions_By_Problem_ID.cpp +++ /dev/null @@ -1,34 +0,0 @@ -#include -using namespace std; -#define TEAM_NUMBER 200 -#define MIN_PROBLEM_ID 'A' -#define MAX_PROBLEM_ID 'H' - -int main() { - for(char i=MIN_PROBLEM_ID;i<=MAX_PROBLEM_ID;i++){ - filesystem::create_directory("p"+string(1,i)); - } - for (int i = 1; i <= TEAM_NUMBER; i++) { - string TeamName = "team" + string(3 - to_string(i).length(), '0') + to_string(i); - for (const auto& entry1 : filesystem::directory_iterator(TeamName)) { - ifstream file(entry1.path()); - string s, line; - - for (int i = 0; i < 5; i++) { - getline(file, line); - s += line; - } - - if (s.find(".%l") == string::npos) { - cout << "fail on " << entry1.path() << '\n'; - return 1; - } - file.close(); - - string problem_ID = "p" + string(1, s[s.find(".%l") - 1]); - string NewName = string(entry1.path()).substr(8) + "_" + TeamName; - filesystem::copy(entry1.path(), problem_ID + "/" +NewName); - } - } - cout << "Successful\n"; -} diff --git a/MyScripts/alias.sh b/MyScripts/alias.sh new file mode 100644 index 0000000..1ca590f --- /dev/null +++ b/MyScripts/alias.sh @@ -0,0 +1,3 @@ +alias stopcms="sudo kill \$(ps aux | grep cms | awk '{print \$2}' | head -n -1) > /dev/null 2>&1" +alias startcms="sudo cmsResourceService -a" +alias restartcms="stopcms; startcms" diff --git a/MyScripts/auto_relaunch.sh b/MyScripts/auto_relaunch.sh new file mode 100644 index 0000000..de8bfac --- /dev/null +++ b/MyScripts/auto_relaunch.sh @@ -0,0 +1,7 @@ +#!/bin/bash +id="1" + +if ! curl -s http://localhost:8888 > /dev/null; then + kill $(ps aux | grep cms | awk '{print $2}' | head -n -1) + /usr/local/bin/cmsResourceService -a <<< $id & +fi diff --git a/MyScripts/dependency.py b/MyScripts/dependency.py new file mode 100644 index 0000000..0daf0bb --- /dev/null +++ b/MyScripts/dependency.py @@ -0,0 +1,70 @@ +# usage : python3 dependency.py pA + +import xml.etree.ElementTree as ET +import json, sys + +file_path = sys.argv[1] + "/problem.xml" + +# Load the XML file +tree = ET.parse(file_path) +root = tree.getroot() + +groups = [] +group_points = {} +group_dependencies = {} +group_counts = {} +group_testcase_regex = {} + +for test in root.find(".//judging").findall(".//test"): # find test in tests + group = test.get('group') + + if group not in groups: + groups.append(group) + group_counts[group] = 0 + + group_counts[group] += 1 + + +for group in root.findall(".//group"): + group_name = group.get('name') + + points = group.get('points', '0') + group_points[group_name] = int(float(points)) + + dependencies = [] + for dep in group.findall('.//dependency'): + dep_name = dep.get('group') + + dependencies.append(dep_name) + if len(group_dependencies[dep_name]): + dependencies.extend(group_dependencies[dep_name]) + + dependencies = list(set(dependencies)) + dependencies.sort() + + group_dependencies[group_name] = dependencies + +for group in groups: + print(f"Group {group} : number: {group_counts[group]}, points: {group_points[group]}, dependency: {group_dependencies[group]}") + +#--------------------------------------------------- + +cur = 0 +for group in groups: + count = group_counts[group] + print(f"{cur:03d} {cur + count - 1:03d}") + cur += count + regex = input() + group_testcase_regex[group] = regex + + +score_parameters = [] +for group in groups: + testcase_regex = group_testcase_regex[group] + for dependency in group_dependencies[group]: + testcase_regex += "|" + group_testcase_regex[dependency] + + score_parameters.append((group_points[group],testcase_regex)) + +json_string = json.dumps(score_parameters) +print('\n\n' + json_string) diff --git a/MyScripts/import_user.sh b/MyScripts/import_user.sh new file mode 100644 index 0000000..21ca21b --- /dev/null +++ b/MyScripts/import_user.sh @@ -0,0 +1,5 @@ +paste id name account password | while read -r name id account password; do + echo "$name, $id, $account, $password" + cmsAddUser $name $id $account -p $password; + cmsAddParticipation -c 1 $account +done diff --git a/MyScripts/moss.py b/MyScripts/moss.py new file mode 100644 index 0000000..a4e7be2 --- /dev/null +++ b/MyScripts/moss.py @@ -0,0 +1,13 @@ +#python moss.py [problem_name] + +import mosspy, sys + +userid = 61861013 + +m = mosspy.Moss(userid, "python") + +m.addFilesByWildcard("Problem_Submissions/" + sys.argv[1] + "/*") + +url = m.send() + +print (sys.argv[1] + " : " + url) diff --git a/Polygon/README.md b/Polygon/README.md index 1625b6d..cae052e 100644 --- a/Polygon/README.md +++ b/Polygon/README.md @@ -1,17 +1,48 @@ -# Package test case from polygon package to cms format +# Convert Polygon Package To CMS Format -1. 把這份repo載下來,並進到Polygon資料夾。或是直接建立一個資料夾並把pack.sh放進去 -2. 到Polygon的Packages點擊Full並下載Linux版。 +1. Go to Polygon's Packages, click Full and Download Linux version. image -3. 解壓縮所有檔案到此資料夾(可順便更改檔名) -image +2. Extract the archive to a new folder (Remember to change file name, you can add multiple problems in that folder) -4. 執行以下指令後會生成一個`cmsTestCase`資料夾,為每一題測資的zip檔。 +Next, there will be two conversion methods, which are `Full Contest Conversion` and `TestCase Only Conversion`. +## Full Contest Conversion +1. Copy pack_to_yaml.sh to your folder or use the following command ``` -sudo chmod a+x pack.sh && ./pack.sh +curl https://raw.githubusercontent.com/erichung9060/cms/main/Polygon/pack_to_yaml.sh -o pack_to_yaml.sh +``` +image + +3. Run the following command, then a folder named Contest will be generated, which is a CMS contest package with problems you added. +``` +chmod u+x pack_to_yaml.sh && ./pack_to_yaml.sh +``` +image + +3. Go into the Contest folder and run the command to import contest to CMS. +``` +chmod u+x import.sh && ./import.sh +``` +4. After importing the contest, you still need to change some settings:\ + a. score mode \ + b. allowed language \ + c. contest's start time and end time + +## TestCase Only Conversion +1. Copy pack_to_testcase.sh to that folder +``` +curl https://raw.githubusercontent.com/erichung9060/cms/main/Polygon/pack_to_testcase.sh -o pack_to_testcase.sh +``` +image + +2. Run the following command, then a folder named cmsTestCase will be generated, which contains zip files for each problem. +``` +chmod u+x pack_to_testcase.sh && ./pack_to_testcase.sh ``` image -5.到CMS Task中下方Test Case的地方點擊` Add multiple testcases`並選擇該題的zip檔上傳 +3. Go to `Test Case` at the bottom of Task on CMS, and click `Add multiple testcases` then select the zip file of the problem to upload. +Screenshot 2023-08-02 at 5 00 27 AM image + +4. Congratulations!🥳 diff --git a/Polygon/pack.sh b/Polygon/pack_to_testcase.sh similarity index 70% rename from Polygon/pack.sh rename to Polygon/pack_to_testcase.sh index 7b125f9..eb7f1aa 100644 --- a/Polygon/pack.sh +++ b/Polygon/pack_to_testcase.sh @@ -5,10 +5,11 @@ if [[ ! -d "cmsTestCase" ]]; then mkdir "cmsTestCase" fi -if [[ $# == 0 ]];then - toDoList=$(ls | sed s/pack.sh//g | sed s/cmsTestCase//g) -else - toDoList=$@ +echo -n "Enter the name of the problem to zip testcase, or leave blank to zip all : " +read toDoList + +if [[ $toDoList == "" ]];then + toDoList=$(ls | sed s/pack_to_yaml.sh//g | sed s/Contest//g) fi for PROBLEM_NAME in $toDoList; do @@ -31,18 +32,18 @@ for PROBLEM_NAME in $toDoList; do ALL="" for ((i = 1; i <= $N; i++)); do - zero="000" - zero=${zero:0:$((3-${#i}))} + index=$((i-1)) + index=$(printf "%03d" $index) if [ $i -lt 10 ]; then - cp "$PROBLEM_NAME/tests/0$i" "$PROBLEM_NAME/RenamedTestCase/input.$zero$i" - cp "$PROBLEM_NAME/tests/0$i.a" "$PROBLEM_NAME/RenamedTestCase/output.$zero$i" + cp "$PROBLEM_NAME/tests/0$i" "$PROBLEM_NAME/RenamedTestCase/input.$index" + cp "$PROBLEM_NAME/tests/0$i.a" "$PROBLEM_NAME/RenamedTestCase/output.$index" else - cp "$PROBLEM_NAME/tests/$i" "$PROBLEM_NAME/RenamedTestCase/input.$zero$i" - cp "$PROBLEM_NAME/tests/$i.a" "$PROBLEM_NAME/RenamedTestCase/output.$zero$i" + cp "$PROBLEM_NAME/tests/$i" "$PROBLEM_NAME/RenamedTestCase/input.$index" + cp "$PROBLEM_NAME/tests/$i.a" "$PROBLEM_NAME/RenamedTestCase/output.$index" fi - ALL+="$PROBLEM_NAME/RenamedTestCase/input.$zero$i $PROBLEM_NAME/RenamedTestCase/output.$zero$i " + ALL+="$PROBLEM_NAME/RenamedTestCase/input.$index $PROBLEM_NAME/RenamedTestCase/output.$index " done if [ -f "cmsTestCase/${PROBLEM_NAME}.zip" ]; then @@ -54,4 +55,4 @@ for PROBLEM_NAME in $toDoList; do echo "Problem : $PROBLEM_NAME finished !" rm -rf "$PROBLEM_NAME/RenamedTestCase" -done \ No newline at end of file +done diff --git a/Polygon/pack_to_yaml.sh b/Polygon/pack_to_yaml.sh new file mode 100644 index 0000000..ad9234b --- /dev/null +++ b/Polygon/pack_to_yaml.sh @@ -0,0 +1,59 @@ +#!/bin/bash +set -e + +# configuration +Contest_Name="test_contest" +Contest_Description="contest of testing cms judge" +#-------------- + +if [[ -d "Contest" ]]; then + rm -r Contest +fi +mkdir "Contest" + +echo -n "Enter the name of the problem to add to a contest, or leave blank to add all : " +read toDoList + +if [[ $toDoList == "" ]];then + toDoList=$(ls | sed s/pack_to_yaml.sh//g | sed s/pack_to_testcase.sh//g | sed s/Contest//g) +fi + +echo -e "name: \"$Contest_Name\" +description: \"$Contest_Description\" +token_mode: disabled +timezone: \"+8\" +tasks:" > "Contest/contest.yaml" + +for PROBLEM_NAME in $toDoList; do + mkdir "Contest/$PROBLEM_NAME" + mkdir "Contest/$PROBLEM_NAME/statement" + mkdir "Contest/$PROBLEM_NAME/gen" + mkdir "Contest/$PROBLEM_NAME/input" + mkdir "Contest/$PROBLEM_NAME/output" + + N=$(($(ls $PROBLEM_NAME/tests | wc -l)/2)) + PROBLEM_TITTLE=$(cat $PROBLEM_NAME/problem.xml | grep -m 1 'value="[^\"]*"' -o | sed -e s/value=// -e s/\"//g) + TIME_LIMIT=$(($(cat $PROBLEM_NAME/problem.xml | grep '' | sed -e s/''// -e s/'<\/time-limit>'//)/1000)) + MEMORY_LIMIT=$(($(cat $PROBLEM_NAME/problem.xml | grep '' | sed -e s/''// -e s/'<\/memory-limit>'//)/1024/1024)) + + for ((i = 01; i <= $N; i++)); do + id=$i + if [ $i -lt 10 ]; then + id="0$i" + fi + + cp "$PROBLEM_NAME/tests/$id" "Contest/$PROBLEM_NAME/input/input$((i-1)).txt" + cp "$PROBLEM_NAME/tests/$id.a" "Contest/$PROBLEM_NAME/output/output$((i-1)).txt" + done + + echo -e "name: $PROBLEM_NAME\ntitle: $PROBLEM_TITTLE\ntime_limit: $TIME_LIMIT\nmemory_limit: $MEMORY_LIMIT\nn_input: $N\ntoken_mode: disabled\npublic_testcases: all\ninfile: \"\"\noutfile: \"\"" > Contest/$PROBLEM_NAME/task.yaml + echo -e "# ST: 100\n$(seq 1 $N)" > Contest/$PROBLEM_NAME/gen/GEN + echo "statement" > Contest/$PROBLEM_NAME/statement/statement.pdf + echo " - \"$PROBLEM_NAME\"" >> "Contest/contest.yaml" + + printf "%s %ds %dMiB %s\n" "$PROBLEM_NAME" "$TIME_LIMIT" "$MEMORY_LIMIT" "$PROBLEM_TITTLE" +done + +echo -e "users:\n - username: \"test\"\n password: \"test\"\n first_name: \"test\"" >> "Contest/contest.yaml" +echo "sudo cmsImportUser --all -L italy_yaml . && sudo cmsImportContest -i -L italy_yaml ." >> "Contest/import.sh" +echo "Finished!" diff --git a/README.md b/README.md index 9e33606..da53c94 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ sudo apt install docker-compose -y ``` **Step. 3 下載cms** ``` -git clone https://github.com/erichung1113/cms.git && cd cms +git clone https://github.com/erichung9060/cms.git && cd cms ``` **Step. 4 執行docker compose** ``` diff --git a/docker-compose.yml b/docker-compose.yml index 3c79ba7..3264e5c 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -6,7 +6,7 @@ services: environment: POSTGRES_HOST_AUTH_METHOD: trust volumes: - - "/cms_docker_postgresql_data:/var/lib/postgresql/data" + - "/cms_docker_postgresql_data:/var/lib/postgresql" cms_test: container_name: cms