Restructure SQL tables

This commit is contained in:
Kiana Sheibani 2023-11-26 15:26:55 -05:00
parent c06c18c0ba
commit 72884497c1
Signed by: toki
GPG key ID: 6CB106C25E86A9F7
6 changed files with 96 additions and 50 deletions

View file

@ -56,7 +56,26 @@ CREATE TABLE IF NOT EXISTS datasets (
adj_decay_rate REAL NOT NULL, adj_decay_rate REAL NOT NULL,
period REAL NOT NULL, period REAL NOT NULL,
tau REAL NOT NULL tau REAL NOT NULL
) STRICT;"; ) STRICT;
CREATE TABLE IF NOT EXISTS players (
id INTEGER PRIMARY KEY,
discrim TEXT NOT NULL,
name TEXT NOT NULL,
prefix TEXT
) STRICT;
CREATE TABLE IF NOT EXISTS events (
id INTEGER PRIMARY KEY,
slug TEXT NOT NULL
) STRICT;
CREATE TABLE IF NOT EXISTS sets (
id TEXT UNIQUE NOT NULL,
event INTEGER NOT NULL,
FOREIGN KEY(event) REFERENCES events
) STRICT;
";
let connection = sqlite::open(path)?; let connection = sqlite::open(path)?;
connection.execute(query)?; connection.execute(query)?;
@ -124,9 +143,6 @@ pub fn new_dataset(
let query2 = format!( let query2 = format!(
r#"CREATE TABLE "{0}_players" ( r#"CREATE TABLE "{0}_players" (
id INTEGER PRIMARY KEY, id INTEGER PRIMARY KEY,
name TEXT,
prefix TEXT,
slug TEXT NOT NULL,
last_played INTEGER NOT NULL, last_played INTEGER NOT NULL,
deviation REAL NOT NULL, deviation REAL NOT NULL,
volatility REAL NOT NULL, volatility REAL NOT NULL,
@ -168,8 +184,8 @@ CREATE VIEW "{0}_view"
sets_A, sets_count_A, sets_B, sets_count_B, sets, sets_count) AS sets_A, sets_count_A, sets_B, sets_count_B, sets, sets_count) AS
SELECT players_A.id, players_B.id, players_A.name, players_B.name, advantage, SELECT players_A.id, players_B.id, players_A.name, players_B.name, advantage,
sets_A, sets_count_A, sets_B, sets_count_B, network.sets, network.sets_count FROM "{0}_network" network sets_A, sets_count_A, sets_B, sets_count_B, network.sets, network.sets_count FROM "{0}_network" network
INNER JOIN "{0}_players" players_A ON player_A = players_A.id INNER JOIN players players_A ON player_A = players_A.id
INNER JOIN "{0}_players" players_B ON player_B = players_B.id;"#, INNER JOIN players players_B ON player_B = players_B.id;"#,
dataset dataset
); );
@ -241,16 +257,35 @@ pub fn update_last_sync(connection: &Connection, dataset: &str) -> sqlite::Resul
// Database Updating // Database Updating
pub fn add_event(connection: &Connection, event: EventId, slug: &str) -> sqlite::Result<()> {
let query = "INSERT OR IGNORE INTO events (id, slug) VALUES (?, ?)";
let mut statement = connection.prepare(&query)?;
statement.bind((1, event.0 as i64))?;
statement.bind((2, slug))?;
statement.into_iter().try_for_each(|x| x.map(|_| ()))
}
pub fn add_set(connection: &Connection, set: &SetId, event: EventId) -> sqlite::Result<()> {
let query = "INSERT OR IGNORE INTO sets (id, event) VALUES (?, ?)";
let mut statement = connection.prepare(&query)?;
statement.bind((1, &set.0.to_string()[..]))?;
statement.bind((2, event.0 as i64))?;
statement.into_iter().try_for_each(|x| x.map(|_| ()))
}
pub fn add_players( pub fn add_players(
connection: &Connection, connection: &Connection,
dataset: &str, dataset: &str,
teams: &Teams<PlayerData>, teams: &Teams<PlayerData>,
time: Timestamp, time: Timestamp,
) -> sqlite::Result<()> { ) -> sqlite::Result<()> {
let query = format!( let query1 = "INSERT OR IGNORE INTO players (id, discrim, name, prefix) VALUES (?, ?, ?, ?)";
let query2 = format!(
r#"INSERT OR IGNORE INTO "{}_players" r#"INSERT OR IGNORE INTO "{}_players"
(id, name, prefix, slug, last_played, deviation, volatility, sets_won, sets_lost) (id, last_played, deviation, volatility, sets_won, sets_lost)
VALUES (?, ?, ?, ?, ?, 2.01, 0.06, '', '')"#, VALUES (?, ?, 2.01, 0.06, '', '')"#,
dataset dataset
); );
@ -260,29 +295,26 @@ pub fn add_players(
id, id,
name, name,
prefix, prefix,
slug, discrim,
}| { }| {
let mut statement = connection.prepare(&query)?; let mut statement = connection.prepare(&query1)?;
statement.bind((1, id.0 as i64))?; statement.bind((1, id.0 as i64))?;
statement.bind((2, &name[..]))?; statement.bind((2, &discrim[..]))?;
statement.bind((3, prefix.as_ref().map(|x| &x[..])))?; statement.bind((3, &name[..]))?;
statement.bind((4, &slug[..]))?; statement.bind((4, prefix.as_ref().map(|x| &x[..])))?;
statement.bind((5, time.0 as i64))?; statement.into_iter().try_for_each(|x| x.map(|_| ()))?;
statement = connection.prepare(&query2)?;
statement.bind((1, id.0 as i64))?;
statement.bind((2, time.0 as i64))?;
statement.into_iter().try_for_each(|x| x.map(|_| ())) statement.into_iter().try_for_each(|x| x.map(|_| ()))
}, },
) )
}) })
} }
pub fn get_player( pub fn get_player(connection: &Connection, player: PlayerId) -> sqlite::Result<PlayerData> {
connection: &Connection, let query = "SELECT name, prefix, discrim FROM players WHERE id = ?";
dataset: &str,
player: PlayerId,
) -> sqlite::Result<PlayerData> {
let query = format!(
r#"SELECT name, prefix, slug FROM "{}_players" WHERE id = ?"#,
dataset
);
let mut statement = connection.prepare(&query)?; let mut statement = connection.prepare(&query)?;
statement.bind((1, player.0 as i64))?; statement.bind((1, player.0 as i64))?;
@ -291,11 +323,11 @@ pub fn get_player(
id: player, id: player,
name: statement.read::<String, _>("name")?, name: statement.read::<String, _>("name")?,
prefix: statement.read::<Option<String>, _>("prefix")?, prefix: statement.read::<Option<String>, _>("prefix")?,
slug: statement.read::<String, _>("slug")?, discrim: statement.read::<String, _>("discrim")?,
}) })
} }
pub fn get_player_data( pub fn get_player_rating_data(
connection: &Connection, connection: &Connection,
dataset: &str, dataset: &str,
player: PlayerId, player: PlayerId,
@ -323,7 +355,7 @@ pub fn set_player_data(
deviation: f64, deviation: f64,
volatility: f64, volatility: f64,
won: bool, won: bool,
set: SetId, set: &SetId,
) -> sqlite::Result<()> { ) -> sqlite::Result<()> {
let query = format!( let query = format!(
r#"UPDATE "{}_players" SET deviation = :dev, volatility = :vol, last_played = :last, r#"UPDATE "{}_players" SET deviation = :dev, volatility = :vol, last_played = :last,
@ -631,7 +663,7 @@ CREATE TABLE IF NOT EXISTS datasets (
id: PlayerId(i), id: PlayerId(i),
name: format!("{}", i), name: format!("{}", i),
prefix: None, prefix: None,
slug: String::from("a"), discrim: String::from("a"),
}) })
.collect() .collect()
} }

