Пример #1
0
 def showProblemDetail(self, pid):
     PrintUtil.info("正在加载题目...")
     p = self.getProblemInfo(globalVar.BASE_CONF.get('contest', 'cid'), pid)
     if not p:
         return
     os.system('clear')
     print(p.problemDetail())
Пример #2
0
    def showProblemList(self):

        PrintUtil.info("正在加载题目列表...")
        # 先尝试从缓存的文件中加载
        i = 1
        try:
            with open(globalVar.BASE_CONF_PATH + 'problemList',
                      'rb') as file_object:
                pList = pickle.load(file_object)
            for p in pList:
                print(p.problemSimple, end=' ')
                if i % 3 == 0:
                    print('')
                i = i + 1
            print('')
        except:
            # 出错就从oj线上加载
            pList = self.getProblemList(
                globalVar.BASE_CONF.get('contest', 'cid'))
            for p in pList:
                print(p.problemSimple(), end=' ')
                if i % 3 == 0:
                    print('')
                i = i + 1
            print('')
Пример #3
0
    def genCode(self, pid, codetype):
        PrintUtil.info('代码文件生成中...')
        p = self.getProblemInfo(globalVar.BASE_CONF.get('contest', 'cid'), pid)

        title = p.title.split('(')[0].strip()

        code = '/*' + p.problemContent() + '\n*/\n\n'
        code = re.sub(r'\r', '', code)

        ccode = '#include <stdio.h>\n\nint main(){\n\n    return 0;\n}'
        cppcode = '#include <iostream> \n\n#include <cstdio>\nusing namespace std;\nint main()\n{\n\n    return 0;\n}'
        javacode = 'import java.util.*;\n\npublic class Main{\n    public static void main(String args[]){\n\n    }\n}'

        suffix = '.c'
        if codetype == 'c':
            code = code + ccode
            suffix = '.c'
        elif codetype == 'cpp':
            suffix = '.cpp'
            code = code + cppcode
        elif codetype == 'java':
            suffix = '.java'
            code = code + javacode
        fileName = pid + '.' + title + suffix
        f = open("./" + fileName, "w")
        f.write(code)
        f.flush()
        f.close()
        PrintUtil.info('文件  [ ' + fileName + ' ]  保存成功 :) ')
Пример #4
0
    def getProblemInfo(self, cid, pid):
        ctype = globalVar.BASE_CONF.get('contest', 'ctype')
        cpass = globalVar.BASE_CONF.get('contest', 'cpass')

        data = {'id': cid, 'type': ctype}
        pwdProbleUrl = globalVar.OJ_CONF.get('urls', 'pwdProblems')
        resp = RequestUtil.doGet(pwdProbleUrl, data) \
            if cpass == '1' else RequestUtil.doGet(AojApi.getUrl('problems'), data)
        # 解析网页数据
        soup = BeautifulSoup(resp.text, "lxml")

        pdiv = soup.find('div', id='title_' + pid)
        if not pdiv:
            PrintUtil.error("你已经AC了或者没有该题目")
            sys.exit(0)
        p = Problem()
        p.pid = re.sub("\D", "", pdiv['id'])
        p.title = pdiv.find('div', class_='nav').string.split('.')[1].strip()
        p.timeAndMem = pdiv.find('div', class_='common').string.strip()

        contentDiv = pdiv.find_all('div')
        p.content = contentDiv[3].pre.string
        p.descr_input = contentDiv[5].pre.string
        p.descr_output = contentDiv[7].pre.string
        p.ex_input = contentDiv[9].pre.string
        p.ex_output = contentDiv[11].pre.string
        p.code = ''
        return p
