Skip to content

Commit 7b61e75

Browse files
kyuridenamidachaemonyuuki3655hiramekundnek
authored
Add cherry-picked release candidates for 1.1.7 (#199)
* 整数判定において、先頭が0だったり、文字数が20以上だったらFalseにするように (#172) * 整数判定において、先頭が0だったり、文字数が20以上だったらFalseにするように * answer.txtを変更 * test_mod_caseをstringに * Makes gen command retry with exponential backoff (#174) Previously, gen command retries with fixed delay of 1.5 seconds indefinitely. It could hurt the service especially when they are experiencing overloaded traffic. This patch changes the retry strategy with exponential backoff starting from 1.5 seconds to 60 seconds at maximum. The gen commands aborts by EnvironmentInitializationError exception after 10 attempts. * #186 Support \dots in input formats (#187) * C++言語アップデートへの対応 (#191) * Fix cpp language configs * Update atcodertools/common/language.py Co-authored-by: DNEK <[email protected]> Co-authored-by: Kazuma Mikami <[email protected]> Co-authored-by: DNEK <[email protected]> * Pythonの言語アップデートに対応 (#192) * Fix crash in new judgement using Python * Fix bugs of Python2 submissions in old judgement Co-authored-by: Matts966 <[email protected]> * 新しい言語のバージョンに対応 (#196) * 新しい言語のバージョンに対応 * gen, submitを新しいのに対応 * Fix regexps Co-authored-by: Kazuma Mikami <[email protected]> * Fix style * Update mock pages * Fix submissions * Fix flake8 Co-authored-by: chaemon <[email protected]> Co-authored-by: Yuki Hamada <[email protected]> Co-authored-by: Takaaki Hirano <[email protected]> Co-authored-by: DNEK <[email protected]> Co-authored-by: Matts966 <[email protected]> Co-authored-by: Matts966 <[email protected]>
1 parent f73f81c commit 7b61e75

File tree

28 files changed

+6110
-2304
lines changed

28 files changed

+6110
-2304
lines changed

atcodertools/client/atcoder.py

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -65,9 +65,9 @@ def __init__(self):
6565
self._session = requests.Session()
6666

6767
def check_logging_in(self):
68-
private_url = "https://arc001.contest.atcoder.jp/settings"
68+
private_url = "https://atcoder.jp/home"
6969
resp = self._request(private_url)
70-
return resp.url == private_url
70+
return resp.text.find("Sign In") == -1
7171

7272
def login(self,
7373
credential_supplier=None,
@@ -89,9 +89,14 @@ def login(self,
8989

9090
username, password = credential_supplier()
9191

92-
resp = self._request("https://arc001.contest.atcoder.jp/login", data={
93-
'name': username,
94-
"password": password
92+
soup = BeautifulSoup(self._session.get(
93+
"https://atcoder.jp/login").text, "html.parser")
94+
token = soup.find_all("form")[1].find(
95+
"input", type="hidden").get("value")
96+
resp = self._request("https://atcoder.jp/login", data={
97+
'username': username,
98+
"password": password,
99+
"csrf_token": token
95100
}, method='POST')
96101

97102
if resp.text.find("パスワードを忘れた方はこちら") != -1:
@@ -104,7 +109,8 @@ def download_problem_list(self, contest: Contest) -> List[Problem]:
104109
resp = self._request(contest.get_problem_list_url())
105110
soup = BeautifulSoup(resp.text, "html.parser")
106111
res = []
107-
for tag in soup.select('.linkwrapper')[0::2]:
112+
for tag in soup.find('table').select('tr')[1::]:
113+
tag = tag.find("a")
108114
alphabet = tag.text
109115
problem_id = tag.get("href").split("/")[-1]
110116
res.append(Problem(contest, alphabet, problem_id))
@@ -158,25 +164,24 @@ def submit_source_code(self, contest: Contest, problem: Problem, lang: Union[str
158164
soup = BeautifulSoup(resp.text, "html.parser")
159165
session_id = soup.find("input", attrs={"type": "hidden"}).get("value")
160166
task_select_area = soup.find(
161-
'select', attrs={"id": "submit-task-selector"})
162-
task_field_name = task_select_area.get("name")
167+
'select', attrs={"id": "select-task"})
163168
task_number = task_select_area.find(
164169
"option", text=re.compile('{} -'.format(problem.get_alphabet()))).get("value")
165170
language_select_area = soup.find(
166-
'select', attrs={"id": "submit-language-selector-{}".format(task_number)})
167-
language_field_name = language_select_area.get("name")
171+
'select', attrs={"data-placeholder": "-"})
168172
language_number = language_select_area.find(
169173
"option", text=lang_option_pattern).get("value")
170174
postdata = {
171-
"__session": session_id,
172-
task_field_name: task_number,
173-
language_field_name: language_number,
174-
"source_code": source
175+
"csrf_token": session_id,
176+
"data.TaskScreenName": task_number,
177+
"data.LanguageId": language_number,
178+
"sourceCode": source
175179
}
176180
resp = self._request(
177181
contest.get_submit_url(),
178182
data=postdata,
179183
method='POST')
184+
180185
return Submission.make_submissions_from(resp.text)[0]
181186

182187
def download_submission_list(self, contest: Contest) -> List[Submission]:

atcodertools/client/models/contest.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,13 @@ def get_problem_list_url(self):
1919
return "{}assignments".format(self.get_url())
2020

2121
def get_submit_url(self):
22-
return "{}submit".format(self.get_url())
22+
return "{}submit".format(self.get_new_url())
2323

2424
def get_my_submissions_url(self, page=1):
25-
return "{}submissions/me/{}".format(self.get_url(), page)
25+
return "{}submissions/me/?page={}".format(self.get_new_url(), page)
2626

2727
def get_submissions_url(self, submission: Submission):
28-
return "{}submissions/{}".format(self.get_new_url(), submission.submission_id)
28+
return "{}submissions/?page={}".format(self.get_new_url(), submission.submission_id)
2929

3030
def to_dict(self):
3131
return {

atcodertools/client/models/submission.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@
33
from bs4 import BeautifulSoup
44

55
PROB_URL_RE = re.compile(
6-
r'"/tasks/([A-Za-z0-9\'~+\-_]+)"')
6+
r'"/contests/.*/tasks/([A-Za-z0-9\'~+\-_]+)"')
77
SUBMISSION_URL_RE = re.compile(
8-
r'"/submissions/([0-9]+)"')
8+
r'/submissions/([0-9]+)')
99

1010

1111
class Submission:

atcodertools/codegen/code_generators/rust.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,6 @@ def _generate_declaration(self, var: Variable):
7373
elif var.dim_num() == 1:
7474
if var.type == Type.str:
7575
constructor = " = vec![String::new(); ({size}) as usize]".format(
76-
type=self._convert_type(var.type),
7776
size=var.first_index.get_length()
7877
)
7978
else:
@@ -84,7 +83,6 @@ def _generate_declaration(self, var: Variable):
8483
elif var.dim_num() == 2:
8584
if var.type == Type.str:
8685
constructor = " = vec![vec![String::new(); ({col_size}) as usize]; ({row_size}) as usize]".format(
87-
type=self._convert_type(var.type),
8886
row_size=var.first_index.get_length(),
8987
col_size=var.second_index.get_length()
9088
)

atcodertools/common/language.py

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,9 @@ def source_code_name(self, name_without_extension: str) -> str:
4141

4242
@classmethod
4343
def from_name(cls, name: str):
44-
for l in ALL_LANGUAGES:
45-
if l.name == name:
46-
return l
44+
for lang in ALL_LANGUAGES:
45+
if lang.name == name:
46+
return lang
4747
raise LanguageNotFoundError(
4848
"No language support for '{}'".format(ALL_LANGUAGE_NAMES))
4949

@@ -52,7 +52,8 @@ def from_name(cls, name: str):
5252
name="cpp",
5353
display_name="C++",
5454
extension="cpp",
55-
submission_lang_pattern=re.compile(".*C\\+\\+14 \\(GCC.*"),
55+
submission_lang_pattern=re.compile(
56+
".*C\\+\\+ \\(GCC 9.*|.*C\\+\\+14 \\(GCC 5.*"),
5657
default_code_generator=cpp.main,
5758
default_template_path=get_default_template_path('cpp'),
5859
)
@@ -61,7 +62,7 @@ def from_name(cls, name: str):
6162
name="java",
6263
display_name="Java",
6364
extension="java",
64-
submission_lang_pattern=re.compile(".*Java8.*"),
65+
submission_lang_pattern=re.compile(".*Java8.*|.*Java \\(OpenJDK 11.*"),
6566
default_code_generator=java.main,
6667
default_template_path=get_default_template_path('java'),
6768
)
@@ -77,9 +78,9 @@ def from_name(cls, name: str):
7778

7879
PYTHON = Language(
7980
name="python",
80-
display_name="Python3",
81+
display_name="Python",
8182
extension="py",
82-
submission_lang_pattern=re.compile(".*Python3.*"),
83+
submission_lang_pattern=re.compile(".*Python3.*|^Python$"),
8384
default_code_generator=python.main,
8485
default_template_path=get_default_template_path('py'),
8586
)
@@ -88,7 +89,7 @@ def from_name(cls, name: str):
8889
name="d",
8990
display_name="D",
9091
extension="d",
91-
submission_lang_pattern=re.compile(".*DMD64.*"),
92+
submission_lang_pattern=re.compile(".*D \\(DMD.*"),
9293
default_code_generator=d.main,
9394
default_template_path=get_default_template_path('d'),
9495
)
@@ -97,7 +98,7 @@ def from_name(cls, name: str):
9798
name="nim",
9899
display_name="NIM",
99100
extension="nim",
100-
submission_lang_pattern=re.compile(".*Nim \\(0.*"),
101+
submission_lang_pattern=re.compile(".*Nim \\(1.*"),
101102
default_code_generator=nim.main,
102103
default_template_path=get_default_template_path('nim'),
103104
default_code_style=CodeStyle(indent_width=2)

atcodertools/fmtprediction/predict_types.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,15 @@ def is_float(text):
4848

4949

5050
def is_int(text):
51-
return re.match(r"-?\d+$", text) is not None
51+
if text == "0":
52+
return True
53+
if re.match(r"-?\d+$", text) is None:
54+
return False
55+
if text[0] == "0":
56+
return False
57+
if len(text) > 19 or (text[0] == '-' and len(text) > 20):
58+
return False
59+
return True
5260

5361

5462
def _convert_to_proper_type(value: str) -> Any:

atcodertools/fmtprediction/tokenize_format.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ def _is_ascii(s):
1111
return all(ord(c) < 128 for c in s)
1212

1313

14-
DOTS_PATTERNS = ["ldots", "cdots", "vdots", "ddots"]
14+
DOTS_PATTERNS = ["ldots", "cdots", "vdots", "ddots", "dots"]
1515

1616

1717
def _is_noise(s):

atcodertools/tools/envgen.py

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
import traceback
77
from multiprocessing import Pool, cpu_count
88
from os.path import expanduser
9-
from time import sleep
9+
import time
1010
from typing import Tuple
1111

1212
from colorama import Fore
@@ -34,6 +34,10 @@ class BannedFileDetectedError(Exception):
3434
pass
3535

3636

37+
class EnvironmentInitializationError(Exception):
38+
pass
39+
40+
3741
def output_splitter():
3842
# for readability
3943
print("=================================================", file=sys.stderr)
@@ -159,16 +163,23 @@ def func(argv: Tuple[AtCoderClient, Problem, Config]):
159163

160164
def prepare_contest(atcoder_client: AtCoderClient,
161165
contest_id: str,
162-
config: Config):
163-
retry_duration = 1.5
166+
config: Config,
167+
retry_delay_secs: float = 1.5,
168+
retry_max_delay_secs: float = 60,
169+
retry_max_tries: int = 10):
170+
attempt_count = 1
164171
while True:
165172
problem_list = atcoder_client.download_problem_list(
166173
Contest(contest_id=contest_id))
167174
if problem_list:
168175
break
169-
sleep(retry_duration)
176+
if 0 < retry_max_tries < attempt_count:
177+
raise EnvironmentInitializationError
170178
logger.warning(
171-
"Failed to fetch. Will retry in {} seconds".format(retry_duration))
179+
"Failed to fetch. Will retry in {} seconds. (Attempt {})".format(retry_delay_secs, attempt_count))
180+
time.sleep(retry_delay_secs)
181+
retry_delay_secs = min(retry_delay_secs * 2, retry_max_delay_secs)
182+
attempt_count += 1
172183

173184
tasks = [(atcoder_client,
174185
problem,

0 commit comments

Comments
 (0)