View file

@ -9,8 +9,8 @@ use time_format::strftime_utc;
mod queries; mod queries;
use queries::*; use queries::*;
mod datasets; mod database;
use datasets::*; use database::*;
mod sync; mod sync;
use sync::*; use sync::*;
mod util; mod util;
@ -470,20 +470,20 @@ fn player_info(dataset: Option<String>, player: String) {
let player_id = PlayerId(player.parse::<u64>().unwrap()); let player_id = PlayerId(player.parse::<u64>().unwrap());
let PlayerData { let PlayerData {
id, id: _,
name, name,
prefix, prefix,
slug, discrim,
} = get_player(&connection, &dataset, player_id).unwrap(); } = get_player(&connection, player_id).unwrap();
let (deviation, volatility, last_played) = let (deviation, volatility, last_played) =
get_player_data(&connection, &dataset, player_id).unwrap(); get_player_rating_data(&connection, &dataset, player_id).unwrap();
print!("\n\x1b]8;;https://www.start.gg/{}\x1b\\", slug); print!("\n\x1b]8;;https://www.start.gg/user/{}\x1b\\", discrim);
if let Some(pre) = prefix { if let Some(pre) = prefix {
print!("\x1b[2m{}\x1b[0m ", pre); print!("\x1b[2m{}\x1b[0m ", pre);
} }
println!("\x1b[1m{}\x1b[0m\x1b]8;;\x1b\\ ({})", name, id.0); println!("\x1b[1m{}\x1b[0m\x1b]8;;\x1b\\ ({})", name, discrim);
} }
// Sync // Sync

