Skip to content

Commit d3e3c0e

Browse files
committed
add algo-method support (get-problem only)
1 parent 1bcccb0 commit d3e3c0e

File tree

5 files changed

+155
-0
lines changed

5 files changed

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

0 commit comments

Comments
 (0)