def from_url(cls, s: str) -> Optional['AtCoderProblem']: # example: http://agc012.contest.atcoder.jp/tasks/agc012_d result = urllib.parse.urlparse(s) dirname, basename = posixpath.split(utils.normpath(result.path)) if result.scheme in ('', 'http', 'https') \ and result.netloc.count('.') == 3 \ and result.netloc.endswith('.contest.atcoder.jp') \ and result.netloc.split('.')[0] \ and dirname == '/tasks' \ and basename: contest_id = result.netloc.split('.')[0] problem_id = basename return cls(contest_id, problem_id) # example: https://beta.atcoder.jp/contests/abc073/tasks/abc073_a m = re.match(r'^/contests/([\w\-_]+)/tasks/([\w\-_]+)$', utils.normpath(result.path)) if result.scheme in ('', 'http', 'https') \ and result.netloc in ('atcoder.jp', 'beta.atcoder.jp') \ and m: contest_id = m.group(1) problem_id = m.group(2) return cls(contest_id, problem_id) return None
def from_url(cls, s: str) -> Optional['AtCoderSubmission']: submission_id = None # type: Optional[int] # example: http://agc001.contest.atcoder.jp/submissions/1246803 result = urllib.parse.urlparse(s) dirname, basename = posixpath.split(utils.normpath(result.path)) if result.scheme in ('', 'http', 'https') \ and result.netloc.count('.') == 3 \ and result.netloc.endswith('.contest.atcoder.jp') \ and result.netloc.split('.')[0] \ and dirname == '/submissions': contest_id = result.netloc.split('.')[0] try: submission_id = int(basename) except ValueError: pass submission_id = None if submission_id is not None: return cls(contest_id=contest_id, submission_id=submission_id) # example: https://beta.atcoder.jp/contests/abc073/submissions/1592381 m = re.match(r'^/contests/([\w\-_]+)/submissions/(\d+)$', utils.normpath(result.path)) if result.scheme in ('', 'http', 'https') \ and result.netloc in ('atcoder.jp', 'beta.atcoder.jp') \ and m: contest_id = m.group(1) try: submission_id = int(m.group(2)) except ValueError: submission_id = None if submission_id is not None: return cls(contest_id=contest_id, submission_id=submission_id) return None
def from_url(cls, url: str) -> Optional['TopcoderProblem']: # example: https://arena.topcoder.com/index.html#/u/practiceCode/14230/10838/10760/1/303803 # example: https://community.topcoder.com/stat?c=problem_statement&pm=10760 result = urllib.parse.urlparse(url) if result.scheme in ('', 'http', 'https'): if result.netloc == 'arena.topcoder.com' and utils.normpath( result.path) in ('/', '/index.html'): dirs = utils.normpath(result.fragment).split('/') if len(dirs) == 8 and dirs[0] == '' and dirs[ 1] == 'u' and dirs[2] == 'practiceCode': try: _ = int(dirs[3]) # round_id _ = int(dirs[4]) # component_id problem_id = int(dirs[5]) _ = int(dirs[6]) # division_id _ = int(dirs[7]) # room_id except ValueError: pass else: return cls(problem_id=problem_id) if result.netloc == 'community.topcoder.com' and utils.normpath( result.path) == '/stat': query = urllib.parse.parse_qs(result.query) if query.get('c') == ['problem_statement'] and len( query.get('pm', [])) == 1: try: problem_id = int(query['pm'][0]) except ValueError: pass else: return cls(problem_id=problem_id) return None
def from_url(cls, url: str) -> Optional['FacebookHackerCupProblem']: # removed format # example: https://www.facebook.com/hackercup/problem/448364075989193/ result = urllib.parse.urlparse(url) if result.scheme in ('', 'http', 'https') \ and result.netloc == 'www.facebook.com' \ and utils.normpath(result.path).startswith('/hackercup/problem/'): dirs = utils.normpath(result.path).split('/') if len(dirs) > 3 and dirs[3].isdigit(): logger.warning( 'The old platform of Facebook Hacker Cup has been replaced. See https://github.com/online-judge-tools/api-client/issues/84' ) # new format # example: https://www.facebook.com/codingcompetitions/hacker-cup/2020/qualification-round/problems/A dirs = utils.normpath(result.path).split('/') if result.scheme in ('', 'http', 'https') \ and result.netloc == 'www.facebook.com' \ and len(dirs) >= 7 and dirs[1] == 'codingcompetitions' and dirs[5] == 'problems': return cls( series_vanity=dirs[2], season_vanity=dirs[3], contest_vanity=dirs[4], display_index=dirs[6], ) return None
def from_url(cls, url: str) -> Optional['AOJProblem']: result = urllib.parse.urlparse(url) # example: http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=1169 # example: http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=DSL_1_A&lang=jp querystring = urllib.parse.parse_qs(result.query) if result.scheme in ('', 'http', 'https') \ and result.netloc == 'judge.u-aizu.ac.jp' \ and utils.normpath(result.path) == '/onlinejudge/description.jsp' \ and querystring.get('id') \ and len(querystring['id']) == 1: n, = querystring['id'] return cls(n) # example: https://onlinejudge.u-aizu.ac.jp/challenges/sources/JAG/Prelim/2881 # example: https://onlinejudge.u-aizu.ac.jp/courses/library/4/CGL/3/CGL_3_B m = re.match( r'^/(challenges|courses)/(sources|library/\d+|lesson/\d+)/(\w+)/(\w+)/(\w+)$', utils.normpath(result.path)) if result.scheme in ('', 'http', 'https') \ and result.netloc == 'onlinejudge.u-aizu.ac.jp' \ and m: n = m.group(5) return cls(n) # example: https://onlinejudge.u-aizu.ac.jp/services/room.html#RitsCamp18Day3/problems/B # NOTE: I don't know how to retrieve the problem id return None
def from_url(cls, url: str) -> Optional['FacebookHackerCupProblem']: # example: https://www.facebook.com/hackercup/problem/448364075989193/ result = urllib.parse.urlparse(url) if result.scheme in ('', 'http', 'https') \ and result.netloc == 'www.facebook.com' \ and utils.normpath(result.path).startswith('/hackercup/problem/'): dirs = utils.normpath(result.path).split('/') if 3 < len(dirs) and dirs[3].isdigit(): problem_id = int(dirs[3]) return cls(problem_id=problem_id) return None
def from_url(cls, url: str) -> Optional['FacebookHackerCupService']: # old format # example: https://www.facebook.com/hackercup/ result = urllib.parse.urlparse(url) if result.scheme in ('', 'http', 'https') \ and result.netloc == 'www.facebook.com' \ and utils.normpath(result.path).startswith('/hackercup'): return cls() # new format # example: https://www.facebook.com/codingcompetitions/ if result.scheme in ('', 'http', 'https') \ and result.netloc == 'www.facebook.com' \ and utils.normpath(result.path).startswith('/codingcompetitions'): return cls() return None
def from_url(cls, url: str) -> Optional['CodeforcesProblem']: result = urllib.parse.urlparse(url) if result.scheme in ('', 'http', 'https') \ and result.netloc in _CODEFORCES_DOMAINS: # "0" is needed. example: https://codeforces.com/contest/1000/problem/0 # "[1-9]?" is sometime used. example: https://codeforces.com/contest/1133/problem/F2 re_for_index = r'(0|[A-Za-z][1-9]?)' table = {} table['contest'] = r'^/contest/([0-9]+)/problem/{}$'.format( re_for_index ) # example: https://codeforces.com/contest/538/problem/H table['problemset'] = r'^/problemset/problem/([0-9]+)/{}$'.format( re_for_index ) # example: https://codeforces.com/problemset/problem/700/B table['gym'] = r'^/gym/([0-9]+)/problem/{}$'.format( re_for_index ) # example: https://codeforces.com/gym/101021/problem/A for kind, expr in table.items(): m = re.match(expr, utils.normpath(result.path)) if m: if m.group(2) == '0': index = 'A' # NOTE: This is broken if there was "A1". else: index = m.group(2).upper() return cls(contest_id=int(m.group(1)), index=index, kind=kind) return None
def get_available_languages( self, session: Optional[requests.Session] = None) -> List[Language]: """ :raises NotLoggedInError: """ session = session or utils.new_default_session() # get url = 'http://{}.contest.atcoder.jp/submit'.format(self.contest_id) resp = _request('GET', url, session=session) msgs = AtCoderService._get_messages_from_cookie(resp.cookies) if AtCoderService._report_messages(msgs, unexpected=True): return [] # check whether logged in path = utils.normpath(urllib.parse.urlparse(resp.url).path) if path.startswith('/login'): log.error('not logged in') raise NotLoggedInError # parse soup = bs4.BeautifulSoup(resp.content.decode(resp.encoding), utils.html_parser) select = soup.find( 'select', class_='submit-language-selector' ) # NOTE: AtCoder can vary languages depending on tasks, even in one contest. here, ignores this fact. languages = [] # type: List[Language] for option in select.find_all('option'): languages += [Language(option.attrs['value'], option.string)] return languages
def from_url(cls, url: str) -> Optional['GoogleCodeJamProblem']: # example: https://codingcompetitions.withgoogle.com/codejam/round/000000000019fd27/000000000020993c # example: https://codingcompetitions.withgoogle.com/kickstart/round/000000000019ffc7/00000000001d3f56 # example: https://code.google.com/codejam/contest/7234486/dashboard # example: https://code.google.com/codejam/contest/7234486/dashboard#s=p0 result = urllib.parse.urlparse(url) if result.scheme in ('', 'http', 'https'): dirs = utils.normpath(result.path).split('/') if result.netloc == 'codingcompetitions.withgoogle.com': if len(dirs) >= 5 and dirs[2] == 'round' and all( c in string.hexdigits for c in dirs[3]) and all(c in string.hexdigits for c in dirs[4]): return cls(domain=result.netloc, kind=dirs[1], contest_id=dirs[3], problem_id=dirs[4]) if result.netloc == 'code.google.com': if len(dirs) >= 5 and dirs[2] == 'contest' and dirs[3].isdigit( ) and dirs[4] == 'dashboard': if result.fragment == '' or re.match( r'^s=p\d+$', result.fragment): problem_id = (result.fragment or 's=p0')[2:] return cls(domain=result.netloc, kind=dirs[1], contest_id=dirs[3], problem_id=problem_id) return None
def from_url(cls, url: str) -> Optional['AtCoderContest']: """ :param url: example: - https://kupc2014.contest.atcoder.jp/tasks/kupc2014_d - https://atcoder.jp/contests/agc030 """ result = urllib.parse.urlparse(url) # example: https://kupc2014.contest.atcoder.jp/tasks/kupc2014_d if result.scheme in ( '', 'http', 'https') and result.hostname.endswith('.contest.atcoder.jp'): contest_id = utils.remove_suffix(result.hostname, '.contest.atcoder.jp') return cls(contest_id) # example: https://atcoder.jp/contests/agc030 if result.scheme in ('', 'http', 'https') and result.hostname in ( 'atcoder.jp', 'beta.atcoder.jp'): m = re.match(r'/contests/([\w\-_]+)/?.*', utils.normpath(result.path)) if m: contest_id = m.group(1) return cls(contest_id) return None
def from_url(cls, url: str) -> Optional['HackerRankProblem']: # example: https://www.hackerrank.com/contests/university-codesprint-2/challenges/the-story-of-a-tree # example: https://www.hackerrank.com/challenges/fp-hello-world result = urllib.parse.urlparse(url) if result.scheme in ('', 'http', 'https') \ and result.netloc in ('hackerrank.com', 'www.hackerrank.com'): m = re.match( r'^/contests/([0-9A-Za-z-]+)/challenges/([0-9A-Za-z-]+)$', utils.normpath(result.path)) if m: return cls(m.group(1), m.group(2)) m = re.match(r'^/challenges/([0-9A-Za-z-]+)$', utils.normpath(result.path)) if m: return cls('master', m.group(1)) return None
def submit_code(self, code: bytes, language_id: LanguageId, filename: Optional[str] = None, session: Optional[requests.Session] = None) -> Submission: """ :raises NotLoggedInError: :raises SubmissionError: """ assert language_id in [ language.id for language in self.get_available_languages(session=session) ] session = session or utils.new_default_session() # get url = 'http://{}.contest.atcoder.jp/submit'.format( self.contest_id) # TODO: use beta.atcoder.jp resp = _request('GET', url, session=session) msgs = AtCoderService._get_messages_from_cookie(resp.cookies) if AtCoderService._report_messages(msgs, unexpected=True): raise SubmissionError # check whether logged in path = utils.normpath(urllib.parse.urlparse(resp.url).path) if path.startswith('/login'): log.error('not logged in') raise NotLoggedInError # parse soup = bs4.BeautifulSoup(resp.content.decode(resp.encoding), utils.html_parser) form = soup.find('form', action=re.compile(r'^/submit\?task_id=')) if not form: log.error('form not found') raise SubmissionError log.debug('form: %s', str(form)) # post task_id = self._get_task_id(session=session) form = utils.FormSender(form, url=resp.url) form.set('task_id', str(task_id)) form.set('source_code', code) form.set('language_id_{}'.format(task_id), str(language_id)) resp = form.request(session=session) resp.raise_for_status() # result msgs = AtCoderService._get_messages_from_cookie(resp.cookies) AtCoderService._report_messages(msgs) if '/submissions/me' in resp.url: # example: https://practice.contest.atcoder.jp/submissions/me#32174 # CAUTION: this URL is not a URL of the submission log.success('success: result: %s', resp.url) # NOTE: ignore the returned legacy URL and use beta.atcoder.jp's one url = 'https://beta.atcoder.jp/contests/{}/submissions/me'.format( self.contest_id) return utils.DummySubmission(url, problem=self) else: log.failure('failure') log.debug('redirected to %s', resp.url) raise SubmissionError('it may be a rate limit')
def from_url(cls, url: str) -> Optional['AnarchyGolfProblem']: # example: http://golf.shinh.org/p.rb?The+B+Programming+Language result = urllib.parse.urlparse(url) if result.scheme in ('', 'http', 'https') \ and result.netloc == 'golf.shinh.org' \ and utils.normpath(result.path) == '/p.rb' \ and result.query: return cls(problem_id=result.query) return None
def from_url(cls, url: str) -> Optional['AOJArenaProblem']: # example: https://onlinejudge.u-aizu.ac.jp/services/room.html#RitsCamp19Day2/problems/A result = urllib.parse.urlparse(url) if result.scheme in ('', 'http', 'https') \ and result.netloc == 'onlinejudge.u-aizu.ac.jp' \ and utils.normpath(result.path) == '/services/room.html': fragment = result.fragment.split('/') if len(fragment) == 3 and fragment[1] == 'problems': return cls(fragment[0], fragment[2].upper()) return None
def from_url(cls, url: str) -> Optional['GoogleCodeJamService']: # example: https://codingcompetitions.withgoogle.com/ # example: https://code.google.com/codejam result = urllib.parse.urlparse(url) if result.scheme in ('', 'http', 'https'): if result.netloc == 'codingcompetitions.withgoogle.com': return cls() if result.netloc == 'code.google.com': dirs = utils.normpath(result.path).split('/') if len(dirs) >= 2 and dirs[1] == 'codejam': return cls() return None
def from_url(cls, s: str) -> Optional['TophProblem']: result = urllib.parse.urlparse(s) dirname, basename = posixpath.split(utils.normpath(result.path)) # example: https://toph.co/p/new-year-couple if result.scheme in ('', 'http', 'https') \ and result.netloc.count('.') == 1 \ and result.netloc.endswith('toph.co') \ and dirname == '/p' \ and basename: problem_id = basename return cls(problem_id) return None
def from_url(cls, url: str) -> Optional['Contest']: # example: https://yukicoder.me/contests/276 # example: http://yukicoder.me/contests/276/all result = urllib.parse.urlparse(url) dirs = utils.normpath(result.path).split('/') if result.scheme in ('', 'http', 'https') and result.netloc == 'yukicoder.me': if len(dirs) >= 3 and dirs[1] == 'contests': try: contest_id = int(dirs[2]) except ValueError: pass else: return cls(contest_id=contest_id) return None
def from_url(cls, url: str) -> Optional['POJProblem']: # example: http://poj.org/problem?id=2104 result = urllib.parse.urlparse(url) if result.scheme in ('', 'http', 'https') \ and result.netloc == 'poj.org' \ and utils.normpath(result.path) == '/problem': query = urllib.parse.parse_qs(result.query) if 'id' in query and len(query['id']) == 1: try: n = int(query['id'][0]) return cls(n) except ValueError: pass return None
def from_url(cls, url: str) -> Optional['CSAcademyProblem']: # example: https://csacademy.com/contest/round-38/task/path-union/ # example: https://csacademy.com/contest/round-38/task/path-union/discussion/ # example: https://csacademy.com/contest/archive/task/swap_permutation/ # example: https://csacademy.com/contest/archive/task/swap_permutation/statement/ result = urllib.parse.urlparse(url) if result.scheme in ('', 'http', 'https') \ and result.netloc in ('csacademy.com', 'www.csacademy.com'): m = re.match( r'^/contest/([0-9A-Za-z_-]+)/task/([0-9A-Za-z_-]+)(|/statement|/solution|/discussion|/statistics|/submissions)/?$', utils.normpath(result.path)) if m: return cls(m.group(1), m.group(2)) return None
def from_url(cls, url: str) -> Optional['CodeforcesContest']: result = urllib.parse.urlparse(url) if result.scheme in ('', 'http', 'https') \ and result.netloc in _CODEFORCES_DOMAINS: table = {} table['contest'] = r'/contest/([0-9]+).*'.format( ) # example: https://codeforces.com/contest/538 table['gym'] = r'/gym/([0-9]+).*'.format( ) # example: https://codeforces.com/gym/101021 for kind, expr in table.items(): m = re.match(expr, utils.normpath(result.path)) if m: return cls(contest_id=int(m.group(1)), kind=kind) return None
def from_url(cls, url: str) -> Optional['TopcoderLongContestProblem']: # example: https://community.topcoder.com/longcontest/?module=ViewProblemStatement&rd=16997&pm=14690 # example: https://community.topcoder.com/longcontest/?module=ViewProblemStatement&rd=16997&compid=57374 # example: https://community.topcoder.com/longcontest/?module=ViewStandings&rd=16997 # example: https://community.topcoder.com/tc?module=MatchDetails&rd=16997 result = urllib.parse.urlparse(url) if result.scheme in ('', 'http', 'https') \ and result.netloc == 'community.topcoder.com' \ and utils.normpath(result.path) in ['/longcontest', '/tc']: querystring = dict(urllib.parse.parse_qsl(result.query)) if 'rd' in querystring: kwargs = {} for name in ['rd', 'cd', 'compid', 'pm']: if name in querystring: kwargs[name] = int(querystring[name]) return cls(**kwargs) return None
def from_url(cls, url: str) -> Optional['YukicoderProblem']: # example: https://yukicoder.me/problems/no/499 # example: http://yukicoder.me/problems/1476 result = urllib.parse.urlparse(url) dirname, basename = posixpath.split(utils.normpath(result.path)) if result.scheme in ('', 'http', 'https') \ and result.netloc == 'yukicoder.me': n = None # type: Optional[int] try: n = int(basename) except ValueError: pass if n is not None: if dirname == '/problems/no': return cls(problem_no=n) if dirname == '/problems': return cls(problem_id=n) return None
def from_url(cls, url: str) -> Optional['CodeforcesProblem']: result = urllib.parse.urlparse(url) if result.scheme in ('', 'http', 'https') \ and result.netloc == 'codeforces.com': table = {} table[ 'contest'] = r'^/contest/([0-9]+)/problem/([0A-Za-z])$' # example: https://codeforces.com/contest/538/problem/H table[ 'problemset'] = r'^/problemset/problem/([0-9]+)/([0A-Za-z])$' # example: https://codeforces.com/problemset/problem/700/B table[ 'gym'] = r'^/gym/([0-9]+)/problem/([0A-Za-z])$' # example: https://codeforces.com/gym/101021/problem/A normalize = (lambda c: c == '0' and 'A' or c.upper()) for kind, expr in table.items(): m = re.match(expr, utils.normpath(result.path)) if m: return cls(int(m.group(1)), normalize(m.group(2)), kind=kind) return None
def from_url(cls, url: str) -> Optional['CodeforcesProblem']: result = urllib.parse.urlparse(url) if result.scheme in ('', 'http', 'https') \ and result.netloc in _CODEFORCES_DOMAINS: # "0" is needed. example: https://codeforces.com/contest/1000/problem/0 # "[1-9]?" is sometime used. example: https://codeforces.com/contest/1133/problem/F2 re_for_index = r'(?P<index>0|[A-Za-z][1-9]?)' table = {} table[ 'contest'] = r'^/contest/(?P<contest>[0-9]+)/problem/{}$'.format( re_for_index ) # example: https://codeforces.com/contest/538/problem/H table[ 'problemset'] = r'^/problemset/problem/(?P<contest>[0-9]+)/{}$'.format( re_for_index ) # example: https://codeforces.com/problemset/problem/700/B table['gym'] = r'^/gym/(?P<contest>[0-9]+)/problem/{}$'.format( re_for_index ) # example: https://codeforces.com/gym/101021/problem/A table[ 'edu'] = r'^/edu/course/(?P<course>[0-9]*)/lesson/(?P<lesson>[0-9]*)/(?P<step>[0-9]*)/practice/contest/(?P<contest>[0-9]*)/problem/{}$'.format( re_for_index ) # example https://codeforces.com/edu/course/2/lesson/2/1/practice/contest/269100/problem/A for kind, expr in table.items(): m = re.match(expr, utils.normpath(result.path)) if m: if m.group('index') == '0': index = 'A' # NOTE: This is broken if there was "A1". else: index = m.group('index').upper() if kind == 'edu': return cls(contest_id=int(m.group('contest')), index=index, kind=kind, course=int(m.group('course')), lesson=int(m.group('lesson')), step=int(m.group('step'))) else: return cls(contest_id=int(m.group('contest')), index=index, kind=kind) return None
def from_url(cls, url: str) -> Optional['KagamizContestSystemProblem']: result = urllib.parse.urlparse(url) # example: https://kcs.miz-miz.biz/contest/2000/view/A # example: https://kcs.miz-miz.biz/contest/2000/view/%5C if result.scheme in ('', 'http', 'https') \ and result.netloc == 'kcs.miz-miz.biz': parts = utils.normpath(result.path).split('/') if len(parts) >= 5 and not parts[0] and parts[ 1] == 'contest' and parts[3] == 'view': problem_id = parts[4] if problem_id: try: contest_id = int(parts[2]) return cls(contest_id=contest_id, problem_id=problem_id) except ValueError: pass return None