Пример #5
0
    def getPassedDetail(self, cid, pid):

        resp = RequestUtil.doGet(AojApi.getUrl('passedProblem'), {'id': cid})
        soup = BeautifulSoup(resp.text, "lxml")
        p = soup.find('div', class_='nav', text=re.compile(r'.*' + pid + '.*'))

        if not p:
            PrintUtil.error("没有该题目...")
            sys.exit(0)
        infolist = [
            'title', 'content', 'descr_input', 'descr_output', 'ex_input',
            'ex_output', 'code', 'score'
        ]
        j = 0
        problem = Problem()
        problem.pid = ''
        problem.timeAndMem = ''
        for i in range(0, 31):
            s = ''
            if p.string is not None:
                s = p.string
            elif p.pre is not None:
                s = p.pre.string
            elif p.span is not None:
                s = p.span.string
            elif p.textarea is not None:
                s = p.textarea.string
            if s is not None and s.strip() != '':
                setattr(problem, infolist[j], s.strip())
                j = j + 1
            p = p.next_sibling
        return problem
Пример #6
0
    def getProblemList(self, cid):
        ctype = globalVar.BASE_CONF.get('contest', 'ctype')
        cpass = globalVar.BASE_CONF.get('contest', 'cpass')

        data = {'id': cid, 'type': ctype}
        pwdProbleUrl = globalVar.OJ_CONF.get('urls', 'pwdProblems')
        resp = RequestUtil.doGet(pwdProbleUrl, data) \
            if cpass == '1' else RequestUtil.doGet(AojApi.getUrl('problems'), data)
        # 解析网页数据
        soup = BeautifulSoup(resp.text, "lxml")
        # 仅获取题目和id
        pList = []
        allProblemDiv = soup.find_all('div', id=re.compile(r'title_\d*'))
        if not allProblemDiv:
            PrintUtil.warn("题目空了,你可能已经AK了.")
            sys.exit(0)
        for pdiv in allProblemDiv:
            p = Problem()
            p.pid = re.sub("\D", "", pdiv['id'])
            title = pdiv.find('div', class_='nav').string.split('.')[1].strip()
            tempStrs = title.split('(')
            p.score = '分数:' + re.sub("\D", "",
                                     tempStrs[len(tempStrs) - 1]).strip()
            p.title = title.split('(')[0].strip()
            pList.append(p)
        # 按分数排序
        pList = sorted(pList, key=lambda pList: pList.score)
        return pList
Пример #7
0
def use_commond(ojOperate):
    if arg_len == 3:
        arg2 = sys.argv[2]
        #if re.match('^\d+$', arg2):
        ojOperate.saveContestInfo(arg2)
        return
    PrintUtil.error("参数错误")
    help_commond()
Пример #8
0
 def saveContestInfo(self, cid):
     PrintUtil.info('正在获取比赛信息...')
     # 保存比赛信息
     globalVar.BASE_CONF.set('contest', 'cid', cid)
     with open(globalVar.BASE_PATH + 'base.conf', 'w') as fw:
         globalVar.BASE_CONF.write(fw)
     self.saveProblemList()
     PrintUtil.info("设置比赛成功!\n")
Пример #9
0
    def showRanking(self):
        cid = globalVar.BASE_CONF.get('contest', 'cid')
        PrintUtil.info("加载排名中...")
        rList = self.getRankingList(cid)
        #    rList = rList.reverse()

        for i in range(0, len(rList))[::-1]:
            rList[i].showUserInfo()
Пример #10
0
def checkout_commond():
    # 切换oj
    if arg_len == 3:
        globalVar.BASE_CONF.set('base', 'oj_name', sys.argv[2])
        with open(globalVar.BASE_CONF_PATH, 'w') as fw:
            globalVar.BASE_CONF.write(fw)
        return
    PrintUtil.error("参数错误")
    help_commond()
Пример #11
0
def test_commond(ojOperate):
    if arg_len == 3:
        arg1 = sys.argv[1]
        arg2 = sys.argv[2]
        if arg1 == "test":
            ojOperate.testCode(arg2)
            return
    PrintUtil.error("参数错误")
    help_commond()
Пример #12
0
def passed_commond(ojOperate):
    if arg_len == 2:
        ojOperate.showPassed()
        return
    elif arg_len == 3 and re.match('^\d+$', sys.argv[2]):
        ojOperate.showPassedDetail(sys.argv[2])
        return
    PrintUtil.error("参数错误")
    help_commond()
