1
Fork 0

sakgjiodfkg

This commit is contained in:
Steffo 2024-11-30 18:51:19 +01:00
parent d0e802d77c
commit e50b31fc3f
Signed by: steffo
GPG key ID: 5ADA3868646C3FC0
12 changed files with 182 additions and 78 deletions

View file

@ -159,11 +159,11 @@ impl WengLinRating {
log::debug!("Getting human score for: {rating:?}±{uncertainty:?}"); log::debug!("Getting human score for: {rating:?}±{uncertainty:?}");
let uncertain = self.0.rating - self.0.uncertainty; let uncertain = self.0.rating - self.0.uncertainty;
log::trace!("Minimum score is: {uncertain:?}"); log::trace!("Minimum score is: {uncertain:?}");
let multiplied = uncertain * 100.0; let multiplied = uncertain * 300.0 / 5.0;
log::trace!("Multiplied score is: {multiplied:?}"); log::trace!("Multiplied score is: {multiplied:?}");
let floored: f64 = multiplied.floor(); let ceiled: f64 = multiplied.ceil();
log::trace!("Floored score is: {floored:?}"); log::trace!("Ceiled score is: {ceiled:?}");
let converted: i64 = floored as i64; let converted: i64 = ceiled as i64;
log::debug!("Human score for {rating:?}±{uncertainty:?} is {converted:?}"); log::debug!("Human score for {rating:?}±{uncertainty:?} is {converted:?}");
converted converted
} }
@ -231,6 +231,15 @@ impl Match {
.get_results::<Self>(conn) .get_results::<Self>(conn)
} }
pub fn played_by(conn: &mut PgConnection, player_id: i32) -> QueryResult<Vec<Self>> {
schema::matches::table
.select(Self::as_select())
.or_filter(schema::matches::player_a_id.eq(player_id))
.or_filter(schema::matches::player_b_id.eq(player_id))
.order_by(schema::matches::instant.desc())
.get_results::<Self>(conn)
}
pub fn played_by_count(conn: &mut PgConnection, player_id: i32) -> QueryResult<i64> { pub fn played_by_count(conn: &mut PgConnection, player_id: i32) -> QueryResult<i64> {
schema::matches::table schema::matches::table
.select(diesel::dsl::count_star()) .select(diesel::dsl::count_star())

View file

@ -75,6 +75,9 @@ async fn main() -> anyhow::Result<Infallible> {
.route("/api/matches/", .route("/api/matches/",
axum::routing::post(routes::matches::post_match) axum::routing::post(routes::matches::post_match)
) )
.route("/api/matches/holycow/:player_id",
axum::routing::post(routes::matches::get_played_by_id)
)
.nest("/telegram/webhook", .nest("/telegram/webhook",
telegram_router telegram_router
) )

View file

@ -1,5 +1,6 @@
use axum::http::StatusCode; use axum::http::StatusCode;
use axum::{Extension, Json}; use axum::{Extension, Json};
use axum::extract::Path;
use diesel::{Connection, PgConnection}; use diesel::{Connection, PgConnection};
use serde::Deserialize; use serde::Deserialize;
use skillratings::weng_lin::WengLinConfig; use skillratings::weng_lin::WengLinConfig;
@ -9,6 +10,14 @@ use teloxide::types::{ChatId, MessageId, ParseMode, ThreadId};
use crate::config; use crate::config;
use crate::database::model::{Match, MatchI, Outcome, Player, WengLinRating}; use crate::database::model::{Match, MatchI, Outcome, Player, WengLinRating};
#[derive(Debug, Clone, Deserialize)]
pub struct MatchII {
name: Option<String>,
player_a: i32,
player_b: i32,
outcome: Outcome,
}
#[axum::debug_handler] #[axum::debug_handler]
pub async fn get_all() pub async fn get_all()
-> Result<Json<Vec<Match>>, StatusCode> -> Result<Json<Vec<Match>>, StatusCode>
@ -22,29 +31,46 @@ pub async fn get_all()
Ok(Json(matches)) Ok(Json(matches))
} }
#[derive(Debug, Clone, Deserialize)] #[axum::debug_handler]
pub struct MatchII { pub async fn get_played_by_id(
name: Option<String>, Path(player_id): Path<i32>,
player_a: i32, )
player_b: i32, -> Result<Json<Vec<Match>>, StatusCode>
outcome: Outcome, {
let mut conn = PgConnection::establish(config::DATABASE_URL())
.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?;
let matches = Match::played_by(&mut conn, player_id)
.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?;
Ok(Json(matches))
} }
fn player_to_text(player: &Player, before: &WengLinRating, after: &WengLinRating) -> String { fn player_to_text(player: &Player, before: &WengLinRating, after: &WengLinRating) -> String {
let name = &player.username; let name = &player.username;
let competitive = &player.competitive; let competitive = &player.competitive;
let telegram_id = &player.telegram_id; let telegram_id = &player.telegram_id.clone().map(|t| t.0);
match competitive { match competitive {
false => { false => {
format!("{name}") match telegram_id {
None =>
format!(r#"<b>{name}</b>"#),
Some(telegram_id) =>
format!(r#"<b><a href="tg://user?id={telegram_id}">{name}</a></b>"#),
}
}, },
true => { true => {
let before = before.human_score(); let before = before.human_score();
let after = after.human_score(); let after = after.human_score();
let change = after - before; let change = after - before;
format!(r#"<b><a href="tg://user?id={telegram_id}">{name}</a></b> <i>({change:+})</i>"#) match telegram_id {
None =>
format!(r#"<b>{name}</b> ({change:+} ★)"#),
Some(telegram_id) =>
format!(r#"<b><a href="tg://user?id={telegram_id}">{name}</a></b> ({change:+} ★)"#),
}
}, },
} }
} }

View file

@ -43,11 +43,22 @@ pub async fn get_all()
Ok(Json(players.into_iter().map(Into::into).collect())) Ok(Json(players.into_iter().map(Into::into).collect()))
} }
// this is an awful hack but idc i'm out of time
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PlayerOO {
id: i32,
telegram_id: Option<TelegramId>,
username: String,
human_score: Option<i64>,
played: i64,
wins: i64,
}
#[axum::debug_handler] #[axum::debug_handler]
pub async fn get_by_id( pub async fn get_by_id(
Path(player_id): Path<i32>, Path(player_id): Path<i32>,
) )
-> Result<Json<PlayerO>, StatusCode> -> Result<Json<PlayerOO>, StatusCode>
{ {
let mut conn = PgConnection::establish(config::DATABASE_URL()) let mut conn = PgConnection::establish(config::DATABASE_URL())
.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?; .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?;
@ -56,14 +67,29 @@ pub async fn get_by_id(
.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)? .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?
.ok_or(StatusCode::NOT_FOUND)?; .ok_or(StatusCode::NOT_FOUND)?;
Ok(Json(player.into())) let played = player.played_count(&mut conn)
.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?;
let wins = player.won_count(&mut conn)
.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?;
let player_o = PlayerO::from(player);
Ok(Json(PlayerOO {
id: player_o.id,
telegram_id: player_o.telegram_id,
username: player_o.username,
human_score: player_o.human_score,
played,
wins,
}))
} }
#[axum::debug_handler] #[axum::debug_handler]
pub async fn get_by_telegram_id( pub async fn get_by_telegram_id(
Path(telegram_id): Path<TelegramId>, Path(telegram_id): Path<TelegramId>,
) )
-> Result<Json<PlayerO>, StatusCode> -> Result<Json<PlayerOO>, StatusCode>
{ {
let mut conn = PgConnection::establish(config::DATABASE_URL()) let mut conn = PgConnection::establish(config::DATABASE_URL())
.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?; .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?;
@ -72,5 +98,20 @@ pub async fn get_by_telegram_id(
.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)? .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?
.ok_or(StatusCode::NOT_FOUND)?; .ok_or(StatusCode::NOT_FOUND)?;
Ok(Json(player.into())) let played = player.played_count(&mut conn)
.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?;
let wins = player.won_count(&mut conn)
.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?;
let player_o = PlayerO::from(player);
Ok(Json(PlayerOO {
id: player_o.id,
telegram_id: player_o.telegram_id,
username: player_o.username,
human_score: player_o.human_score,
played,
wins,
}))
} }

View file

@ -1,3 +1,14 @@
export default async function Page() { import {ProfileBox} from "@/components/ProfileBox"
import {PlayerOO} from "@/holycow"
export default async function Page({params: {telegramId}}) {
const playerResponse = await fetch(`${process.env.BASE_URL}/api/results/telegram/${telegramId}`)
const player: PlayerOO = await playerResponse.json()
return (
<ProfileBox
player={player}
/>
)
} }

View file

@ -18,3 +18,7 @@ hr {
/* TODO: Fix in bluelib */ /* TODO: Fix in bluelib */
align-items: center; align-items: center;
} }
.fof {
text-align: center;
}

View file

@ -28,7 +28,13 @@ export default function RootLayout({ children }) {
<body> <body>
<header> <header>
<h2> <h2>
Stagione 1 <span>
Stagione 1:
</span>
<br/>
<small>
Standard Brawl
</small>
</h2> </h2>
</header> </header>
<TelegramContext.Provider value={telegram}> <TelegramContext.Provider value={telegram}>
@ -38,7 +44,9 @@ export default function RootLayout({ children }) {
<p> <p>
© Stefano Pigozzi © Stefano Pigozzi
&nbsp;-&nbsp; &nbsp;-&nbsp;
che cursata, non ha senso, che cursata Star Shard
&nbsp;-&nbsp;
che cursata le miniapp di telegram
</p> </p>
</footer> </footer>
</body> </body>

View file

@ -0,0 +1,19 @@
import {ProfileBox} from "@/components/ProfileBox"
import {PlayerOO} from "@/holycow"
export default async function Page() {
return (
<div className={"panel box fof"}>
<h3>
👍
</h3>
<p>
hai scoperto la pagina di tutti i tempi
</p>
<p>
congrats!!
</p>
</div>
)
}

View file

@ -14,8 +14,6 @@ export default function Page() {
useEffect( useEffect(
() => { () => {
switch(startParam) { switch(startParam) {
case undefined:
return
case "profile": case "profile":
router.replace(`/${data.user.id}/profile`) router.replace(`/${data.user.id}/profile`)
return return
@ -23,7 +21,7 @@ export default function Page() {
router.replace(`/${data.user.id}/report`) router.replace(`/${data.user.id}/report`)
return return
default: default:
router.replace(`/error404`) router.replace(`/none`)
return return
} }
}, },
@ -32,7 +30,7 @@ export default function Page() {
return ( return (
<LoadingBox> <LoadingBox>
Connecting to Telegram... Connessione a Telegram in corso...
</LoadingBox> </LoadingBox>
) )
} }

View file

@ -1,81 +1,57 @@
import {StatPanel} from "@/components/StatPanel" import {StatPanel} from "@/components/StatPanel"
import {PlayerOO} from "@/holycow"
import classNames from "classnames" import classNames from "classnames"
export type ProfileBoxProps = { export type ProfileBoxProps = {
userName: string, player: PlayerOO
played: number,
won: number,
rating: number,
uncertainty: number,
} }
export function ProfileBox({userName, played, won, rating, uncertainty}: ProfileBoxProps) { export function ProfileBox({player}: ProfileBoxProps) {
return ( return (
<div className={"chapter-1"}> <div className={"chapter-1"}>
<div className={"panel box"}> <div className={"panel box"}>
<h3> <h3>
{userName} {player.username}
</h3> </h3>
<div className={"chapter-4"}> <div className={"chapter-4"}>
<StatPanel <StatPanel
name={"Giocate"} name={"Giocate"}
className={classNames({
"fade": player.played === 0
})}
value={( value={(
<data <data value={player.played}>
className={classNames({ {player.played}
"fade": played === 0
})}
value={played}
>
{played}
</data> </data>
)} )}
/> />
<StatPanel <StatPanel
name={"Vinte"} name={"Vinte"}
className={classNames({
"fade": player.wins === 0,
"green": player.wins !== 0,
})}
value={( value={(
<data <data value={player.wins}>
className={classNames({ {player.wins}
"fade": won === 0
})}
value={won}
>
{won}
</data> </data>
)} )}
/> />
<StatPanel {player.human_score !== null &&
name={"Punteggio"} <StatPanel
value={( name={"★"}
<span className={"yellow"}
className={classNames({ value={(
"fade": rating === 0 <span>
})} <data value={player.human_score}>
> {player.human_score}
{rating === 0 </data>
? </span>
<> )}
<data value={rating}> />
- }
</data>
</>
:
<>
<data value={rating}>
{rating}
</data>
<span>
±
</span>
<data value={uncertainty}>
{uncertainty}
</data>
</>
}
</span>
)}
/>
</div> </div>
</div> </div>
</div> </div>

View file

@ -1,9 +1,9 @@
import classNames from "classnames"; import classNames from "classnames";
import style from "./StatPanel.module.css" import style from "./StatPanel.module.css"
export function StatPanel({name, value, display = value}) { export function StatPanel({className, name, value, display = value}) {
return ( return (
<div className={classNames("panel", style.panel)}> <div className={classNames("panel", style.panel, className)}>
<h4 className={style.name}> <h4 className={style.name}>
{name} {name}
</h4> </h4>

View file

@ -10,3 +10,12 @@ export type PlayerO = {
username: string, username: string,
human_score: null | number, human_score: null | number,
} }
export type PlayerOO = {
id: number,
telegram_id: number,
username: string,
human_score: null | number,
played: number,
wins: number,
}