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:?}");
let uncertain = self.0.rating - self.0.uncertainty;
log::trace!("Minimum score is: {uncertain:?}");
let multiplied = uncertain * 100.0;
let multiplied = uncertain * 300.0 / 5.0;
log::trace!("Multiplied score is: {multiplied:?}");
let floored: f64 = multiplied.floor();
log::trace!("Floored score is: {floored:?}");
let converted: i64 = floored as i64;
let ceiled: f64 = multiplied.ceil();
log::trace!("Ceiled score is: {ceiled:?}");
let converted: i64 = ceiled as i64;
log::debug!("Human score for {rating:?}±{uncertainty:?} is {converted:?}");
converted
}
@ -231,6 +231,15 @@ impl Match {
.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> {
schema::matches::table
.select(diesel::dsl::count_star())

View file

@ -75,6 +75,9 @@ async fn main() -> anyhow::Result<Infallible> {
.route("/api/matches/",
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",
telegram_router
)

View file

@ -1,5 +1,6 @@
use axum::http::StatusCode;
use axum::{Extension, Json};
use axum::extract::Path;
use diesel::{Connection, PgConnection};
use serde::Deserialize;
use skillratings::weng_lin::WengLinConfig;
@ -9,6 +10,14 @@ use teloxide::types::{ChatId, MessageId, ParseMode, ThreadId};
use crate::config;
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]
pub async fn get_all()
-> Result<Json<Vec<Match>>, StatusCode>
@ -22,29 +31,46 @@ pub async fn get_all()
Ok(Json(matches))
}
#[derive(Debug, Clone, Deserialize)]
pub struct MatchII {
name: Option<String>,
player_a: i32,
player_b: i32,
outcome: Outcome,
#[axum::debug_handler]
pub async fn get_played_by_id(
Path(player_id): Path<i32>,
)
-> Result<Json<Vec<Match>>, StatusCode>
{
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 {
let name = &player.username;
let competitive = &player.competitive;
let telegram_id = &player.telegram_id;
let telegram_id = &player.telegram_id.clone().map(|t| t.0);
match competitive {
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 => {
let before = before.human_score();
let after = after.human_score();
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()))
}
// 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]
pub async fn get_by_id(
Path(player_id): Path<i32>,
)
-> Result<Json<PlayerO>, StatusCode>
-> Result<Json<PlayerOO>, StatusCode>
{
let mut conn = PgConnection::establish(config::DATABASE_URL())
.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?;
@ -56,14 +67,29 @@ pub async fn get_by_id(
.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?
.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]
pub async fn get_by_telegram_id(
Path(telegram_id): Path<TelegramId>,
)
-> Result<Json<PlayerO>, StatusCode>
-> Result<Json<PlayerOO>, StatusCode>
{
let mut conn = PgConnection::establish(config::DATABASE_URL())
.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?;
@ -72,5 +98,20 @@ pub async fn get_by_telegram_id(
.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?
.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 */
align-items: center;
}
.fof {
text-align: center;
}

View file

@ -28,7 +28,13 @@ export default function RootLayout({ children }) {
<body>
<header>
<h2>
Stagione 1
<span>
Stagione 1:
</span>
<br/>
<small>
Standard Brawl
</small>
</h2>
</header>
<TelegramContext.Provider value={telegram}>
@ -38,7 +44,9 @@ export default function RootLayout({ children }) {
<p>
© Stefano Pigozzi
&nbsp;-&nbsp;
che cursata, non ha senso, che cursata
Star Shard
&nbsp;-&nbsp;
che cursata le miniapp di telegram
</p>
</footer>
</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(
() => {
switch(startParam) {
case undefined:
return
case "profile":
router.replace(`/${data.user.id}/profile`)
return
@ -23,7 +21,7 @@ export default function Page() {
router.replace(`/${data.user.id}/report`)
return
default:
router.replace(`/error404`)
router.replace(`/none`)
return
}
},
@ -32,7 +30,7 @@ export default function Page() {
return (
<LoadingBox>
Connecting to Telegram...
Connessione a Telegram in corso...
</LoadingBox>
)
}

View file

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

View file

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

View file

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