Пример #13
0
def submit_commond(ojOperate):
    if arg_len == 3:
        arg1 = sys.argv[1]
        arg2 = sys.argv[2]
        if arg1 == "submit":
            ojOperate.showSubmitResult(arg2)
            return
    PrintUtil.error("参数错误")
    help_commond()
Пример #14
0
    def login(self, username, password):
        data = {'email': username, 'passwd': password}
        resp = RequestUtil.doPost(url=AojApi.getUrl('login'), data=data)
        jdata = json.loads(resp.text)

        if jdata['code'] == 0 and jdata['response']['message'] == 'success':
            return True
        else:
            PrintUtil.error(jdata['errorMessage'])
            return False
Пример #15
0
 def showContestList(self, containPassed):
     contestList = self.getContestList(containPassed)
     for c in contestList:
         if isinstance(c, Contest):
             c.problemDetail()
         else:
             PrintUtil.error('contest type error')
             break
     print(''.join(' id' + '\t' + '{:35}'.format('名称') + '语言' + '\t' +
                   '结束时间' + '\t\t' + '描述'))
Пример #16
0
    def showPassedDetail(self, pid):
        cid = globalVar.BASE_CONF.get('contest', 'cid')

        problem = self.getPassedDetail(cid, pid)
        try:
            problem.code.index('输入描述')
            PrintUtil.info(problem.code)
        except:
            print(problem.problemDetail())
        PrintUtil.success(problem.score)
Пример #17
0
    def showSubmitResult(self, fileName):
        pid = fileName.split('.')[0]
        if not re.match('^\d+$', pid):
            PrintUtil.error("文件命名错误,请以'id.'开头, 例: 70.简单求和.c")
            return
        try:
            f = open(fileName, "r")
        except:
            PrintUtil.error("没有找到文件.检查文件名是否有误")
            return
        code = f.read()
        f.close()

        self.submitCode(code, pid)
Пример #18
0
def list_commond(ojOperate):
    if arg_len == 3 or arg_len == 4:
        arg2 = sys.argv[2]
        if arg2 == "-c":
            if arg_len == 4 and sys.argv[3] == '-a':
                ojOperate.showContestList(True)
            else:
                ojOperate.showContestList(False)
            return
        elif arg2 == "-p":
            ojOperate.showProblemList()
            return
    PrintUtil.error("参数错误\n")
    help_commond()
Пример #19
0
def input_name_pass_login(ojOperate):
    username = input(termcolor.colored('请输入用户名: ', 'cyan'))
    password = getpass.getpass(termcolor.colored('请输入密码: ', 'cyan'))
    loginSuccess = ojOperate.login(username, password)

    if loginSuccess:
        # 保存cookie
        RequestUtil.session.cookies.save(ignore_discard=True,
                                         ignore_expires=True)
        PrintUtil.info('登录成功!')
        # 保存账号密码
        option = input(termcolor.colored(u'\n是否保存用户名及密码? (yes/no) ', 'cyan'))
        if option == 'yes':
            # 保存密码
            try:
                globalVar.BASE_CONF.set('user', 'username', username)
                # 先简单base64编码加密意思意思...
                bytesString = password.encode(encoding="utf-8")
                encodestr = base64.b64encode(bytesString)
                globalVar.BASE_CONF.set('user', 'password',
                                        encodestr.decode(encoding='utf-8'))
                with open(globalVar.BASE_CONF_PATH, 'w') as fw:
                    globalVar.BASE_CONF.write(fw)
                PrintUtil.success('保存密码成功  :)')
            except Exception as e:
                PrintUtil.info("保存密码失败 :(")
                PrintUtil.error(e)
    else:
        sys.exit(0)
