Skip to content

Commit a9688ea

Browse files
committed
Merge branch 'master' into pr/hotate29/1212
2 parents cf8aaa6 + bd01442 commit a9688ea

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+250
-575
lines changed

.github/workflows/ci.yml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,8 +82,20 @@ jobs:
8282
./atcoder-problems-frontend/node_modules
8383
key: ${{ runner.os }}-cargo-${{ hashFiles('atcoder-problems-frontend/yarn.lock') }}
8484

85+
- name: Cache cargo registry
86+
uses: actions/cache@v2
87+
with:
88+
path: |
89+
~/.cargo/git
90+
~/.cargo/registry/cache
91+
~/.cargo/registry/index
92+
./atcoder-problems-backend/target
93+
key: ${{ runner.os }}-cargo-${{ hashFiles('atcoder-problems-backend/Cargo.lock') }}
94+
8595
- name: Install dependencies
8696
run: yarn
97+
- name: Setup mdBook
98+
run: cargo install mdbook
8799
- name: build
88100
run: yarn build
89101
- name: test

atcoder-problems-backend/Cargo.lock

Lines changed: 0 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

atcoder-problems-backend/Cargo.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ fern = "0.6.1"
1212

1313
rand = "0.8.4"
1414
chrono = "0.4"
15-
regex = "1"
1615
rust-s3 = { version = "0.27.0-rc4", features = ["no-verify-ssl"] }
1716
serde = { version = "1.0", features = ["derive"] }
1817
serde_json = "1.0"

atcoder-problems-backend/atcoder-client/src/atcoder/contest.rs

Lines changed: 24 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use anyhow::{anyhow, Result};
1+
use anyhow::{Context, Result};
22

33
use super::AtCoderContest;
44

