diff --git a/src/broadcaster.rs b/src/broadcaster.rs index 5082e5847a90cd3617212298d600114c2ca48bc9..72f148cbc4d37b4d18b4d371ae78f197932ac33a 100644 --- a/src/broadcaster.rs +++ b/src/broadcaster.rs @@ -60,7 +60,7 @@ impl Broadcaster { fn remove_stale_clients(&mut self) { let mut ok_clients = Vec::new(); - for client in self.clients.iter() { + for client in &self.clients { let result = client.clone().try_send(Bytes::from("data: ping\n\n")); if let Ok(()) = result { @@ -73,7 +73,7 @@ impl Broadcaster { pub fn new_client(&mut self) -> Client { let (tx, rx) = channel(100); - tx.clone() + tx .try_send(Bytes::from("data: connected\n\n")) .unwrap(); @@ -84,7 +84,7 @@ impl Broadcaster { pub fn send(&self, event: &str, msg: &str) { let msg = Bytes::from(["event:", event, "\n", "data: ", msg, "\n\n"].concat()); - for client in self.clients.iter() { + for client in &self.clients { client.clone().try_send(msg.clone()).unwrap_or(()); } } diff --git a/src/import_contest.rs b/src/import_contest.rs index bbeac6228aba2fc3ef4dd38de86548b1e47e7c19..ddc42ff281de239c4798dbdff98ccca47845577c 100644 --- a/src/import_contest.rs +++ b/src/import_contest.rs @@ -368,9 +368,11 @@ fn read_string_from_zip_by_name<R: Read + Seek>( pub use xml::contest::Contest; pub use xml::problem::Problem; +pub type ContestProblemsZipReport<R> = (Contest, Vec<(String, Problem)>, ZipArchive<R>, String); + pub fn import_file<R: Read + Seek>( reader: R, -) -> Result<(Contest, Vec<(String, Problem)>, ZipArchive<R>, String), ImportContestError> { +) -> Result<ContestProblemsZipReport<R>, ImportContestError> { let mut report = String::new(); let mut zip = ZipArchive::new(reader)?; @@ -389,7 +391,7 @@ pub fn import_file<R: Read + Seek>( for name in zip .file_names() .filter(|name| PROBLEM_XML_PATH_REGEX.is_match(name)) - .map(|s| s.into()) + .map(std::convert::Into::into) .collect::<Vec<String>>() { println!("{}", name); @@ -400,7 +402,7 @@ pub fn import_file<R: Read + Seek>( report.push_str("\n---\n"); report.push_str(&read_string_from_zip_by_name(&mut zip, &name)?); report.push_str("---\n"); - report.push_str("\n"); + report.push('\n'); problems.push(( PROBLEM_XML_PATH_REGEX @@ -417,13 +419,13 @@ pub fn import_file<R: Read + Seek>( Ok((contest, problems, zip, report)) } -pub fn format_width(pattern_path: &String, i: usize) -> String { +#[must_use] pub fn format_width(pattern_path: &str, i: usize) -> String { lazy_static! { static ref WIDTH_REGEX: Regex = Regex::new(r"%0(\d)+d").unwrap(); } WIDTH_REGEX .replace(pattern_path, |caps: &Captures| { - return format!("{:0width$}", i, width = caps[1].parse().unwrap()); + format!("{:0width$}", i, width = caps[1].parse().unwrap()) }) .into() } diff --git a/src/main.rs b/src/main.rs index efbbbc092e0744e23ef0fb4eb8173aa193da51e3..1d4a5216ed1ae37670400b89bc879a4e3798e57e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -98,11 +98,11 @@ fn create_job_from_submission(submission: Submission, metadata: ProblemByContest memory_limit_kib: metadata.memory_limit_bytes / 1_024, which: Some(job::Which::Judgement(job::Judgement { - source_text: submission.source_text.into(), + source_text: submission.source_text, test_count: metadata.test_count, - test_pattern: format!("./{}/{}", metadata.id, metadata.test_pattern).into(), + test_pattern: format!("./{}/{}", metadata.id, metadata.test_pattern), checker_language: metadata.checker_language, - checker_source_path: format!("./{}/{}", metadata.id, metadata.checker_path).into(), + checker_source_path: format!("./{}/{}", metadata.id, metadata.checker_path), })), } } @@ -172,7 +172,7 @@ async fn main() -> Result<(), Box<dyn Error>> { .app_data(Data::new(job_sender_data.clone())) .app_data(Data::new(job_result_sender_data.clone())) .app_data(Data::new(languages_data.clone())) - .app_data(Data::new(tz.clone())) + .app_data(Data::new(tz)) .wrap(ErrorHandlers::new().handler(http::StatusCode::UNAUTHORIZED, pages::render_401)) .wrap(ErrorHandlers::new().handler(http::StatusCode::BAD_REQUEST, pages::render_400)) .wrap( @@ -237,7 +237,7 @@ async fn main() -> Result<(), Box<dyn Error>> { let update_dabase_sender = job_result_sender.clone(); log::info!("Starting at {}", addr); tokio::try_join!( - server.run().map_err(|e| Into::<Box<dyn Error>>::into(e)), + server.run().map_err(Into::<Box<dyn Error>>::into), Server::builder() .add_service(JobQueueServer::new(JobQueuer { job_receiver, @@ -245,12 +245,10 @@ async fn main() -> Result<(), Box<dyn Error>> { languages, })) .serve(addr) - .map_err(|e| Into::<Box<dyn Error>>::into(e)), - update_database(update_dabase_sender.subscribe(), pool.clone()).map_err(|e| Into::< + .map_err(Into::<Box<dyn Error>>::into), + update_database(update_dabase_sender.subscribe(), pool.clone()).map_err(Into::< Box<dyn Error>, - >::into( - e - )) + >::into) )?; Ok(()) diff --git a/src/models/submission.rs b/src/models/submission.rs index ac095c5d0eb2b546491bc2a1a6566017d03970b1..5ecad3644972fb7d10d7d510aa56bbec253f3c41 100644 --- a/src/models/submission.rs +++ b/src/models/submission.rs @@ -24,6 +24,7 @@ pub struct Submission { pub failed_test: Option<i32>, } +#[allow(clippy::type_complexity)] const SUBMISSION_COLUMNS: ( submission::uuid, submission::verdict, diff --git a/src/models/user.rs b/src/models/user.rs index 02d477079f77de182a36f63e06fde432d01aadd2..510da99613799eb0003bfba8aea11c71e3d4a19e 100644 --- a/src/models/user.rs +++ b/src/models/user.rs @@ -76,7 +76,7 @@ pub fn check_matching_password( { Some(user) => Ok( if argon2::verify_encoded(&user.hashed_password, password.as_bytes())? { - PasswordMatched::PasswordMatches(get_user_by_name(connection, &name)?) + PasswordMatched::PasswordMatches(get_user_by_name(connection, name)?) } else { PasswordMatched::PasswordDoesntMatch }, diff --git a/src/pages/create_contest.rs b/src/pages/create_contest.rs index aaeb9c0e9a81ffe8499296a3d6865d1d14dbfbcf..a96705535e378486e4b8eaffcfa038307f602467 100644 --- a/src/pages/create_contest.rs +++ b/src/pages/create_contest.rs @@ -94,7 +94,7 @@ async fn create_contest( let polygon_zip = form .polygon_zip - .ok_or(PageError::Validation("Arquivo não informado".into()))?; + .ok_or_else(|| PageError::Validation("Arquivo não informado".into()))?; let imported = import_contest::import_file(polygon_zip) .map_err(|e| PageError::Validation(format!("Não foi possível importar: {}", e)))?; let mut connection = pool.get()?; @@ -124,7 +124,7 @@ async fn create_contest( fn polygon_url_to_id_without_revision(url: String) -> String { url.replace("https://polygon.codeforces.com/", "polygon.") - .replace("/", ".") + .replace('/', ".") } let problem_label: HashMap<String, String> = @@ -176,7 +176,7 @@ async fn create_contest( let mut filenames = zip .file_names() .filter(|name| files_regex.is_match(name)) - .map(|s| s.to_string()) + .map(std::string::ToString::to_string) .collect::<Vec<_>>(); filenames.sort(); for name in filenames { @@ -188,7 +188,7 @@ async fn create_contest( .as_str(); let data_path = format!("/data/{}/{}", problem_id, relative_path); - if name.ends_with("/") { + if name.ends_with('/') { info!("Creating directory {} into {}", name, data_path); create_dir_all(data_path)?; continue; @@ -211,7 +211,7 @@ async fn create_contest( .solution .iter() .find(|s| s.tag == "main") - .ok_or(PageError::Validation("No main solution".into()))? + .ok_or_else(|| PageError::Validation("No main solution".into()))? .source; let problem = problem::upsert_problem( @@ -268,17 +268,17 @@ async fn create_contest( .join(import_contest::format_width(&problem.test_pattern, i)); info!("Extracting {:#?} from zip", test_name); std::io::copy( - &mut zip.by_name(&test_name.to_str().unwrap())?, + &mut zip.by_name(test_name.to_str().unwrap())?, &mut File::create(PathBuf::from("/data/").join(&test_path))?, )?; } else { - let cmd: Vec<_> = test.cmd.as_ref().unwrap().split(" ").collect(); + let cmd: Vec<_> = test.cmd.as_ref().unwrap().split(' ').collect(); let run_stats = language::run_cached( &job_sender, &job_result_sender, &"cpp.17.g++".into(), - format!("./{}/files/{}.cpp", problem.id, cmd.get(0).unwrap()), - cmd[1..].iter().map(|s| s.clone().into()).collect(), + format!("./{}/files/{}.cpp", problem.id, cmd.first().unwrap()), + cmd[1..].iter().map(|s| <&str>::clone(s).into()).collect(), None, Some(test_path.clone()), problem.memory_limit_bytes / 1_024, @@ -325,9 +325,9 @@ async fn create_contest( problem.id, problem.main_solution_path )))?, problem.test_count, - format!("./{}/{}", problem.id, problem.test_pattern).into(), + format!("./{}/{}", problem.id, problem.test_pattern), problem.checker_language, - format!("./{}/{}", problem.id, problem.checker_path).into(), + format!("./{}/{}", problem.id, problem.checker_path), problem.memory_limit_bytes / 1_024, problem.time_limit_ms, ) @@ -340,7 +340,7 @@ async fn create_contest( contest::NewContestProblems { label: problem_label .get(&problem_id_without_revision) - .ok_or(PageError::Validation( + .ok_or_else(|| PageError::Validation( "Arquivo não contém problemas listados".into(), ))? .to_string() diff --git a/src/pages/create_submission.rs b/src/pages/create_submission.rs index fdd83933a13759db5987e6ee75e226ad73c176db..1ad7ed3cc5fc7dbbdc4caa89263ad216b9a9b290 100644 --- a/src/pages/create_submission.rs +++ b/src/pages/create_submission.rs @@ -28,7 +28,7 @@ async fn create_submission( languages .get(&form.language) - .ok_or(PageError::Validation("Linguagem inexistente".into()))?; + .ok_or_else(|| PageError::Validation("Linguagem inexistente".into()))?; if !logged_user.is_admin && form.language != "cpp.17.g++" { return Err(PageError::Validation( @@ -66,9 +66,9 @@ async fn create_submission( which: Some(job::Which::Judgement(job::Judgement { source_text: (&form.source_text).into(), test_count: metadata.test_count, - test_pattern: format!("./{}/{}", metadata.id, metadata.test_pattern).into(), + test_pattern: format!("./{}/{}", metadata.id, metadata.test_pattern), checker_language: metadata.checker_language, - checker_source_path: format!("./{}/{}", metadata.id, metadata.checker_path).into(), + checker_source_path: format!("./{}/{}", metadata.id, metadata.checker_path), })), }) .await?; diff --git a/src/pages/get_contest_scoreboard_by_id.rs b/src/pages/get_contest_scoreboard_by_id.rs index 61c33dcc75d2a73b1acdb92952235a377c2e40d4..e2c55da2dfb896cc85215af2ef850cdf8163394a 100644 --- a/src/pages/get_contest_scoreboard_by_id.rs +++ b/src/pages/get_contest_scoreboard_by_id.rs @@ -42,13 +42,13 @@ async fn get_contest_scoreboard_by_id( let scores = problem::get_problems_by_contest_id_with_score(&mut connection, contest_id)?; let submissions = submission::get_submissions_user_by_contest(&mut connection, logged_user.id, contest_id)?; - let mut scores: Vec<_> = scores.into_iter().group_by(|e| e.user_name.as_ref().map(|s| s.clone())).into_iter().map(|(user_name, problems)| { + let mut scores: Vec<_> = scores.into_iter().group_by(|e| e.user_name.as_ref().cloned()).into_iter().map(|(user_name, problems)| { let problems: Vec<_> = problems.map(|p| get_formatted_problem_by_contest_with_score(&p, &contest)).collect(); Score { user_name, - solved_count: i64::try_from(problems.iter().filter(|p| p.first_ac_submission_time != "").count()).unwrap(), - penalty: problems.iter().filter(|p| p.first_ac_submission_time != "") + solved_count: i64::try_from(problems.iter().filter(|p| !p.first_ac_submission_time.is_empty()).count()).unwrap(), + penalty: problems.iter().filter(|p| !p.first_ac_submission_time.is_empty()) .map(|p| match p.first_ac_submission_minutes { Some(x) if x >= 0 => x, _ => 0, diff --git a/src/pages/get_problems.rs b/src/pages/get_problems.rs index 6050b7f7b5d989d5f4af90072c82e0bfaaf3040b..e07654ed9beb15008425bd98b49f3b2ff26e4187 100644 --- a/src/pages/get_problems.rs +++ b/src/pages/get_problems.rs @@ -36,7 +36,7 @@ pub async fn get_problems( label: p.label.clone(), memory_limit_mib: p.memory_limit_bytes / 1_024 / 1_024, time_limit: format!("{}", f64::from(p.time_limit_ms) / 1000.0) - .replacen(".", ",", 1), + .replacen('.', ",", 1), user_accepted_count: p.user_accepted_count, }) .collect(), diff --git a/src/pages/get_submissions.rs b/src/pages/get_submissions.rs index 69af7849a2925c4861c34436ea4121747fd18ee6..2fbaa90e248c0d03119f33a38a61bc25a04ea7d0 100644 --- a/src/pages/get_submissions.rs +++ b/src/pages/get_submissions.rs @@ -18,11 +18,11 @@ pub fn render_submissions( } render( - &hb, + hb, "submissions", &Context { base, - submissions: get_formatted_submissions(&tz, &submissions), + submissions: get_formatted_submissions(tz, &submissions), }, ) } diff --git a/src/pages/mod.rs b/src/pages/mod.rs index c2641a71d47bcbc2d2619280b7700ecccacd9dbc..cc9cec79fd07a33148e43a79a00c2ccb79e3a54f 100644 --- a/src/pages/mod.rs +++ b/src/pages/mod.rs @@ -107,19 +107,16 @@ fn get_formatted_problem_by_contest_with_score( Some(cs) => format_duration(t - cs), None => "*".into(), }) - .unwrap_or("".into()), + .unwrap_or_else(|| "".into()), first_ac_submission_minutes: p.first_ac_submission_instant.and_then(|t| { - match contest.start_instant { - Some(cs) => Some((t - cs).num_minutes()), - None => None, - } + contest.start_instant.map(|cs| (t - cs).num_minutes()) }), failed_submissions: p.failed_submissions, id: p.id, name: p.name.clone(), label: p.label.clone(), memory_limit_mib: p.memory_limit_bytes / 1_024 / 1_024, - time_limit: format!("{}", f64::from(p.time_limit_ms) / 1000.0).replacen(".", ",", 1), + time_limit: format!("{}", f64::from(p.time_limit_ms) / 1000.0).replacen('.', ",", 1), user_accepted_count: p.user_accepted_count, } } @@ -130,8 +127,7 @@ fn assert_contest_not_started( ) -> Result<(), PageError> { if contest .start_instant - .map(|s| s > Local::now().naive_utc()) - .unwrap_or(false) + .map_or(false, |s| s > Local::now().naive_utc()) && !logged_user.is_admin { return Err(PageError::Forbidden( @@ -162,20 +158,17 @@ fn format_utc_date_time(tz: &Tz, input: NaiveDateTime) -> String { fn get_formatted_submissions( tz: &Tz, - vec: &Vec<(Submission, ContestProblem, User)>, + vec: &[(Submission, ContestProblem, User)], ) -> Vec<FormattedSubmission> { vec.iter() .map(|(submission, contest_problem, user)| FormattedSubmission { uuid: (&submission.uuid).into(), verdict: submission .verdict - .as_ref() - .map(|s| String::from(s)) - .unwrap_or("WJ".into()) - .into(), + .as_ref().map_or_else(|| "WJ".into(), String::from), problem_label: contest_problem.label.clone(), submission_instant: format_utc_date_time(tz, submission.submission_instant), - error_output: submission.error_output.as_ref().map(|s| s.into()), + error_output: submission.error_output.as_ref().map(std::convert::Into::into), user_name: user.name.clone(), time_ms: submission.time_ms, memory: match submission.memory_kib { @@ -208,9 +201,9 @@ fn get_formatted_contest(tz: &Tz, contest: &Contest) -> FormattedContest { FormattedContest { id: contest.id, name: contest.name.clone(), - start_instant: contest.start_instant.map(|i| format_utc_date_time(&tz, i)), - end_instant: contest.end_instant.map(|i| format_utc_date_time(&tz, i)), - creation_instant: format_utc_date_time(&tz, contest.creation_instant), + start_instant: contest.start_instant.map(|i| format_utc_date_time(tz, i)), + end_instant: contest.end_instant.map(|i| format_utc_date_time(tz, i)), + creation_instant: format_utc_date_time(tz, contest.creation_instant), grade_ratio: contest.grade_ratio, grade_after_ratio: contest.grade_after_ratio, accepted_count: 0, @@ -225,9 +218,9 @@ fn get_formatted_contest_acs(tz: &Tz, contest: &ContestWithAcs) -> FormattedCont FormattedContest { id: contest.id, name: contest.name.clone(), - start_instant: contest.start_instant.map(|i| format_utc_date_time(&tz, i)), - end_instant: contest.end_instant.map(|i| format_utc_date_time(&tz, i)), - creation_instant: format_utc_date_time(&tz, contest.creation_instant), + start_instant: contest.start_instant.map(|i| format_utc_date_time(tz, i)), + end_instant: contest.end_instant.map(|i| format_utc_date_time(tz, i)), + creation_instant: format_utc_date_time(tz, contest.creation_instant), grade_ratio: contest.grade_ratio, grade_after_ratio: contest.grade_after_ratio, accepted_count: contest.accepted_count, @@ -245,7 +238,7 @@ fn get_formatted_contest_acs(tz: &Tz, contest: &ContestWithAcs) -> FormattedCont None => 0.0, }) ) - .replacen(".", ",", 1), + .replacen('.', ",", 1), None => "".into(), }, } diff --git a/src/pages/prelude.rs b/src/pages/prelude.rs index c65d78026103a20e7b81f01d821b162545a79a15..df74491c032bb5b21ae539894ac5e877b2ae69ee 100644 --- a/src/pages/prelude.rs +++ b/src/pages/prelude.rs @@ -150,9 +150,7 @@ pub fn redirect_to_referer(message: String, request: &HttpRequest) -> HttpRespon let referer = request .headers() .get("Referer") - .and_then(|h| h.to_str().ok()) - .map(|s| s.into()) - .unwrap_or(env::var("BASE_URL").expect("BASE_URL environment variable is not set")); + .and_then(|h| h.to_str().ok()).map_or_else(|| env::var("BASE_URL").expect("BASE_URL environment variable is not set"), std::convert::Into::into); FlashMessage::info(message).send(); HttpResponse::SeeOther() .append_header((header::LOCATION, HeaderValue::from_str(&referer).unwrap())) diff --git a/src/setup.rs b/src/setup.rs index c85a0e74dd0f945481aecdd72e91e2f44cac0e77..e1fba9967a8ae82f4df01b57360b98ee5a96d4d1 100644 --- a/src/setup.rs +++ b/src/setup.rs @@ -29,10 +29,10 @@ pub fn setup_admin(connection: &mut PgConnection) { .expect("Error saving new user"); } PasswordMatched::PasswordMatches(_) => { - info!("Admin already created and is using default password.",) + info!("Admin already created and is using default password.",); } PasswordMatched::PasswordDoesntMatch => { - info!("Admin already created and is not using the default password.",) + info!("Admin already created and is not using the default password.",); } } }