如何创办一场算法竞赛

学弟最近问我算法竞赛如何筹办,所以来写篇博客

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()

OVER

上一篇:Java猿社区—ShardingSphere4.0.0-RC1实现分库分表+读写分离


下一篇:Objective-C GCD深入理解