Пример #20
0
    def testCode(self, fileName):
        # 编译
        compilep = subprocess.Popen(['g++', fileName],
                                    shell=False,
                                    stdout=subprocess.PIPE,
                                    stderr=subprocess.STDOUT)

        res = ''
        for line in compilep.stdout.readlines():
            res = res + line.decode()
        if res.find('error') >= 0:
            PrintUtil.info('编译错误')
            PrintUtil.error(res)
            return
        # 执行
        ## 读取测试数据
        pid = fileName.split('.')[0]
        problem = self.getProblemInfo(
            globalVar.BASE_CONF.get('contest', 'cid'), pid)
        ex_input = problem.ex_input
        ex_output = problem.ex_output

        execp = subprocess.Popen(['./a.out'],
                                 shell=False,
                                 stdin=subprocess.PIPE,
                                 stdout=subprocess.PIPE,
                                 stderr=subprocess.STDOUT)
        out, err = execp.communicate(input=ex_input.encode())
        PrintUtil.info("测试输出:")
        print(out.decode(), end="")
        PrintUtil.info("正确输出:")
        print(ex_output, end="")
Пример #21
0
    def getPassedList(self, cid):
        resp = RequestUtil.doGet(AojApi.getUrl('passedProblem'), {'id': cid})
        soup = BeautifulSoup(resp.text, "lxml")
        titles = soup.find_all('div', class_='nav')
        if not titles:
            PrintUtil.error("你还没有做过此比赛的题目 :)")
            sys.exit(0)

        problemList = []
        for t in titles:
            title = t.string.strip().split('.')[1]
            tempStrs = title.split('(')
            p = Problem()
            p.score = int(re.sub("\D", "", tempStrs[len(tempStrs) - 1]))
            p.title = title.split('(')[0].strip()
            p.pid = t.string.strip().split('.')[0]
            problemList.append(p)

        return problemList
Пример #22
0
def help_commond():
    info = "\n" \
           " list -c          | 列出所有正在进行的比赛\n" \
           " use id           | 根据id选择比赛\n" \
           " list -p          | 列出当前比赛题目\n" \
           " show id          | 显示id对应题目的详细信息\n" \
           " show id -g c     | 显示题目信息并生成c语言代码文件 可选参数cpp java\n" \
           " submit filename  | 提交代码文件判题\n" \
           " show ranking     | 显示当前参加比赛对应的排名\n" \
           " list -c -a       | 列出所有进行和已结束的比赛\n" \
           " passed           | 显示所有已提交过的题目列表\n" \
           " passed id        | 显示已提交题目详细信息\n" \
           " login            | 登录\n" \
           " checkout 'ojName'| 切换oj\n" \
           " help             | 显示此帮助信息\n" \
           "\n" \
           "--------------------------------------------------\n"
    PrintUtil.info(info)
    sys.exit(0)
Пример #23
0
def show_commond(ojOperate):
    if arg_len == 3:
        arg2 = sys.argv[2]
        if re.match('^\d+$', arg2):
            ojOperate.showProblemDetail(arg2)
            return
        elif arg2 == "ranking":
            ojOperate.showRanking()
            return
    elif arg_len == 5:
        arg2 = sys.argv[2]
        arg3 = sys.argv[3]
        arg4 = sys.argv[4]
        if re.match('\d+', arg2) and arg3 == '-g' and re.match(
                r'^(java|c|cpp)$', arg4):
            ojOperate.showProblemDetail(arg2)
            ojOperate.genCode(arg2, arg4)
            return
    PrintUtil.error("参数错误")
    help_commond()
Пример #24
0
    def login(self, username, password):
        # 验证码识别率较低..索性尝试5次
        tryloginTime = 5
        while (tryloginTime > 0):
            resp = RequestUtil.doPost(url=AojApi.getUrl('login'),
                                      data=self.getLoginData(
                                          username, password))

            soup = BeautifulSoup(resp.text, "lxml")
            divlist = soup.find_all('div', class_='user')

            if len(divlist) > 3:
                info = divlist[3].font.string
                if info != "验证码有误":
                    PrintUtil.error(info)
                    return False
            else:
                return True
            tryloginTime = tryloginTime - 1
        if tryloginTime <= 0:
            PrintUtil.error("oooops...验证码识别失败,再试试?")
