Figure out database shenanigans
This commit is contained in:
parent
8823120942
commit
5ca754e972
14 changed files with 310 additions and 39 deletions
20
.idea/runConfigurations/Backend.xml
Normal file
20
.idea/runConfigurations/Backend.xml
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
<component name="ProjectRunConfigurationManager">
|
||||||
|
<configuration default="false" name="Backend" type="CargoCommandRunConfiguration" factoryName="Cargo Command">
|
||||||
|
<option name="buildProfileId" value="dev" />
|
||||||
|
<option name="command" value="run" />
|
||||||
|
<option name="workingDirectory" value="file://$PROJECT_DIR$/holycow_backend" />
|
||||||
|
<envs />
|
||||||
|
<option name="emulateTerminal" value="true" />
|
||||||
|
<option name="channel" value="DEFAULT" />
|
||||||
|
<option name="requiredFeatures" value="true" />
|
||||||
|
<option name="allFeatures" value="false" />
|
||||||
|
<option name="withSudo" value="false" />
|
||||||
|
<option name="buildTarget" value="REMOTE" />
|
||||||
|
<option name="backtrace" value="SHORT" />
|
||||||
|
<option name="isRedirectInput" value="false" />
|
||||||
|
<option name="redirectInputPath" value="" />
|
||||||
|
<method v="2">
|
||||||
|
<option name="CARGO.BUILD_TASK_PROVIDER" enabled="true" />
|
||||||
|
</method>
|
||||||
|
</configuration>
|
||||||
|
</component>
|
|
@ -8,7 +8,7 @@
|
||||||
<node-interpreter value="project" />
|
<node-interpreter value="project" />
|
||||||
<envs />
|
<envs />
|
||||||
<EXTENSION ID="com.intellij.lang.javascript.buildTools.npm.rc.StartBrowserRunConfigurationExtension">
|
<EXTENSION ID="com.intellij.lang.javascript.buildTools.npm.rc.StartBrowserRunConfigurationExtension">
|
||||||
<browser with-js-debugger="true" url="http://localhost:3000" />
|
<browser url="http://localhost:3000" />
|
||||||
</EXTENSION>
|
</EXTENSION>
|
||||||
<method v="2" />
|
<method v="2" />
|
||||||
</configuration>
|
</configuration>
|
||||||
|
|
56
holycow_backend/Cargo.lock
generated
56
holycow_backend/Cargo.lock
generated
|
@ -26,6 +26,21 @@ dependencies = [
|
||||||
"memchr",
|
"memchr",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "android-tzdata"
|
||||||
|
version = "0.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "android_system_properties"
|
||||||
|
version = "0.1.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "anyhow"
|
name = "anyhow"
|
||||||
version = "1.0.93"
|
version = "1.0.93"
|
||||||
|
@ -202,7 +217,12 @@ version = "0.4.38"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401"
|
checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"android-tzdata",
|
||||||
|
"iana-time-zone",
|
||||||
|
"js-sys",
|
||||||
"num-traits",
|
"num-traits",
|
||||||
|
"wasm-bindgen",
|
||||||
|
"windows-targets 0.52.6",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -318,6 +338,7 @@ checksum = "cbf9649c05e0a9dbd6d0b0b8301db5182b972d0fd02f0a7c6736cf632d7c0fd5"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 2.6.0",
|
"bitflags 2.6.0",
|
||||||
"byteorder",
|
"byteorder",
|
||||||
|
"chrono",
|
||||||
"diesel_derives",
|
"diesel_derives",
|
||||||
"itoa",
|
"itoa",
|
||||||
"pq-sys",
|
"pq-sys",
|
||||||
|
@ -630,11 +651,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc"
|
checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "holycow_api"
|
name = "holycow_backend"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"axum",
|
"axum",
|
||||||
|
"chrono",
|
||||||
"diesel",
|
"diesel",
|
||||||
"diesel_migrations",
|
"diesel_migrations",
|
||||||
"log",
|
"log",
|
||||||
|
@ -792,6 +814,29 @@ dependencies = [
|
||||||
"tower-service",
|
"tower-service",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "iana-time-zone"
|
||||||
|
version = "0.1.61"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "235e081f3925a06703c2d0117ea8b91f042756fd6e7a6e5d901e8ca1a996b220"
|
||||||
|
dependencies = [
|
||||||
|
"android_system_properties",
|
||||||
|
"core-foundation-sys",
|
||||||
|
"iana-time-zone-haiku",
|
||||||
|
"js-sys",
|
||||||
|
"wasm-bindgen",
|
||||||
|
"windows-core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "iana-time-zone-haiku"
|
||||||
|
version = "0.1.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f"
|
||||||
|
dependencies = [
|
||||||
|
"cc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "icu_collections"
|
name = "icu_collections"
|
||||||
version = "1.5.0"
|
version = "1.5.0"
|
||||||
|
@ -2211,6 +2256,15 @@ dependencies = [
|
||||||
"windows-sys 0.52.0",
|
"windows-sys 0.52.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-core"
|
||||||
|
version = "0.52.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9"
|
||||||
|
dependencies = [
|
||||||
|
"windows-targets 0.52.6",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows-sys"
|
name = "windows-sys"
|
||||||
version = "0.48.0"
|
version = "0.48.0"
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
[package]
|
[package]
|
||||||
name = "holycow_api"
|
name = "holycow_backend"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
anyhow = "1.0.93"
|
anyhow = "1.0.93"
|
||||||
axum = { version = "0.7.9", features = ["macros"] }
|
axum = { version = "0.7.9", features = ["macros"] }
|
||||||
diesel = { version = "2.2.5", features = ["postgres"] }
|
diesel = { version = "2.2.5", features = ["chrono", "postgres"] }
|
||||||
diesel_migrations = { version = "2.2.0", features = ["postgres"] }
|
diesel_migrations = { version = "2.2.0", features = ["postgres"] }
|
||||||
log = "0.4.22"
|
log = "0.4.22"
|
||||||
micronfig = "0.3.0"
|
micronfig = "0.3.0"
|
||||||
|
@ -15,3 +15,4 @@ skillratings = "0.27.1"
|
||||||
teloxide = { version = "0.13.0", features = ["webhooks-axum"] }
|
teloxide = { version = "0.13.0", features = ["webhooks-axum"] }
|
||||||
tokio = { version = "1.41.1", features = ["macros", "rt-multi-thread", "net"] }
|
tokio = { version = "1.41.1", features = ["macros", "rt-multi-thread", "net"] }
|
||||||
serde = { version = "1.0.215", features = ["derive"] }
|
serde = { version = "1.0.215", features = ["derive"] }
|
||||||
|
chrono = "0.4.38"
|
||||||
|
|
|
@ -6,4 +6,4 @@ file = "src/schema.rs"
|
||||||
custom_type_derives = ["diesel::query_builder::QueryId", "Clone"]
|
custom_type_derives = ["diesel::query_builder::QueryId", "Clone"]
|
||||||
|
|
||||||
[migrations_directory]
|
[migrations_directory]
|
||||||
dir = "/mnt/work/steffo/holycow_api/migrations"
|
dir = "./migrations"
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
DROP TABLE IF EXISTS games;
|
|
|
@ -1,11 +0,0 @@
|
||||||
CREATE TABLE games (
|
|
||||||
id INTEGER PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
|
|
||||||
|
|
||||||
p1 BPCHAR,
|
|
||||||
p2 BPCHAR,
|
|
||||||
|
|
||||||
p1result BPCHAR,
|
|
||||||
|
|
||||||
CONSTRAINT not_self CHECK (p1 != p2),
|
|
||||||
CONSTRAINT acceptable_result CHECK (p1result = 'W' OR p1result = 'T' OR p1result = 'L')
|
|
||||||
);
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
DROP TABLE IF EXISTS matches;
|
||||||
|
DROP TYPE IF EXISTS outcome_t;
|
||||||
|
DROP TABLE IF EXISTS players;
|
||||||
|
DROP TYPE IF EXISTS wenglin_t;
|
|
@ -0,0 +1,43 @@
|
||||||
|
CREATE TYPE wenglin_t AS (
|
||||||
|
rating float8,
|
||||||
|
uncertainty float8
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE players (
|
||||||
|
id INTEGER GENERATED ALWAYS AS IDENTITY,
|
||||||
|
|
||||||
|
wenglin wenglin_t NOT NULL DEFAULT ROW(25.0, 25.0 / 3),
|
||||||
|
|
||||||
|
telegram_id BIGINT,
|
||||||
|
|
||||||
|
CONSTRAINT telegram_ids_are_unique UNIQUE (telegram_id),
|
||||||
|
PRIMARY KEY (id)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TYPE outcome_t AS ENUM (
|
||||||
|
'AWins',
|
||||||
|
'BWins',
|
||||||
|
'Tie'
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE matches (
|
||||||
|
id INTEGER GENERATED ALWAYS AS IDENTITY,
|
||||||
|
instant TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||||
|
name VARCHAR,
|
||||||
|
|
||||||
|
player_a_id BIGINT NOT NULL,
|
||||||
|
player_a_wenglin_before wenglin_t NOT NULL,
|
||||||
|
player_a_wenglin_after wenglin_t NOT NULL,
|
||||||
|
|
||||||
|
player_b_id BIGINT NOT NULL,
|
||||||
|
player_b_wenglin_before wenglin_t NOT NULL,
|
||||||
|
player_b_wenglin_after wenglin_t NOT NULL,
|
||||||
|
|
||||||
|
outcome outcome_t NOT NULL,
|
||||||
|
|
||||||
|
CONSTRAINT match_unique_name UNIQUE (name),
|
||||||
|
CONSTRAINT not_same_player CHECK (player_a_id != player_b_id),
|
||||||
|
FOREIGN KEY (player_a_id) REFERENCES players (id),
|
||||||
|
FOREIGN KEY (player_b_id) REFERENCES players (id),
|
||||||
|
PRIMARY KEY (id)
|
||||||
|
);
|
|
@ -1,7 +0,0 @@
|
||||||
SELECT
|
|
||||||
played,
|
|
||||||
wins
|
|
||||||
FROM
|
|
||||||
(SELECT COUNT(*) AS played FROM games WHERE :p = p1 OR :p = p2) AS pt,
|
|
||||||
(SELECT COUNT(*) AS wins FROM games WHERE (:p = p1 AND p1result = 'W') OR (:p = p2 AND p1result = 'L')) AS wt
|
|
||||||
;
|
|
|
@ -1,13 +1,13 @@
|
||||||
use std::convert::Infallible;
|
use std::convert::Infallible;
|
||||||
use std::process::exit;
|
use std::process::exit;
|
||||||
use std::sync::Arc;
|
|
||||||
use anyhow::Context;
|
use anyhow::Context;
|
||||||
use axum::http::StatusCode;
|
use axum::http::StatusCode;
|
||||||
use diesel::{Connection, PgConnection};
|
use diesel::{Connection, PgConnection};
|
||||||
use diesel_migrations::MigrationHarness;
|
use diesel_migrations::MigrationHarness;
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
|
|
||||||
mod config;
|
mod config;
|
||||||
|
mod schema;
|
||||||
|
mod types;
|
||||||
|
|
||||||
pub const MIGRATIONS: diesel_migrations::EmbeddedMigrations = diesel_migrations::embed_migrations!();
|
pub const MIGRATIONS: diesel_migrations::EmbeddedMigrations = diesel_migrations::embed_migrations!();
|
||||||
|
|
||||||
|
@ -55,13 +55,8 @@ async fn main() -> anyhow::Result<Infallible> {
|
||||||
exit(1)
|
exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
|
||||||
struct HolyCowResults {
|
|
||||||
played: u16,
|
|
||||||
wins: u16,
|
|
||||||
rating: u16,
|
|
||||||
}
|
|
||||||
|
|
||||||
fn results_handler() -> Result<HolyCowResults, StatusCode> {
|
|
||||||
|
|
||||||
|
#[axum::debug_handler]
|
||||||
|
async fn results_handler() -> Result<String, StatusCode> {
|
||||||
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,46 @@
|
||||||
// @generated automatically by Diesel CLI.
|
// @generated automatically by Diesel CLI.
|
||||||
|
|
||||||
|
pub mod sql_types {
|
||||||
|
#[derive(diesel::query_builder::QueryId, Clone, diesel::sql_types::SqlType)]
|
||||||
|
#[diesel(postgres_type(name = "outcome_t"))]
|
||||||
|
pub struct OutcomeT;
|
||||||
|
|
||||||
|
#[derive(diesel::query_builder::QueryId, Clone, diesel::sql_types::SqlType)]
|
||||||
|
#[diesel(postgres_type(name = "wenglin_t"))]
|
||||||
|
pub struct WenglinT;
|
||||||
|
}
|
||||||
|
|
||||||
diesel::table! {
|
diesel::table! {
|
||||||
games (id) {
|
use diesel::sql_types::*;
|
||||||
|
use super::sql_types::WenglinT;
|
||||||
|
use super::sql_types::OutcomeT;
|
||||||
|
|
||||||
|
matches (id) {
|
||||||
id -> Int4,
|
id -> Int4,
|
||||||
p1 -> Nullable<Bpchar>,
|
instant -> Timestamptz,
|
||||||
p2 -> Nullable<Bpchar>,
|
name -> Nullable<Varchar>,
|
||||||
p1result -> Nullable<Bpchar>,
|
player_a_id -> Int8,
|
||||||
|
player_a_wenglin_before -> WenglinT,
|
||||||
|
player_a_wenglin_after -> WenglinT,
|
||||||
|
player_b_id -> Int8,
|
||||||
|
player_b_wenglin_before -> WenglinT,
|
||||||
|
player_b_wenglin_after -> WenglinT,
|
||||||
|
outcome -> OutcomeT,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
diesel::table! {
|
||||||
|
use diesel::sql_types::*;
|
||||||
|
use super::sql_types::WenglinT;
|
||||||
|
|
||||||
|
players (id) {
|
||||||
|
id -> Int4,
|
||||||
|
wenglin -> WenglinT,
|
||||||
|
telegram_id -> Nullable<Int8>,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
diesel::allow_tables_to_appear_in_same_query!(
|
||||||
|
matches,
|
||||||
|
players,
|
||||||
|
);
|
||||||
|
|
137
holycow_backend/src/types.rs
Normal file
137
holycow_backend/src/types.rs
Normal file
|
@ -0,0 +1,137 @@
|
||||||
|
use std::io::Write;
|
||||||
|
use chrono::{DateTime, Utc};
|
||||||
|
use diesel::{AsExpression, FromSqlRow, Identifiable, Insertable, Queryable, QueryableByName, Selectable};
|
||||||
|
use diesel::backend::Backend;
|
||||||
|
use diesel::deserialize::FromSql;
|
||||||
|
use diesel::pg::Pg;
|
||||||
|
use diesel::serialize::ToSql;
|
||||||
|
use diesel::sql_types as sql;
|
||||||
|
use diesel::serialize::Output as DieselOutput;
|
||||||
|
use crate::schema;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, FromSqlRow, AsExpression)]
|
||||||
|
#[diesel(sql_type = sql::BigInt)]
|
||||||
|
#[diesel(check_for_backend(Pg))]
|
||||||
|
pub struct TelegramId(pub teloxide::types::ChatId);
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, FromSqlRow, AsExpression)]
|
||||||
|
#[diesel(sql_type = schema::sql_types::WenglinT)]
|
||||||
|
#[diesel(check_for_backend(Pg))]
|
||||||
|
pub struct WengLinRating(pub skillratings::weng_lin::WengLinRating);
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Queryable, QueryableByName, Identifiable, Selectable)]
|
||||||
|
#[diesel(table_name = schema::players)]
|
||||||
|
#[diesel(check_for_backend(Pg))]
|
||||||
|
pub struct Player {
|
||||||
|
pub id: i32,
|
||||||
|
pub wenglin: WengLinRating,
|
||||||
|
pub telegram_id: Option<TelegramId>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Insertable)]
|
||||||
|
#[diesel(table_name = schema::players)]
|
||||||
|
#[diesel(check_for_backend(Pg))]
|
||||||
|
pub struct PlayerI {
|
||||||
|
pub wenglin: WengLinRating,
|
||||||
|
pub telegram_id: TelegramId,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, FromSqlRow, AsExpression)]
|
||||||
|
#[diesel(sql_type = schema::sql_types::OutcomeT)]
|
||||||
|
pub enum Outcome {
|
||||||
|
AWins,
|
||||||
|
BWins,
|
||||||
|
Tie,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Queryable, QueryableByName, Identifiable, Selectable)]
|
||||||
|
#[diesel(table_name = schema::matches)]
|
||||||
|
#[diesel(check_for_backend(Pg))]
|
||||||
|
pub struct Match {
|
||||||
|
pub id: i32,
|
||||||
|
pub instant: DateTime<Utc>,
|
||||||
|
pub name: Option<String>,
|
||||||
|
pub player_a_id: TelegramId,
|
||||||
|
pub player_a_wenglin_before: WengLinRating,
|
||||||
|
pub player_a_wenglin_after: WengLinRating,
|
||||||
|
pub player_b_id: TelegramId,
|
||||||
|
pub player_b_wenglin_before: WengLinRating,
|
||||||
|
pub player_b_wenglin_after: WengLinRating,
|
||||||
|
pub outcome: Outcome,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Insertable)]
|
||||||
|
#[diesel(table_name = schema::matches)]
|
||||||
|
#[diesel(check_for_backend(Pg))]
|
||||||
|
pub struct MatchI {
|
||||||
|
pub instant: DateTime<Utc>,
|
||||||
|
pub name: Option<String>,
|
||||||
|
pub player_a_id: TelegramId,
|
||||||
|
pub player_a_wenglin_before: WengLinRating,
|
||||||
|
pub player_a_wenglin_after: WengLinRating,
|
||||||
|
pub player_b_id: TelegramId,
|
||||||
|
pub player_b_wenglin_before: WengLinRating,
|
||||||
|
pub player_b_wenglin_after: WengLinRating,
|
||||||
|
pub outcome: Outcome,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
impl FromSql<sql::BigInt, Pg> for TelegramId {
|
||||||
|
fn from_sql(bytes: <Pg as Backend>::RawValue<'_>) -> diesel::deserialize::Result<Self> {
|
||||||
|
let s = <i64 as FromSql<sql::BigInt, Pg>>::from_sql(bytes)?;
|
||||||
|
|
||||||
|
Ok(Self(teloxide::types::ChatId(s)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromSql<schema::sql_types::WenglinT, Pg> for WengLinRating {
|
||||||
|
fn from_sql(bytes: <Pg as Backend>::RawValue<'_>) -> diesel::deserialize::Result<Self> {
|
||||||
|
let rating = <f64 as FromSql<sql::Double, Pg>>::from_sql(bytes)?;
|
||||||
|
let uncertainty = <f64 as FromSql<sql::Double, Pg>>::from_sql(bytes)?;
|
||||||
|
|
||||||
|
let rating = skillratings::weng_lin::WengLinRating::from((rating, uncertainty));
|
||||||
|
Ok(Self(rating))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromSql<schema::sql_types::OutcomeT, Pg> for Outcome {
|
||||||
|
fn from_sql(bytes: <Pg as Backend>::RawValue<'_>) -> diesel::deserialize::Result<Self> {
|
||||||
|
let o = match bytes.as_bytes() {
|
||||||
|
b"AWins" => Self::AWins,
|
||||||
|
b"BWins" => Self::BWins,
|
||||||
|
b"Tie" => Self::Tie,
|
||||||
|
_ => Err(anyhow::Error::msg("unknown enum variant"))?
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(o)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ToSql<sql::BigInt, Pg> for TelegramId {
|
||||||
|
fn to_sql<'b>(&'b self, out: &mut diesel::serialize::Output<'b, '_, Pg>) -> diesel::serialize::Result {
|
||||||
|
<i64 as ToSql<sql::BigInt, Pg>>::to_sql(&self.0.0, out)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ToSql<schema::sql_types::WenglinT, Pg> for WengLinRating {
|
||||||
|
fn to_sql<'b>(&'b self, out: &mut DieselOutput<'b, '_, Pg>) -> diesel::serialize::Result {
|
||||||
|
<f64 as ToSql<sql::Double, Pg>>::to_sql(&self.0.rating, out)?;
|
||||||
|
<f64 as ToSql<sql::Double, Pg>>::to_sql(&self.0.uncertainty, out)?;
|
||||||
|
|
||||||
|
Ok(diesel::serialize::IsNull::No)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ToSql<schema::sql_types::OutcomeT, Pg> for Outcome {
|
||||||
|
fn to_sql<'b>(&'b self, out: &mut DieselOutput<'b, '_, Pg>) -> diesel::serialize::Result {
|
||||||
|
out.write_all(
|
||||||
|
match self {
|
||||||
|
Outcome::AWins => b"AWins",
|
||||||
|
Outcome::BWins => b"BWins",
|
||||||
|
Outcome::Tie => b"Tie",
|
||||||
|
}
|
||||||
|
)?;
|
||||||
|
|
||||||
|
Ok(diesel::serialize::IsNull::No)
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"name": "holycow",
|
"name": "holycow_frontend",
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|
Loading…
Reference in a new issue