View file

@ -79,7 +79,7 @@ struct Player {
#[derive(cynic::QueryFragment, Debug)] #[derive(cynic::QueryFragment, Debug)]
struct User { struct User {
slug: Option<String>, discriminator: Option<String>,
} }
// Unwrap // Unwrap
@ -129,7 +129,7 @@ impl QueryUnwrap<EventSetsVars> for EventSets {
id: p_.id?, id: p_.id?,
name: p_.gamer_tag?, name: p_.gamer_tag?,
prefix: p_.prefix.filter(|pr| !pr.is_empty()), prefix: p_.prefix.filter(|pr| !pr.is_empty()),
slug: p_.user?.slug?, discrim: p_.user?.discriminator?,
}) })
}) })
.try_collect() .try_collect()

View file

@ -28,7 +28,7 @@ struct Player {
#[derive(cynic::QueryFragment, Debug)] #[derive(cynic::QueryFragment, Debug)]
struct User { struct User {
slug: Option<String>, discriminator: Option<String>,
} }
// Unwrapping // Unwrapping
@ -38,7 +38,7 @@ pub struct PlayerData {
pub id: PlayerId, pub id: PlayerId,
pub name: String, pub name: String,
pub prefix: Option<String>, pub prefix: Option<String>,
pub slug: String, pub discrim: String,
} }
impl QueryUnwrap<PlayerInfoVars> for PlayerInfo { impl QueryUnwrap<PlayerInfoVars> for PlayerInfo {
@ -50,7 +50,7 @@ impl QueryUnwrap<PlayerInfoVars> for PlayerInfo {
id: player.id?, id: player.id?,
name: player.gamer_tag?, name: player.gamer_tag?,
prefix: player.prefix.filter(|pr| !pr.is_empty()), prefix: player.prefix.filter(|pr| !pr.is_empty()),
slug: player.user?.slug?, discrim: player.user?.discriminator?,
}) })
} }
} }

View file