@@ -11,57 +11,57 @@ pub(super) fn scrape_normal(html: &str) -> Result<Vec<AtCoderContest>> {
1111
Html::parse_document(html)
1212
.select(&Selector::parse("tbody").unwrap())
1313
.next()
14-
.ok_or_else(|| anyhow!("Failed to parse html."))?
14+
.context("Failed to parse html.")?
1515
.select(&Selector::parse("tr").unwrap())
1616
.map(|tr| {
1717
let selector = Selector::parse("td").unwrap();
1818
let mut tds = tr.select(&selector);
1919
let start = tds
2020
.next()
21-
.ok_or_else(|| anyhow!("Failed to parse html."))?
21+
.context("Failed to parse html.")?
2222
.text()
2323
.next()
24-
.ok_or_else(|| anyhow!("Failed to parse html."))?;
24+
.context("Failed to parse html.")?;
2525
let start = DateTime::parse_from_str(start, "%Y-%m-%d %H:%M:%S%z")?;
2626
let start = start.timestamp() as u64;
2727

28-
let contest = tds.next().ok_or_else(|| anyhow!("Failed to parse html."))?;
28+
let contest = tds.next().context("Failed to parse html.")?;
2929
let contest_title = contest
3030
.select(&Selector::parse("a").unwrap())
3131
.next()
32-
.ok_or_else(|| anyhow!("Failed to parse html."))?
32+
.context("Failed to parse html.")?
3333
.text()
3434
.next()
35-
.ok_or_else(|| anyhow!("Failed to parse html."))?;
35+
.context("Failed to parse html.")?;
3636
let contest_link = contest
3737
.select(&Selector::parse("a").unwrap())
3838
.next()
39-
.ok_or_else(|| anyhow!("Failed to parse html."))?
39+
.context("Failed to parse html.")?
4040
.value()
4141
.attr("href")
42-
.ok_or_else(|| anyhow!("Failed to parse html."))?;
42+
.context("Failed to parse html.")?;
4343
let contest_id = contest_link
4444
.rsplit('/')
4545
.next()
46-
.ok_or_else(|| anyhow!("Failed to parse html."))?;
46+
.context("Failed to parse html.")?;
4747

4848
let duration = tds.next().unwrap().text().next().unwrap();
4949
let mut duration = duration.split(':');
5050
let hours = duration
5151
.next()
52-
.ok_or_else(|| anyhow!("Failed to parse html."))?
52+
.context("Failed to parse html.")?
5353
.parse::<u64>()?;
5454
let minutes = duration
5555
.next()
56-
.ok_or_else(|| anyhow!("Failed to parse html."))?
56+
.context("Failed to parse html.")?
5757
.parse::<u64>()?;
5858
let duration = hours * 3600 + minutes * 60;
5959
let rated = tds
6060
.next()
61-
.ok_or_else(|| anyhow!("Failed to parse html."))?
61+
.context("Failed to parse html.")?
6262
.text()
6363
.next()
64-
.ok_or_else(|| anyhow!("Failed to parse html."))?;
64+
.context("Failed to parse html.")?;
6565
Ok(AtCoderContest {
6666
id: contest_id.to_owned(),
6767
start_epoch_second: start,
@@ -77,41 +77,41 @@ pub(super) fn scrape_permanent(html: &str) -> Result<Vec<AtCoderContest>> {
7777
Html::parse_document(html)
7878
.select(&Selector::parse("#contest-table-permanent").unwrap())
7979
.next()
80-
.ok_or_else(|| anyhow!("Failed to parse html."))?
80+
.context("Failed to parse html.")?
8181
.select(&Selector::parse("tbody").unwrap())
8282
.next()
83-
.ok_or_else(|| anyhow!("Failed to parse html."))?
83+
.context("Failed to parse html.")?
8484
.select(&Selector::parse("tr").unwrap())
8585
.map(|tr| {
8686
let selector = Selector::parse("td").unwrap();
8787
let mut tds = tr.select(&selector);
8888

89-
let contest = tds.next().ok_or_else(|| anyhow!("Failed to parse html."))?;
89+
let contest = tds.next().context("Failed to parse html.")?;
9090
let contest_title = contest
9191
.select(&Selector::parse("a").unwrap())
9292
.next()
93-
.ok_or_else(|| anyhow!("Failed to parse html."))?
93+
.context("Failed to parse html.")?
9494
.text()
9595
.next()
96-
.ok_or_else(|| anyhow!("Failed to parse html."))?;
96+
.context("Failed to parse html.")?;
9797
let contest_link = contest
9898
.select(&Selector::parse("a").unwrap())
9999
.next()
100-
.ok_or_else(|| anyhow!("Failed to parse html."))?
100+
.context("Failed to parse html.")?
101101
.value()
102102
.attr("href")
103-
.ok_or_else(|| anyhow!("Failed to parse html."))?;
103+
.context("Failed to parse html.")?;
104104
let contest_id = contest_link
105105
.rsplit('/')
106106
.next()
107-
.ok_or_else(|| anyhow!("Failed to parse html."))?;
107+
.context("Failed to parse html.")?;
108108

109109
let rated = tds
110110
.next()
111-
.ok_or_else(|| anyhow!("Failed to parse html."))?
111+
.context("Failed to parse html.")?
112112
.text()
113113
.next()
114-
.ok_or_else(|| anyhow!("Failed to parse html."))?;
114+
.context("Failed to parse html.")?;
115115
Ok(AtCoderContest {
116116
id: contest_id.to_owned(),
117117
start_epoch_second: 0,

atcoder-problems-backend/atcoder-client/src/atcoder/problem.rs

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use anyhow::{anyhow, Result};
1+
use anyhow::{Context, Result};
22

33
use super::AtCoderProblem;
44

@@ -8,34 +8,34 @@ pub(super) fn scrape(html: &str, contest_id: &str) -> Result<Vec<AtCoderProblem>
88
Html::parse_document(html)
99
.select(&Selector::parse("tbody").unwrap())
1010
.next()
11-
.ok_or_else(|| anyhow!("Failed to parse html."))?
11+
.context("Failed to parse html.")?
1212
.select(&Selector::parse("tr").unwrap())
1313
.map(|tr| {
1414
let selector = Selector::parse("td").unwrap();
1515
let mut tds = tr.select(&selector);
1616
let position = tds
1717
.next()
18-
.ok_or_else(|| anyhow!("Failed to parse html."))?
18+
.context("Failed to parse html.")?
1919
.text()
2020
.next()
21-
.ok_or_else(|| anyhow!("Failed to parse html."))?
21+
.context("Failed to parse html.")?
2222
.to_owned();
23-
let problem = tds.next().ok_or_else(|| anyhow!("Failed to parse html."))?;
23+
let problem = tds.next().context("Failed to parse html.")?;
2424
let id = problem
2525
.select(&Selector::parse("a").unwrap())
2626
.next()
27-
.ok_or_else(|| anyhow!("Failed to parse html."))?
27+
.context("Failed to parse html.")?
2828
.value()
2929
.attr("href")
30-
.ok_or_else(|| anyhow!("Failed to parse html."))?
30+
.context("Failed to parse html.")?
3131
.rsplit('/')
3232
.next()
33-
.ok_or_else(|| anyhow!("Failed to parse html."))?
33+
.context("Failed to parse html.")?
3434
.to_owned();
3535
let title = problem
3636
.text()
3737
.next()
38-
.ok_or_else(|| anyhow!("Failed to parse html."))?
38+
.context("Failed to parse html.")?
3939
.to_owned();
4040
Ok(AtCoderProblem {
4141
id,

atcoder-problems-backend/atcoder-client/src/atcoder/submission.rs

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use super::AtCoderSubmission;
22

3-
use anyhow::{anyhow, Result};
3+
use anyhow::{Context, Result};
44

55
use chrono::DateTime;
66
use regex::Regex;
@@ -16,7 +16,7 @@ pub(super) fn scrape_submission_page_count(html: &str) -> Result<u32> {
1616
.flat_map(|href| href.rsplit('=').next())
1717
.flat_map(str::parse)
1818
.max()
19-
.ok_or_else(|| anyhow!("Failed to parse html."))
19+
.context("Failed to parse html.")
2020
}
2121

2222
pub(super) fn scrape(html_text: &str, contest_id: &str) -> Result<Vec<AtCoderSubmission>> {
@@ -29,46 +29,46 @@ pub(super) fn scrape(html_text: &str, contest_id: &str) -> Result<Vec<AtCoderSub
2929
Html::parse_document(html_text)
3030
.select(&tbody_selector)
3131
.next()
32-
.ok_or_else(|| anyhow!("Failed to parse html."))?
32+
.context("Failed to parse html.")?
3333
.select(&tr_selector)
3434
.map(|tr| {
3535
let mut tds = tr.select(&td_selector);
3636

3737
let time = tds
3838
.next()
39-
.ok_or_else(|| anyhow!("Failed to parse html."))?
39+
.context("Failed to parse html.")?
4040
.text()
4141
.next()
42-
.ok_or_else(|| anyhow!("Failed to parse html."))?;
42+
.context("Failed to parse html.")?;
4343
let time = DateTime::parse_from_str(time, "%Y-%m-%d %H:%M:%S%z")?;
4444
let epoch_second = time.timestamp() as u64;
4545

4646
let problem_id = tds
4747
.next()
48-
.ok_or_else(|| anyhow!("Failed to parse html."))?
48+
.context("Failed to parse html.")?
4949
.select(&a_selector)
5050
.next()
51-
.ok_or_else(|| anyhow!("Failed to parse html."))?
51+
.context("Failed to parse html.")?
5252
.value()
5353
.attr("href")
54-
.ok_or_else(|| anyhow!("Failed to parse html."))?
54+
.context("Failed to parse html.")?
5555
.rsplit('/')
5656
.next()
57-
.ok_or_else(|| anyhow!("Failed to parse html."))?
57+
.context("Failed to parse html.")?
5858
.to_owned();
5959

6060
let user_id = tds
6161
.next()
62-
.ok_or_else(|| anyhow!("Failed to parse html."))?
62+
.context("Failed to parse html.")?
6363
.select(&a_selector)
6464
.next()
65-
.ok_or_else(|| anyhow!("Failed to parse html."))?
65+
.context("Failed to parse html.")?
6666
.value()
6767
.attr("href")
68-
.ok_or_else(|| anyhow!("Failed to parse html."))?
68+
.context("Failed to parse html.")?
6969
.rsplit('/')
7070
.next()
71-
.ok_or_else(|| anyhow!("Failed to parse html."))?
71+
.context("Failed to parse html.")?
7272
.to_owned();
7373

7474
let language = tds
@@ -79,28 +79,28 @@ pub(super) fn scrape(html_text: &str, contest_id: &str) -> Result<Vec<AtCoderSub
7979

8080
let point: f64 = tds
8181
.next()
82-
.ok_or_else(|| anyhow!("Failed to parse html."))?
82+
.context("Failed to parse html.")?
8383
.text()
8484
.next()
85-
.ok_or_else(|| anyhow!("Failed to parse html."))?
85+
.context("Failed to parse html.")?
8686
.parse()?;
8787

8888
let length = tds
8989
.next()
90-
.ok_or_else(|| anyhow!("Failed to parse html."))?
90+
.context("Failed to parse html.")?
9191
.text()
9292
.next()
93-
.ok_or_else(|| anyhow!("Failed to parse html."))?
93+
.context("Failed to parse html.")?
9494
.replace("Byte", "")
9595
.trim()
9696
.parse::<u64>()?;
9797

9898
let result = tds
9999
.next()
100-
.ok_or_else(|| anyhow!("Failed to parse html."))?
100+
.context("Failed to parse html.")?
101101
.text()
102102
.next()
103-
.ok_or_else(|| anyhow!("Failed to parse html."))?
103+
.context("Failed to parse html.")?
104104
.to_owned();
105105

106106
let execution_time = tds
@@ -115,13 +115,13 @@ pub(super) fn scrape(html_text: &str, contest_id: &str) -> Result<Vec<AtCoderSub
115115
Some(href) => re.is_match(href),
116116
None => false,
117117
})
118-
.ok_or_else(|| anyhow!("Failed to parse html."))?
118+
.context("Failed to parse html.")?
119119
.value()
120120
.attr("href")
121-
.ok_or_else(|| anyhow!("Failed to parse html."))?
121+
.context("Failed to parse html.")?
122122
.rsplit('/')
123123
.next()
124-
.ok_or_else(|| anyhow!("Failed to parse html."))?
124+
.context("Failed to parse html.")?
125125
.trim()
126126
.parse::<u64>()?;
127127
Ok(AtCoderSubmission {

atcoder-problems-backend/atcoder-client/src/util.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use anyhow::{anyhow, Result};
1+
use anyhow::{anyhow, Context, Result};
22

33
use serde::de::DeserializeOwned;
44

@@ -30,10 +30,10 @@ pub(crate) async fn get_json<T: DeserializeOwned>(url: &str) -> Result<T> {
3030
.header("accept", "application/json")
3131
.send()
3232
.await
33-
.map_err(|_| anyhow!("Failed to get json from {}", url))?
33+
.with_context(|| format!("Failed to get json from {}", url))?
3434
.json::<T>()
3535
.await
36-
.map_err(|_| anyhow!("Failed to parse json from {}", url))
36+
.with_context(|| format!("Failed to parse json from {}", url))
3737
}
3838

3939
pub trait Problem {

0 commit comments

Comments
 (0)