|
|
|
@ -1,13 +1,7 @@
|
|
|
|
|
use crate::model::{Division, Game, League, Period, Player};
|
|
|
|
|
use serde::{Deserialize, Serialize};
|
|
|
|
|
use sqlx::FromRow;
|
|
|
|
|
use sqlx::PgPool;
|
|
|
|
|
use crate::model::{
|
|
|
|
|
Player,
|
|
|
|
|
Game,
|
|
|
|
|
League,
|
|
|
|
|
Division,
|
|
|
|
|
Period,
|
|
|
|
|
};
|
|
|
|
|
use serde::{Serialize, Deserialize};
|
|
|
|
|
|
|
|
|
|
#[derive(FromRow, Deserialize, Serialize, Debug)]
|
|
|
|
|
pub struct TeamStats {
|
|
|
|
@ -17,7 +11,29 @@ pub struct TeamStats {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(FromRow, Deserialize, Serialize, Debug)]
|
|
|
|
|
pub struct IihfGameStats {
|
|
|
|
|
pub struct IihfStats {
|
|
|
|
|
pub team_name: String,
|
|
|
|
|
pub team_id: i32,
|
|
|
|
|
pub reg_wins: i32,
|
|
|
|
|
pub reg_losses: i32,
|
|
|
|
|
pub ot_wins: i32,
|
|
|
|
|
pub ot_losses: i32,
|
|
|
|
|
pub ties: i32,
|
|
|
|
|
pub points: i32,
|
|
|
|
|
}
|
|
|
|
|
#[derive(FromRow, Deserialize, Serialize, Debug)]
|
|
|
|
|
pub struct IihfStatsI64 {
|
|
|
|
|
pub team_name: String,
|
|
|
|
|
pub team_id: i32,
|
|
|
|
|
pub reg_wins: i64,
|
|
|
|
|
pub reg_losses: i64,
|
|
|
|
|
pub ot_wins: i64,
|
|
|
|
|
pub ot_losses: i64,
|
|
|
|
|
pub ties: i64,
|
|
|
|
|
pub points: i64,
|
|
|
|
|
}
|
|
|
|
|
#[derive(FromRow, Deserialize, Serialize, Debug)]
|
|
|
|
|
pub struct IihfPoints {
|
|
|
|
|
pub team_name: String,
|
|
|
|
|
pub team_id: i32,
|
|
|
|
|
pub points: i32,
|
|
|
|
@ -41,8 +57,7 @@ pub struct PlayerStats {
|
|
|
|
|
pub points: i64,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl Game {
|
|
|
|
|
pub async fn box_score(pool: &PgPool, id: i32) -> Result<Vec<PlayerStats>, sqlx::Error> {
|
|
|
|
|
pub async fn game_box_score(pool: &PgPool, game_id: i32) -> Result<Vec<PlayerStats>, sqlx::Error> {
|
|
|
|
|
let query = r#"
|
|
|
|
|
SELECT
|
|
|
|
|
COUNT(shots.id) AS points,
|
|
|
|
@ -50,7 +65,8 @@ impl Game {
|
|
|
|
|
COUNT(CASE WHEN shots.assistant = game_players.id OR shots.assistant_second = game_players.id THEN shots.id END) AS assists,
|
|
|
|
|
players.name
|
|
|
|
|
FROM game_players
|
|
|
|
|
JOIN players ON game_players.player = players.id
|
|
|
|
|
JOIN players
|
|
|
|
|
ON game_players.player = players.id
|
|
|
|
|
LEFT JOIN shots
|
|
|
|
|
ON shots.goal=true
|
|
|
|
|
AND (shots.shooter=game_players.id
|
|
|
|
@ -66,11 +82,11 @@ impl Game {
|
|
|
|
|
goals DESC;
|
|
|
|
|
"#;
|
|
|
|
|
sqlx::query_as::<_, PlayerStats>(query)
|
|
|
|
|
.bind(id)
|
|
|
|
|
.bind(game_id)
|
|
|
|
|
.fetch_all(pool)
|
|
|
|
|
.await
|
|
|
|
|
}
|
|
|
|
|
pub async fn goals(pool: &PgPool, id: i32) -> Result<Vec<GoalDetails>, sqlx::Error> {
|
|
|
|
|
pub async fn game_goals(pool: &PgPool, game_id: i32) -> Result<Vec<GoalDetails>, sqlx::Error> {
|
|
|
|
|
sqlx::query_as::<_, GoalDetails>(
|
|
|
|
|
r#"
|
|
|
|
|
SELECT
|
|
|
|
@ -104,78 +120,23 @@ impl Game {
|
|
|
|
|
ORDER BY
|
|
|
|
|
periods.period_type ASC,
|
|
|
|
|
shots.period_time DESC;
|
|
|
|
|
"#)
|
|
|
|
|
.bind(id)
|
|
|
|
|
"#,
|
|
|
|
|
)
|
|
|
|
|
.bind(game_id)
|
|
|
|
|
.fetch_all(pool)
|
|
|
|
|
.await
|
|
|
|
|
}
|
|
|
|
|
pub async fn iihf_stats(pool: &PgPool, game_id: i32) -> Result<Vec<IihfGameStats>, sqlx::Error> {
|
|
|
|
|
pub async fn game_iihf_stats(pool: &PgPool, game_id: i32) -> Result<Vec<IihfStats>, sqlx::Error> {
|
|
|
|
|
let query = r#"
|
|
|
|
|
SELECT
|
|
|
|
|
(CASE WHEN
|
|
|
|
|
COUNT(CASE WHEN shots.goal=true
|
|
|
|
|
AND scoring_team.id=teams.id
|
|
|
|
|
THEN shots.id
|
|
|
|
|
END) >
|
|
|
|
|
COUNT(CASE WHEN shots.goal=true
|
|
|
|
|
AND scoring_team.id!=teams.id
|
|
|
|
|
THEN shots.id
|
|
|
|
|
END)
|
|
|
|
|
AND (SELECT COUNT(id) FROM periods WHERE periods.game=games.id) <= 3
|
|
|
|
|
THEN 1
|
|
|
|
|
ELSE 0
|
|
|
|
|
END) AS reg_wins,
|
|
|
|
|
(CASE WHEN
|
|
|
|
|
COUNT(CASE WHEN shots.goal=true
|
|
|
|
|
AND scoring_team.id=teams.id
|
|
|
|
|
THEN shots.id
|
|
|
|
|
END) <
|
|
|
|
|
COUNT(CASE WHEN shots.goal=true
|
|
|
|
|
AND scoring_team.id!=teams.id
|
|
|
|
|
THEN shots.id
|
|
|
|
|
END)
|
|
|
|
|
AND (SELECT COUNT(id) FROM periods WHERE periods.game=games.id) <= 3
|
|
|
|
|
THEN 1
|
|
|
|
|
ELSE 0
|
|
|
|
|
END) AS reg_losses,
|
|
|
|
|
(CASE WHEN
|
|
|
|
|
COUNT(CASE WHEN shots.goal=true
|
|
|
|
|
AND scoring_team.id=teams.id
|
|
|
|
|
THEN shots.id
|
|
|
|
|
END) >
|
|
|
|
|
COUNT(CASE WHEN shots.goal=true
|
|
|
|
|
AND scoring_team.id!=teams.id
|
|
|
|
|
THEN shots.id
|
|
|
|
|
END)
|
|
|
|
|
AND (SELECT COUNT(id) FROM periods WHERE periods.game=games.id) > 3
|
|
|
|
|
THEN 1
|
|
|
|
|
ELSE 0
|
|
|
|
|
END) AS ot_wins,
|
|
|
|
|
(CASE WHEN
|
|
|
|
|
COUNT(CASE WHEN shots.goal=true
|
|
|
|
|
AND scoring_team.id=teams.id
|
|
|
|
|
THEN shots.id
|
|
|
|
|
END) <
|
|
|
|
|
COUNT(CASE WHEN shots.goal=true
|
|
|
|
|
AND scoring_team.id!=teams.id
|
|
|
|
|
THEN shots.id
|
|
|
|
|
END)
|
|
|
|
|
AND (SELECT COUNT(id) FROM periods WHERE periods.game=games.id) > 3
|
|
|
|
|
THEN 1
|
|
|
|
|
ELSE 0
|
|
|
|
|
END) AS ot_losses,
|
|
|
|
|
(CASE WHEN
|
|
|
|
|
COUNT(CASE WHEN shots.goal=true
|
|
|
|
|
AND scoring_team.id=teams.id
|
|
|
|
|
THEN shots.id
|
|
|
|
|
END) =
|
|
|
|
|
COUNT(CASE WHEN shots.goal=true
|
|
|
|
|
AND scoring_team.id!=teams.id
|
|
|
|
|
THEN shots.id
|
|
|
|
|
END)
|
|
|
|
|
THEN 1
|
|
|
|
|
ELSE 0
|
|
|
|
|
END) AS ties
|
|
|
|
|
teams.id AS team_id,
|
|
|
|
|
teams.name AS team_name,
|
|
|
|
|
reg_win(games.id, teams.id) AS reg_wins,
|
|
|
|
|
reg_loss(games.id, teams.id) AS reg_losses,
|
|
|
|
|
ot_win(games.id, teams.id) AS ot_wins,
|
|
|
|
|
ot_loss(games.id, teams.id) AS ot_losses,
|
|
|
|
|
tie(games.id, teams.id) AS ties,
|
|
|
|
|
iihf_points(games.id, teams.id) AS points
|
|
|
|
|
FROM games
|
|
|
|
|
JOIN periods ON periods.game=games.id
|
|
|
|
|
JOIN shots ON shots.period=periods.id
|
|
|
|
@ -188,7 +149,7 @@ impl Game {
|
|
|
|
|
WHERE games.id=4
|
|
|
|
|
GROUP BY teams.id,games.id;
|
|
|
|
|
"#;
|
|
|
|
|
sqlx::query_as::<_, IihfGameStats>(query)
|
|
|
|
|
sqlx::query_as::<_, IihfStats>(query)
|
|
|
|
|
.bind(game_id)
|
|
|
|
|
.fetch_all(pool)
|
|
|
|
|
.await
|
|
|
|
@ -197,10 +158,10 @@ impl Game {
|
|
|
|
|
/// NOTE: The algorithm used here requires that a 4th period is the "overtime";
|
|
|
|
|
/// it does not check if there was only two periods, followed by an overtime.
|
|
|
|
|
/// This should be sufficient for most.
|
|
|
|
|
pub async fn iihf_score(pool: &PgPool, game_id: i32) -> Result<Vec<IihfGameStats>, sqlx::Error> {
|
|
|
|
|
pub async fn game_iihf_points(pool: &PgPool, game_id: i32) -> Result<Vec<IihfPoints>, sqlx::Error> {
|
|
|
|
|
let query = r#"
|
|
|
|
|
SELECT
|
|
|
|
|
calculate_iihf_points(games.id, teams.id) AS points,
|
|
|
|
|
iihf_points(games.id, teams.id) AS points,
|
|
|
|
|
teams.name AS team_name,
|
|
|
|
|
teams.id AS team_id
|
|
|
|
|
FROM games
|
|
|
|
@ -210,13 +171,13 @@ impl Game {
|
|
|
|
|
WHERE games.id=$1
|
|
|
|
|
ORDER BY points;
|
|
|
|
|
"#;
|
|
|
|
|
sqlx::query_as::<_, IihfGameStats>(query)
|
|
|
|
|
sqlx::query_as::<_, IihfPoints>(query)
|
|
|
|
|
.bind(game_id)
|
|
|
|
|
.fetch_all(pool)
|
|
|
|
|
.await
|
|
|
|
|
}
|
|
|
|
|
/// Returns the number of shots and goals for each team in the game.
|
|
|
|
|
pub async fn score(pool: &PgPool, game_id: i32) -> Result<Vec<TeamStats>, sqlx::Error> {
|
|
|
|
|
pub async fn game_score(pool: &PgPool, game_id: i32) -> Result<Vec<TeamStats>, sqlx::Error> {
|
|
|
|
|
let query = r#"
|
|
|
|
|
SELECT
|
|
|
|
|
COUNT(CASE WHEN shots.goal = true THEN shots.id END) AS goals,
|
|
|
|
@ -235,12 +196,106 @@ impl Game {
|
|
|
|
|
.fetch_all(pool)
|
|
|
|
|
.await
|
|
|
|
|
}
|
|
|
|
|
pub async fn game_play_by_play(
|
|
|
|
|
pool: &PgPool,
|
|
|
|
|
game_id: i32,
|
|
|
|
|
) -> Result<Vec<ShotDetails>, sqlx::Error> {
|
|
|
|
|
sqlx::query_as::<_, ShotDetails>(
|
|
|
|
|
r#"
|
|
|
|
|
SELECT
|
|
|
|
|
shots.shooter AS player_id,
|
|
|
|
|
shots.assistant AS first_assist_id,
|
|
|
|
|
shots.assistant_second AS second_assist_id,
|
|
|
|
|
shots.goal AS is_goal,
|
|
|
|
|
players.name AS player_name,
|
|
|
|
|
p_assistant.name AS first_assist_name,
|
|
|
|
|
p_assistant_second.name AS second_assist_name,
|
|
|
|
|
game_players.player_number AS player_number,
|
|
|
|
|
gp_assistant.player_number AS first_assist_number,
|
|
|
|
|
gp_assistant_second.player_number AS second_assist_number,
|
|
|
|
|
teams.name AS team_name,
|
|
|
|
|
teams.id AS team_id,
|
|
|
|
|
shots.period_time AS time_remaining,
|
|
|
|
|
period_types.id AS period_id,
|
|
|
|
|
period_types.short_name AS period_short_name
|
|
|
|
|
FROM shots
|
|
|
|
|
JOIN game_players ON game_players.id=shots.shooter
|
|
|
|
|
JOIN players ON players.id=game_players.player
|
|
|
|
|
JOIN teams ON teams.id=game_players.team
|
|
|
|
|
LEFT JOIN game_players gp_assistant ON gp_assistant.id=shots.assistant
|
|
|
|
|
LEFT JOIN players p_assistant ON p_assistant.id=gp_assistant.player
|
|
|
|
|
LEFT JOIN game_players gp_assistant_second ON gp_assistant_second.id=shots.assistant_second
|
|
|
|
|
LEFT JOIN players p_assistant_second ON p_assistant_second.id=gp_assistant_second.player
|
|
|
|
|
JOIN periods ON shots.period=periods.id
|
|
|
|
|
JOIN period_types ON periods.period_type=period_types.id
|
|
|
|
|
WHERE periods.game=$1
|
|
|
|
|
ORDER BY
|
|
|
|
|
periods.period_type ASC,
|
|
|
|
|
shots.period_time DESC;
|
|
|
|
|
"#,
|
|
|
|
|
)
|
|
|
|
|
.bind(game_id)
|
|
|
|
|
.fetch_all(pool)
|
|
|
|
|
.await
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl Game {
|
|
|
|
|
pub async fn score(&self, pool: &PgPool) -> Result<Vec<TeamStats>, sqlx::Error> {
|
|
|
|
|
game_score(pool, self.id).await
|
|
|
|
|
}
|
|
|
|
|
pub async fn box_score(&self, pool: &PgPool) -> Result<Vec<PlayerStats>, sqlx::Error> {
|
|
|
|
|
game_box_score(pool, self.id).await
|
|
|
|
|
}
|
|
|
|
|
pub async fn iihf_points(&self, pool: &PgPool) -> Result<Vec<IihfPoints>, sqlx::Error> {
|
|
|
|
|
game_iihf_points(pool, self.id).await
|
|
|
|
|
}
|
|
|
|
|
pub async fn iihf_stats(&self, pool: &PgPool) -> Result<Vec<IihfStats>, sqlx::Error> {
|
|
|
|
|
game_iihf_stats(pool, self.id).await
|
|
|
|
|
}
|
|
|
|
|
pub async fn goals(&self, pool: &PgPool) -> Result<Vec<GoalDetails>, sqlx::Error> {
|
|
|
|
|
game_goals(pool, self.id).await
|
|
|
|
|
}
|
|
|
|
|
pub async fn play_by_play(&self, pool: &PgPool) -> Result<Vec<ShotDetails>, sqlx::Error> {
|
|
|
|
|
game_play_by_play(pool, self.id).await
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub async fn division_iihf_stats(pool: &PgPool, division_id: i32) -> Result<Vec<IihfStatsI64>, sqlx::Error> {
|
|
|
|
|
sqlx::query_as::<_, IihfStatsI64>(
|
|
|
|
|
r#"
|
|
|
|
|
SELECT
|
|
|
|
|
SUM(reg_win(games.id, teams.id)) AS reg_wins,
|
|
|
|
|
SUM(reg_loss(games.id, teams.id)) AS reg_losses,
|
|
|
|
|
SUM(ot_win(games.id, teams.id)) AS ot_wins,
|
|
|
|
|
SUM(ot_loss(games.id, teams.id)) AS ot_losses,
|
|
|
|
|
SUM(tie(games.id, teams.id)) AS ties,
|
|
|
|
|
SUM(iihf_points(games.id, teams.id)) AS points,
|
|
|
|
|
teams.id AS team_id,
|
|
|
|
|
teams.name AS team_name
|
|
|
|
|
FROM
|
|
|
|
|
games
|
|
|
|
|
JOIN teams ON teams.id=games.team_home OR teams.id=games.team_away
|
|
|
|
|
WHERE games.division=$1
|
|
|
|
|
GROUP BY
|
|
|
|
|
teams.id
|
|
|
|
|
ORDER BY
|
|
|
|
|
points DESC;
|
|
|
|
|
"#
|
|
|
|
|
)
|
|
|
|
|
.bind(division_id)
|
|
|
|
|
.fetch_all(pool)
|
|
|
|
|
.await
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl Division {
|
|
|
|
|
pub async fn iihf_stats(&self, pool: &PgPool) -> Result<Vec<IihfStatsI64>, sqlx::Error> {
|
|
|
|
|
division_iihf_stats(pool, self.id).await
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl Player {
|
|
|
|
|
pub async fn latest_league(pool: &PgPool, id: i32) -> Result<Option<League>, sqlx::Error> {
|
|
|
|
|
let query =
|
|
|
|
|
r#"
|
|
|
|
|
let query = r#"
|
|
|
|
|
SELECT leagues.*
|
|
|
|
|
FROM players
|
|
|
|
|
JOIN game_players ON game_players.player=players.id
|
|
|
|
@ -258,8 +313,7 @@ impl Player {
|
|
|
|
|
.await
|
|
|
|
|
}
|
|
|
|
|
pub async fn latest_stats(pool: &PgPool, id: i32) -> Result<Vec<GoalDetails>, sqlx::Error> {
|
|
|
|
|
let query =
|
|
|
|
|
r#"
|
|
|
|
|
let query = r#"
|
|
|
|
|
SELECT
|
|
|
|
|
players.id AS player_id,
|
|
|
|
|
p_assist.id AS first_assist_id,
|
|
|
|
@ -354,7 +408,11 @@ ORDER BY
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl League {
|
|
|
|
|
pub async fn player_stats(pool: &PgPool, player_id: i32, league_id: i32) -> Result<PlayerStats, sqlx::Error> {
|
|
|
|
|
pub async fn player_stats(
|
|
|
|
|
pool: &PgPool,
|
|
|
|
|
player_id: i32,
|
|
|
|
|
league_id: i32,
|
|
|
|
|
) -> Result<PlayerStats, sqlx::Error> {
|
|
|
|
|
let query = r#"
|
|
|
|
|
SELECT
|
|
|
|
|
COUNT(goals.id) AS goals,
|
|
|
|
@ -390,8 +448,6 @@ impl League {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#[derive(FromRow, Deserialize, Serialize, Debug)]
|
|
|
|
|
pub struct GoalDetails {
|
|
|
|
|
pub player_id: i32,
|
|
|
|
@ -428,73 +484,18 @@ pub struct ShotDetails {
|
|
|
|
|
pub second_assist_number: Option<i32>,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pub async fn get_play_by_play_from_game(pool: &PgPool, game: &Game) -> Result<Vec<ShotDetails>, sqlx::Error> {
|
|
|
|
|
sqlx::query_as::<_, ShotDetails>(
|
|
|
|
|
r#"
|
|
|
|
|
SELECT
|
|
|
|
|
shots.shooter AS player_id,
|
|
|
|
|
shots.assistant AS first_assist_id,
|
|
|
|
|
shots.assistant_second AS second_assist_id,
|
|
|
|
|
shots.goal AS is_goal,
|
|
|
|
|
players.name AS player_name,
|
|
|
|
|
p_assistant.name AS first_assist_name,
|
|
|
|
|
p_assistant_second.name AS second_assist_name,
|
|
|
|
|
game_players.player_number AS player_number,
|
|
|
|
|
gp_assistant.player_number AS first_assist_number,
|
|
|
|
|
gp_assistant_second.player_number AS second_assist_number,
|
|
|
|
|
teams.name AS team_name,
|
|
|
|
|
teams.id AS team_id,
|
|
|
|
|
shots.period_time AS time_remaining,
|
|
|
|
|
period_types.id AS period_id,
|
|
|
|
|
period_types.short_name AS period_short_name
|
|
|
|
|
FROM shots
|
|
|
|
|
JOIN game_players ON game_players.id=shots.shooter
|
|
|
|
|
JOIN players ON players.id=game_players.player
|
|
|
|
|
JOIN teams ON teams.id=game_players.team
|
|
|
|
|
LEFT JOIN game_players gp_assistant ON gp_assistant.id=shots.assistant
|
|
|
|
|
LEFT JOIN players p_assistant ON p_assistant.id=gp_assistant.player
|
|
|
|
|
LEFT JOIN game_players gp_assistant_second ON gp_assistant_second.id=shots.assistant_second
|
|
|
|
|
LEFT JOIN players p_assistant_second ON p_assistant_second.id=gp_assistant_second.player
|
|
|
|
|
JOIN periods ON shots.period=periods.id
|
|
|
|
|
JOIN period_types ON periods.period_type=period_types.id
|
|
|
|
|
WHERE periods.game=$1
|
|
|
|
|
ORDER BY
|
|
|
|
|
periods.period_type ASC,
|
|
|
|
|
shots.period_time DESC;
|
|
|
|
|
"#)
|
|
|
|
|
.bind(game.id)
|
|
|
|
|
.fetch_all(pool)
|
|
|
|
|
.await
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
|
mod tests {
|
|
|
|
|
use std::env;
|
|
|
|
|
use crate::model::{Game, League, Player};
|
|
|
|
|
use crate::views::{game_play_by_play, get_player_stats_overview, Notification, game_score, game_goals, game_iihf_stats, game_iihf_points, game_box_score, division_iihf_stats};
|
|
|
|
|
use ormx::Table;
|
|
|
|
|
use crate::model::{
|
|
|
|
|
Game,
|
|
|
|
|
Player,
|
|
|
|
|
League,
|
|
|
|
|
};
|
|
|
|
|
use crate::views::{
|
|
|
|
|
Notification,
|
|
|
|
|
get_player_stats_overview,
|
|
|
|
|
get_play_by_play_from_game,
|
|
|
|
|
};
|
|
|
|
|
use std::env;
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn check_play_by_play() {
|
|
|
|
|
tokio_test::block_on(async move {
|
|
|
|
|
let pool = db_connect().await;
|
|
|
|
|
let game = Game::get(&pool, 3)
|
|
|
|
|
.await
|
|
|
|
|
.unwrap();
|
|
|
|
|
let pbp = get_play_by_play_from_game(&pool, &game)
|
|
|
|
|
.await
|
|
|
|
|
.unwrap();
|
|
|
|
|
let pbp = game_play_by_play(&pool, 3).await.unwrap();
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -502,12 +503,8 @@ mod tests {
|
|
|
|
|
fn get_latest_stats_of_player() {
|
|
|
|
|
tokio_test::block_on(async move {
|
|
|
|
|
let pool = db_connect().await;
|
|
|
|
|
let player = Player::get(&pool, 2)
|
|
|
|
|
.await
|
|
|
|
|
.unwrap();
|
|
|
|
|
let latest = Player::latest_stats(&pool, player.id)
|
|
|
|
|
.await
|
|
|
|
|
.unwrap();
|
|
|
|
|
let player = Player::get(&pool, 2).await.unwrap();
|
|
|
|
|
let latest = Player::latest_stats(&pool, player.id).await.unwrap();
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -515,13 +512,11 @@ mod tests {
|
|
|
|
|
fn check_league_player_stats() {
|
|
|
|
|
tokio_test::block_on(async move {
|
|
|
|
|
let pool = db_connect().await;
|
|
|
|
|
let league = League::get(&pool, 1)
|
|
|
|
|
.await
|
|
|
|
|
.unwrap();
|
|
|
|
|
let player = Player::get(&pool, 2)
|
|
|
|
|
let league = League::get(&pool, 1).await.unwrap();
|
|
|
|
|
let player = Player::get(&pool, 2).await.unwrap();
|
|
|
|
|
let stats = League::player_stats(&pool, player.id, league.id)
|
|
|
|
|
.await
|
|
|
|
|
.unwrap();
|
|
|
|
|
let stats = League::player_stats(&pool, player.id, league.id).await.unwrap();
|
|
|
|
|
assert_eq!(stats.name, "Hillary Scanlon");
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
@ -530,9 +525,7 @@ mod tests {
|
|
|
|
|
fn check_latest_league_for_player() {
|
|
|
|
|
tokio_test::block_on(async move {
|
|
|
|
|
let pool = db_connect().await;
|
|
|
|
|
let player = Player::get(&pool, 5)
|
|
|
|
|
.await
|
|
|
|
|
.unwrap();
|
|
|
|
|
let player = Player::get(&pool, 5).await.unwrap();
|
|
|
|
|
let league = Player::latest_league(&pool, player.id)
|
|
|
|
|
.await
|
|
|
|
|
.unwrap()
|
|
|
|
@ -545,12 +538,7 @@ mod tests {
|
|
|
|
|
fn check_score_details_from_game() {
|
|
|
|
|
tokio_test::block_on(async move {
|
|
|
|
|
let pool = db_connect().await;
|
|
|
|
|
let game = Game::get(&pool, 3)
|
|
|
|
|
.await
|
|
|
|
|
.unwrap();
|
|
|
|
|
let scores = Game::goals(&pool, game.id)
|
|
|
|
|
.await
|
|
|
|
|
.unwrap();
|
|
|
|
|
let scores = game_goals(&pool, 3).await.unwrap();
|
|
|
|
|
println!("{scores:?}");
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
@ -559,32 +547,55 @@ mod tests {
|
|
|
|
|
fn check_box_score_from_game() {
|
|
|
|
|
tokio_test::block_on(async move {
|
|
|
|
|
let pool = db_connect().await;
|
|
|
|
|
let game = Game::get(&pool, 4)
|
|
|
|
|
.await
|
|
|
|
|
.unwrap();
|
|
|
|
|
let scores = Game::box_score(&pool, game.id)
|
|
|
|
|
.await
|
|
|
|
|
.unwrap();
|
|
|
|
|
let scores = game_box_score(&pool, 4).await.unwrap();
|
|
|
|
|
println!("{scores:?}");
|
|
|
|
|
let second_top_scorer = scores.get(1).unwrap();
|
|
|
|
|
assert_eq!(second_top_scorer.name, "Allyssa Foulds");
|
|
|
|
|
assert_eq!(second_top_scorer.goals, 1, "Allysa should have 1 goal..");
|
|
|
|
|
assert_eq!(second_top_scorer.assists, 2, "Allyssa should have 2 assists.");
|
|
|
|
|
assert_eq!(
|
|
|
|
|
second_top_scorer.assists, 2,
|
|
|
|
|
"Allyssa should have 2 assists."
|
|
|
|
|
);
|
|
|
|
|
assert_eq!(second_top_scorer.points, 3, "Allysa should have 3 points.");
|
|
|
|
|
assert_eq!(scores.len(), 8, "Players which did not receive any points should not be in the box score.");
|
|
|
|
|
assert_eq!(
|
|
|
|
|
scores.len(),
|
|
|
|
|
8,
|
|
|
|
|
"Players which did not receive any points should not be in the box score."
|
|
|
|
|
);
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn check_iihf_score() {
|
|
|
|
|
fn check_division_iihf_points() {
|
|
|
|
|
tokio_test::block_on(async move {
|
|
|
|
|
let pool = db_connect().await;
|
|
|
|
|
let game = Game::get(&pool, 4)
|
|
|
|
|
.await
|
|
|
|
|
.unwrap();
|
|
|
|
|
let score = Game::iihf_score(&pool, game.id)
|
|
|
|
|
.await
|
|
|
|
|
.unwrap();
|
|
|
|
|
let score = division_iihf_stats(&pool, 1).await.unwrap();
|
|
|
|
|
assert_eq!(score.get(0).unwrap().points, 10);
|
|
|
|
|
assert_eq!(score.get(0).unwrap().team_name, "Bullseye");
|
|
|
|
|
assert_eq!(score.get(0).unwrap().reg_losses, 0);
|
|
|
|
|
assert_eq!(score.get(0).unwrap().ties, 2);
|
|
|
|
|
assert_eq!(score.get(1).unwrap().points, 4);
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn check_iihf_stats() {
|
|
|
|
|
tokio_test::block_on(async move {
|
|
|
|
|
let pool = db_connect().await;
|
|
|
|
|
let score = game_iihf_stats(&pool, 4).await.unwrap();
|
|
|
|
|
assert_eq!(score.get(0).unwrap().points, 2);
|
|
|
|
|
assert_eq!(score.get(0).unwrap().team_name, "Bullseye");
|
|
|
|
|
assert_eq!(score.get(0).unwrap().reg_losses, 0);
|
|
|
|
|
assert_eq!(score.get(0).unwrap().ties, 1);
|
|
|
|
|
assert_eq!(score.get(1).unwrap().points, 2);
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn check_iihf_points() {
|
|
|
|
|
tokio_test::block_on(async move {
|
|
|
|
|
let pool = db_connect().await;
|
|
|
|
|
let score = game_iihf_points(&pool, 4).await.unwrap();
|
|
|
|
|
assert_eq!(score.get(0).unwrap().points, 2);
|
|
|
|
|
assert_eq!(score.get(0).unwrap().team_name, "Bullseye");
|
|
|
|
|
assert_eq!(score.get(1).unwrap().points, 2);
|
|
|
|
@ -595,12 +606,7 @@ mod tests {
|
|
|
|
|
fn check_game_score() {
|
|
|
|
|
tokio_test::block_on(async move {
|
|
|
|
|
let pool = db_connect().await;
|
|
|
|
|
let game = Game::get(&pool, 1)
|
|
|
|
|
.await
|
|
|
|
|
.unwrap();
|
|
|
|
|
let score = Game::score(&pool, game.id)
|
|
|
|
|
.await
|
|
|
|
|
.unwrap();
|
|
|
|
|
let score = game_score(&pool, 1).await.unwrap();
|
|
|
|
|
assert_eq!(score.get(0).unwrap().goals, 1);
|
|
|
|
|
assert_eq!(score.get(1).unwrap().goals, 1);
|
|
|
|
|
})
|
|
|
|
@ -621,9 +627,7 @@ mod tests {
|
|
|
|
|
fn check_lifetime_stats() {
|
|
|
|
|
tokio_test::block_on(async move {
|
|
|
|
|
let pool = db_connect().await;
|
|
|
|
|
let lifetime_stats = Player::lifetime_stats(&pool, 5)
|
|
|
|
|
.await
|
|
|
|
|
.unwrap();
|
|
|
|
|
let lifetime_stats = Player::lifetime_stats(&pool, 5).await.unwrap();
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -654,7 +658,8 @@ JOIN positions ON positions.id=game_players.position;
|
|
|
|
|
.unwrap();
|
|
|
|
|
let minutes = result.period_time_left / 60;
|
|
|
|
|
let seconds = result.period_time_left % 60;
|
|
|
|
|
println!("{0} {1} player #{3} {2} has scored! Time of the goal: {4}:{5} in the {6}",
|
|
|
|
|
println!(
|
|
|
|
|
"{0} {1} player #{3} {2} has scored! Time of the goal: {4}:{5} in the {6}",
|
|
|
|
|
result.scorer_team_name,
|
|
|
|
|
result.position,
|
|
|
|
|
result.scorer_name,
|
|
|
|
@ -668,12 +673,12 @@ JOIN positions ON positions.id=game_players.position;
|
|
|
|
|
|
|
|
|
|
/// A simple function to connect to the database.
|
|
|
|
|
async fn db_connect() -> sqlx::PgPool {
|
|
|
|
|
let db_url = env::var("DATABASE_URL").expect("DATABASE_URL environment variable must be set to run tests.");
|
|
|
|
|
let db_url = env::var("DATABASE_URL")
|
|
|
|
|
.expect("DATABASE_URL environment variable must be set to run tests.");
|
|
|
|
|
sqlx::postgres::PgPoolOptions::new()
|
|
|
|
|
.max_connections(1)
|
|
|
|
|
.connect(&db_url)
|
|
|
|
|
.await
|
|
|
|
|
.expect("Active database connection must be made")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|