@ -25,7 +25,7 @@ pub struct TournamentEventsVars<'a> {
pub struct TournamentEvents { pub struct TournamentEvents {
#[arguments(query: { #[arguments(query: {
page: $page, page: $page,
perPage: 250, perPage: 225,
sortBy: "endAt asc", sortBy: "endAt asc",
filter: { filter: {
past: true, past: true,
@ -62,6 +62,7 @@ struct Tournament {
#[cynic(variables = "TournamentEventsVars")] #[cynic(variables = "TournamentEventsVars")]
struct Event { struct Event {
id: Option<EventId>, id: Option<EventId>,
slug: Option<String>,
start_at: Option<Timestamp>, start_at: Option<Timestamp>,
} }
@ -81,6 +82,7 @@ pub struct TournamentData {
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct EventData { pub struct EventData {
pub id: EventId, pub id: EventId,
pub slug: String,
pub time: Timestamp, pub time: Timestamp,
} }
@ -103,6 +105,7 @@ impl<'a> QueryUnwrap<TournamentEventsVars<'a>> for TournamentEvents {
.filter_map(|event| { .filter_map(|event| {
Some(EventData { Some(EventData {
id: event.id?, id: event.id?,
slug: event.slug?,
time: event.start_at?, time: event.start_at?,
}) })
}) })

View file

@ -2,7 +2,7 @@ use std::f64::consts::PI;
use std::thread::sleep; use std::thread::sleep;
use std::time::Duration; use std::time::Duration;
use crate::datasets::*; use crate::database::*;
use crate::error; use crate::error;
use crate::queries::*; use crate::queries::*;
use sqlite::*; use sqlite::*;
@ -200,10 +200,12 @@ fn update_from_set(
let player2 = it.next().unwrap()[0].id; let player2 = it.next().unwrap()[0].id;
drop(it); drop(it);
let (deviation1, volatility1, last_played1) = get_player_data(connection, dataset, player1)?; let (deviation1, volatility1, last_played1) =
get_player_rating_data(connection, dataset, player1)?;
let time1 = time.0.checked_sub(last_played1.0).unwrap_or(0); let time1 = time.0.checked_sub(last_played1.0).unwrap_or(0);
let (deviation2, volatility2, last_played2) = get_player_data(connection, dataset, player1)?; let (deviation2, volatility2, last_played2) =
get_player_rating_data(connection, dataset, player1)?;
let time2 = time.0.checked_sub(last_played2.0).unwrap_or(0); let time2 = time.0.checked_sub(last_played2.0).unwrap_or(0);
let advantage = match get_advantage(connection, dataset, player1, player2) { let advantage = match get_advantage(connection, dataset, player1, player2) {
@ -250,7 +252,7 @@ fn update_from_set(
dev_new1, dev_new1,
vol_new1, vol_new1,
results.winner == 0, results.winner == 0,
results.id.clone(), &results.id,
)?; )?;
set_player_data( set_player_data(
connection, connection,
@ -260,7 +262,7 @@ fn update_from_set(
dev_new2, dev_new2,
vol_new2, vol_new2,
results.winner == 1, results.winner == 1,
results.id.clone(), &results.id,
)?; )?;
adjust_advantages( adjust_advantages(
@ -298,6 +300,8 @@ pub fn sync_dataset(
num_events num_events
); );
add_event(connection, event.id, &event.slug)?;
let mut sets = let mut sets =
get_event_sets(event.id, auth).unwrap_or_else(|| error("Could not access start.gg", 1)); get_event_sets(event.id, auth).unwrap_or_else(|| error("Could not access start.gg", 1));
@ -308,6 +312,7 @@ pub fn sync_dataset(
sets.sort_by_key(|set| set.time); sets.sort_by_key(|set| set.time);
sets.into_iter().try_for_each(|set| { sets.into_iter().try_for_each(|set| {
add_set(connection, &set.id, event.id)?;
update_from_set(connection, dataset, &metadata, event.time, set) update_from_set(connection, dataset, &metadata, event.time, set)
})?; })?;
} }
@ -318,7 +323,7 @@ pub fn sync_dataset(
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use crate::datasets::tests::*; use crate::database::tests::*;
#[test] #[test]
fn glicko_single() -> sqlite::Result<()> { fn glicko_single() -> sqlite::Result<()> {
@ -344,8 +349,14 @@ mod tests {
"{:?}", "{:?}",
get_advantage(&connection, "test", PlayerId(1), PlayerId(2))?.unwrap() get_advantage(&connection, "test", PlayerId(1), PlayerId(2))?.unwrap()
); );
println!("{:?}", get_player_data(&connection, "test", PlayerId(1))); println!(
println!("{:?}", get_player_data(&connection, "test", PlayerId(2))); "{:?}",
get_player_rating_data(&connection, "test", PlayerId(1))
);
println!(
"{:?}",
get_player_rating_data(&connection, "test", PlayerId(2))
);
Ok(()) Ok(())
} }