Skip to content

Commit 8511f29

Browse files
committed
add algo-method support (get-problem only)
1 parent 8529981 commit 8511f29

File tree

5 files changed

+154
-0
lines changed

5 files changed

+154
-0
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ $ pip3 install online-judge-api-client
2323

2424
| website | get sample cases | get system cases | get metadata | get contest data | login service | submit code |
2525
|--------------------------------------------------------------------------------|--------------------|--------------------|--------------------|--------------------|--------------------|--------------------|
26+
| [Algo-Method](https://algo-method.com) | :heavy_check_mark: | | | | | |
2627
| [Aizu Online Judge](https://onlinejudge.u-aizu.ac.jp/home) | :heavy_check_mark: | :heavy_check_mark: | | | | |
2728
| [Anarchy Golf](http://golf.shinh.org/) | :heavy_check_mark: | :grey_question: (same to samples) | | | | |
2829
| [AtCoder](https://atcoder.jp/) | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |

onlinejudge/service/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
# Python Version: 3.x
2+
import onlinejudge.service.algo_method
23
import onlinejudge.service.anarchygolf
34
import onlinejudge.service.aoj
45
import onlinejudge.service.atcoder

onlinejudge/service/algo_method.py

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
# Python Version: 3.x
2+
# -*- coding: utf-8 -*-
3+
"""
4+
the module for Algo-Method (https://algo-method.com/)
5+
"""
6+
7+
import urllib.parse
8+
from typing import *
9+
import json
10+
import re
11+
12+
import bs4
13+
import requests
14+
15+
import onlinejudge._implementation.testcase_zipper
16+
import onlinejudge._implementation.utils as utils
17+
import onlinejudge.dispatch
18+
import onlinejudge.type
19+
20+
import posixpath
21+
22+
class AlgoMethodService(onlinejudge.type.Service):
23+
def get_url(self) -> str:
24+
return 'https://algo-method.com/'
25+
26+
def get_name(self) -> str:
27+
return 'algo-method'
28+
29+
@classmethod
30+
def from_url(cls, url: str) -> Optional['AlgoMethodService']:
31+
# example: https://algo-method.com/
32+
result = urllib.parse.urlparse(url)
33+
if result.scheme in ('', 'http', 'https') \
34+
and result.netloc == 'algo-method.com':
35+
return cls()
36+
return None
37+
38+
39+
class AlgoMethodProblem(onlinejudge.type.Problem):
40+
def __init__(self, *, problem_id: str):
41+
self.problem_id = problem_id
42+
43+
def download_sample_cases(self, *, session: Optional[requests.Session] = None) -> List[onlinejudge.type.TestCase]:
44+
session = session or utils.get_default_session()
45+
# get
46+
resp = utils.request('GET', self.get_url(), session=session)
47+
# parse
48+
soup = bs4.BeautifulSoup(resp.content.decode(resp.encoding), utils.HTML_PARSER)
49+
samples = onlinejudge._implementation.testcase_zipper.SampleZipper()
50+
for case, name in self._parse_sample_cases(soup):
51+
samples.add(case.encode(), name)
52+
return samples.get()
53+
54+
def _parse_sample_cases(self, soup: bs4.BeautifulSoup) -> List[Tuple[str, str]]:
55+
bodyMD = json.loads(soup.find(id='__NEXT_DATA__').get_text())['props']['pageProps']['tasks']['body']
56+
pattern = r'#### ([入出]力例 \d ?)\r\n```IOExample\r\n([\s\S]+?)```'
57+
cases = re.findall(pattern, bodyMD)
58+
for name, case in cases:
59+
yield (utils.dos2unix(case), name)
60+
61+
def get_url(self) -> str:
62+
return 'https://algo-method.com/tasks/{}'.format(self.problem_id)
63+
64+
def get_service(self) -> AlgoMethodService:
65+
return AlgoMethodService()
66+
67+
@classmethod
68+
def from_url(cls, url: str) -> Optional['AlgoMethodProblem']:
69+
# example: https://algo-method.com/tasks/15
70+
result = urllib.parse.urlparse(url)
71+
dirname, basename = posixpath.split(utils.normpath(result.path))
72+
if result.scheme in ('', 'http', 'https') \
73+
and result.netloc == 'algo-method.com' \
74+
and dirname == '/tasks' \
75+
and basename:
76+
return cls(problem_id=basename)
77+
return None
78+
79+
80+
onlinejudge.dispatch.services += [AlgoMethodService]
81+
onlinejudge.dispatch.problems += [AlgoMethodProblem]

onlinejudge_api/main.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ def get_parser() -> argparse.ArgumentParser:
5858
# get-problem
5959
epilog = textwrap.dedent("""\
6060
supported services:
61+
Algo-Method
6162
Aizu Online Judge
6263
Anarchy Golf
6364
AtCoder

tests/get_problem_algo_method.py

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
import unittest
2+
3+
from onlinejudge_api.main import main
4+
5+
6+
class GetProblemAlgoMethodTest(unittest.TestCase):
7+
def test_tasks_22(self):
8+
url = 'https://algo-method.com/tasks/22'
9+
expected = {
10+
"status": "ok",
11+
"messages": [],
12+
"result": {
13+
"url": "https://algo-method.com/tasks/22",
14+
"tests": [
15+
{
16+
"input": "power\n",
17+
"output": "w\n"
18+
},
19+
{
20+
"input": "otter\n",
21+
"output": "t\n"
22+
},
23+
],
24+
"context": {}
25+
},
26+
}
27+
actual = main(['get-problem', url], debug=True)
28+
self.assertEqual(expected, actual)
29+
30+
def test_tasks_24(self):
31+
url = 'https://algo-method.com/tasks/24'
32+
expected = {
33+
"status": "ok",
34+
"messages": [],
35+
"result": {
36+
"url": "https://algo-method.com/tasks/24",
37+
"tests": [
38+
{
39+
"input": "1 2\n",
40+
"output": "3\n"
41+
}
42+
],
43+
"context": {}
44+
},
45+
}
46+
actual = main(['get-problem', url], debug=True)
47+
self.assertEqual(expected, actual)
48+
49+
def test_tasks_529(self):
50+
url = 'https://algo-method.com/tasks/529'
51+
expected = {
52+
"status": "ok",
53+
"messages": [],
54+
"result": {
55+
"url": "https://algo-method.com/tasks/529",
56+
"tests": [
57+
{
58+
"input": "7\n0 1 0 0 1 5\n",
59+
"output": "0\n1\n2\n1\n1\n2\n3\n"
60+
},
61+
{
62+
"input": "7\n0 0 0 0 0 0\n",
63+
"output": "0\n1\n1\n1\n1\n1\n1\n"
64+
}
65+
],
66+
"context": {}
67+
},
68+
}
69+
actual = main(['get-problem', url], debug=True)
70+
self.assertEqual(expected, actual)

0 commit comments

Comments
 (0)