学弟最近问我算法竞赛如何筹办,所以来写篇博客
1. 硬件设施
服务器,注意内存和带宽,我一直找学校老师要的校内服务器,4核20G内存,在100人同时使用时没压力
然后就是测评机,cpu的每个核心可以当一台测评机,校赛的时候我找了4台机房电脑,创建了8个测评机
如果要发气球的话提前买好气球核氦气罐
2. 软件设施
我们一直使用的domjudge作为比赛的测评系统
服务器用的ubuntu18.04,https://cndrew.cn/2020/07/05/domjudge/ 这里写的已经很清楚了,我没必要再写了
然后是测评机的配置,我发现了使用docker配置测评机更加简单,直接在dockerhub上搜domjudge,上边有官方群发布的测评机镜像,然后就是傻瓜式的配置
3. 出题
这里有一些出题脚本,首先是目录结构,每个题目有一个文件夹,内部data文件夹代表测试数据,里边有1.in文件,分别代表测试数据的输入
然后是两个文件夹out1和out2,分别代表两个对拍标程的输出,这里有一个检测两个对拍是否一致的脚本
import os
from time import *
os.system("g++ 1.cpp -o 1")
os.system("g++ 2.cpp -o 2")
L=os.listdir("./data")
for i in L:
os.system('1 <./data/'+i+'> ./out1/'+i.replace('in','out'));
os.system('2 <./data/'+i+'> ./out2/'+i.replace('in','out'));
L=os.listdir('./out1')
for i in L:
os.system('fc \"out1\\'+i+'\" \"out2\\'+i+'\"')
os.system("pause")
和一个造数据的模板
from random import*
def Gen(T):
F=open("./data/"+str(T)+".in","w")
for i in range(60):
F.write("%d"%(randint(0,9)));
F.write("\n");
F.close()
for i in range(1,21):
Gen(i)
在该文件夹下要有A.pdf,作为A题的题面,会由之后的脚本打包成domjudge识别的试题格式
如果试题准备完成后,在主文件夹下使用这个脚本,可以自动的打包试题成为上传到domjudge的压缩包
import os
import shutil
def data(path):
os.system('md data\secret')
os.system('copy '+path+'data\* '+'.\data\secret\\')
os.system('copy '+path+'out1\* '+'.\data\secret\\')
L=os.listdir("./data/secret")
for i in L:
if('out' in i):
os.system('rename '+'.\data\secret\\'+i+' '+i.replace('out','ans'))
def files(id):
os.system('cd.>domjudge-problem.ini')
F=open('domjudge-problem.ini','w')
F.write('probid=\''+'w'+id+'\'\n')
F.write("timelimit=\'1\'")
F.close()
os.system('cd.>problem.yaml')
F=open('problem.yaml','w')
F.write('name: \'Problem '+id+'\'\n')
F.close()
for i in range(65,75):
path='.\\'+chr(i)+'\\'
data(path)
files(chr(i))
os.system('copy '+path+chr(i)+'.pdf '+'.\problem.pdf')
os.system('D:\Winrar\winrar.exe a '+chr(i)+'.zip '+'domjudge-problem.ini '+'problem.yaml '+'problem.pdf '+'data')
os.system('del problem.pdf problem.yaml domjudge-problem.ini')
shutil.rmtree('data')
4. 平台测试
最后要拿不同语言在平台上测试,检查时间限制的问题
5. 参赛选手导入
上边链接中讲了怎么造队伍账号,需要team.tsv 文件,这里有xlsx转换脚本
import pandas as pd
F=open("teams.tsv","w",encoding='utf-8')
F.write("teams\t1\n")
teams=pd.read_excel('teams.xlsx')
id=0
for i in teams['队伍中文名']:
id+=1
F.write("%d\t\t3\t%s\t\t\t\t\n"%(id,i))
F.close()
还需要account.tsv,每个account和每个team所对应,脚本:
import pandas as pd
F=open("accounts.tsv","w",encoding='utf-8')
F.write("accounts\t1\n")
teams=pd.read_excel('offical_teams.xlsx')
id=0
for i in teams['队伍中文名']:
id+=1
F.write("team\t%s\tteam%03d\tqwe\n"%(i,id))
F.close()
还有群发邮件的脚本:
import smtplib
import pandas as pd
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.application import MIMEApplication
msg_from=
passwd=
subject= "华为杯中国海洋大学程序设计竞赛 竞赛通知"
content1= "同学你好:\n\n欢迎报名参加华为杯中国海洋大学程序设计竞赛!\n"
teams=pd.read_excel('teams.xlsx')
pdf1 = MIMEApplication(open('../Doc/华为杯竞赛说明2.0.pdf','rb').read())
pdf1.add_header('Content-Disposition', 'attachment', filename='华为杯竞赛说明2.0.pdf')
pdf2 = MIMEApplication(open('../Doc/domjudge使用说明.pdf','rb').read())
pdf2.add_header('Content-Disposition', 'attachment', filename='domjudge使用说明.pdf')
pdf3 = MIMEApplication(open('../Doc/domjudge使用说明官方原版.pdf','rb').read())
pdf3.add_header('Content-Disposition', 'attachment', filename='domjudge使用说明官方原版.pdf')
F=open("accounts.tsv","r",encoding='utf-8')
F.readline()
teams=pd.read_excel('teams.xlsx')
a=0
for index,team in teams.iterrows():
content2="队伍中文名:"+str(team['队伍中文名'])+"\n"+\
"队伍英文名:"+str(team['队伍英文名'])+"\n"+\
"手机号码:"+str(team['手机号码'])+"\n"+\
"是否女队:"+str(team['是否女队'])+"\n"+\
"队员一姓名专业:"+str(team['队员一姓名'])+" "+str(team['队员一年级专业'])+"\n"+\
"队员二姓名专业:"+str(team['队员二姓名'])+" "+str(team['队员二年级专业'])+"\n"+\
"队员三姓名专业:"+str(team['队员三姓名'])+" "+str(team['队员三年级专业'])+"\n"
content3="除此之外,还需要补充收集是否为研究生队伍,队员中有一名研究生即为研究生队伍:收集链接:"+\
'https://www.wjx.cn/jq/95107267.aspx'+"\n"+\
"若队伍信息有错,或缺少队员,请在上述链接中的信息修改中一同反馈。\n"
content4='线上选拔赛将于10月31日13:00举行,请按时参加,网络赛参赛网址:http://222.195.151.172,需要用校园网访问,可以提前登陆进行环境测试,更多详细细节请见附件。\n'
account=F.readline().split('\n')[0].split('\t')
content5="网络赛用户名:"+account[2]+"\n"+\
"网络赛密码:"+account[3]+"\n"
content6="祝比赛顺利!\n\n华为杯主办方\n"
content=content1+content2+content3+content4+content5+content6
a+=1
if(a==-1):
msg_to=str(team['邮箱'])
text = MIMEText(content.encode('utf8'),_charset='utf8')
mail = MIMEMultipart()
mail['Subject'] = subject
mail['From'] = msg_from
mail['To'] = msg_to
mail.attach(text)
mail.attach(pdf1)
mail.attach(pdf2)
mail.attach(pdf3)
try:
s = smtplib.SMTP_SSL("smtp.qq.com",465)
# s = smtplib.SMTP_SSL("smtp.aliyun.com",465)
s.login(msg_from, passwd)
s.sendmail(msg_from, msg_to, mail.as_bytes())
print(msg_to+" 发送成功")
except:
print(msg_to+" 发送失败")
finally:
s.quit()
F.close()