Skip to content

add algo-method support (get-problems only) #152

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ $ pip3 install online-judge-api-client

| website | get sample cases | get system cases | get metadata | get contest data | login service | submit code |
|--------------------------------------------------------------------------------|--------------------|--------------------|--------------------|--------------------|--------------------|--------------------|
| [Algo-Method](https://algo-method.com) | :heavy_check_mark: | | | | | |
| [Aizu Online Judge](https://onlinejudge.u-aizu.ac.jp/home) | :heavy_check_mark: | :heavy_check_mark: | | | | |
| [Anarchy Golf](http://golf.shinh.org/) | :heavy_check_mark: | :grey_question: (same to samples) | | | | |
| [AtCoder](https://atcoder.jp/) | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
Expand Down
1 change: 1 addition & 0 deletions onlinejudge/service/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# Python Version: 3.x
import onlinejudge.service.algo_method
import onlinejudge.service.anarchygolf
import onlinejudge.service.aoj
import onlinejudge.service.atcoder
Expand Down
81 changes: 81 additions & 0 deletions onlinejudge/service/algo_method.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
# Python Version: 3.x
# -*- coding: utf-8 -*-
"""
the module for Algo-Method (https://algo-method.com/)
"""

import json
import posixpath
import re
import urllib.parse
from typing import *

import bs4
import requests

import onlinejudge._implementation.testcase_zipper
import onlinejudge._implementation.utils as utils
import onlinejudge.dispatch
import onlinejudge.type


class AlgoMethodService(onlinejudge.type.Service):
def get_url(self) -> str:
return 'https://algo-method.com/'

def get_name(self) -> str:
return 'algo-method'

@classmethod
def from_url(cls, url: str) -> Optional['AlgoMethodService']:
# example: https://algo-method.com/
result = urllib.parse.urlparse(url)
if result.scheme in ('', 'http', 'https') \
and result.netloc == 'algo-method.com':
return cls()
return None


class AlgoMethodProblem(onlinejudge.type.Problem):
def __init__(self, *, problem_id: str):
self.problem_id = problem_id

def download_sample_cases(self, *, session: Optional[requests.Session] = None) -> List[onlinejudge.type.TestCase]:
session = session or utils.get_default_session()
# get
resp = utils.request('GET', self.get_url(), session=session)
# parse
soup = bs4.BeautifulSoup(resp.text, utils.HTML_PARSER)
samples = onlinejudge._implementation.testcase_zipper.SampleZipper()
for case, name in self._parse_sample_cases(soup):
samples.add(case.encode(), name)
return samples.get()

def _parse_sample_cases(self, soup: bs4.BeautifulSoup) -> Generator[Tuple[str, str], None, None]:
body_md = json.loads(soup.find(id='__NEXT_DATA__').get_text())['props']['pageProps']['tasks']['body']
pattern = r'#### ([入出]力例 \d ?)\r\n```IOExample\r\n([\s\S]+?)```'
cases = re.findall(pattern, body_md)
for name, case in cases:
yield (utils.dos2unix(case), name)

def get_url(self) -> str:
return 'https://algo-method.com/tasks/{}'.format(self.problem_id)

def get_service(self) -> AlgoMethodService:
return AlgoMethodService()

@classmethod
def from_url(cls, url: str) -> Optional['AlgoMethodProblem']:
# example: https://algo-method.com/tasks/15
result = urllib.parse.urlparse(url)
dirname, basename = posixpath.split(utils.normpath(result.path))
if result.scheme in ('', 'http', 'https') \
and result.netloc == 'algo-method.com' \
and dirname == '/tasks' \
and basename:
return cls(problem_id=basename)
return None


onlinejudge.dispatch.services += [AlgoMethodService]
onlinejudge.dispatch.problems += [AlgoMethodProblem]
1 change: 1 addition & 0 deletions onlinejudge_api/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ def get_parser() -> argparse.ArgumentParser:
# get-problem
epilog = textwrap.dedent("""\
supported services:
Algo-Method
Aizu Online Judge
Anarchy Golf
AtCoder
Expand Down
65 changes: 65 additions & 0 deletions tests/get_problem_algo_method.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import unittest

from onlinejudge_api.main import main


class GetProblemAlgoMethodTest(unittest.TestCase):
def test_tasks_22(self):
url = 'https://algo-method.com/tasks/22'
expected = {
"status": "ok",
"messages": [],
"result": {
"url": "https://algo-method.com/tasks/22",
"tests": [
{
"input": "power\n",
"output": "w\n"
},
{
"input": "otter\n",
"output": "t\n"
},
],
"context": {}
},
}
actual = main(['get-problem', url], debug=True)
self.assertEqual(expected, actual)

def test_tasks_24(self):
url = 'https://algo-method.com/tasks/24'
expected = {
"status": "ok",
"messages": [],
"result": {
"url": "https://algo-method.com/tasks/24",
"tests": [{
"input": "1 2\n",
"output": "3\n"
}],
"context": {}
},
}
actual = main(['get-problem', url], debug=True)
self.assertEqual(expected, actual)

def test_tasks_529(self):
url = 'https://algo-method.com/tasks/529'
expected = {
"status": "ok",
"messages": [],
"result": {
"url": "https://algo-method.com/tasks/529",
"tests": [{
"input": "7\n0 1 0 0 1 5\n",
"output": "0\n1\n2\n1\n1\n2\n3\n"
}, {
"input": "7\n0 0 0 0 0 0\n",
"output": "0\n1\n1\n1\n1\n1\n1\n"
}],
"context": {}
},
}
actual = main(['get-problem', url], debug=True)
self.assertEqual(expected, actual)