Пример #25
0
    def getRankingList(self, cid):
        rankData = {"id": cid}
        resp = RequestUtil.doGet(AojApi.getUrl('rank'), rankData)
        soup = BeautifulSoup(resp.text, "lxml")
        rankingTr = soup.find_all('tr', id=re.compile('\d*'))
        if not rankingTr:
            PrintUtil.error("没有该比赛排名...重新选择比赛")
            sys.exit(0)

        rList = []
        for tr in rankingTr:
            stu = UserInfo()
            td = tr.find_all('td')
            stu.rank = td[0].div.string
            stu.username = td[1].div.string
            stu.name = td[2].div.string
            stu.stuid = td[3].div.string
            stu.college = td[4].div.string
            stu.major = td[5].div.string
            stu.score = td[6].div.string
            stu.subTime = td[7].div.string
            rList.append(stu)
        return rList
Пример #26
0
    def submitCode(self, code, pid):

        subData = {
            'answer': code,
            'id': pid,
            'type': globalVar.BASE_CONF.get('contest', 'ctype')
        }
        resp = RequestUtil.doPost(AojApi.getUrl('submitCode'), subData)
        # {"id":"125","result":"Wrong Answer.","score":0,"time":"21:34:35"}
        try:
            jdata = json.loads(resp.text)
            result = jdata['result']
            score = jdata['score']
            time = jdata['time']
            color = "red"
            if result == "Answer Correct.":
                color = "green"

            print(
                termcolor.colored(result, color) + '\n' + "得分:" +
                termcolor.colored(str(score), color) + '\n' + "提交时间:" +
                termcolor.colored(time, color))
        except:
            PrintUtil.error('oops!提交出错了,请重新提交. *_*.')
Пример #27
0
    def saveContestInfo(self, cid):
        PrintUtil.info('正在获取比赛信息...')
        resp = RequestUtil.doGet(AojApi.getUrl('contest'))
        jdata = json.loads(resp.text)
        datalist = jdata.get('list')

        ctype = '1'  # 类型 ...1代表c 0表示java
        cpass = '******'  # 是否需要密码 0为不需要

        # 根据比赛id查找比赛类型
        for data in datalist:
            if str(data['id']) == cid:
                ctype = data['isjava']
                break
        # 判断是否需要密码
        data = {'id': cid, 'type': ctype}
        needPasswordTest = RequestUtil.doGet(AojApi.getUrl('problems'), data)

        # Struts Problem Report页面报错编码不是utf-8
        if 'ISO-8859-1' in needPasswordTest.encoding:
            PrintUtil.error('没有该比赛 -_-\"')
            return
        try:
            # 如果不需要密码就没有这个头信息会抛异常,比之前的解析内容判断速度快,虽然不雅
            hasKeyContentLength = needPasswordTest.headers['Content-Length']
            cpass = '******'
            passwd = input(termcolor.colored(u'你需要输入密码参加该比赛: ', 'green'))
            joindata = {'password': passwd, 'id': cid}
            passwdisRight = RequestUtil.doGet(AojApi.getUrl('pwdProblems'),
                                              joindata)
            if passwdisRight.text == 'no':
                PrintUtil.error('密码错误!')
                return
        except:
            pass

        # 保存比赛信息
        globalVar.BASE_CONF.set('contest', 'cid', cid)
        globalVar.BASE_CONF.set('contest', 'ctype', ctype)
        globalVar.BASE_CONF.set('contest', 'cpass', cpass)
        with open(globalVar.BASE_PATH + 'base.conf', 'w') as fw:
            globalVar.BASE_CONF.write(fw)
        self.saveProblemList()
        PrintUtil.info("设置比赛成功! 'coj list -p' 显示题目列表\n")
Пример #28
0
 def saveProblemList(self):
     PrintUtil.info('正在缓存题目信息...')
     pList = self.getProblemList(globalVar.BASE_CONF.get('contest', 'cid'))
     if not pList:
         PrintUtil.warn('获取题目信息失败')
     try:
         with open(globalVar.BASE_PATH + 'problemList',
                   'wb') as file_object:
             pickle.dump(pList, file_object)
     except Exception as e:
         PrintUtil.error('缓存失败 :(')
         print(e)
         pass
