from dataclasses import dataclass, field
from enum import Enum
from typing import List, cast
from bs4 import BeautifulSoup
import bs4
from lxml import html
from lxml.etree import _Element
from lxml.html import HtmlMixin
from .interfaces.AioHttpHelper import AioHttpHelperInterface
from .util import soup_find_bs4Tag
[docs]class E_STATUS(str, Enum):
NOT_SUBMITTED = ""
AC = "AC"
ERROR = "ERROR"
[docs]@dataclass
class Questions:
when: str
Q: str
A: str
[docs]@dataclass
class Materials:
text: str
url: str
[docs]@dataclass
class ContestPage:
id: str
url: str
title: str
problems: List[ProblemMeta]
# questions: List[Questions]
materials: List[Materials]
[docs]def parse_problems(resp: str) -> List[ProblemMeta]:
soup = BeautifulSoup(resp, 'lxml')
currentContestList = soup.find('div', class_='datatable')
assert isinstance(currentContestList, bs4.Tag)
trs: List[BeautifulSoup] = currentContestList.find_all('tr')
ret = []
for i in range(1, len(trs)):
tds = trs[i].find_all('td')
namediv = tds[1].div.div
row = ProblemMeta(
id=tds[0].get_text().strip(),
url=tds[0].find('a')['href'],
name=namediv.get_text().strip(),
passed=tds[3].get_text().split('x')[-1].strip(),
)
if 'class' in trs[i].attrs:
classes: str = trs[i].attrs['class'] # mypy ?, List[str]
if 'accepted-problem' in classes:
row.status = E_STATUS.AC
elif 'rejected-problem' in classes:
row.status = E_STATUS.ERROR
limit = tds[1].find('div', class_="notice").get_text().strip()
if limit.startswith('standard input/output'):
limit = limit[len('standard input/output'):].strip()
try:
t, m = limit.split(',')
row.time_limit_msec = int(float(t.strip().split(' ')[0]) * 1000)
row.memory_limit_kb = int(float(m.strip().split(' ')[0]) * 1000)
except:
pass
ret.append(row)
return ret
[docs]def parse_materials(resp: str) -> List[Materials]:
doc = html.fromstring(resp)
captions = cast(List[_Element], doc.xpath('.//div[@class="caption titled"]'))
ret = []
for c in captions:
title = c.text[1:].strip()
if title != 'Contest materials':
continue
links = cast(List[_Element], c.getparent().xpath('.//a[@href]'))
for a in links:
title_text = str(cast(HtmlMixin, html.fromstring(a.get('title'))).text_content())
ret.append(Materials(text=title_text, url=a.get('href')))
return ret