From 57cb2bcabae6da906030af3f6f64928af0ce1e19 Mon Sep 17 00:00:00 2001 From: kenkoooo Date: Wed, 26 Jun 2019 16:49:53 +0900 Subject: [PATCH] Resolved #207 --- .../src/sql/problems_submissions.rs | 56 ++++++++++++++----- .../tests/test_problems_submissions.rs | 23 ++++++-- 2 files changed, 61 insertions(+), 18 deletions(-) diff --git a/atcoder-problems-backend/src/sql/problems_submissions.rs b/atcoder-problems-backend/src/sql/problems_submissions.rs index b1ca4a64d..d4bffa15a 100644 --- a/atcoder-problems-backend/src/sql/problems_submissions.rs +++ b/atcoder-problems-backend/src/sql/problems_submissions.rs @@ -1,5 +1,5 @@ use crate::sql::models::Submission; -use crate::sql::schema::{fastest, first, shortest, submissions}; +use crate::sql::schema::{contests, fastest, first, shortest, submissions}; use diesel; use diesel::dsl::*; use diesel::pg::upsert::excluded; @@ -59,30 +59,51 @@ pub trait ProblemsSubmissionUpdater { impl ProblemsSubmissionUpdater for PgConnection { fn update_submissions_of_problems(&self, ac_submissions: &[Submission]) -> QueryResult { - info!("Updating shortest submissions..."); - update_shortest_submissions(self, ac_submissions)?; + let contests: BTreeMap = contests::table + .select((contests::id, contests::start_epoch_second)) + .load::<(String, i64)>(self)? + .into_iter() + .collect::>(); + + let f = |s: &&Submission| { + contests + .get(&s.contest_id) + .filter(|&&start| start < s.epoch_second) + .is_some() + }; info!("Updating first submissions..."); - update_first_submissions(self, ac_submissions)?; + update_first_submissions(self, ac_submissions, f)?; + + info!("Updating shortest submissions..."); + update_shortest_submissions(self, ac_submissions, f)?; info!("Updating fastest submissions..."); - update_fastest_submissions(self, ac_submissions) + update_fastest_submissions(self, ac_submissions, f) } } -fn update_first_submissions( +fn update_first_submissions( conn: &PgConnection, ac_submissions: &[Submission], -) -> QueryResult { + f: F, +) -> QueryResult +where + F: Fn(&&Submission) -> bool, +{ let records = load_records!(first, conn, id: i64)?; - let values = update_aggregation(&records, ac_submissions.iter(), |s| s.id); + let values = update_aggregation(&records, ac_submissions.iter().filter(f), |s| s.id); upsert_values!(first, values, conn) } -fn update_fastest_submissions( +fn update_fastest_submissions( conn: &PgConnection, ac_submissions: &[Submission], -) -> QueryResult { + f: F, +) -> QueryResult +where + F: Fn(&&Submission) -> bool, +{ type Opi32 = Option; let records = load_records!(fastest, conn, execution_time: Opi32)? .into_iter() @@ -92,18 +113,25 @@ fn update_fastest_submissions( .collect::>(); let values = update_aggregation( &records, - ac_submissions.iter().filter(|s| s.execution_time.is_some()), + ac_submissions + .iter() + .filter(|s| s.execution_time.is_some()) + .filter(f), |s| s.execution_time.unwrap(), ); upsert_values!(fastest, values, conn) } -fn update_shortest_submissions( +fn update_shortest_submissions( conn: &PgConnection, ac_submissions: &[Submission], -) -> QueryResult { + f: F, +) -> QueryResult +where + F: Fn(&&Submission) -> bool, +{ let records = load_records!(shortest, conn, length: i32)?; - let values = update_aggregation(&records, ac_submissions.iter(), |s| s.length); + let values = update_aggregation(&records, ac_submissions.iter().filter(f), |s| s.length); upsert_values!(shortest, values, conn) } diff --git a/atcoder-problems-backend/tests/test_problems_submissions.rs b/atcoder-problems-backend/tests/test_problems_submissions.rs index de2470c9d..1ede9762e 100644 --- a/atcoder-problems-backend/tests/test_problems_submissions.rs +++ b/atcoder-problems-backend/tests/test_problems_submissions.rs @@ -44,10 +44,24 @@ fn insert_submissions(conn: &PgConnection, submissions: &[Submission]) { #[test] fn test_problem_info_aggregator() { + use diesel::connection::SimpleConnection; + + fn setup_contests() -> PgConnection { + let conn = utils::connect_to_test_sql(); + conn.batch_execute( + r#" + INSERT INTO contests (id, start_epoch_second, duration_second, title, rate_change) VALUES + ('contest1', 0, 0, '', ''), ('contest2', 0, 0, '', ''); + "#, + ) + .unwrap(); + conn + } let submissions1 = vec![Submission { id: 1, problem_id: "problem1".to_owned(), contest_id: "contest1".to_owned(), + epoch_second: 10, length: 20, execution_time: Some(10), ..Default::default() @@ -56,13 +70,14 @@ fn test_problem_info_aggregator() { id: 2, problem_id: "problem1".to_owned(), contest_id: "contest2".to_owned(), + epoch_second: 10, length: 10, execution_time: Some(10), ..Default::default() }]; { - let conn = utils::connect_to_test_sql(); + let conn = setup_contests(); conn.update_submissions_of_problems(&submissions1).unwrap(); insert_submissions(&conn, &submissions1); @@ -81,7 +96,7 @@ fn test_problem_info_aggregator() { assert_eq!(first[0].2, submissions1[0].id); } { - let conn = utils::connect_to_test_sql(); + let conn = setup_contests(); conn.update_submissions_of_problems(&submissions2).unwrap(); insert_submissions(&conn, &submissions2); @@ -101,7 +116,7 @@ fn test_problem_info_aggregator() { } { - let conn = utils::connect_to_test_sql(); + let conn = setup_contests(); conn.update_submissions_of_problems(&submissions1).unwrap(); insert_submissions(&conn, &submissions1); let shortest = get_shortest(&conn); @@ -120,7 +135,7 @@ fn test_problem_info_aggregator() { } { - let conn = utils::connect_to_test_sql(); + let conn = setup_contests(); conn.update_submissions_of_problems(&submissions2).unwrap(); insert_submissions(&conn, &submissions2);