Пример #29
0
def aoj_cli_main():
    if arg_len < 2:
        PrintUtil.error("参数错误")
        help_commond()
        return

    arg1 = sys.argv[1]
    # 不需要判断登录的命令

    if arg1 == "help":
        help_commond()
        sys.exit(0)
    if arg1 == "checkout":
        checkout_commond()
        sys.exit(0)

    # 获取 对应oj 的操作类
    try:
        module = __import__(
            globalVar.OJ_NAME + '.' + globalVar.OJ_NAME + 'Operate', globals(),
            locals(), [globalVar.OJ_NAME + 'Operate'])
        ojClass = getattr(module, globalVar.OJ_NAME.capitalize() + 'Operate')
        ojOperate = ojClass()
    except ModuleNotFoundError:
        # todo:添加支持oj列表
        PrintUtil.error("不支持oj: " + globalVar.OJ_NAME +
                        ", 使用 aoj checkout 'oj name' 切换")
        sys.exit(0)

    if arg1 == "login":
        input_name_pass_login(ojOperate)
        sys.exit(0)

    check_login(ojOperate)

    if arg1 == "list":
        list_commond(ojOperate)
    elif arg1 == "use":
        use_commond(ojOperate)
    elif arg1 == "show":
        show_commond(ojOperate)
    elif arg1 == "submit":
        submit_commond(ojOperate)
    elif arg1 == "passed":
        passed_commond(ojOperate)
    elif arg1 == "test":
        test_commond(ojOperate)
    else:
        PrintUtil.error("参数错误")
        help_commond()
Пример #30
0
def check_login(ojOperate):
    # 判断是否登录
    if not os.path.exists(globalVar.BASE_PATH + ".cookies/" +
                          globalVar.OJ_NAME):
        logo = "" \
               "                                        \n" \
               "   █████╗      ██████╗          ██╗     \n" \
               "   ██╔══██╗    ██╔═══██╗         ██║    \n" \
               "   ███████║    ██║   ██║         ██║    \n" \
               "   ██╔══██║    ██║   ██║    ██   ██║    \n" \
               "   ██║  ██║    ╚██████╔╝    ╚█████╔╝    \n" \
               "   ╚═╝  ╚═╝     ╚═════╝      ╚════╝     \n" \

        PrintUtil.info(logo)
        PrintUtil.info("欢迎使用 aoj ,登录后享受丝滑刷题")
        PrintUtil.info("使用\'aoj help\' 查看帮助信息")
        sys.exit(0)
    elif not ojOperate.isLogin():
        PrintUtil.info('登录失效')
        # 验证用户是否已经保存密码
        try:
            username = globalVar.BASE_CONF.get('user', 'username')
            encodePassword = globalVar.BASE_CONF.get('user', 'password')
            # 解码
            password = base64.b64decode(
                encodePassword.encode('utf-8')).decode('utf-8')
            if username == '' or password == '':
                input_name_pass_login(ojOperate)
            else:
                # 账号密码不为空, 尝试自动登录
                PrintUtil.info('正在尝试重新登录...')
                isSuccess = ojOperate.login(username, password)
                if isSuccess:
                    # 保存cookie
                    RequestUtil.session.cookies.save(ignore_discard=True,
                                                     ignore_expires=True)
                    PrintUtil.success("自动登录成功!")
                else:
                    globalVar.BASE_CONF.set('user', 'password', '')
                    with open(globalVar.BASE_CONF_PATH, 'w') as fw:
                        globalVar.BASE_CONF.write(fw)
                    PrintUtil.error("尝试自动登录失败, 手动登录 :(")
                    input_name_pass_login(ojOperate)
        except KeyboardInterrupt:
            pass
        except:
            PrintUtil.error("登录失败,请稍后重试 :<")
            sys.exit(0)