Skip to content

Commit

Permalink
V0.3.1 (#77)
Browse files Browse the repository at this point in the history
* fix: drain_filter to extract_if

* feat: submaps (aka respawn maps)

- Submaps are collections of territories within regions of a map
- Respawn maps are implemented through submaps of the main map;
  currently submap id 0 is the main map and submap id 1 is the respawn
  map
- For respawn, the order of execution is as follows:
1. We process submap 0 (the main map) as normal
2. We determine which team(s) were eliminated on the main map and which
   have not yet used any respawns (teams.respawn_count < 1)
3. If any teams have previously been on submap id 1 but are now present
   on submap 0,  then we discard any turns made on submap id 1 by
   players on those teams
4. We process submap 1 (the secondary map), assigning the protected
   territories of any team which has succesfully returned to submap 0 to
   the NCAA (team id 0)
5. We randomly shuffle the eligible eliminated teams
6. We take all submap 1 territories owned by NCAA and add them to a pool
   of re-assignable territories
7. We take all teams that own more than one territory on submap 1 and
   select all but one of their territories to add to the pool of
   re-assignable territories randomly (but all such territories will be
   placed after any NCAA territories to ensure NCAA territories are
   exhausted first)
8. We reassign the territories from the re-assignable pool until either
   it is exhausted or all respawn-eligible teams have recevied a single
   territory
9. We merge all results from all submaps and write it to the database

* fix: update auth to use territory ownership as sot

* fix: minor bugs

* fix: lints

* fix: back to green

* chore: clippies
  • Loading branch information
mautamu authored Mar 17, 2024
1 parent 58986b2 commit 6345cfb
Show file tree
Hide file tree
Showing 16 changed files with 1,572 additions and 851 deletions.
1,793 changes: 1,062 additions & 731 deletions Cargo.lock

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ jsonwebtoken = "8.0.1"
rand = {version = "0.8", features = ["std"]}
rand_chacha="0.3"
reqwest = { version = "0.11.8", default-features = false, features = ["json", "rustls-tls"] }
rocket = {version = "0.5.0-rc.3", features = ["secrets", "json"] }
rocket = {version = "0.5.0-rc.4", features = ["secrets", "json"] }
rocket_sync_db_pools = {version = "0.1.0-rc.3", features=["diesel_postgres_pool"]}
rocket_oauth2 = {git = "https://github.com/mautamu/rocket_oauth2", branch="next", features = ["hyper_rustls_adapter"]}
okapi = {version = "0.7.0-rc.1" }
Expand Down
2 changes: 1 addition & 1 deletion src/db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */

use rocket_sync_db_pools::{database, diesel};
use rocket_sync_db_pools::database;
#[database("postgres_global")]
pub struct DbConn(diesel::PgConnection);
38 changes: 25 additions & 13 deletions src/model/auth/route.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
use crate::db::DbConn;
use crate::model::reddit::route::{audit_trail, Cip, UA};
use crate::model::{
Claims, CurrentStrength, Latest, Log, MoveInfo, MoveSub, PlayerWithTurnsAndAdditionalTeam,
Poll, PollResponse, Ratings, Stats, TurnInfo, UpdateUser, UserIdFast,
Claims, Latest, Log, MoveInfo, MoveSub, PlayerWithTurnsAndAdditionalTeam, Poll, PollResponse,
Ratings, Stats, TurnInfo, UpdateUser, UserIdFast,
};
use crate::schema::{
cfbr_stats, region_ownership, territory_adjacency, territory_ownership, turns, users,
Expand Down Expand Up @@ -71,6 +71,20 @@ pub(crate) async fn me(
}
}

pub(crate) fn has_territories(
turn_id: &i32,
team_id: &i32,
conn: &mut PgConnection,
) -> Result<bool, diesel::result::Error> {
use diesel::dsl::count;
Ok(territory_ownership::table
.select(count(territory_ownership::id))
.filter(territory_ownership::turn_id.eq(turn_id))
.filter(territory_ownership::owner_id.eq(team_id))
.first::<i64>(conn)?
> 0)
}

#[get("/join?<team>", rank = 1)]
pub(crate) async fn join_team(
team: i32,
Expand Down Expand Up @@ -100,12 +114,14 @@ pub(crate) async fn join_team(

// Does the team they want to join have territories?
// check that team has territories
let has_territories: bool = conn
.run(move |connection| CurrentStrength::load_id(team, connection))
let latest = conn
.run(Latest::latest)
.await
.map_err(|_| crate::Error::BadRequest {})?
.territories
> 0;
.map_err(|_| crate::Error::InternalServerError {})?;

let has_territories: bool = conn
.run(move |c| has_territories(&latest.id, &team, c))
.await?;
// If user has no team (and thus no active_team), then allow them to join anything
if users.active_team.unwrap_or_default().name.is_some() {
return std::result::Result::Err(crate::Error::BadRequest {});
Expand Down Expand Up @@ -284,7 +300,7 @@ pub(crate) async fn make_move<'v>(
let v2_verif = match &movesub.token_v2 {
None => false,
Some(mv_tv2) => {
if mv_tv2 == "" {
if mv_tv2.is_empty() {
return std::result::Result::Ok(Json(StatusWrapper {
code: 4004,
message: "Captcha required.".to_string(),
Expand All @@ -306,11 +322,7 @@ pub(crate) async fn make_move<'v>(
dbg!(e);
crate::Error::InternalServerError {}
})?;
if r_v2_result.score > 0.5 {
true
} else {
false
}
r_v2_result.score > 0.5
}
};

Expand Down
8 changes: 4 additions & 4 deletions src/model/captchasvc/model.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,10 @@ impl Captchas {
.select((captchas::title, captchas::content, captchas::creation))
.first::<Captchas>(conn)?;
true_content.delete(conn)?;
Ok(
true_content.creation.timestamp() - Utc::now().naive_utc().timestamp() < 600
&& content == true_content.content,
)
Ok(true_content.creation.and_utc().timestamp()
- Utc::now().naive_utc().and_utc().timestamp()
< 600
&& content == true_content.content)
}

pub fn delete(&self, conn: &mut PgConnection) -> Result<usize, diesel::result::Error> {
Expand Down
21 changes: 11 additions & 10 deletions src/model/discord/route.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ pub(crate) fn login(oauth2: OAuth2<DiscordUserInfo>, cookies: &CookieJar<'_>) ->
#[allow(dead_code)]
#[get("/logout")]
pub(crate) async fn logout(cookies: &CookieJar<'_>) -> Flash<Redirect> {
cookies.remove_private(Cookie::named("jwt"));
cookies.remove_private(Cookie::named("username"));
cookies.remove_private(Cookie::build("jwt"));
cookies.remove_private(Cookie::build("username"));
Flash::success(Redirect::to("/"), "Successfully logged out.")
//TODO: Implement a deletion call to reddit.
}
Expand Down Expand Up @@ -54,10 +54,13 @@ pub(crate) async fn callback(
match userinfo {
Ok(user_info) => {
let new_user = UpsertableUser {
uname: String::from(user_info.name()),
uname: user_info.name(),
platform: String::from("discord"),
};
match conn.run(move |c| UpsertableUser::upsert(new_user, c)).await {
match conn
.run(move |c| UpsertableUser::upsert(&new_user, c))
.await
{
Ok(_n) => {
let name = user_info.name();
match conn
Expand All @@ -76,22 +79,20 @@ pub(crate) async fn callback(
exp: timestamp,
};
cookies.add_private(
Cookie::build("username", user_info.name())
Cookie::build(("username", user_info.name()))
.same_site(SameSite::Lax)
.domain(config.settings.base_url.clone())
.path("/")
.max_age(Duration::hours(168))
.finish(),
.max_age(Duration::hours(168)),
);
match Claims::put(config.settings.cookie_key.as_bytes(), new_claims) {
Ok(s) => {
cookies.add_private(
Cookie::build("jwt", s)
Cookie::build(("jwt", s))
.same_site(SameSite::Lax)
.domain(config.settings.base_url.clone())
.path("/")
.max_age(Duration::hours(720))
.finish(),
.max_age(Duration::hours(720)),
);
std::result::Result::Ok(Redirect::to("/"))
}
Expand Down
20 changes: 10 additions & 10 deletions src/model/player/model.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
use crate::model::team::TeamWithColors;
use crate::model::turn::{LastTurn, PastTurn};
use crate::model::{Colors, Ratings, Stats, Team, Turn, UserId};
use crate::model::{Colors, Ratings, Stats, Team, UserId};
use crate::schema::{award_info, awards, moves, past_turns, teams, territories, turninfo, users};
use diesel::prelude::*;
use diesel::result::Error;
Expand All @@ -20,15 +20,15 @@ pub struct Award {
info: String,
}

#[derive(Serialize)]
pub(crate) struct Player {
pub(crate) id: i32,
pub(crate) name: String,
pub(crate) team: Team,
pub(crate) ratings: Ratings,
pub(crate) stats: Stats,
pub(crate) turns: Vec<Turn>,
}
// #[derive(Serialize)]
// pub(crate) struct Player {
// pub(crate) id: i32,
// pub(crate) name: String,
// pub(crate) team: Team,
// pub(crate) ratings: Ratings,
// pub(crate) stats: Stats,
// pub(crate) turns: Vec<Turn>,
// }

#[derive(Queryable, Serialize, Deserialize, JsonSchema)]
/// A brief summary of a Player on a Team to display on the Team's page
Expand Down
2 changes: 1 addition & 1 deletion src/model/ratings/model.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ impl Ratings {
let gameTurns = Self::fromarr(stat.gameTurns, [0, 5, 10, 25, 40]);
let mvps = Self::fromarr(stat.mvps, [0, 1, 5, 10, 25]);
let streak = Self::fromarr(stat.streak, [0, 3, 5, 10, 25]);
let mut numbers = vec![totalTurns, gameTurns, mvps, streak]; // awards
let mut numbers = [totalTurns, gameTurns, mvps, streak]; // awards
numbers.sort_unstable();
let mid = ((numbers[1] as f32 + numbers[2] as f32) / 2_f32).round() as i32;
let overall: i32 = mid;
Expand Down
26 changes: 13 additions & 13 deletions src/model/reddit/route.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ pub(crate) fn login(oauth2: OAuth2<RedditUserInfo>, cookies: &CookieJar<'_>) ->

#[get("/logout")]
pub(crate) async fn logout(cookies: &CookieJar<'_>) -> Flash<Redirect> {
cookies.remove_private(Cookie::named("jwt"));
cookies.remove_private(Cookie::named("username"));
cookies.remove_private(Cookie::build("jwt"));
cookies.remove_private(Cookie::build("username"));
Flash::success(Redirect::to("/"), "Successfully logged out.")
//TODO: Implement a deletion call to reddit.
}
Expand Down Expand Up @@ -75,14 +75,15 @@ pub(crate) async fn callback(

let uname_ban_chk = uname.clone();
// We also want to ensure the user has a validated email with Reddit:
if !user_info
let has_verified_email = user_info
.get("has_verified_email")
.unwrap_or_else(|| {
dbg!("Error serializing user email check");
&serde_json::json!(false)
})
.as_bool()
.unwrap_or(false)
.unwrap_or(false);
if !has_verified_email
&& conn
.run(move |c| {
bans::table
Expand Down Expand Up @@ -115,15 +116,16 @@ pub(crate) async fn callback(

dbg!(user_info.get("is_suspended"));

if user_info
let is_suspended = user_info
.get("is_suspended")
.unwrap_or_else(|| {
dbg!("Error: unable to know if user was suspended");
&serde_json::json!(false)
})
.as_bool()
.unwrap_or(false)
{
.unwrap_or(false);

if is_suspended {
conn.run(move |c| UpsertableUser::flag(uname_2_int, c))
.await
.map_err(|e| {
Expand Down Expand Up @@ -160,25 +162,23 @@ pub(crate) async fn callback(
// Now we build a private `Cookie` to return to the user
// that contains the user's username (which is used in some low-sec processes)
cookies.add_private(
Cookie::build("username", uname)
Cookie::build(("username", uname))
.same_site(SameSite::Lax)
.domain(config.settings.base_url.clone())
.path("/")
.max_age(Duration::hours(720))
.finish(),
.max_age(Duration::hours(720)),
);

// Now we build the private JWT `Cookie` to return to the user
// that contains more information and is used in secure processes.
match Claims::put(config.settings.cookie_key.as_bytes(), new_claims) {
Ok(s) => {
cookies.add_private(
Cookie::build("jwt", s)
Cookie::build(("jwt", s))
.same_site(SameSite::Lax)
.domain(config.settings.base_url.clone())
.path("/")
.max_age(Duration::hours(720))
.finish(),
.max_age(Duration::hours(720)),
);
std::result::Result::Ok(Redirect::to("/"))
}
Expand Down
1 change: 0 additions & 1 deletion src/model/region/model.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ use crate::schema::regions;
use diesel::prelude::*;

use schemars::JsonSchema;
use std::result::Result;

#[derive(Serialize, Queryable, Deserialize, JsonSchema)]
pub(crate) struct Region {
Expand Down
26 changes: 13 additions & 13 deletions src/model/stats/model.rs
Original file line number Diff line number Diff line change
Expand Up @@ -171,19 +171,19 @@ impl CurrentStrength {
.first::<CurrentStrength>(conn)
}

pub(crate) fn load_id(team: i32, conn: &mut PgConnection) -> Result<CurrentStrength, Error> {
statistics::table
.select((
statistics::tname,
statistics::playercount,
statistics::merccount,
statistics::starpower,
statistics::territorycount,
))
.filter(statistics::team.eq(team))
.order(statistics::turn_id.desc())
.first::<CurrentStrength>(conn)
}
// pub(crate) fn load_id(team: i32, conn: &mut PgConnection) -> Result<CurrentStrength, Error> {
// statistics::table
// .select((
// statistics::tname,
// statistics::playercount,
// statistics::merccount,
// statistics::starpower,
// statistics::territorycount,
// ))
// .filter(statistics::team.eq(team))
// .order(statistics::turn_id.desc())
// .first::<CurrentStrength>(conn)
// }
/* statistics::table
.select((
statistics::tname,
Expand Down
1 change: 0 additions & 1 deletion src/model/territory/model.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ use diesel::prelude::*;

use schemars::JsonSchema;
use serde_json::Value;
use std::result::Result;

#[derive(Serialize, Queryable, Deserialize, JsonSchema)]
pub(crate) struct Territory {
Expand Down
18 changes: 9 additions & 9 deletions src/model/turn/model.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,15 @@ use diesel::result::Error;
use schemars::JsonSchema;
use serde_json::Value;

#[derive(Serialize)]
pub(crate) struct Turn {
pub(crate) season: i32,
pub(crate) day: i32,
pub(crate) stars: i32,
pub(crate) mvp: bool,
pub(crate) territory: String,
pub(crate) team: String,
}
// #[derive(Serialize)]
// pub(crate) struct Turn {
// pub(crate) season: i32,
// pub(crate) day: i32,
// pub(crate) stars: i32,
// pub(crate) mvp: bool,
// pub(crate) territory: String,
// pub(crate) team: String,
// }

#[derive(Queryable, Serialize, Deserialize, JsonSchema)]
pub(crate) struct LastTurn {
Expand Down
Loading

0 comments on commit 6345cfb

Please sign in to comment.