def cfLoadProblemSln(userId: str): with getConnection() as con: r = con.execute( 'SELECT id, contestId, problemIdx FROM Problem WHERE userId = :userId', { 'userId': userId }).fetchone() pid, contestId, problemIdx = None, None, None if r != None: pid, contestId, problemIdx = r[0], r[1], r[2] if con.execute( 'SELECT problemId FROM ProblemSln WHERE problemId = :pid', { 'pid': pid }).fetchone() != None: return ProblemSln(pid) else: raise CriticalException( f'There is no problem with Id = {userId}') stands = cfSession.get( f'https://codeforces.com/api/contest.standings?contestId={contestId}&from=1&count=10&showUnofficial=true' ).json()['result'] if stands['contest']['phase'].lower() != 'finished': raise CriticalException( f'The contest is not finished yet, so can\'t download any solutions yet' ) ProblemSln._parseAndstoreSubmissionSln( contestId, _findAcceptedSub(contestId, problemIdx, stands), pid) return ProblemSln(pid)
def _parseAndStoreSubmissionTests(contestId: int, subId: int, problemId: int, trans: list = None, transSep: str = None) -> int: """ trans will receive each test case input and output seperated by transSep and its supposed to print the same. Also, If input or ouput are empty then the case won't be saved. """ bs = bs4.BeautifulSoup( cfSession.get( f'https://codeforces.com/contest/{contestId}/submission/{subId}' ).text, 'lxml') xcsrf = bs.select_one('meta[name="X-Csrf-Token"]').get('content') d = cfSession.post( 'https://codeforces.com/data/submitSource', headers={ 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8', 'X-Csrf-Token': xcsrf }, data=f'submissionId={subId}&csrf_token={xcsrf}').json() cnt = 0 with getConnection() as con: for i in range(1, int(d['testCount']) + 1): ipt, opt = d[f'input#{i}'].replace( '\r\n', '\n').strip(), d[f'answer#{i}'].replace('\r\n', '\n').strip() if trans != None: transInput = f'{ipt}\n{transSep}\n{opt}' try: ipt, opt = subprocess.run( trans, text=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, check=True, input=transInput).stdout.split(transSep) except subprocess.CalledProcessError as er: raise CriticalException( 'Case transformer exited with non-zero code.') elif ipt.endswith('...') or opt.endswith('...'): ipt, opt = None, None if ipt != None and (str.isspace(ipt) == False and len(ipt) > 0) and opt != None and ( str.isspace(opt) == False and len(opt) > 0): cnt += 1 con.execute( 'INSERT INTO Test(problemId, id, input, answer) VALUES(:problemId, :id, :input, :answer)', { 'problemId': problemId, 'id': f'CF{i}', 'input': ipt, 'answer': opt }) return cnt
def tryFindAcceptedSub(solverHandle: str) -> int: solverSubs = cfSession.get( f'https://codeforces.com/api/contest.status?contestId={contestId}&handle={solverHandle}&from=1&count=100000' ).json()['result'] return next( (s['id'] for s in solverSubs if s['problem']['index'].upper() == problemIdx and s['verdict'] == 'OK' and s['programmingLanguage'].find('++') != -1), -1)
def cfAddContest(contestId: int, problemUserIdPrefix: str = None) -> list: if problemUserIdPrefix == None: problemUserIdPrefix = str(contestId) logging.info( 'No problem id orefix was supplied so will use contest id instead.' ) probs = cfSession.get( f'https://codeforces.com/api/contest.standings?contestId={contestId}&from=1&count=1&showUnofficial=false' ).json()['result']['problems'] res = [] for p in probs: res.append( Problem.addProblem(f'{problemUserIdPrefix}{p["index"]}', contestId, p["index"])) logging.info( f'Added {len(res)} problems from contest {contestId} to db.') return res
def cfLoadTestSet(userId: str, transformerPath: str = None) -> int: with getConnection() as con: r = con.execute( 'SELECT id, contestId, problemIdx FROM Problem WHERE userId = :userId', { 'userId': userId }).fetchone() pid, contestId, problemIdx = None, None, None if r != None: pid, contestId, problemIdx = r[0], r[1], r[2] con.execute( "DELETE FROM Test WHERE problemId = :pid AND id LIKE 'CF%'", {'pid': pid}) con.commit() else: raise CriticalException( f'There is no problem with id: {userId} in db.') stands = cfSession.get( f'https://codeforces.com/api/contest.standings?contestId={contestId}&from=1&count=10&showUnofficial=true' ).json()['result'] loadSamples = stands['contest']['phase'].lower() != 'finished' if loadSamples == False: acc = _findAcceptedSub(contestId, problemIdx, stands) if acc != None: con.commit() if transformerPath != None: trans, transSep = compiler.compile( transformerPath), '!@#$%^&*()_' trans.append('--seperator') trans.append(transSep) else: trans, transSep = None, None return TestSet._parseAndStoreSubmissionTests( contestId, acc, pid, trans, transSep) else: logging.info( f"Couldn't find any accepted submission for problem {userId} so I will load samples instead." ) loadSamples = True if loadSamples: logging.info(f'Loading problem {userId} samples.') return TestSet._parseAndStoreProblemSamples( contestId, problemIdx, pid)
def _parseAndStoreProblemSamples(contestId: int, probIdx: int, problemId: int) -> int: bs = bs4.BeautifulSoup( cfSession.get( f'https://codeforces.com/contest/{contestId}/problem/{probIdx}' ).text, 'lxml') samplesDiv: bs4.Tag = bs.select_one('div.sample-tests') inputs = samplesDiv.select('div.input>pre') outputs = samplesDiv.select('div.output>pre') with getConnection() as con: for i in range(len(inputs)): con.execute( 'INSERT INTO Test(problemId, id, input, answer) VALUES(:problemId, :id, :input, :answer)', { 'problemId': problemId, 'id': f'CF{i+1}', 'input': inputs[i].text, 'answer': outputs[i].text }) return len(inputs)
def _parseAndstoreSubmissionSln(contestId: int, subId: int, problemId: int) -> None: bs = bs4.BeautifulSoup( cfSession.get( f'https://codeforces.com/contest/{contestId}/submission/{subId}' ).text, 'lxml') xcsrf = bs.select_one('meta[name="X-Csrf-Token"]').get('content') d = cfSession.post( 'https://codeforces.com/data/submitSource', headers={ 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8', 'X-Csrf-Token': xcsrf }, data=f'submissionId={subId}&csrf_token={xcsrf}').json() with getConnection() as con: con.execute( 'INSERT INTO ProblemSln(problemId, source) VALUES(:pid, :src)', { 'pid': problemId, 'src': d['source'].replace('\r\n', '\n') })