diff --git a/cli/src/commands/board.rs b/cli/src/commands/board.rs new file mode 100644 index 0000000..8111032 --- /dev/null +++ b/cli/src/commands/board.rs @@ -0,0 +1,279 @@ +use clap::Subcommand; +use color_eyre::Result; +use futures::StreamExt; +use lichess_api::client::LichessApi; +use lichess_api::model::board::*; +use lichess_api::model::{Color, Room, VariantKey}; +use reqwest; + +type Lichess = LichessApi; + +#[derive(Debug, Subcommand)] +pub enum BoardCommand { + /// Abort a game + Abort { + /// Game ID + game_id: String, + }, + /// Go berserk on an arena tournament game + Berserk { + /// Game ID + game_id: String, + }, + /// Stream the messages of a game chat + StreamChat { + /// Game ID + game_id: String, + }, + /// Write in the chat of a game + WriteChat { + /// Game ID + game_id: String, + /// Room (player or spectator) + #[arg(long, default_value = "player")] + room: String, + /// Message text + text: String, + }, + /// Claim victory when the opponent has left the game for a while + ClaimVictory { + /// Game ID + game_id: String, + }, + /// Create/accept/decline draw offers + HandleDraw { + /// Game ID + game_id: String, + /// Accept a draw offer + #[arg(long)] + accept: bool, + }, + /// Make a move in a game + MakeMove { + /// Game ID + game_id: String, + /// Move in UCI format (e.g., e2e4) + r#move: String, + /// Whether to offer a draw + #[arg(long)] + offering_draw: bool, + }, + /// Resign a game + Resign { + /// Game ID + game_id: String, + }, + /// Create a seek to get paired with another player + CreateSeek { + /// Whether the game is rated + #[arg(long)] + rated: bool, + /// Clock time in minutes + #[arg(long)] + time: Option, + /// Clock increment in seconds + #[arg(long)] + increment: Option, + /// Days per turn for correspondence games + #[arg(long)] + days: Option, + /// Chess variant + #[arg(long, default_value = "standard")] + variant: String, + /// Color preference (random, white, black) + #[arg(long, default_value = "random")] + color: String, + /// Rating range minimum + #[arg(long)] + rating_range_min: Option, + /// Rating range maximum + #[arg(long)] + rating_range_max: Option, + }, + /// Stream incoming events (challenges, game starts) + StreamEvents, + /// Stream the state of a game being played + StreamGame { + /// Game ID + game_id: String, + }, + /// Propose/accept/decline takebacks + HandleTakeback { + /// Game ID + game_id: String, + /// Accept a takeback offer + #[arg(long)] + accept: bool, + }, +} + +impl BoardCommand { + pub async fn run(self, lichess: Lichess) -> Result<()> { + match self { + BoardCommand::Abort { game_id } => { + let request = abort::PostRequest::new(&game_id); + let result = lichess.board_abort_game(request).await?; + println!("Game aborted: {}", result); + Ok(()) + } + BoardCommand::Berserk { game_id } => { + let request = berserk::PostRequest::new(&game_id); + let result = lichess.board_berserk_game(request).await?; + println!("Berserk activated: {}", result); + Ok(()) + } + BoardCommand::StreamChat { game_id } => { + let request = chat::GetRequest::new(&game_id); + let mut stream = lichess.board_stream_game_chat(request).await?; + println!("Streaming chat messages:"); + while let Some(Ok(messages)) = stream.next().await { + for chat_line in messages { + println!("{}: {}", chat_line.user, chat_line.text); + } + } + Ok(()) + } + BoardCommand::WriteChat { + game_id, + room, + text, + } => { + let room_enum = match room.as_str() { + "spectator" => Room::Spectator, + _ => Room::Player, + }; + let request = chat::PostRequest::new(&game_id, room_enum, &text); + let result = lichess.board_write_in_chat(request).await?; + println!("Message sent: {}", result); + Ok(()) + } + BoardCommand::ClaimVictory { game_id } => { + let request = claim_victory::PostRequest::new(&game_id); + let result = lichess.board_claim_victory(request).await?; + println!("Victory claimed: {}", result); + Ok(()) + } + BoardCommand::HandleDraw { game_id, accept } => { + let request = draw::PostRequest::new(&game_id, accept); + let result = lichess.board_handle_draw(request).await?; + println!("Draw handled: {}", result); + Ok(()) + } + BoardCommand::MakeMove { + game_id, + r#move, + offering_draw, + } => { + let request = r#move::PostRequest::new(&game_id, &r#move, offering_draw); + let result = lichess.board_make_move(request).await?; + println!("Move made: {}", result); + Ok(()) + } + BoardCommand::Resign { game_id } => { + let request = resign::PostRequest::new(&game_id); + let result = lichess.board_resign_game(request).await?; + println!("Game resigned: {}", result); + Ok(()) + } + BoardCommand::CreateSeek { + rated, + time, + increment, + days, + variant, + color, + rating_range_min, + rating_range_max, + } => { + let variant_key = match variant.as_str() { + "standard" => VariantKey::Standard, + "chess960" => VariantKey::Chess960, + "crazyhouse" => VariantKey::Crazyhouse, + "antichess" => VariantKey::Antichess, + "atomic" => VariantKey::Atomic, + "horde" => VariantKey::Horde, + "kingOfTheHill" => VariantKey::KingOfTheHill, + "racingKings" => VariantKey::RacingKings, + "threeCheck" => VariantKey::ThreeCheck, + _ => VariantKey::Standard, + }; + + let color_choice = match color.as_str() { + "white" => Color::White, + "black" => Color::Black, + _ => Color::Random, + }; + + let seek_type = if let Some(days) = days { + seek::SeekType::Correspondence { days: days.into() } + } else { + let time_mins = time.unwrap_or(10.0); + let time_secs = (time_mins * 60.0) as u32; + seek::SeekType::RealTime { + time: time_secs, + increment: increment.unwrap_or(0), + } + }; + + let rating_range = if rating_range_min.is_some() || rating_range_max.is_some() { + format!( + "{}-{}", + rating_range_min.unwrap_or(800), + rating_range_max.unwrap_or(2800) + ) + } else { + "".to_string() + }; + + let query = seek::PostQuery { + seek_type, + rated, + variant: variant_key, + color: color_choice, + rating_range, + }; + + let request = seek::PostRequest::new(query); + let mut stream = lichess.board_create_a_seek(request).await?; + println!("Creating seek:"); + while let Some(event) = stream.next().await { + match event { + Ok(json) => println!("Event: {}", json), + Err(e) => eprintln!("Error: {}", e), + } + } + Ok(()) + } + BoardCommand::StreamEvents => { + let request = stream::events::GetRequest::new(); + let mut stream = lichess.board_stream_incoming_events(request).await?; + println!("Streaming incoming events:"); + while let Some(event) = stream.next().await { + match event { + Ok(event) => println!("Event: {:#?}", event), + Err(e) => eprintln!("Error: {}", e), + } + } + Ok(()) + } + BoardCommand::StreamGame { game_id } => { + let request = stream::game::GetRequest::new(&game_id); + let mut stream = lichess.board_stream_board_state(request).await?; + println!("Streaming game state:"); + while let Some(event) = stream.next().await { + match event { + Ok(event) => println!("Event: {:#?}", event), + Err(e) => eprintln!("Error: {}", e), + } + } + Ok(()) + } + BoardCommand::HandleTakeback { game_id, accept } => { + let request = takeback::PostRequest::new(&game_id, accept); + let result = lichess.board_handle_takeback(request).await?; + println!("Takeback handled: {}", result); + Ok(()) + } + } + } +} diff --git a/cli/src/commands/mod.rs b/cli/src/commands/mod.rs index 485ab59..6b1aa6e 100644 --- a/cli/src/commands/mod.rs +++ b/cli/src/commands/mod.rs @@ -1,8 +1,10 @@ +pub mod board; pub mod challenges; pub mod external_engine; pub mod puzzles; pub mod users; +pub use board::BoardCommand; pub use challenges::ChallengesCommand; pub use external_engine::ExternalEngineCommand; pub use puzzles::PuzzlesCommand; diff --git a/cli/src/main.rs b/cli/src/main.rs index d11a365..6701569 100644 --- a/cli/src/main.rs +++ b/cli/src/main.rs @@ -4,7 +4,9 @@ use clap::builder::Styles; use clap::builder::styling::AnsiColor; use clap::{Parser, Subcommand}; use color_eyre::Result; -use commands::{ChallengesCommand, ExternalEngineCommand, PuzzlesCommand, UsersCommand}; +use commands::{ + BoardCommand, ChallengesCommand, ExternalEngineCommand, PuzzlesCommand, UsersCommand, +}; use lichess_api::client::LichessApi; use reqwest; use tracing::level_filters::LevelFilter; @@ -33,6 +35,10 @@ struct Cli { #[derive(Debug, Subcommand)] enum Command { + Board { + #[clap(subcommand)] + command: BoardCommand, + }, Puzzles { #[clap(subcommand)] command: PuzzlesCommand, @@ -94,6 +100,7 @@ impl App { async fn run(self, args: Cli) -> Result<()> { match args.command { + Command::Board { command } => command.run(self.lichess).await, Command::Puzzles { command } => command.run(self.lichess).await, Command::Engine { command } => command.run(self.lichess).await, Command::Challenges { command } => command.run(self.lichess).await, diff --git a/lib/src/api/board.rs b/lib/src/api/board.rs index 87d1396..6d4e25a 100644 --- a/lib/src/api/board.rs +++ b/lib/src/api/board.rs @@ -19,7 +19,7 @@ impl LichessApi { pub async fn board_stream_game_chat( &self, request: impl Into, - ) -> Result>> { + ) -> Result>>> { self.get_streamed_models(request.into()).await } diff --git a/lib/src/client.rs b/lib/src/client.rs index e58b123..89045b5 100644 --- a/lib/src/client.rs +++ b/lib/src/client.rs @@ -80,7 +80,15 @@ impl LichessApi { let convert_err = |e: reqwest::Error| Error::Request(e.to_string()); let request = reqwest::Request::try_from(http_request).map_err(convert_err)?; - debug!(?request, "sending"); + let body_text = if let Some(body) = request.body() { + match body.as_bytes() { + Some(bytes) => String::from_utf8_lossy(bytes).to_string(), + None => "".to_string(), + } + } else { + "".to_string() + }; + debug!(?request, body = %body_text, "sending"); let response = self.client.execute(request).await; debug!(?response, "received"); let stream = response diff --git a/lib/src/model/board/stream/events.rs b/lib/src/model/board/stream/events.rs index a89323a..df6ed2b 100644 --- a/lib/src/model/board/stream/events.rs +++ b/lib/src/model/board/stream/events.rs @@ -51,16 +51,26 @@ pub struct GameEventInfo { pub color: Color, pub last_move: String, pub source: Source, + pub status: GameStatus, pub variant: Variant, pub speed: Speed, pub perf: String, pub rated: bool, pub has_moved: bool, - pub opponent: Opponent, + pub opponent: GameEventOpponent, pub is_my_turn: bool, pub seconds_left: Option, + pub tournament_id: Option, pub compat: Option, pub winner: Option, + pub rating_diff: Option, + pub id: String, +} + +#[derive(Clone, Debug, Deserialize, Serialize)] +pub struct GameStatus { + pub id: u32, + pub name: String, } #[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize)] @@ -78,15 +88,25 @@ pub enum Source { Relay, Pool, Swiss, + Arena, } -#[skip_serializing_none] #[derive(Clone, Debug, Serialize, Deserialize)] -pub struct Opponent { - pub id: Option, - pub username: String, - pub rating: Option, - pub ai: Option, +#[serde(untagged)] +#[serde(rename_all_fields = "camelCase")] +pub enum GameEventOpponent { + Player { + id: String, + username: String, + rating: u32, + #[serde(skip_serializing_if = "Option::is_none")] + rating_diff: Option, + }, + AI { + id: Option, // Always null for AI + username: String, + ai: u32, + }, } #[derive(Clone, Debug, Deserialize, Serialize)] diff --git a/lib/src/model/board/stream/game.rs b/lib/src/model/board/stream/game.rs index 86f51c6..d272c17 100644 --- a/lib/src/model/board/stream/game.rs +++ b/lib/src/model/board/stream/game.rs @@ -2,6 +2,31 @@ use crate::model::{Clock, Room, Speed, Variant}; use serde::{Deserialize, Serialize}; use serde_with::skip_serializing_none; +#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize)] +#[serde(rename_all = "lowercase")] +pub enum GameColor { + White, + Black, +} + +#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize)] +#[serde(rename_all = "camelCase")] +pub enum GameStatusName { + Created, + Started, + Aborted, + Mate, + Resign, + Stalemate, + Timeout, + Draw, + Outoftime, + Cheat, + NoStart, + UnknownFinish, + VariantEnd, +} + #[derive(Default, Clone, Debug, Serialize)] pub struct GetQuery; @@ -26,26 +51,26 @@ impl> From for GetRequest { pub enum Event { GameFull { #[serde(flatten)] - game_full: GameFull, + game_full: GameFullEvent, }, GameState { #[serde(flatten)] - game_state: GameState, + game_state: GameStateEvent, }, ChatLine { #[serde(flatten)] - chat_line: ChatLine, + chat_line: ChatLineEvent, }, OpponentGone { #[serde(flatten)] - opponent_gone: OpponentGone, + opponent_gone: OpponentGoneEvent, }, } #[skip_serializing_none] #[derive(Clone, Debug, Deserialize, Serialize)] #[serde(rename_all = "camelCase")] -pub struct GameFull { +pub struct GameFullEvent { pub id: String, pub variant: Variant, pub rated: bool, @@ -56,14 +81,14 @@ pub struct GameFull { pub white: GameEventPlayer, pub black: GameEventPlayer, pub initial_fen: Option, - pub state: Option, + pub state: Option, pub tournament_id: Option, } #[skip_serializing_none] #[derive(Clone, Debug, Deserialize, Serialize)] #[serde(rename_all = "camelCase")] -pub struct GameState { +pub struct GameStateEvent { // Will always be gameState, but needed to avoid cycles. pub r#type: Option, pub moves: String, @@ -71,8 +96,8 @@ pub struct GameState { pub btime: u64, pub winc: u64, pub binc: u64, - pub status: String, - pub winner: Option, + pub status: GameStatusName, + pub winner: Option, pub wdraw: Option, pub bdraw: Option, pub wtakeback: Option, @@ -82,7 +107,7 @@ pub struct GameState { #[skip_serializing_none] #[derive(Clone, Debug, Deserialize, Serialize)] #[serde(rename_all = "camelCase")] -pub struct ChatLine { +pub struct ChatLineEvent { pub room: Room, pub username: String, pub text: String, @@ -91,40 +116,23 @@ pub struct ChatLine { #[skip_serializing_none] #[derive(Clone, Debug, Deserialize, Serialize)] #[serde(rename_all = "camelCase")] -pub struct OpponentGone { +pub struct OpponentGoneEvent { pub gone: bool, pub claim_win_in_seconds: Option, } -#[skip_serializing_none] #[derive(Clone, Debug, Deserialize, Serialize)] -#[serde(untagged)] -#[serde(rename_all = "camelCase")] -pub enum GameEventPlayer { - AI { - #[serde(flatten)] - ai: GameEventAI, - }, - Human { - #[serde(flatten)] - human: GameEventHuman, - }, - Anonymous {}, -} - -#[derive(Clone, Debug, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct GameEventAI { - pub ai_level: u32, -} - -#[skip_serializing_none] -#[derive(Clone, Debug, Serialize, Deserialize)] -pub struct GameEventHuman { +pub struct GameEventPlayer { pub id: String, pub name: String, + #[serde(skip_serializing_if = "Option::is_none")] + pub ai_level: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub title: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub rating: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub provisional: Option, } diff --git a/lib/src/model/challenges/mod.rs b/lib/src/model/challenges/mod.rs index 1cd1d17..b499c3a 100644 --- a/lib/src/model/challenges/mod.rs +++ b/lib/src/model/challenges/mod.rs @@ -204,6 +204,7 @@ pub struct ChallengeDeclinedEvent { #[derive(Clone, Debug, Deserialize, Serialize)] #[serde(tag = "type")] #[serde(rename_all = "camelCase")] +#[serde(rename_all_fields = "camelCase")] pub enum TimeControl { Clock { increment: u32, @@ -216,16 +217,20 @@ pub enum TimeControl { Unlimited, } -#[skip_serializing_none] #[derive(Clone, Debug, Deserialize, Serialize)] pub struct ChallengeUser { pub id: String, pub name: String, pub rating: u32, pub title: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub flair: Option<String>, + #[serde(skip_serializing_if = "Option::is_none")] pub patron: Option<bool>, + #[serde(skip_serializing_if = "Option::is_none")] pub provisional: Option<bool>, + #[serde(skip_serializing_if = "Option::is_none")] pub online: Option<bool>, + #[serde(skip_serializing_if = "Option::is_none")] pub lag: Option<u32>, } diff --git a/lib/src/model/mod.rs b/lib/src/model/mod.rs index 34b6d29..2aaf05f 100644 --- a/lib/src/model/mod.rs +++ b/lib/src/model/mod.rs @@ -389,7 +389,7 @@ pub struct Clock { pub total_time: Option<u32>, } -#[derive(Clone, Debug, PartialEq, Eq, Serialize)] +#[derive(Clone, Copy, Debug, PartialEq, Eq)] pub enum Days { One, Two, @@ -400,6 +400,26 @@ pub enum Days { Fourteen, } +impl Serialize for Days { + fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> + where + S: serde::Serializer, + { + let value: u32 = (*self).into(); + value.serialize(serializer) + } +} + +impl<'de> Deserialize<'de> for Days { + fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> + where + D: serde::Deserializer<'de>, + { + let value = u32::deserialize(deserializer)?; + Ok(Days::from(value)) + } +} + impl From<u32> for Days { fn from(value: u32) -> Self { match value { diff --git a/lib/tests/data/response/challenge_ai.json b/lib/tests/data/response/challenge_ai.json deleted file mode 100644 index 6d0b73d..0000000 --- a/lib/tests/data/response/challenge_ai.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "id": "0PBNxATa", - "variant": { - "key": "standard", - "name": "Standard", - "short": "Std" - }, - "speed": "blitz", - "perf": "blitz", - "rated": false, - "fen": "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1", - "turns": 0, - "source": "ai", - "status": { - "id": 20, - "name": "started" - }, - "createdAt": 1704320123711, - "player": "white" -} diff --git a/lib/tests/data/response/challenge_anonymous.json b/lib/tests/data/response/challenge_anonymous.json deleted file mode 100644 index 125485f..0000000 --- a/lib/tests/data/response/challenge_anonymous.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "type": "challenge", - "challenge": { - "id": "7pGLxJ4F", - "url": "https://lichess.org/VU0nyvsW", - "status": "created", - "destUser": { - "id": "thibot", - "name": "thibot", - "rating": 1500, - "provisional": true, - "online": true, - "lag": 45 - }, - "variant": { - "key": "standard", - "name": "Standard", - "short": "Std" - }, - "rated": true, - "timeControl": { - "type": "clock", - "limit": 300, - "increment": 25, - "show": "5+25" - }, - "color": "random", - "speed": "rapid", - "perf": { - "icon": "#", - "name": "Rapid" - } - } -} diff --git a/lib/tests/data/response/challenge_canceled_event.json b/lib/tests/data/response/challenge_canceled_event.json deleted file mode 100644 index b98bd31..0000000 --- a/lib/tests/data/response/challenge_canceled_event.json +++ /dev/null @@ -1,46 +0,0 @@ -{ - "type": "challengeCanceled", - "challenge": { - "id": "H9fIRZUk", - "url": "https://lichess.org/H9fIRZUk", - "status": "canceled", - "challenger": { - "id": "bot1", - "name": "Bot1", - "rating": 1500, - "title": "BOT", - "provisional": true, - "online": true, - "lag": 4 - }, - "destUser": { - "id": "bobby", - "name": "Bobby", - "rating": 1635, - "title": "GM", - "provisional": true, - "online": true, - "lag": 4 - }, - "variant": { - "key": "standard", - "name": "Standard", - "short": "Std" - }, - "rated": true, - "speed": "rapid", - "timeControl": { - "type": "clock", - "limit": 600, - "increment": 0, - "show": "10+0" - }, - "color": "random", - "finalColor": "black", - "perf": { - "icon": "", - "name": "Rapid" - }, - "direction": "out" - } -} \ No newline at end of file diff --git a/lib/tests/data/response/challenge_canceled.json b/lib/tests/data/response/challenge_canceled_event1.json similarity index 52% rename from lib/tests/data/response/challenge_canceled.json rename to lib/tests/data/response/challenge_canceled_event1.json index 9e3d3f2..7773f56 100644 --- a/lib/tests/data/response/challenge_canceled.json +++ b/lib/tests/data/response/challenge_canceled_event1.json @@ -1,25 +1,26 @@ { "type": "challengeCanceled", "challenge": { - "id": "7pGLxJ4F", - "url": "https://lichess.org/VU0nyvsW", - "status": "created", + "id": "H9fIRZUk", + "url": "https://lichess.org/H9fIRZUk", + "status": "canceled", "challenger": { - "id": "lovlas", - "name": "Lovlas", - "title": "IM", - "rating": 2506, - "patron": true, + "id": "bot1", + "name": "Bot1", + "rating": 1500, + "title": "BOT", + "provisional": true, "online": true, - "lag": 24 + "lag": 4 }, "destUser": { - "id": "thibot", - "name": "thibot", - "rating": 1500, + "id": "bobby", + "name": "Bobby", + "rating": 1635, + "title": "GM", "provisional": true, "online": true, - "lag": 45 + "lag": 4 }, "variant": { "key": "standard", @@ -27,17 +28,19 @@ "short": "Std" }, "rated": true, + "speed": "rapid", "timeControl": { "type": "clock", - "limit": 300, - "increment": 25, - "show": "5+25" + "limit": 600, + "increment": 0, + "show": "10+0" }, "color": "random", - "speed": "rapid", + "finalColor": "black", "perf": { - "icon": "#", + "icon": "", "name": "Rapid" - } + }, + "direction": "out" } -} +} \ No newline at end of file diff --git a/lib/tests/data/response/challenge_canceled_event2.json b/lib/tests/data/response/challenge_canceled_event2.json new file mode 100644 index 0000000..67ec795 --- /dev/null +++ b/lib/tests/data/response/challenge_canceled_event2.json @@ -0,0 +1,38 @@ +{ + "type": "challengeCanceled", + "challenge": { + "id": "vN6JvOli", + "url": "https://lichess.org/vN6JvOli", + "status": "canceled", + "challenger": { + "id": "elena", + "name": "Elena", + "rating": 2308, + "title": "WIM", + "patron": true + }, + "destUser": { + "id": "diego", + "name": "Diego", + "rating": 1941, + "title": null, + "flair": "smileys.winking-face-with-tongue" + }, + "variant": { + "key": "standard", + "name": "Standard", + "short": "Std" + }, + "rated": false, + "speed": "correspondence", + "timeControl": { + "type": "unlimited" + }, + "color": "random", + "finalColor": "white", + "perf": { + "icon": "", + "name": "Correspondence" + } + } +} \ No newline at end of file diff --git a/lib/tests/data/response/challenge_declined_event.json b/lib/tests/data/response/challenge_declined_event.json deleted file mode 100644 index c7dbf29..0000000 --- a/lib/tests/data/response/challenge_declined_event.json +++ /dev/null @@ -1,48 +0,0 @@ -{ - "type": "challengeDeclined", - "challenge": { - "id": "H9fIRZUk", - "url": "https://lichess.org/H9fIRZUk", - "status": "declined", - "challenger": { - "id": "bot1", - "name": "Bot1", - "rating": 1500, - "title": "BOT", - "provisional": true, - "online": true, - "lag": 4 - }, - "destUser": { - "id": "bobby", - "name": "Bobby", - "rating": 1635, - "title": "GM", - "provisional": true, - "online": true, - "lag": 4 - }, - "variant": { - "key": "standard", - "name": "Standard", - "short": "Std" - }, - "rated": true, - "speed": "rapid", - "timeControl": { - "type": "clock", - "limit": 600, - "increment": 0, - "show": "10+0" - }, - "color": "random", - "finalColor": "black", - "perf": { - "icon": "", - "name": "Rapid" - }, - "direction": "out", - "declineReason": "I'm not accepting challenges at the moment", - "declineReasonKey": "generic" - } -} \ No newline at end of file diff --git a/lib/tests/data/response/challenge_declined.json b/lib/tests/data/response/challenge_declined_event1.json similarity index 54% rename from lib/tests/data/response/challenge_declined.json rename to lib/tests/data/response/challenge_declined_event1.json index e516952..a9f6b1e 100644 --- a/lib/tests/data/response/challenge_declined.json +++ b/lib/tests/data/response/challenge_declined_event1.json @@ -1,25 +1,26 @@ { "type": "challengeDeclined", "challenge": { - "id": "7pGLxJ4F", - "url": "https://lichess.org/VU0nyvsW", + "id": "H9fIRZUk", + "url": "https://lichess.org/H9fIRZUk", "status": "declined", "challenger": { - "id": "lovlas", - "name": "Lovlas", - "title": "IM", - "rating": 2506, - "patron": true, + "id": "bot1", + "name": "Bot1", + "rating": 1500, + "title": "BOT", + "provisional": true, "online": true, - "lag": 24 + "lag": 4 }, "destUser": { - "id": "thibot", - "name": "thibot", - "rating": 1500, + "id": "bobby", + "name": "Bobby", + "rating": 1635, + "title": "GM", "provisional": true, "online": true, - "lag": 45 + "lag": 4 }, "variant": { "key": "standard", @@ -27,19 +28,21 @@ "short": "Std" }, "rated": true, + "speed": "rapid", "timeControl": { "type": "clock", - "limit": 300, - "increment": 25, - "show": "5+25" + "limit": 600, + "increment": 0, + "show": "10+0" }, "color": "random", - "speed": "rapid", + "finalColor": "black", "perf": { - "icon": "#", + "icon": "", "name": "Rapid" }, - "declineReason": "I'm not interested in playing right now", + "direction": "out", + "declineReason": "I'm not accepting challenges at the moment", "declineReasonKey": "generic" } -} +} \ No newline at end of file diff --git a/lib/tests/data/response/challenge_declined_event2.json b/lib/tests/data/response/challenge_declined_event2.json new file mode 100644 index 0000000..c239af0 --- /dev/null +++ b/lib/tests/data/response/challenge_declined_event2.json @@ -0,0 +1,40 @@ +{ + "type": "challengeDeclined", + "challenge": { + "id": "HVGoj16M", + "url": "https://lichess.org/HVGoj16M", + "status": "declined", + "challenger": { + "id": "adriana", + "name": "Adriana", + "rating": 584, + "title": null + }, + "destUser": { + "id": "gabriela", + "name": "Gabriela", + "rating": 1569, + "title": null, + "flair": "people.pregnant-person-light-skin-tone", + "online": true + }, + "variant": { + "key": "standard", + "name": "Standard", + "short": "Std" + }, + "rated": false, + "speed": "correspondence", + "timeControl": { + "type": "unlimited" + }, + "color": "random", + "finalColor": "black", + "perf": { + "icon": "", + "name": "Correspondence" + }, + "declineReason": "I'm not accepting challenges at the moment.", + "declineReasonKey": "generic" + } +} \ No newline at end of file diff --git a/lib/tests/data/response/challenge_declined_json.json b/lib/tests/data/response/challenge_declined_json.json index 8dbf39f..c572813 100644 --- a/lib/tests/data/response/challenge_declined_json.json +++ b/lib/tests/data/response/challenge_declined_json.json @@ -1,45 +1,45 @@ { - "id": "H9fIRZUk", - "url": "https://lichess.org/H9fIRZUk", - "status": "declined", - "challenger": { - "id": "bot1", - "name": "Bot1", - "rating": 1500, - "title": "BOT", - "provisional": true, - "online": true, - "lag": 4 - }, - "destUser": { - "id": "bobby", - "name": "Bobby", - "rating": 1635, - "title": "GM", - "provisional": true, - "online": true, - "lag": 4 - }, - "variant": { - "key": "standard", - "name": "Standard", - "short": "Std" - }, - "rated": true, - "speed": "rapid", - "timeControl": { - "type": "clock", - "limit": 600, - "increment": 0, - "show": "10+0" - }, - "color": "random", - "finalColor": "black", - "perf": { - "icon": "", - "name": "Rapid" - }, - "direction": "out", - "declineReason": "I'm not accepting challenges at the moment", - "declineReasonKey": "generic" + "id": "H9fIRZUk", + "url": "https://lichess.org/H9fIRZUk", + "status": "declined", + "challenger": { + "id": "bot1", + "name": "Bot1", + "rating": 1500, + "title": "BOT", + "provisional": true, + "online": true, + "lag": 4 + }, + "destUser": { + "id": "bobby", + "name": "Bobby", + "rating": 1635, + "title": "GM", + "provisional": true, + "online": true, + "lag": 4 + }, + "variant": { + "key": "standard", + "name": "Standard", + "short": "Std" + }, + "rated": true, + "speed": "rapid", + "timeControl": { + "type": "clock", + "limit": 600, + "increment": 0, + "show": "10+0" + }, + "color": "random", + "finalColor": "black", + "perf": { + "icon": "", + "name": "Rapid" + }, + "direction": "out", + "declineReason": "I'm not accepting challenges at the moment", + "declineReasonKey": "generic" } \ No newline at end of file diff --git a/lib/tests/data/response/challenge_event.json b/lib/tests/data/response/challenge_event.json deleted file mode 100644 index 65b9473..0000000 --- a/lib/tests/data/response/challenge_event.json +++ /dev/null @@ -1,50 +0,0 @@ -{ - "type": "challenge", - "challenge": { - "id": "H9fIRZUk", - "url": "https://lichess.org/H9fIRZUk", - "status": "created", - "challenger": { - "id": "bot1", - "name": "Bot1", - "rating": 1500, - "title": "BOT", - "provisional": true, - "online": true, - "lag": 4 - }, - "destUser": { - "id": "bobby", - "name": "Bobby", - "rating": 1635, - "title": "GM", - "provisional": true, - "online": true, - "lag": 4 - }, - "variant": { - "key": "standard", - "name": "Standard", - "short": "Std" - }, - "rated": true, - "speed": "rapid", - "timeControl": { - "type": "clock", - "limit": 600, - "increment": 0, - "show": "10+0" - }, - "color": "random", - "finalColor": "black", - "perf": { - "icon": "", - "name": "Rapid" - }, - "direction": "in" - }, - "compat": { - "bot": false, - "board": true - } -} \ No newline at end of file diff --git a/lib/tests/data/response/challenge.json b/lib/tests/data/response/challenge_event1.json similarity index 58% rename from lib/tests/data/response/challenge.json rename to lib/tests/data/response/challenge_event1.json index 17e0aae..da27030 100644 --- a/lib/tests/data/response/challenge.json +++ b/lib/tests/data/response/challenge_event1.json @@ -1,25 +1,26 @@ { "type": "challenge", "challenge": { - "id": "7pGLxJ4F", - "url": "https://lichess.org/VU0nyvsW", + "id": "H9fIRZUk", + "url": "https://lichess.org/H9fIRZUk", "status": "created", "challenger": { - "id": "lovlas", - "name": "Lovlas", - "title": "IM", - "rating": 2506, - "patron": true, + "id": "bot1", + "name": "Bot1", + "rating": 1500, + "title": "BOT", + "provisional": true, "online": true, - "lag": 24 + "lag": 4 }, "destUser": { - "id": "thibot", - "name": "thibot", - "rating": 1500, + "id": "bobby", + "name": "Bobby", + "rating": 1635, + "title": "GM", "provisional": true, "online": true, - "lag": 45 + "lag": 4 }, "variant": { "key": "standard", @@ -27,22 +28,23 @@ "short": "Std" }, "rated": true, + "speed": "rapid", "timeControl": { "type": "clock", - "limit": 300, - "increment": 25, - "show": "5+25" + "limit": 600, + "increment": 0, + "show": "10+0" }, "color": "random", - "speed": "rapid", + "finalColor": "black", "perf": { - "icon": "#", + "icon": "", "name": "Rapid" }, - "finalColor": "white" + "direction": "in" }, "compat": { "bot": false, "board": true } -} +} \ No newline at end of file diff --git a/lib/tests/data/response/challenge_event2.json b/lib/tests/data/response/challenge_event2.json new file mode 100644 index 0000000..8ac20da --- /dev/null +++ b/lib/tests/data/response/challenge_event2.json @@ -0,0 +1,42 @@ +{ + "type": "challenge", + "challenge": { + "id": "HVGoj16M", + "url": "https://lichess.org/HVGoj16M", + "status": "created", + "challenger": { + "id": "adriana", + "name": "Adriana", + "rating": 584, + "title": null + }, + "destUser": { + "id": "gabriela", + "name": "Gabriela", + "rating": 1569, + "title": null, + "flair": "people.pregnant-person-light-skin-tone", + "online": true + }, + "variant": { + "key": "standard", + "name": "Standard", + "short": "Std" + }, + "rated": false, + "speed": "correspondence", + "timeControl": { + "type": "unlimited" + }, + "color": "random", + "finalColor": "black", + "perf": { + "icon": "", + "name": "Correspondence" + } + }, + "compat": { + "bot": false, + "board": true + } +} \ No newline at end of file diff --git a/lib/tests/data/response/challenge_json.json b/lib/tests/data/response/challenge_json.json index d3eb91a..91c0b52 100644 --- a/lib/tests/data/response/challenge_json.json +++ b/lib/tests/data/response/challenge_json.json @@ -1,43 +1,43 @@ { - "id": "H9fIRZUk", - "url": "https://lichess.org/H9fIRZUk", - "status": "created", - "challenger": { - "id": "bot1", - "name": "Bot1", - "rating": 1500, - "title": "BOT", - "provisional": true, - "online": true, - "lag": 4 - }, - "destUser": { - "id": "bobby", - "name": "Bobby", - "rating": 1635, - "title": "GM", - "provisional": true, - "online": true, - "lag": 4 - }, - "variant": { - "key": "standard", - "name": "Standard", - "short": "Std" - }, - "rated": true, - "speed": "rapid", - "timeControl": { - "type": "clock", - "limit": 600, - "increment": 0, - "show": "10+0" - }, - "color": "random", - "finalColor": "black", - "perf": { - "icon": "", - "name": "Rapid" - }, - "direction": "out" + "id": "H9fIRZUk", + "url": "https://lichess.org/H9fIRZUk", + "status": "created", + "challenger": { + "id": "bot1", + "name": "Bot1", + "rating": 1500, + "title": "BOT", + "provisional": true, + "online": true, + "lag": 4 + }, + "destUser": { + "id": "bobby", + "name": "Bobby", + "rating": 1635, + "title": "GM", + "provisional": true, + "online": true, + "lag": 4 + }, + "variant": { + "key": "standard", + "name": "Standard", + "short": "Std" + }, + "rated": true, + "speed": "rapid", + "timeControl": { + "type": "clock", + "limit": 600, + "increment": 0, + "show": "10+0" + }, + "color": "random", + "finalColor": "black", + "perf": { + "icon": "", + "name": "Rapid" + }, + "direction": "out" } \ No newline at end of file diff --git a/lib/tests/data/response/challenge_open_json.json b/lib/tests/data/response/challenge_open_json.json index 549a596..fa18fc1 100644 --- a/lib/tests/data/response/challenge_open_json.json +++ b/lib/tests/data/response/challenge_open_json.json @@ -1,26 +1,26 @@ { - "id": "XaP00j5r", - "url": "https://lichess.org/XaP00j5r", - "status": "created", - "challenger": null, - "destUser": null, - "variant": { - "key": "standard", - "name": "Standard", - "short": "Std" - }, - "rated": false, - "speed": "correspondence", - "timeControl": { - "type": "unlimited" - }, - "color": "random", - "finalColor": "black", - "perf": { - "icon": "", - "name": "Correspondence" - }, - "open": {}, - "urlWhite": "https://lichess.org/XaP00j5r?color=white", - "urlBlack": "https://lichess.org/XaP00j5r?color=black" + "id": "XaP00j5r", + "url": "https://lichess.org/XaP00j5r", + "status": "created", + "challenger": null, + "destUser": null, + "variant": { + "key": "standard", + "name": "Standard", + "short": "Std" + }, + "rated": false, + "speed": "correspondence", + "timeControl": { + "type": "unlimited" + }, + "color": "random", + "finalColor": "black", + "perf": { + "icon": "", + "name": "Correspondence" + }, + "open": {}, + "urlWhite": "https://lichess.org/XaP00j5r?color=white", + "urlBlack": "https://lichess.org/XaP00j5r?color=black" } \ No newline at end of file diff --git a/lib/tests/data/response/chat_line.json b/lib/tests/data/response/chat_line_event.json similarity index 98% rename from lib/tests/data/response/chat_line.json rename to lib/tests/data/response/chat_line_event.json index 8885192..ee3e396 100644 --- a/lib/tests/data/response/chat_line.json +++ b/lib/tests/data/response/chat_line_event.json @@ -3,4 +3,4 @@ "username": "thibault", "text": "Good luck, have fun", "room": "player" -} +} \ No newline at end of file diff --git a/lib/tests/data/response/chat_line_spectator.json b/lib/tests/data/response/chat_line_spectator.json deleted file mode 100644 index 64dcf29..0000000 --- a/lib/tests/data/response/chat_line_spectator.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "type": "chatLine", - "username": "lovlas", - "text": "!eval", - "room": "spectator" -} diff --git a/lib/tests/data/response/game_chat.json b/lib/tests/data/response/game_chat.json new file mode 100644 index 0000000..722c3a9 --- /dev/null +++ b/lib/tests/data/response/game_chat.json @@ -0,0 +1,14 @@ +[ + { + "text": "Takeback sent", + "user": "lichess" + }, + { + "text": "Takeback accepted", + "user": "lichess" + }, + { + "text": "Good game, well played", + "user": "thibault" + } +] \ No newline at end of file diff --git a/lib/tests/data/response/game_finish.json b/lib/tests/data/response/game_finish.json deleted file mode 100644 index 13dd509..0000000 --- a/lib/tests/data/response/game_finish.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "type": "gameFinish", - "game": { - "gameId": "rCRw1AuO", - "fullId": "rCRw1AuOvonq", - "color": "black", - "fen": "r1bqkbnr/pppp2pp/2n1pp2/8/8/3PP3/PPPB1PPP/RN1QKBNR w KQkq - 2 4", - "hasMoved": true, - "isMyTurn": false, - "lastMove": "b8c6", - "opponent": { - "id": "philippe", - "rating": 1790, - "username": "Philippe" - }, - "perf": "correspondence", - "rated": false, - "secondsLeft": 1209600, - "source": "friend", - "speed": "correspondence", - "variant": { - "key": "standard", - "name": "Standard" - }, - "compat": { - "bot": false, - "board": true - } - } -} diff --git a/lib/tests/data/response/game_finish_ai_event.json b/lib/tests/data/response/game_finish_ai_event.json new file mode 100644 index 0000000..d038434 --- /dev/null +++ b/lib/tests/data/response/game_finish_ai_event.json @@ -0,0 +1,34 @@ +{ + "type": "gameFinish", + "game": { + "fullId": "0jJlyweLDRZW", + "gameId": "0jJlyweL", + "fen": "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1", + "color": "white", + "lastMove": "", + "source": "ai", + "status": { + "id": 25, + "name": "aborted" + }, + "variant": { + "key": "standard", + "name": "Standard" + }, + "speed": "correspondence", + "perf": "correspondence", + "rated": false, + "hasMoved": false, + "opponent": { + "id": null, + "username": "Stockfish level 1", + "ai": 1 + }, + "isMyTurn": false, + "compat": { + "bot": false, + "board": true + }, + "id": "0jJlyweL" + } +} \ No newline at end of file diff --git a/lib/tests/data/response/game_finish_event.json b/lib/tests/data/response/game_finish_event.json new file mode 100644 index 0000000..384d2d8 --- /dev/null +++ b/lib/tests/data/response/game_finish_event.json @@ -0,0 +1,38 @@ +{ + "type": "gameFinish", + "game": { + "fullId": "crObTQDb257U", + "gameId": "crObTQDb", + "fen": "rnbqkbnr/pppp1ppp/8/4p3/4P3/8/PPPP1PPP/RNBQKBNR w KQkq - 0 2", + "color": "white", + "lastMove": "e7e5", + "source": "friend", + "status": { + "id": 31, + "name": "resign" + }, + "variant": { + "key": "standard", + "name": "Standard" + }, + "speed": "blitz", + "perf": "blitz", + "rated": true, + "hasMoved": true, + "opponent": { + "id": "aaron", + "username": "Aaron", + "rating": 932, + "ratingDiff": 5 + }, + "isMyTurn": false, + "secondsLeft": 300, + "winner": "black", + "ratingDiff": -3, + "compat": { + "bot": false, + "board": true + }, + "id": "crObTQDb" + } +} \ No newline at end of file diff --git a/lib/tests/data/response/game_full_ai.json b/lib/tests/data/response/game_full_ai.json deleted file mode 100644 index 8c2beee..0000000 --- a/lib/tests/data/response/game_full_ai.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "id": "4JurXGpQ", - "variant": { - "key": "standard", - "name": "Standard", - "short": "Std" - }, - "speed": "correspondence", - "perf": { - "name": "Correspondance" - }, - "rated": false, - "createdAt": 1706471805992, - "white": { - "id": "saintmau46", - "name": "saintmau46", - "rating": 1500, - "provisional": true - }, - "black": { - "aiLevel": 1 - }, - "initialFen": "startpos", - "type": "gameFull", - "state": { - "type": "gameState", - "moves": "", - "wtime": 2147483647, - "btime": 2147483647, - "winc": 0, - "binc": 0, - "status": "started" - } -} diff --git a/lib/tests/data/response/game_full_anonymous.json b/lib/tests/data/response/game_full_anonymous.json deleted file mode 100644 index 682e8bc..0000000 --- a/lib/tests/data/response/game_full_anonymous.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "id": "TtAx77HD", - "variant": { - "key": "antichess", - "name": "Antichess", - "short": "Anti" - }, - "speed": "correspondence", - "perf": { - "name": "Antichess" - }, - "rated": false, - "createdAt": 1696590464597, - "white": {}, - "black": { - "id": "tarr3n", - "name": "Tarr3n", - "rating": 1925, - "provisional": false - }, - "initialFen": "startpos", - "type": "gameFull", - "state": { - "type": "gameState", - "moves": "", - "wtime": 2147483647, - "btime": 2147483647, - "winc": 0, - "binc": 0, - "status": "started" - } -} diff --git a/lib/tests/data/response/game_full_event.json b/lib/tests/data/response/game_full_event.json new file mode 100644 index 0000000..ddfbc60 --- /dev/null +++ b/lib/tests/data/response/game_full_event.json @@ -0,0 +1,39 @@ +{ + "id": "BEOucQJo", + "variant": { + "key": "standard", + "name": "Standard", + "short": "Std" + }, + "speed": "rapid", + "perf": { + "name": "Rapid" + }, + "rated": false, + "createdAt": 1745112707998, + "white": { + "id": "bobby", + "name": "Bobby", + "rating": 1751 + }, + "black": { + "id": "mary", + "name": "Mary", + "rating": 1021 + }, + "initialFen": "startpos", + "clock": { + "initial": 900000, + "increment": 0 + }, + "type": "gameFull", + "state": { + "type": "gameState", + "moves": "d2d3", + "wtime": 900000, + "btime": 900000, + "winc": 0, + "binc": 0, + "status": "started" + } +} \ No newline at end of file diff --git a/lib/tests/data/response/game_full_human.json b/lib/tests/data/response/game_full_human.json deleted file mode 100644 index dddb00a..0000000 --- a/lib/tests/data/response/game_full_human.json +++ /dev/null @@ -1,41 +0,0 @@ -{ - "type": "gameFull", - "id": "5IrD6Gzz", - "rated": true, - "variant": { - "key": "standard", - "name": "Standard", - "short": "Std" - }, - "clock": { - "initial": 1200000, - "increment": 10000 - }, - "speed": "classical", - "perf": { - "name": "Classical" - }, - "createdAt": 1523825103562, - "white": { - "id": "lovlas", - "name": "lovlas", - "provisional": false, - "rating": 2500, - "title": "IM" - }, - "black": { - "id": "leela", - "name": "leela", - "rating": 2390 - }, - "initialFen": "startpos", - "state": { - "type": "gameState", - "moves": "e2e4 c7c5 f2f4 d7d6 g1f3 b8c6 f1c4 g8f6 d2d3 g7g6 e1g1 f8g7", - "wtime": 7598040, - "btime": 8395220, - "winc": 10000, - "binc": 10000, - "status": "started" - } -} diff --git a/lib/tests/data/response/game_json.json b/lib/tests/data/response/game_json.json deleted file mode 100644 index 2ce22a3..0000000 --- a/lib/tests/data/response/game_json.json +++ /dev/null @@ -1,76 +0,0 @@ -{ - "id": "q7ZvsdUF", - "rated": true, - "variant": "standard", - "speed": "blitz", - "perf": "blitz", - "createdAt": 1514505150384, - "lastMoveAt": 1514505592843, - "status": "draw", - "players": { - "white": { - "user": { - "name": "Lance5500", - "title": "LM", - "patron": true, - "id": "lance5500" - }, - "rating": 2389, - "ratingDiff": 4 - }, - "black": { - "user": { - "name": "TryingHard87", - "id": "tryinghard87" - }, - "rating": 2498, - "ratingDiff": -4 - } - }, - "winner": "white", - "opening": { - "eco": "D31", - "name": "Semi-Slav Defense: Marshall Gambit", - "ply": 7 - }, - "moves": "d4 d5 c4 c6 Nc3 e6 e4 Nd7 exd5 cxd5 cxd5 exd5 Nxd5 Nb6 Bb5+ Bd7 Qe2+ Ne7 Nxb6 Qxb6 Bxd7+ Kxd7 Nf3 Qa6 Ne5+ Ke8 Qf3 f6 Nd3 Qc6 Qe2 Kf7 O-O Kg8 Bd2 Re8 Rac1 Nf5 Be3 Qe6 Rfe1 g6 b3 Bd6 Qd2 Kf7 Bf4 Qd7 Bxd6 Nxd6 Nc5 Rxe1+ Rxe1 Qc6 f3 Re8 Rxe8 Nxe8 Kf2 Nc7 Qb4 b6 Qc4+ Nd5 Nd3 Qe6 Nb4 Ne7 Qxe6+ Kxe6 Ke3 Kd6 g3 h6 Kd3 h5 Nc2 Kd5 a3 Nc6 Ne3+ Kd6 h4 Nd8 g4 Ne6 Ke4 Ng7 Nc4+ Ke6 d5+ Kd7 a4 g5 gxh5 Nxh5 hxg5 fxg5 Kf5 Nf4 Ne3 Nh3 Kg4 Ng1 Nc4 Kc7 Nd2 Kd6 Kxg5 Kxd5 f4 Nh3+ Kg4 Nf2+ Kf3 Nd3 Ke3 Nc5 Kf3 Ke6 Ke3 Kf5 Kd4 Ne6+ Kc4", - "pgn": "[Event \"Casual blitz game\"]\n[Site \"https://lichess.org/q7ZvsdUF\"]\n[Date \"2023.03.18\"]\n[White \"musil7\"]\n[Black \"lichess AI level 1\"]\n[Result \"1-0\"]\n[UTCDate \"2023.03.18\"]\n[UTCTime \"19:28:15\"]\n[WhiteElo \"1500\"]\n[BlackElo \"?\"]\n[Variant \"Standard\"]\n[TimeControl \"300+3\"]\n[ECO \"A40\"]\n[Opening \"Horwitz Defense\"]\n[Termination \"Normal\"]\n[Annotator \"lichess.org\"]\n\n1. d4 { [%eval 0.0] [%clk 0:05:00] } 1... e6 { [%eval 0.2] [%clk 0:05:00] } { A40 Horwitz Defense } 2. Bf4 { [%eval 0.0] [%clk 0:04:58] } 2... d6 { [%eval 0.48] [%clk 0:05:01] } 3. Nf3 { [%eval 0.7] [%clk 0:05:00] } 3... Qf6?! { (0.70 → 1.30) Inaccuracy. d5 was best. } { [%eval 1.3] [%clk 0:05:03] } (3... d5 4. c4 Bd6 5. Bxd6 Qxd6 6. Nc3 Nf6 7. c5 Qe7 8. e3) 4. e3 { [%eval 0.87] [%clk 0:05:01] } 4... Nh6?! { (0.87 → 1.63) Inaccuracy. Nc6 was best. } { [%eval 1.63] [%clk 0:05:04] } (4... Nc6 5. Bg3 Nge7 6. c4 Nf5 7. Nc3 Nxg3 8. hxg3 Bd7 9. Rb1) 5. Bd3 { [%eval 1.52] [%clk 0:04:58] } 5... e5?! { (1.52 → 2.34) Inaccuracy. Qd8 was best. } { [%eval 2.34] [%clk 0:05:05] } (5... Qd8 6. c4 g6 7. h4 f6 8. Nc3 Nc6 9. Bc2 Bd7 10. d5 exd5 11. cxd5 Ne5 12. Nd4) 6. dxe5 { [%eval 2.44] [%clk 0:04:59] } 6... dxe5 { [%eval 2.52] [%clk 0:05:03] } 7. Bg3?? { (2.52 → 0.38) Blunder. Bxe5 was best. } { [%eval 0.38] [%clk 0:05:00] } (7. Bxe5 Qd8 8. Bf4 Nd7 9. Qe2 c6 10. O-O g6 11. Nbd2 Bg7 12. Bd6 Bxb2 13. Rad1 Bf6) 7... Nc6 { [%eval 0.45] [%clk 0:05:02] } 8. Nc3 { [%eval 0.29] [%clk 0:05:00] } 8... Bg4?! { (0.29 → 0.98) Inaccuracy. Bb4 was best. } { [%eval 0.98] [%clk 0:05:01] } (8... Bb4 9. Qd2) 9. Qe2?! { (0.98 → 0.40) Inaccuracy. Be4 was best. } { [%eval 0.4] [%clk 0:04:49] } (9. Be4) 9... Bb4 { [%eval 0.45] [%clk 0:04:59] } 10. O-O?! { (0.45 → -0.47) Inaccuracy. Be4 was best. } { [%eval -0.47] [%clk 0:04:41] } (10. Be4) 10... Rd8? { (-0.47 → 0.98) Mistake. Bxc3 was best. } { [%eval 0.98] [%clk 0:04:57] } (10... Bxc3 11. bxc3 Nf5 12. c4 O-O 13. h3 Bh5 14. Rab1 Rae8 15. Bxf5 Qxf5 16. Rxb7 e4 17. Nh4) 11. Ne4? { (0.98 → -0.37) Mistake. Be4 was best. } { [%eval -0.37] [%clk 0:04:37] } (11. Be4 Bxc3) 11... Qf5?? { (-0.37 → 3.41) Blunder. Qg6 was best. } { [%eval 3.41] [%clk 0:04:58] } (11... Qg6 12. Nc5 Nf5 13. Bxf5 Qxf5 14. Nxb7 Rb8 15. c3 Be7 16. Qa6 Bxf3 17. gxf3 Qxf3 18. Na5) 12. h3?? { (3.41 → 0.30) Blunder. Nd6+ was best. } { [%eval 0.3] [%clk 0:04:32] } (12. Nd6+ cxd6 13. Bxf5 Nxf5 14. h3 Bh5 15. c3 Bc5 16. Bxe5 dxe5 17. g4 Nxe3 18. fxe3 Bg6) 12... Rxd3?? { (0.30 → 2.65) Blunder. Bxf3 was best. } { [%eval 2.65] [%clk 0:04:57] } (12... Bxf3 13. Qxf3 Qxf3 14. gxf3 Nf5 15. a3 Be7 16. Nd2 Nxg3 17. fxg3 f5 18. Kf2 g6 19. Ke2) 13. cxd3 { [%eval 2.48] [%clk 0:04:32] } 13... Bxh3? { (2.48 → 4.54) Mistake. Bxf3 was best. } { [%eval 4.54] [%clk 0:04:57] } (13... Bxf3 14. Qxf3 Qxf3 15. gxf3 f5 16. Ng5 f4 17. exf4 exf4 18. Bxf4 Bd6 19. Bxd6 cxd6 20. d4) 14. gxh3 { [%eval 4.49] [%clk 0:04:30] } 14... f6 { [%eval 4.81] [%clk 0:04:57] } 15. Kg2 { [%eval 5.11] [%clk 0:04:23] } 15... Qg6 { [%eval 4.99] [%clk 0:04:58] } 16. Nh4 { [%eval 5.14] [%clk 0:04:16] } 16... Qxe4+?! { (5.14 → 6.96) Inaccuracy. Qf7 was best. } { [%eval 6.96] [%clk 0:04:57] } (16... Qf7 17. f4 Be7 18. Kh1 Kd7 19. fxe5 f5 20. Nc3 g5 21. d4 gxh4 22. Bf4 Rg8 23. Rg1) 17. dxe4 { [%eval 6.96] [%clk 0:04:16] } 17... Kf8 { [%eval 8.02] [%clk 0:04:57] } 18. Nf5 { [%eval 7.0] [%clk 0:04:16] } 18... Kg8 { [%eval 8.1] [%clk 0:04:56] } 19. Nxh6+ { [%eval 8.6] [%clk 0:04:18] } 19... Kf8 { [%eval 8.6] [%clk 0:04:56] } 20. Nf5 { [%eval 8.51] [%clk 0:04:19] } 20... Bc5 { [%eval 10.44] [%clk 0:04:56] } 21. Rac1 { [%eval 8.72] [%clk 0:04:16] } 21... Be7 { [%eval 10.64] [%clk 0:04:56] } 22. Rfd1 { [%eval 9.77] [%clk 0:04:17] } 22... Bb4? { (9.77 → Mate in 6) Checkmate is now unavoidable. h5 was best. } { [%eval #6] [%clk 0:04:56] } (22... h5 23. Rd7 Rh7 24. Qc4 g6 25. Nh4 Kg7 26. Rxc7 Kh6 27. Qg8 Rg7 28. Qh8+ Rh7 29. Qe8) 23. a3?! { (Mate in 6 → 11.50) Lost forced checkmate sequence. Rxc6 was best. } { [%eval 11.5] [%clk 0:04:17] } (23. Rxc6 bxc6 24. Qc4 Bd6 25. Rxd6 cxd6 26. Qe6 g6 27. Qe7+ Kg8 28. Qg7#) 23... g6?! { (11.50 → Mate in 6) Checkmate is now unavoidable. Bc5 was best. } { [%eval #6] [%clk 0:04:56] } (23... Bc5 24. Qc4 Bd6 25. Qe6 a6 26. Qc8+ Kf7 27. Qxh8 g5 28. Qxh7+ Kf8 29. Qg6 Na7 30. Qg7+) 24. Nh4? { (Mate in 6 → 9.24) Lost forced checkmate sequence. Rxc6 was best. } { [%eval 9.24] [%clk 0:04:13] } (24. Rxc6 gxf5 25. Rxc7 Be7 26. Qh5 Rg8 27. Rd8+ Kg7 28. Rxe7+ Kh8 29. Rxh7#) 24... g5 { [%eval 12.49] [%clk 0:04:56] } 25. Nf3 { [%eval 8.82] [%clk 0:04:12] } 25... g4 { [%eval 10.27] [%clk 0:04:56] } 26. hxg4 { [%eval 9.46] [%clk 0:04:13] } 26... h5 { [%eval 10.89] [%clk 0:04:56] } 27. g5 { [%eval 10.18] [%clk 0:04:10] } 27... Ba5?! { (10.18 → Mate in 9) Checkmate is now unavoidable. Bd6 was best. } { [%eval #9] [%clk 0:04:56] } (27... Bd6 28. Qc4 h4 29. Qe6 h3+ 30. Kh1 Rg8 31. Bh2 Be7 32. Qf5 Rg7 33. g6) 28. gxf6?! { (Mate in 9 → 27.34) Lost forced checkmate sequence. Qc4 was best. } { [%eval 27.34] [%clk 0:04:08] } (28. Qc4 Bb4 29. g6 Kg7 30. Qf7+ Kh6 31. g7 Rf8 32. gxf8=Q+ Bxf8 33. Qxf6+ Kh7 34. Ng5+ Kg8) 28... Rh6?! { (27.34 → Mate in 5) Checkmate is now unavoidable. Bd2 was best. } { [%eval #5] [%clk 0:04:56] } (28... Bd2 29. Ng5) 29. Bh4?! { (Mate in 5 → 15.96) Lost forced checkmate sequence. Rxc6 was best. } { [%eval 15.96] [%clk 0:04:06] } (29. Rxc6 Rxf6 30. Rxf6+ Ke7 31. Qc4 Kxf6 32. Qg8 Bd2 33. Bh4#) 29... Rg6+ { [%eval 15.6] [%clk 0:04:57] } 30. Kh3 { [%eval #15] [%clk 0:04:03] } 30... Kg8 { [%eval #5] [%clk 0:04:56] } 31. Rg1 { [%eval #6] [%clk 0:04:04] } 31... Rxg1 { [%eval #5] [%clk 0:04:57] } 32. Rxg1+ { [%eval #4] [%clk 0:04:06] } 32... Kf8 { [%eval #4] [%clk 0:04:58] } 33. Rg7 { [%eval #3] [%clk 0:04:00] } 33... b5 { [%eval #3] [%clk 0:04:59] } 34. Bg5 { [%eval #4] [%clk 0:04:02] } 34... a6 { [%eval #3] [%clk 0:04:59] } 35. Bh6 { [%eval #4] [%clk 0:04:04] } 35... b4 { [%eval #2] [%clk 0:04:59] } 36. Rxc7+ { [%eval #4] [%clk 0:04:03] } 36... Ke8 { [%eval #4] [%clk 0:05:00] } 37. Rxc6 { [%eval #4] [%clk 0:04:04] } 37... Bd8 { [%eval #4] [%clk 0:05:02] } 38. Qxa6 { [%eval #3] [%clk 0:04:02] } 38... bxa3 { [%eval #3] [%clk 0:05:03] } 39. bxa3 { [%eval #3] [%clk 0:04:02] } 39... Bxf6 { [%eval #3] [%clk 0:05:04] } 40. Rxf6 { [%eval #2] [%clk 0:04:00] } 40... Ke7 { [%eval #2] [%clk 0:05:05] } 41. Qe6+ { [%eval #2] [%clk 0:03:58] } 41... Kd8 { [%eval #2] [%clk 0:05:05] } 42. Rf8+ { [%eval #2] [%clk 0:03:45] } 42... Kc7 { [%eval #2] [%clk 0:05:07] } 43. Rf7+ { [%eval #1] [%clk 0:03:47] } 43... Kb8 { [%eval #1] [%clk 0:05:08] } 44. Qe8# { [%clk 0:03:46] } { White wins by checkmate. } 1-0\n\n\n", - "clock": { - "initial": 300, - "increment": 3, - "totalTime": 420 - }, - "clocks": [ - 30003, - 30003, - 29843, - 30147 - ], - "analysis": [ - { - "eval": 70 - }, - { - "eval": 130, - "best": "d6d5", - "variation": "d5 c4 Bd6 Bxd6 Qxd6 Nc3 Nf6 c5 Qe7 e3", - "judgment": { - "name": "Inaccuracy", - "comment": "Inaccuracy. d5 was best." - } - }, - { - "eval": -37, - "best": "d3e4", - "variation": "Be4 Bxc3", - "judgment": { - "name": "Mistake", - "comment": "Mistake. Be4 was best." - } - } - ], - "division": { - "middle": 17, - "end": 63 - } -} diff --git a/lib/tests/data/response/game_start.json b/lib/tests/data/response/game_start.json deleted file mode 100644 index 6f59c67..0000000 --- a/lib/tests/data/response/game_start.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "type": "gameStart", - "game": { - "gameId": "rCRw1AuO", - "fullId": "rCRw1AuOvonq", - "color": "black", - "fen": "r1bqkbnr/pppp2pp/2n1pp2/8/8/3PP3/PPPB1PPP/RN1QKBNR w KQkq - 2 4", - "hasMoved": true, - "isMyTurn": false, - "lastMove": "b8c6", - "opponent": { - "id": "philippe", - "rating": 1790, - "username": "Philippe" - }, - "perf": "correspondence", - "rated": false, - "secondsLeft": 1209600, - "source": "friend", - "speed": "correspondence", - "variant": { - "key": "standard", - "name": "Standard" - }, - "compat": { - "bot": false, - "board": true - } - } -} diff --git a/lib/tests/data/response/game_start_ai_event.json b/lib/tests/data/response/game_start_ai_event.json new file mode 100644 index 0000000..dd24c35 --- /dev/null +++ b/lib/tests/data/response/game_start_ai_event.json @@ -0,0 +1,34 @@ +{ + "type": "gameStart", + "game": { + "fullId": "0jJlyweLDRZW", + "gameId": "0jJlyweL", + "fen": "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1", + "color": "white", + "lastMove": "", + "source": "ai", + "status": { + "id": 20, + "name": "started" + }, + "variant": { + "key": "standard", + "name": "Standard" + }, + "speed": "correspondence", + "perf": "correspondence", + "rated": false, + "hasMoved": false, + "opponent": { + "id": null, + "username": "Stockfish level 1", + "ai": 1 + }, + "isMyTurn": true, + "compat": { + "bot": false, + "board": true + }, + "id": "0jJlyweL" + } +} \ No newline at end of file diff --git a/lib/tests/data/response/game_start_event.json b/lib/tests/data/response/game_start_event.json new file mode 100644 index 0000000..decd0c7 --- /dev/null +++ b/lib/tests/data/response/game_start_event.json @@ -0,0 +1,35 @@ +{ + "type": "gameStart", + "game": { + "fullId": "crObTQDb257U", + "gameId": "crObTQDb", + "fen": "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1", + "color": "white", + "lastMove": "", + "source": "friend", + "status": { + "id": 20, + "name": "started" + }, + "variant": { + "key": "standard", + "name": "Standard" + }, + "speed": "blitz", + "perf": "blitz", + "rated": true, + "hasMoved": false, + "opponent": { + "id": "aaron", + "username": "Aaron", + "rating": 932 + }, + "isMyTurn": true, + "secondsLeft": 300, + "compat": { + "bot": false, + "board": true + }, + "id": "crObTQDb" + } +} \ No newline at end of file diff --git a/lib/tests/data/response/game_state.json b/lib/tests/data/response/game_state_event.json similarity index 70% rename from lib/tests/data/response/game_state.json rename to lib/tests/data/response/game_state_event.json index 83b7265..82ec8ef 100644 --- a/lib/tests/data/response/game_state.json +++ b/lib/tests/data/response/game_state_event.json @@ -5,5 +5,9 @@ "btime": 8395220, "winc": 10000, "binc": 10000, + "wdraw": false, + "bdraw": false, + "wtakeback": false, + "btakeback": false, "status": "started" -} +} \ No newline at end of file diff --git a/lib/tests/data/response/live_streamers.json b/lib/tests/data/response/live_streamers.json index 7a5d15d..243e584 100644 --- a/lib/tests/data/response/live_streamers.json +++ b/lib/tests/data/response/live_streamers.json @@ -1,39 +1,39 @@ [ - { - "name": "PokochajSzachy", - "title": "CM", - "flair": "symbols.orange-heart", - "patron": true, - "id": "pokochajszachy", - "stream": { - "service": "twitch", - "status": "CHess & Chill & Good Music !youtube !instagram lichess.org [EN] [PL]", - "lang": "pl" + { + "name": "PokochajSzachy", + "title": "CM", + "flair": "symbols.orange-heart", + "patron": true, + "id": "pokochajszachy", + "stream": { + "service": "twitch", + "status": "CHess & Chill & Good Music !youtube !instagram lichess.org [EN] [PL]", + "lang": "pl" + }, + "streamer": { + "name": "Pokochaj Szachy", + "headline": "Streaming in Polish and English. Come by and say hello!", + "description": "Hi! Have a good time watching the stream! I very often play against viewers on DGT chessboard.", + "twitch": "https://www.twitch.tv/pokochajszachy", + "image": "https://image.lichess1.org/display?fmt=png&h=350&op=thumbnail&path=pokochajszachy:streamer:pokochajszachy:qfVf3nXP.png&w=350&sig=e329d57f8e6815da63dba66992fa8b3c4b100ba9" + } }, - "streamer": { - "name": "Pokochaj Szachy", - "headline": "Streaming in Polish and English. Come by and say hello!", - "description": "Hi! Have a good time watching the stream! I very often play against viewers on DGT chessboard.", - "twitch": "https://www.twitch.tv/pokochajszachy", - "image": "https://image.lichess1.org/display?fmt=png&h=350&op=thumbnail&path=pokochajszachy:streamer:pokochajszachy:qfVf3nXP.png&w=350&sig=e329d57f8e6815da63dba66992fa8b3c4b100ba9" + { + "name": "XadrezTotalTV", + "flair": "objects.telescope", + "id": "xadreztotaltv", + "stream": { + "service": "youTube", + "status": "Xadrez Total | Analisando partidas e batendo papo Lichess.org", + "lang": "en-US" + }, + "streamer": { + "name": "XadrezTotal", + "headline": "Empresa de Organizaçao de torenios FIDE", + "description": "Xadrez Total é uma empresa que organiza torneios FIDE", + "twitch": "https://www.twitch.tv/xadreztotaltv", + "youTube": "https://www.youtube.com/channel/UCl0pW-vG9r8AT8N2bJdMu8Q/live", + "image": "https://image.lichess1.org/display?fmt=webp&h=350&op=thumbnail&path=xadreztotaltv:streamer:xadreztotaltv:4DueCXhP.jpg&w=350&sig=e5fb7e683cb3ec7258778f727decd50b0495417a" + } } - }, - { - "name": "XadrezTotalTV", - "flair": "objects.telescope", - "id": "xadreztotaltv", - "stream": { - "service": "youTube", - "status": "Xadrez Total | Analisando partidas e batendo papo Lichess.org", - "lang": "en-US" - }, - "streamer": { - "name": "XadrezTotal", - "headline": "Empresa de Organizaçao de torenios FIDE", - "description": "Xadrez Total é uma empresa que organiza torneios FIDE", - "twitch": "https://www.twitch.tv/xadreztotaltv", - "youTube": "https://www.youtube.com/channel/UCl0pW-vG9r8AT8N2bJdMu8Q/live", - "image": "https://image.lichess1.org/display?fmt=webp&h=350&op=thumbnail&path=xadreztotaltv:streamer:xadreztotaltv:4DueCXhP.jpg&w=350&sig=e5fb7e683cb3ec7258778f727decd50b0495417a" - } - } ] \ No newline at end of file diff --git a/lib/tests/data/response/notes.json b/lib/tests/data/response/notes.json index bc93860..b50b6d4 100644 --- a/lib/tests/data/response/notes.json +++ b/lib/tests/data/response/notes.json @@ -1,17 +1,17 @@ [ - { - "from": { - "name": "thibault", - "patron": true, - "id": "thibault" - }, - "to": { - "name": "DrNykterstein", - "title": "GM", - "patron": true, - "id": "drnykterstein" - }, - "text": "This guy is good at chess", - "date": 1690585691898 - } -] + { + "from": { + "name": "thibault", + "patron": true, + "id": "thibault" + }, + "to": { + "name": "DrNykterstein", + "title": "GM", + "patron": true, + "id": "drnykterstein" + }, + "text": "This guy is good at chess", + "date": 1690585691898 + } +] \ No newline at end of file diff --git a/lib/tests/data/response/opponent_gone_true.json b/lib/tests/data/response/opponent_gone_event.json similarity index 97% rename from lib/tests/data/response/opponent_gone_true.json rename to lib/tests/data/response/opponent_gone_event.json index 4712881..71d5a72 100644 --- a/lib/tests/data/response/opponent_gone_true.json +++ b/lib/tests/data/response/opponent_gone_event.json @@ -2,4 +2,4 @@ "type": "opponentGone", "gone": true, "claimWinInSeconds": 8 -} +} \ No newline at end of file diff --git a/lib/tests/data/response/opponent_gone_false.json b/lib/tests/data/response/opponent_gone_false.json deleted file mode 100644 index 4e8ade9..0000000 --- a/lib/tests/data/response/opponent_gone_false.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "type": "opponentGone", - "gone": false -} diff --git a/lib/tests/data/response/players.json b/lib/tests/data/response/players.json index 93e5162..e737b81 100644 --- a/lib/tests/data/response/players.json +++ b/lib/tests/data/response/players.json @@ -1,63 +1,63 @@ { - "bullet": [ - { - "id": "bahadirozen", - "username": "BahadirOzen", - "perfs": { - "bullet": { - "rating": 3018, - "progress": 18 + "bullet": [ + { + "id": "bahadirozen", + "username": "BahadirOzen", + "perfs": { + "bullet": { + "rating": 3018, + "progress": 18 + } + }, + "online": true, + "title": "FM" + }, + { + "id": "penguingim1", + "username": "penguingim1", + "perfs": { + "bullet": { + "rating": 2983, + "progress": -36 + } + }, + "title": "GM", + "online": true, + "patron": true + }, + { + "id": "night-king96", + "username": "Night-King96", + "perfs": { + "bullet": { + "rating": 2958, + "progress": 35 + } + }, + "title": "GM" } - }, - "online": true, - "title": "FM" - }, - { - "id": "penguingim1", - "username": "penguingim1", - "perfs": { - "bullet": { - "rating": 2983, - "progress": -36 + ], + "blitz": [], + "rapid": [], + "classical": [], + "ultraBullet": [], + "chess960": [], + "crazyhouse": [], + "antichess": [ + { + "id": "theunknownguyreborn", + "username": "TheUnknownGuyReborn", + "perfs": { + "antichess": { + "rating": 2452, + "progress": 0 + } + } } - }, - "title": "GM", - "online": true, - "patron": true - }, - { - "id": "night-king96", - "username": "Night-King96", - "perfs": { - "bullet": { - "rating": 2958, - "progress": 35 - } - }, - "title": "GM" - } - ], - "blitz": [], - "rapid": [], - "classical": [], - "ultraBullet": [], - "chess960": [], - "crazyhouse": [], - "antichess": [ - { - "id": "theunknownguyreborn", - "username": "TheUnknownGuyReborn", - "perfs": { - "antichess": { - "rating": 2452, - "progress": 0 - } - } - } - ], - "atomic": [], - "horde": [], - "kingOfTheHill": [], - "racingKings": [], - "threeCheck": [] -} + ], + "atomic": [], + "horde": [], + "kingOfTheHill": [], + "racingKings": [], + "threeCheck": [] +} \ No newline at end of file diff --git a/lib/tests/data/response/public_user_data.json b/lib/tests/data/response/public_user_data.json index 37039b6..960d662 100644 --- a/lib/tests/data/response/public_user_data.json +++ b/lib/tests/data/response/public_user_data.json @@ -1 +1,76 @@ -{"id":"leelachess","username":"LeelaChess","perfs":{"blitz":{"games":12447,"rating":2658,"rd":152,"prog":7,"prov":true},"bullet":{"games":7828,"rating":2601,"rd":159,"prog":-5,"prov":true},"correspondence":{"games":0,"rating":1500,"rd":500,"prog":0,"prov":true},"classical":{"games":28,"rating":2240,"rd":206,"prog":-49,"prov":true},"rapid":{"games":4074,"rating":2493,"rd":162,"prog":22,"prov":true}},"title":"BOT","verified":true,"createdAt":1523743988559,"profile":{"country":"CA","firstName":"Leela","bio":"Leela Chess Zero playing full strength.\r\n\r\nI play Ultrabullet, Bullet, Blitz and Rapid. Send me a challenge and wait for your turn!\r\n\r\nIf you are titled and want a longer matchup, please DM me.\r\n\r\nDonations: paypal.me/careless25","lastName":"Chess","links":"lczero.org\r\nhttps://github.com/glinscott/leela-chess\r\nhttps://discord.gg/pKujYxD\r\nhttps://lichess.org/blog/WtNG7CcAAFMTTHPj/gm-andrew-tang-vs-leela-chess-zero\r\npaypal.me/careless25"},"seenAt":1612507810851,"playTime":{"total":15995698,"tv":13223545},"url":"https://lichess.org/@/LeelaChess","count":{"all":54765,"rated":28023,"ai":299,"draw":2212,"drawH":2175,"loss":2456,"lossH":2264,"win":50097,"winH":50027,"bookmark":0,"playing":0,"import":4,"me":0},"followable":true,"following":false,"blocking":false,"followsYou":false} +{ + "id": "leelachess", + "username": "LeelaChess", + "perfs": { + "blitz": { + "games": 12447, + "rating": 2658, + "rd": 152, + "prog": 7, + "prov": true + }, + "bullet": { + "games": 7828, + "rating": 2601, + "rd": 159, + "prog": -5, + "prov": true + }, + "correspondence": { + "games": 0, + "rating": 1500, + "rd": 500, + "prog": 0, + "prov": true + }, + "classical": { + "games": 28, + "rating": 2240, + "rd": 206, + "prog": -49, + "prov": true + }, + "rapid": { + "games": 4074, + "rating": 2493, + "rd": 162, + "prog": 22, + "prov": true + } + }, + "title": "BOT", + "verified": true, + "createdAt": 1523743988559, + "profile": { + "country": "CA", + "firstName": "Leela", + "bio": "Leela Chess Zero playing full strength.\r\n\r\nI play Ultrabullet, Bullet, Blitz and Rapid. Send me a challenge and wait for your turn!\r\n\r\nIf you are titled and want a longer matchup, please DM me.\r\n\r\nDonations: paypal.me/careless25", + "lastName": "Chess", + "links": "lczero.org\r\nhttps://github.com/glinscott/leela-chess\r\nhttps://discord.gg/pKujYxD\r\nhttps://lichess.org/blog/WtNG7CcAAFMTTHPj/gm-andrew-tang-vs-leela-chess-zero\r\npaypal.me/careless25" + }, + "seenAt": 1612507810851, + "playTime": { + "total": 15995698, + "tv": 13223545 + }, + "url": "https://lichess.org/@/LeelaChess", + "count": { + "all": 54765, + "rated": 28023, + "ai": 299, + "draw": 2212, + "drawH": 2175, + "loss": 2456, + "lossH": 2264, + "win": 50097, + "winH": 50027, + "bookmark": 0, + "playing": 0, + "import": 4, + "me": 0 + }, + "followable": true, + "following": false, + "blocking": false, + "followsYou": false +} \ No newline at end of file diff --git a/lib/tests/data/response/rating_history.json b/lib/tests/data/response/rating_history.json index d495603..f0d3434 100644 --- a/lib/tests/data/response/rating_history.json +++ b/lib/tests/data/response/rating_history.json @@ -1,14 +1,36 @@ [ - { - "name": "Bullet", - "points": [ - [2011, 0, 8, 1472], - [2011, 0, 9, 1332], - [2011, 8, 12, 1314] - ] - }, - { - "name": "Blitz", - "points": [[2011, 7, 29, 1332]] - } -] + { + "name": "Bullet", + "points": [ + [ + 2011, + 0, + 8, + 1472 + ], + [ + 2011, + 0, + 9, + 1332 + ], + [ + 2011, + 8, + 12, + 1314 + ] + ] + }, + { + "name": "Blitz", + "points": [ + [ + 2011, + 7, + 29, + 1332 + ] + ] + } +] \ No newline at end of file diff --git a/lib/tests/data/response/streamers.json b/lib/tests/data/response/streamers.json index 9e60196..c3d0add 100644 --- a/lib/tests/data/response/streamers.json +++ b/lib/tests/data/response/streamers.json @@ -1,21 +1,21 @@ [ - { - "id": "chess-network", - "name": "Chess-Network", - "title": "NM", - "patron": true, - "stream": { - "service": "twitch", - "status": "Tuesday night 🐴 chess | lichess.org", - "lang": "en" - }, - "streamer": { - "name": "ChessNetwork", - "headline": "Chess with commentary, tournament competition, viewer interaction, and more.", - "description": "I'm a self-taught National Master in chess from Pennsylvania, USA who was introduced to the game by my father in 1988 at age 8. I've been playing since, enjoy teaching, and have been a broadcaster of all things chess since 2011. It's my hope your experience with this stream is both fun and educational. 😎 -Jerry", - "twitch": "https://twitch.tv/chessnetwork", - "youTube": "https://www.youtube.com/channel/UCCDOQrpqLqKVcTCKzqarxLg/live", - "image": "https://image.lichess1.org/display?h=350&op=thumbnail&path=orlandikill:streamer:orlandikill:wiw356Np.jpg&w=350&sig=9912e0c45e42f37e7cd2716af6bd41bb10497b0c" + { + "id": "chess-network", + "name": "Chess-Network", + "title": "NM", + "patron": true, + "stream": { + "service": "twitch", + "status": "Tuesday night 🐴 chess | lichess.org", + "lang": "en" + }, + "streamer": { + "name": "ChessNetwork", + "headline": "Chess with commentary, tournament competition, viewer interaction, and more.", + "description": "I'm a self-taught National Master in chess from Pennsylvania, USA who was introduced to the game by my father in 1988 at age 8. I've been playing since, enjoy teaching, and have been a broadcaster of all things chess since 2011. It's my hope your experience with this stream is both fun and educational. 😎 -Jerry", + "twitch": "https://twitch.tv/chessnetwork", + "youTube": "https://www.youtube.com/channel/UCCDOQrpqLqKVcTCKzqarxLg/live", + "image": "https://image.lichess1.org/display?h=350&op=thumbnail&path=orlandikill:streamer:orlandikill:wiw356Np.jpg&w=350&sig=9912e0c45e42f37e7cd2716af6bd41bb10497b0c" + } } - } -] +] \ No newline at end of file diff --git a/lib/tests/data/response/tv_channels.json b/lib/tests/data/response/tv_channels.json index 2b25414..5ee9ac1 100644 --- a/lib/tests/data/response/tv_channels.json +++ b/lib/tests/data/response/tv_channels.json @@ -1,147 +1,147 @@ { - "bot": { - "user": { - "id": "leelachess", - "name": "LeelaChess", - "title": "BOT" - }, - "rating": 2660, - "gameId": "Zznv9MIl", - "color": "black" - }, - "blitz": { - "user": { - "id": "lekkerkortook", - "name": "LekkerKortOok" - }, - "rating": 2603, - "gameId": "hTJ4v7Mp", - "color": "black" - }, - "racingKings": { - "user": { - "id": "chesslo21", - "name": "chesslo21" - }, - "rating": 2123, - "gameId": "lgCDl5Of", - "color": "white" - }, - "ultraBullet": { - "user": { - "id": "farmville", - "name": "Farmville" - }, - "rating": 2338, - "gameId": "NEY6OQ32", - "color": "white" - }, - "bullet": { - "user": { - "id": "nurmibrah", - "name": "nurmiBrah" - }, - "rating": 2499, - "gameId": "5LgyE516", - "color": "black" - }, - "classical": { - "user": { - "id": "holden_m_j_thomas", - "name": "Holden_M_J_Thomas" - }, - "rating": 1806, - "gameId": "k3oLby6N", - "color": "white" - }, - "threeCheck": { - "user": { - "id": "pepellou", - "name": "pepellou", - "patron": true - }, - "rating": 1978, - "gameId": "Og5RCvmu", - "color": "black" - }, - "antichess": { - "user": { - "id": "maria-bakkar", - "name": "maria-bakkar" - }, - "rating": 2103, - "gameId": "toCr41yx", - "color": "black" - }, - "computer": { - "user": { - "id": "oh_my_goat_im_so_bat", - "name": "oh_my_goat_Im_so_bat" - }, - "rating": 2314, - "gameId": "TkI4qZxu", - "color": "black" - }, - "horde": { - "user": { - "id": "habitualchess", - "name": "HabitualChess" - }, - "rating": 1803, - "gameId": "oMofN63H", - "color": "white" - }, - "rapid": { - "user": { - "id": "denpayd", - "name": "DenpaYD" - }, - "rating": 2289, - "gameId": "IcWOl8ee" - }, - "atomic": { - "user": { - "id": "meetyourdemise", - "name": "MeetYourDemise" - }, - "rating": 2210, - "gameId": "tvMxtCMN", - "color": "white" - }, - "crazyhouse": { - "user": { - "id": "mathace", - "name": "mathace" - }, - "rating": 2397, - "gameId": "i3gTZlUb", - "color": "black" - }, - "chess960": { - "user": { - "id": "voja_7", - "name": "voja_7" - }, - "rating": 1782, - "gameId": "lrXLcedu", - "color": "white" - }, - "kingOfTheHill": { - "user": { - "id": "nadime", - "name": "Nadime" - }, - "rating": 1500, - "gameId": "DsQn8aEV", - "color": "white" - }, - "best": { - "user": { - "id": "lekkerkortook", - "name": "LekkerKortOok" - }, - "rating": 2603, - "gameId": "hTJ4v7Mp", - "color": "black" - } -} + "bot": { + "user": { + "id": "leelachess", + "name": "LeelaChess", + "title": "BOT" + }, + "rating": 2660, + "gameId": "Zznv9MIl", + "color": "black" + }, + "blitz": { + "user": { + "id": "lekkerkortook", + "name": "LekkerKortOok" + }, + "rating": 2603, + "gameId": "hTJ4v7Mp", + "color": "black" + }, + "racingKings": { + "user": { + "id": "chesslo21", + "name": "chesslo21" + }, + "rating": 2123, + "gameId": "lgCDl5Of", + "color": "white" + }, + "ultraBullet": { + "user": { + "id": "farmville", + "name": "Farmville" + }, + "rating": 2338, + "gameId": "NEY6OQ32", + "color": "white" + }, + "bullet": { + "user": { + "id": "nurmibrah", + "name": "nurmiBrah" + }, + "rating": 2499, + "gameId": "5LgyE516", + "color": "black" + }, + "classical": { + "user": { + "id": "holden_m_j_thomas", + "name": "Holden_M_J_Thomas" + }, + "rating": 1806, + "gameId": "k3oLby6N", + "color": "white" + }, + "threeCheck": { + "user": { + "id": "pepellou", + "name": "pepellou", + "patron": true + }, + "rating": 1978, + "gameId": "Og5RCvmu", + "color": "black" + }, + "antichess": { + "user": { + "id": "maria-bakkar", + "name": "maria-bakkar" + }, + "rating": 2103, + "gameId": "toCr41yx", + "color": "black" + }, + "computer": { + "user": { + "id": "oh_my_goat_im_so_bat", + "name": "oh_my_goat_Im_so_bat" + }, + "rating": 2314, + "gameId": "TkI4qZxu", + "color": "black" + }, + "horde": { + "user": { + "id": "habitualchess", + "name": "HabitualChess" + }, + "rating": 1803, + "gameId": "oMofN63H", + "color": "white" + }, + "rapid": { + "user": { + "id": "denpayd", + "name": "DenpaYD" + }, + "rating": 2289, + "gameId": "IcWOl8ee" + }, + "atomic": { + "user": { + "id": "meetyourdemise", + "name": "MeetYourDemise" + }, + "rating": 2210, + "gameId": "tvMxtCMN", + "color": "white" + }, + "crazyhouse": { + "user": { + "id": "mathace", + "name": "mathace" + }, + "rating": 2397, + "gameId": "i3gTZlUb", + "color": "black" + }, + "chess960": { + "user": { + "id": "voja_7", + "name": "voja_7" + }, + "rating": 1782, + "gameId": "lrXLcedu", + "color": "white" + }, + "kingOfTheHill": { + "user": { + "id": "nadime", + "name": "Nadime" + }, + "rating": 1500, + "gameId": "DsQn8aEV", + "color": "white" + }, + "best": { + "user": { + "id": "lekkerkortook", + "name": "LekkerKortOok" + }, + "rating": 2603, + "gameId": "hTJ4v7Mp", + "color": "black" + } +} \ No newline at end of file diff --git a/lib/tests/data/response/tv_stream_featured.json b/lib/tests/data/response/tv_stream_featured.json index cc9b0ae..77de87f 100644 --- a/lib/tests/data/response/tv_stream_featured.json +++ b/lib/tests/data/response/tv_stream_featured.json @@ -1,30 +1,30 @@ { - "t": "featured", - "d": { - "id": "qVSOPtMc", - "orientation": "black", - "players": [ - { - "color": "white", - "user": { - "name": "lizen9", - "id": "lizen9", - "title": "GM" - }, - "rating": 2531, - "seconds": 60 - }, - { - "color": "black", - "user": { - "name": "lizen29", - "title": "WGM", - "id": "lizen29" - }, - "rating": 2594, - "seconds": 60 - } - ], - "fen": "rnbqk1r1/ppp1ppbp/8/N2p2p1/8/1PQPP3/P1P2PPn/R1B1K1NR" - } -} + "t": "featured", + "d": { + "id": "qVSOPtMc", + "orientation": "black", + "players": [ + { + "color": "white", + "user": { + "name": "lizen9", + "id": "lizen9", + "title": "GM" + }, + "rating": 2531, + "seconds": 60 + }, + { + "color": "black", + "user": { + "name": "lizen29", + "title": "WGM", + "id": "lizen29" + }, + "rating": 2594, + "seconds": 60 + } + ], + "fen": "rnbqk1r1/ppp1ppbp/8/N2p2p1/8/1PQPP3/P1P2PPn/R1B1K1NR" + } +} \ No newline at end of file diff --git a/lib/tests/data/response/tv_stream_featured_untitled.json b/lib/tests/data/response/tv_stream_featured_untitled.json index dc24535..0218561 100644 --- a/lib/tests/data/response/tv_stream_featured_untitled.json +++ b/lib/tests/data/response/tv_stream_featured_untitled.json @@ -1,27 +1,30 @@ { - "t": "featured", - "d": { - "id": "Z1D1mDnU", - "orientation": "black", - "players": [ - { - "color": "white", - "user": { - "name": "Kex09", - "flair": "nature.cat-face", - "patron": true, - "id": "kex09" - }, - "rating": 2354, - "seconds": 60 - }, - { - "color": "black", - "user": { "name": "antiltchess", "id": "antiltchess" }, - "rating": 2368, - "seconds": 60 - } - ], - "fen": "1n2k3/6P1/6p1/1p2p3/3p4/1p4K1/8/r7 w - - 3 28" - } -} + "t": "featured", + "d": { + "id": "Z1D1mDnU", + "orientation": "black", + "players": [ + { + "color": "white", + "user": { + "name": "Kex09", + "flair": "nature.cat-face", + "patron": true, + "id": "kex09" + }, + "rating": 2354, + "seconds": 60 + }, + { + "color": "black", + "user": { + "name": "antiltchess", + "id": "antiltchess" + }, + "rating": 2368, + "seconds": 60 + } + ], + "fen": "1n2k3/6P1/6p1/1p2p3/3p4/1p4K1/8/r7 w - - 3 28" + } +} \ No newline at end of file diff --git a/lib/tests/data/response/tv_stream_fen.json b/lib/tests/data/response/tv_stream_fen.json index bf465b9..26ec98a 100644 --- a/lib/tests/data/response/tv_stream_fen.json +++ b/lib/tests/data/response/tv_stream_fen.json @@ -1,9 +1,9 @@ { - "t": "fen", - "d": { - "fen": "5rk1/6p1/p4q2/4p3/2p5/2P2bNQ/PP3P1P/1K1RR3 w - - 4 32", - "lm": "h8g8", - "wc": 14, - "bc": 30 - } -} + "t": "fen", + "d": { + "fen": "5rk1/6p1/p4q2/4p3/2p5/2P2bNQ/PP3P1P/1K1RR3 w - - 4 32", + "lm": "h8g8", + "wc": 14, + "bc": 30 + } +} \ No newline at end of file diff --git a/lib/tests/data/response/user_activities.json b/lib/tests/data/response/user_activities.json index 5bf2102..4f3a026 100644 --- a/lib/tests/data/response/user_activities.json +++ b/lib/tests/data/response/user_activities.json @@ -1,507 +1,682 @@ [ - { - "interval": { "start": 1503100800, "end": 1503187200 }, - "games": { - "bullet": { - "win": 0, - "loss": 1, - "draw": 0, - "rp": { "before": 1619, "after": 1615 } - } - }, - "puzzles": { - "score": { - "win": 1, - "loss": 0, - "draw": 0, - "rp": { "before": 1641, "after": 1641 } - } - }, - "tournaments": { - "nb": 1, - "best": [ - { - "tournament": { "id": "VtgU6IWP", "name": "Hourly Bullet Arena" }, - "nbGames": 1, - "score": 0, - "rank": 56, - "rankPercent": 82 - } - ] - }, - "practice": [ - { - "url": "/practice/-/overloaded-pieces/o734CNqp", - "name": "Overloaded Pieces", - "nbPositions": 1 - } - ], - "correspondenceMoves": { - "nb": 7, - "games": [ - { - "id": "FoA24Xgm", - "color": "black", - "url": "/FoA24Xgm/black", - "variant": "standard", - "speed": "correspondence", - "perf": "correspondence", - "rated": true, - "opponent": { "user": "wixkid", "rating": 1775 } + { + "interval": { + "start": 1503100800, + "end": 1503187200 }, - { - "id": "YdaQfiVN", - "color": "black", - "url": "/YdaQfiVN/black", - "variant": "standard", - "speed": "correspondence", - "perf": "correspondence", - "rated": false, - "opponent": { "user": "kickdarkness", "rating": 2008 } + "games": { + "bullet": { + "win": 0, + "loss": 1, + "draw": 0, + "rp": { + "before": 1619, + "after": 1615 + } + } }, - { - "id": "sgJmN0Tp", - "color": "white", - "url": "/sgJmN0Tp/white", - "variant": "standard", - "speed": "correspondence", - "perf": "correspondence", - "rated": false, - "opponent": { "user": "gerobum", "rating": 1831 } - } - ] - }, - "correspondenceEnds": { - "score": { - "win": 1, - "loss": 1, - "draw": 0, - "rp": { "before": 1895, "after": 1873 } - }, - "games": [ - { - "id": "FoA24Xgm", - "color": "black", - "url": "/FoA24Xgm/black", - "variant": "standard", - "speed": "correspondence", - "perf": "correspondence", - "rated": true, - "opponent": { "user": "wixkid", "rating": 1775 } + "puzzles": { + "score": { + "win": 1, + "loss": 0, + "draw": 0, + "rp": { + "before": 1641, + "after": 1641 + } + } }, - { - "id": "DkYfPA76", - "color": "white", - "url": "/DkYfPA76/white", - "variant": "standard", - "speed": "correspondence", - "perf": "correspondence", - "rated": true, - "opponent": { "user": "d3partures", "rating": 1743 } - } - ] - }, - "follows": { - "in": { - "ids": ["sicknsolo", "victress", "adityaprakash17", "anonymous_enemy"] - }, - "out": { "ids": ["lonerdruid"] } - }, - "teams": [{ "url": "/team/lichess-stars", "name": "Lichess Stars" }], - "posts": [ - { - "topicUrl": "/forum/lichess-feedback/new-study-visibility-mode-unlisted", - "topicName": "New study visibility mode: unlisted", - "posts": [ - { - "url": "/forum/redirect/post/OvPsDw1I", - "text": "It's like private, except people who know the study URL can still access it.\r\n\r\nYep, just like with youtube videos." - }, - { - "url": "/forum/redirect/post/p8zOwutq", - "text": "The \"My private studies\" folder is currently bugged out, the fix will come in a few hours.\r\n\r\nCan you show me a study chapter where symbols don't appear?" - } - ] - }, - { - "topicUrl": "/forum/general-chess-discussion/yeah-but-lichess-is-full-of-commies", - "topicName": "\"Yeah, but lichess is full of commies\"", + "tournaments": { + "nb": 1, + "best": [ + { + "tournament": { + "id": "VtgU6IWP", + "name": "Hourly Bullet Arena" + }, + "nbGames": 1, + "score": 0, + "rank": 56, + "rankPercent": 82 + } + ] + }, + "practice": [ + { + "url": "/practice/-/overloaded-pieces/o734CNqp", + "name": "Overloaded Pieces", + "nbPositions": 1 + } + ], + "correspondenceMoves": { + "nb": 7, + "games": [ + { + "id": "FoA24Xgm", + "color": "black", + "url": "/FoA24Xgm/black", + "variant": "standard", + "speed": "correspondence", + "perf": "correspondence", + "rated": true, + "opponent": { + "user": "wixkid", + "rating": 1775 + } + }, + { + "id": "YdaQfiVN", + "color": "black", + "url": "/YdaQfiVN/black", + "variant": "standard", + "speed": "correspondence", + "perf": "correspondence", + "rated": false, + "opponent": { + "user": "kickdarkness", + "rating": 2008 + } + }, + { + "id": "sgJmN0Tp", + "color": "white", + "url": "/sgJmN0Tp/white", + "variant": "standard", + "speed": "correspondence", + "perf": "correspondence", + "rated": false, + "opponent": { + "user": "gerobum", + "rating": 1831 + } + } + ] + }, + "correspondenceEnds": { + "score": { + "win": 1, + "loss": 1, + "draw": 0, + "rp": { + "before": 1895, + "after": 1873 + } + }, + "games": [ + { + "id": "FoA24Xgm", + "color": "black", + "url": "/FoA24Xgm/black", + "variant": "standard", + "speed": "correspondence", + "perf": "correspondence", + "rated": true, + "opponent": { + "user": "wixkid", + "rating": 1775 + } + }, + { + "id": "DkYfPA76", + "color": "white", + "url": "/DkYfPA76/white", + "variant": "standard", + "speed": "correspondence", + "perf": "correspondence", + "rated": true, + "opponent": { + "user": "d3partures", + "rating": 1743 + } + } + ] + }, + "follows": { + "in": { + "ids": [ + "sicknsolo", + "victress", + "adityaprakash17", + "anonymous_enemy" + ] + }, + "out": { + "ids": [ + "lonerdruid" + ] + } + }, + "teams": [ + { + "url": "/team/lichess-stars", + "name": "Lichess Stars" + } + ], "posts": [ - { - "url": "/forum/redirect/post/eaFQzRQ2", - "text": "I'm not communist either. Hello :)" - }, - { - "url": "/forum/redirect/post/G35OInLP", - "text": "@NeverBeenTimid Quite simply, not everything has to be about money...\r\n\r\nIt should go without saying; but in case it doesn't, we have lichess to remind us.\r\n\r\nI want to believe that exploiting workers and lying to consumers is not the only way to build something. I want to show that a community, bound by a common passion for chess, with a touch of humanism, is capable of building great things. I reject investment, paywalls, advertisements, proprietary software, user tracking: these things are no" - } + { + "topicUrl": "/forum/lichess-feedback/new-study-visibility-mode-unlisted", + "topicName": "New study visibility mode: unlisted", + "posts": [ + { + "url": "/forum/redirect/post/OvPsDw1I", + "text": "It's like private, except people who know the study URL can still access it.\r\n\r\nYep, just like with youtube videos." + }, + { + "url": "/forum/redirect/post/p8zOwutq", + "text": "The \"My private studies\" folder is currently bugged out, the fix will come in a few hours.\r\n\r\nCan you show me a study chapter where symbols don't appear?" + } + ] + }, + { + "topicUrl": "/forum/general-chess-discussion/yeah-but-lichess-is-full-of-commies", + "topicName": "\"Yeah, but lichess is full of commies\"", + "posts": [ + { + "url": "/forum/redirect/post/eaFQzRQ2", + "text": "I'm not communist either. Hello :)" + }, + { + "url": "/forum/redirect/post/G35OInLP", + "text": "@NeverBeenTimid Quite simply, not everything has to be about money...\r\n\r\nIt should go without saying; but in case it doesn't, we have lichess to remind us.\r\n\r\nI want to believe that exploiting workers and lying to consumers is not the only way to build something. I want to show that a community, bound by a common passion for chess, with a touch of humanism, is capable of building great things. I reject investment, paywalls, advertisements, proprietary software, user tracking: these things are no" + } + ] + } ] - } - ] - }, - { - "interval": { "start": 1503014400, "end": 1503100800 }, - "games": { - "blitz": { - "win": 1, - "loss": 1, - "draw": 0, - "rp": { "before": 1681, "after": 1690 } - }, - "bullet": { - "win": 2, - "loss": 0, - "draw": 0, - "rp": { "before": 1619, "after": 1619 } - }, - "classical": { - "win": 0, - "loss": 1, - "draw": 0, - "rp": { "before": 1811, "after": 1811 } - } }, - "tournaments": { - "nb": 3, - "best": [ - { - "tournament": { "id": "Ri7eoNg5", "name": "Dubois Arena" }, - "nbGames": 2, - "score": 5, - "rank": 1, - "rankPercent": 20 + { + "interval": { + "start": 1503014400, + "end": 1503100800 }, - { - "tournament": { "id": "HJA80s7w", "name": "STL Rapid & Blitz Day 5" }, - "nbGames": 1, - "score": 2, - "rank": 387, - "rankPercent": 50 + "games": { + "blitz": { + "win": 1, + "loss": 1, + "draw": 0, + "rp": { + "before": 1681, + "after": 1690 + } + }, + "bullet": { + "win": 2, + "loss": 0, + "draw": 0, + "rp": { + "before": 1619, + "after": 1619 + } + }, + "classical": { + "win": 0, + "loss": 1, + "draw": 0, + "rp": { + "before": 1811, + "after": 1811 + } + } }, - { - "tournament": { "id": "WhfhjujR", "name": "Hourly SuperBlitz Arena" }, - "nbGames": 1, - "score": 0, - "rank": 95, - "rankPercent": 86 - } - ] - }, - "correspondenceMoves": { - "nb": 2, - "games": [ - { - "id": "FoA24Xgm", - "color": "black", - "url": "/FoA24Xgm/black", - "variant": "standard", - "speed": "correspondence", - "perf": "correspondence", - "rated": true, - "opponent": { "user": "wixkid", "rating": 1775 } - } - ] - }, - "follows": { "in": { "ids": ["saviter", "mattrenfer", "amenhotep_-_iv"] } }, - "posts": [ - { - "topicUrl": "/forum/lichess-feedback/study-moves-not-showing-", - "topicName": "''Study'' moves not showing ?", - "posts": [ - { - "url": "/forum/redirect/post/HQdvhx6O", - "text": "Which study are you on?" - } - ] - } - ] - }, - { - "interval": { "start": 1502928000, "end": 1503014400 }, - "correspondenceMoves": { - "nb": 8, - "games": [ - { - "id": "FoA24Xgm", - "color": "black", - "url": "/FoA24Xgm/black", - "variant": "standard", - "speed": "correspondence", - "perf": "correspondence", - "rated": true, - "opponent": { "user": "wixkid", "rating": 1775 } + "tournaments": { + "nb": 3, + "best": [ + { + "tournament": { + "id": "Ri7eoNg5", + "name": "Dubois Arena" + }, + "nbGames": 2, + "score": 5, + "rank": 1, + "rankPercent": 20 + }, + { + "tournament": { + "id": "HJA80s7w", + "name": "STL Rapid & Blitz Day 5" + }, + "nbGames": 1, + "score": 2, + "rank": 387, + "rankPercent": 50 + }, + { + "tournament": { + "id": "WhfhjujR", + "name": "Hourly SuperBlitz Arena" + }, + "nbGames": 1, + "score": 0, + "rank": 95, + "rankPercent": 86 + } + ] }, - { - "id": "sgJmN0Tp", - "color": "white", - "url": "/sgJmN0Tp/white", - "variant": "standard", - "speed": "correspondence", - "perf": "correspondence", - "rated": false, - "opponent": { "user": "gerobum", "rating": 1831 } + "correspondenceMoves": { + "nb": 2, + "games": [ + { + "id": "FoA24Xgm", + "color": "black", + "url": "/FoA24Xgm/black", + "variant": "standard", + "speed": "correspondence", + "perf": "correspondence", + "rated": true, + "opponent": { + "user": "wixkid", + "rating": 1775 + } + } + ] }, - { - "id": "DEvU83fu", - "color": "black", - "url": "/DEvU83fu/black", - "variant": "standard", - "speed": "correspondence", - "perf": "correspondence", - "rated": true, - "opponent": { "user": "carlsenforever", "rating": 2038 } + "follows": { + "in": { + "ids": [ + "saviter", + "mattrenfer", + "amenhotep_-_iv" + ] + } }, - { - "id": "DkYfPA76", - "color": "white", - "url": "/DkYfPA76/white", - "variant": "standard", - "speed": "correspondence", - "perf": "correspondence", - "rated": true, - "opponent": { "user": "d3partures", "rating": 1743 } - } - ] - }, - "correspondenceEnds": { - "score": { - "win": 0, - "loss": 1, - "draw": 0, - "rp": { "before": 1911, "after": 1904 } - }, - "games": [ - { - "id": "DEvU83fu", - "color": "black", - "url": "/DEvU83fu/black", - "variant": "standard", - "speed": "correspondence", - "perf": "correspondence", - "rated": true, - "opponent": { "user": "carlsenforever", "rating": 2038 } - } - ] - }, - "follows": { "in": { "ids": ["lesauteurdeclasse"] } }, - "posts": [ - { - "topicUrl": "/forum/lichess-feedback/bad-changes-to-gameboard-canvas-on-mobile", - "topicName": "Bad changes to gameboard canvas on mobile", "posts": [ - { - "url": "/forum/redirect/post/jSa2XPpo", - "text": "Is it better now?" - } + { + "topicUrl": "/forum/lichess-feedback/study-moves-not-showing-", + "topicName": "''Study'' moves not showing ?", + "posts": [ + { + "url": "/forum/redirect/post/HQdvhx6O", + "text": "Which study are you on?" + } + ] + } ] - } - ] - }, - { - "interval": { "start": 1502841600, "end": 1502928000 }, - "games": { - "blitz": { - "win": 0, - "loss": 0, - "draw": 1, - "rp": { "before": 1684, "after": 1681 } - } }, - "correspondenceMoves": { - "nb": 12, - "games": [ - { - "id": "DEvU83fu", - "color": "black", - "url": "/DEvU83fu/black", - "variant": "standard", - "speed": "correspondence", - "perf": "correspondence", - "rated": true, - "opponent": { "user": "carlsenforever", "rating": 2038 } + { + "interval": { + "start": 1502928000, + "end": 1503014400 }, - { - "id": "DkYfPA76", - "color": "white", - "url": "/DkYfPA76/white", - "variant": "standard", - "speed": "correspondence", - "perf": "correspondence", - "rated": true, - "opponent": { "user": "d3partures", "rating": 1743 } + "correspondenceMoves": { + "nb": 8, + "games": [ + { + "id": "FoA24Xgm", + "color": "black", + "url": "/FoA24Xgm/black", + "variant": "standard", + "speed": "correspondence", + "perf": "correspondence", + "rated": true, + "opponent": { + "user": "wixkid", + "rating": 1775 + } + }, + { + "id": "sgJmN0Tp", + "color": "white", + "url": "/sgJmN0Tp/white", + "variant": "standard", + "speed": "correspondence", + "perf": "correspondence", + "rated": false, + "opponent": { + "user": "gerobum", + "rating": 1831 + } + }, + { + "id": "DEvU83fu", + "color": "black", + "url": "/DEvU83fu/black", + "variant": "standard", + "speed": "correspondence", + "perf": "correspondence", + "rated": true, + "opponent": { + "user": "carlsenforever", + "rating": 2038 + } + }, + { + "id": "DkYfPA76", + "color": "white", + "url": "/DkYfPA76/white", + "variant": "standard", + "speed": "correspondence", + "perf": "correspondence", + "rated": true, + "opponent": { + "user": "d3partures", + "rating": 1743 + } + } + ] }, - { - "id": "sgJmN0Tp", - "color": "white", - "url": "/sgJmN0Tp/white", - "variant": "standard", - "speed": "correspondence", - "perf": "correspondence", - "rated": false, - "opponent": { "user": "gerobum", "rating": 1831 } + "correspondenceEnds": { + "score": { + "win": 0, + "loss": 1, + "draw": 0, + "rp": { + "before": 1911, + "after": 1904 + } + }, + "games": [ + { + "id": "DEvU83fu", + "color": "black", + "url": "/DEvU83fu/black", + "variant": "standard", + "speed": "correspondence", + "perf": "correspondence", + "rated": true, + "opponent": { + "user": "carlsenforever", + "rating": 2038 + } + } + ] + }, + "follows": { + "in": { + "ids": [ + "lesauteurdeclasse" + ] + } }, - { - "id": "FoA24Xgm", - "color": "black", - "url": "/FoA24Xgm/black", - "variant": "standard", - "speed": "correspondence", - "perf": "correspondence", - "rated": true, - "opponent": { "user": "wixkid", "rating": 1775 } - } - ] - }, - "follows": { - "in": { "ids": ["rvleander", "mmichael"] }, - "out": { "ids": ["wolfram_ep"] } - }, - "posts": [ - { - "topicUrl": "/forum/lichess-feedback/keyboard-input-changed-today-maybe-a-bug", - "topicName": "Keyboard input changed today, maybe a bug.", - "posts": [ - { - "url": "/forum/redirect/post/nD4mZjFN", - "text": "That was a bug, it's now fixed! Thanks for the report @TheZyrax " - } - ] - }, - { - "topicUrl": "/forum/lichess-feedback/learnpractice-stopped-saving-my-progress", - "topicName": "Learn/Practice stopped saving my progress", "posts": [ - { - "url": "/forum/redirect/post/wWacFp3p", - "text": "We're on it. Thanks for the bug report." - }, - { - "url": "/forum/redirect/post/cOYiuEgz", - "text": "It's now fixed. Sorry for the inconvenience." - } + { + "topicUrl": "/forum/lichess-feedback/bad-changes-to-gameboard-canvas-on-mobile", + "topicName": "Bad changes to gameboard canvas on mobile", + "posts": [ + { + "url": "/forum/redirect/post/jSa2XPpo", + "text": "Is it better now?" + } + ] + } ] - }, - { - "topicUrl": "/forum/lichess-feedback/help-translate-lichess", - "topicName": "Help translate Lichess", + }, + { + "interval": { + "start": 1502841600, + "end": 1502928000 + }, + "games": { + "blitz": { + "win": 0, + "loss": 0, + "draw": 1, + "rp": { + "before": 1684, + "after": 1681 + } + } + }, + "correspondenceMoves": { + "nb": 12, + "games": [ + { + "id": "DEvU83fu", + "color": "black", + "url": "/DEvU83fu/black", + "variant": "standard", + "speed": "correspondence", + "perf": "correspondence", + "rated": true, + "opponent": { + "user": "carlsenforever", + "rating": 2038 + } + }, + { + "id": "DkYfPA76", + "color": "white", + "url": "/DkYfPA76/white", + "variant": "standard", + "speed": "correspondence", + "perf": "correspondence", + "rated": true, + "opponent": { + "user": "d3partures", + "rating": 1743 + } + }, + { + "id": "sgJmN0Tp", + "color": "white", + "url": "/sgJmN0Tp/white", + "variant": "standard", + "speed": "correspondence", + "perf": "correspondence", + "rated": false, + "opponent": { + "user": "gerobum", + "rating": 1831 + } + }, + { + "id": "FoA24Xgm", + "color": "black", + "url": "/FoA24Xgm/black", + "variant": "standard", + "speed": "correspondence", + "perf": "correspondence", + "rated": true, + "opponent": { + "user": "wixkid", + "rating": 1775 + } + } + ] + }, + "follows": { + "in": { + "ids": [ + "rvleander", + "mmichael" + ] + }, + "out": { + "ids": [ + "wolfram_ep" + ] + } + }, "posts": [ - { - "url": "/forum/redirect/post/8dzjnLRV", - "text": "Are you a native speaker of a non-english language? You can help making lichess better! No technical skills required.\r\n\r\nHead to https://crowdin.com/project/lichess and start suggesting translations! You can also vote for your favourite translations.\r\n\r\nlichess is a non-profit association, and the result of volunteer collaboration of the Internet chess community. We believe that together, we can achieve great things - for chess, for humanity, for freedom! And now we need your help, more than eve" - }, - { - "url": "/forum/redirect/post/omISXRjU", - "text": "@Wolfram_EP Thank you for stepping in.\r\n\r\nFor now, we chose not to translate variant names such as Bullet, Blitz, Chess960, Crazyhouse, etc. They're like proper nouns. We might change our minds about it later on, but for now they're not supposed to be translated.\r\n\r\nI think lichess has good support for russian pluralization, can you confirm? https://github.com/ornicar/lila/blob/40e2dfbb18735f3f55dd796d5f8017ea39cb8f10/modules/i18n/src/main/I18nQuantity.scala#L44-L50\r\n\r\nHowever crowdin got it wro" - }, - { - "url": "/forum/redirect/post/jG6jM9qO", - "text": "I can't seem to be able to fix Russian pluralization on crowdin. Could you please send them an email asking if they can fix it on their side? Thanks." - }, - { - "url": "/forum/redirect/post/Xpcdpm2Y", - "text": "Ah, thank you, that helps.\r\n\r\nI changed lichess code to match crowdin: https://github.com/ornicar/lila/commit/7a1cbabe5fc27e779c0ab419b3a6bd85fb2bd76b\r\n\r\nAbout transliteration: yes, you're right. I now realize that, for instance, in french, we transliterate russian city names.\r\nDo you think the word \"Lichess\" should be transliterated as well?\r\n\r\nWould you like to be lichess russian translation manager on crowdin? It's quite a big responsibility, because we have thousands of russian speaking play" - }, - { - "url": "/forum/redirect/post/WiILZb1M", - "text": "Thanks. You're now a proofreader on Crowdin. It means you can decide which Russian translation is correct, and add/edit contexts.\r\n\r\nSeriousness is the only commitment I can ask for. I do not expect that you will do all the work. This is an open source project, people put in the time they want and can, and we only look at what has been done, never at what more could have been done.\r\n\r\nSo yeah, no pressure. We can also name other Russian proofreaders when we find them." - } + { + "topicUrl": "/forum/lichess-feedback/keyboard-input-changed-today-maybe-a-bug", + "topicName": "Keyboard input changed today, maybe a bug.", + "posts": [ + { + "url": "/forum/redirect/post/nD4mZjFN", + "text": "That was a bug, it's now fixed! Thanks for the report @TheZyrax " + } + ] + }, + { + "topicUrl": "/forum/lichess-feedback/learnpractice-stopped-saving-my-progress", + "topicName": "Learn/Practice stopped saving my progress", + "posts": [ + { + "url": "/forum/redirect/post/wWacFp3p", + "text": "We're on it. Thanks for the bug report." + }, + { + "url": "/forum/redirect/post/cOYiuEgz", + "text": "It's now fixed. Sorry for the inconvenience." + } + ] + }, + { + "topicUrl": "/forum/lichess-feedback/help-translate-lichess", + "topicName": "Help translate Lichess", + "posts": [ + { + "url": "/forum/redirect/post/8dzjnLRV", + "text": "Are you a native speaker of a non-english language? You can help making lichess better! No technical skills required.\r\n\r\nHead to https://crowdin.com/project/lichess and start suggesting translations! You can also vote for your favourite translations.\r\n\r\nlichess is a non-profit association, and the result of volunteer collaboration of the Internet chess community. We believe that together, we can achieve great things - for chess, for humanity, for freedom! And now we need your help, more than eve" + }, + { + "url": "/forum/redirect/post/omISXRjU", + "text": "@Wolfram_EP Thank you for stepping in.\r\n\r\nFor now, we chose not to translate variant names such as Bullet, Blitz, Chess960, Crazyhouse, etc. They're like proper nouns. We might change our minds about it later on, but for now they're not supposed to be translated.\r\n\r\nI think lichess has good support for russian pluralization, can you confirm? https://github.com/ornicar/lila/blob/40e2dfbb18735f3f55dd796d5f8017ea39cb8f10/modules/i18n/src/main/I18nQuantity.scala#L44-L50\r\n\r\nHowever crowdin got it wro" + }, + { + "url": "/forum/redirect/post/jG6jM9qO", + "text": "I can't seem to be able to fix Russian pluralization on crowdin. Could you please send them an email asking if they can fix it on their side? Thanks." + }, + { + "url": "/forum/redirect/post/Xpcdpm2Y", + "text": "Ah, thank you, that helps.\r\n\r\nI changed lichess code to match crowdin: https://github.com/ornicar/lila/commit/7a1cbabe5fc27e779c0ab419b3a6bd85fb2bd76b\r\n\r\nAbout transliteration: yes, you're right. I now realize that, for instance, in french, we transliterate russian city names.\r\nDo you think the word \"Lichess\" should be transliterated as well?\r\n\r\nWould you like to be lichess russian translation manager on crowdin? It's quite a big responsibility, because we have thousands of russian speaking play" + }, + { + "url": "/forum/redirect/post/WiILZb1M", + "text": "Thanks. You're now a proofreader on Crowdin. It means you can decide which Russian translation is correct, and add/edit contexts.\r\n\r\nSeriousness is the only commitment I can ask for. I do not expect that you will do all the work. This is an open source project, people put in the time they want and can, and we only look at what has been done, never at what more could have been done.\r\n\r\nSo yeah, no pressure. We can also name other Russian proofreaders when we find them." + } + ] + } ] - } - ] - }, - { - "interval": { "start": 1502755200, "end": 1502841600 }, - "follows": { - "in": { - "ids": [ - "area11", - "reisui", - "gr4ndma", - "theclassicalking", - "outrunyoutoo" - ] - } - } - }, - { - "interval": { "start": 1502668800, "end": 1502755200 }, - "correspondenceMoves": { - "nb": 8, - "games": [ - { - "id": "DEvU83fu", - "color": "black", - "url": "/DEvU83fu/black", - "variant": "standard", - "speed": "correspondence", - "perf": "correspondence", - "rated": true, - "opponent": { "user": "carlsenforever", "rating": 2038 } + }, + { + "interval": { + "start": 1502755200, + "end": 1502841600 + }, + "follows": { + "in": { + "ids": [ + "area11", + "reisui", + "gr4ndma", + "theclassicalking", + "outrunyoutoo" + ] + } + } + }, + { + "interval": { + "start": 1502668800, + "end": 1502755200 }, - { - "id": "FoA24Xgm", - "color": "black", - "url": "/FoA24Xgm/black", - "variant": "standard", - "speed": "correspondence", - "perf": "correspondence", - "rated": true, - "opponent": { "user": "wixkid", "rating": 1775 } + "correspondenceMoves": { + "nb": 8, + "games": [ + { + "id": "DEvU83fu", + "color": "black", + "url": "/DEvU83fu/black", + "variant": "standard", + "speed": "correspondence", + "perf": "correspondence", + "rated": true, + "opponent": { + "user": "carlsenforever", + "rating": 2038 + } + }, + { + "id": "FoA24Xgm", + "color": "black", + "url": "/FoA24Xgm/black", + "variant": "standard", + "speed": "correspondence", + "perf": "correspondence", + "rated": true, + "opponent": { + "user": "wixkid", + "rating": 1775 + } + }, + { + "id": "lWbgq0Gh", + "color": "black", + "url": "/lWbgq0Gh/black", + "variant": "standard", + "speed": "correspondence", + "perf": "correspondence", + "rated": true, + "opponent": { + "user": "passat17", + "rating": 1701 + } + }, + { + "id": "sgJmN0Tp", + "color": "white", + "url": "/sgJmN0Tp/white", + "variant": "standard", + "speed": "correspondence", + "perf": "correspondence", + "rated": false, + "opponent": { + "user": "gerobum", + "rating": 1831 + } + } + ] }, - { - "id": "lWbgq0Gh", - "color": "black", - "url": "/lWbgq0Gh/black", - "variant": "standard", - "speed": "correspondence", - "perf": "correspondence", - "rated": true, - "opponent": { "user": "passat17", "rating": 1701 } + "correspondenceEnds": { + "score": { + "win": 1, + "loss": 0, + "draw": 0, + "rp": { + "before": 1907, + "after": 1915 + } + }, + "games": [ + { + "id": "lWbgq0Gh", + "color": "black", + "url": "/lWbgq0Gh/black", + "variant": "standard", + "speed": "correspondence", + "perf": "correspondence", + "rated": true, + "opponent": { + "user": "passat17", + "rating": 1701 + } + } + ] }, - { - "id": "sgJmN0Tp", - "color": "white", - "url": "/sgJmN0Tp/white", - "variant": "standard", - "speed": "correspondence", - "perf": "correspondence", - "rated": false, - "opponent": { "user": "gerobum", "rating": 1831 } + "follows": { + "in": { + "ids": [ + "lionnessebim1" + ] + } } - ] }, - "correspondenceEnds": { - "score": { - "win": 1, - "loss": 0, - "draw": 0, - "rp": { "before": 1907, "after": 1915 } - }, - "games": [ - { - "id": "lWbgq0Gh", - "color": "black", - "url": "/lWbgq0Gh/black", - "variant": "standard", - "speed": "correspondence", - "perf": "correspondence", - "rated": true, - "opponent": { "user": "passat17", "rating": 1701 } + { + "interval": { + "start": 1502582400, + "end": 1502668800 + }, + "games": { + "blitz": { + "win": 1, + "loss": 0, + "draw": 0, + "rp": { + "before": 1681, + "after": 1684 + } + } + }, + "follows": { + "in": { + "ids": [ + "lesourd", + "marcolom", + "kn89", + "naeroon" + ] + } } - ] - }, - "follows": { "in": { "ids": ["lionnessebim1"] } } - }, - { - "interval": { "start": 1502582400, "end": 1502668800 }, - "games": { - "blitz": { - "win": 1, - "loss": 0, - "draw": 0, - "rp": { "before": 1681, "after": 1684 } - } - }, - "follows": { "in": { "ids": ["lesourd", "marcolom", "kn89", "naeroon"] } } - } -] + } +] \ No newline at end of file diff --git a/lib/tests/data/response/user_activity.json b/lib/tests/data/response/user_activity.json index b711bd1..6f8ec84 100644 --- a/lib/tests/data/response/user_activity.json +++ b/lib/tests/data/response/user_activity.json @@ -1,53 +1,53 @@ [ - { - "interval": { - "start": 1745020800000, - "end": 1745107200000 - }, - "games": { - "blitz": { - "win": 1, - "loss": 0, - "draw": 0, - "rp": { - "before": 1712, - "after": 1717 - } - } - }, - "follows": { - "in": { - "ids": [ - "aadhya5", - "mrbernhardknarkson", - "biggiantsandwich" - ] - } - } - }, - { - "interval": { - "start": 1744934400000, - "end": 1745020800000 - }, - "puzzles": { - "score": { - "win": 0, - "loss": 1, - "draw": 0, - "rp": { - "before": 1911, - "after": 1911 - } - } - }, - "follows": { - "in": { - "ids": [ - "midnight_marauder", - "aryanraj2014" - ] - } - } - } + { + "interval": { + "start": 1745020800000, + "end": 1745107200000 + }, + "games": { + "blitz": { + "win": 1, + "loss": 0, + "draw": 0, + "rp": { + "before": 1712, + "after": 1717 + } + } + }, + "follows": { + "in": { + "ids": [ + "aadhya5", + "mrbernhardknarkson", + "biggiantsandwich" + ] + } + } + }, + { + "interval": { + "start": 1744934400000, + "end": 1745020800000 + }, + "puzzles": { + "score": { + "win": 0, + "loss": 1, + "draw": 0, + "rp": { + "before": 1911, + "after": 1911 + } + } + }, + "follows": { + "in": { + "ids": [ + "midnight_marauder", + "aryanraj2014" + ] + } + } + } ] \ No newline at end of file diff --git a/lib/tests/data/response/user_extended.json b/lib/tests/data/response/user_extended.json index 6a6d607..b972989 100644 --- a/lib/tests/data/response/user_extended.json +++ b/lib/tests/data/response/user_extended.json @@ -1,127 +1,127 @@ { - "id": "mary", - "username": "Mary", - "perfs": { - "bullet": { - "games": 119, - "rating": 1066, - "rd": 101, - "prog": -1 + "id": "mary", + "username": "Mary", + "perfs": { + "bullet": { + "games": 119, + "rating": 1066, + "rd": 101, + "prog": -1 + }, + "blitz": { + "games": 34, + "rating": 1007, + "rd": 55, + "prog": -59 + }, + "rapid": { + "games": 134, + "rating": 1021, + "rd": 70, + "prog": 26 + }, + "classical": { + "games": 451, + "rating": 1136, + "rd": 78, + "prog": -1 + }, + "correspondence": { + "games": 35, + "rating": 1049, + "rd": 45, + "prog": 15 + }, + "chess960": { + "games": 52, + "rating": 996, + "rd": 72, + "prog": -9 + }, + "kingOfTheHill": { + "games": 1998, + "rating": 1169, + "rd": 79, + "prog": -13 + }, + "threeCheck": { + "games": 6, + "rating": 946, + "rd": 52, + "prog": 32 + }, + "antichess": { + "games": 79, + "rating": 1143, + "rd": 48, + "prog": 61 + }, + "atomic": { + "games": 239, + "rating": 978, + "rd": 76, + "prog": 22 + }, + "horde": { + "games": 246, + "rating": 1031, + "rd": 108, + "prog": -28 + }, + "crazyhouse": { + "games": 473, + "rating": 1063, + "rd": 88, + "prog": 2 + }, + "puzzle": { + "games": 37, + "rating": 977, + "rd": 86, + "prog": 26 + } }, - "blitz": { - "games": 34, - "rating": 1007, - "rd": 55, - "prog": -59 + "flair": "food-drink.coconut", + "createdAt": 1744526339498, + "profile": { + "location": "Mary City", + "cfcRating": 1173, + "rcfRating": 897, + "flag": "MF", + "dsbRating": 1110, + "fideRating": 1050, + "ecfRating": 1249, + "uscfRating": 1217, + "bio": "The elementary form of value of a commodity is contained in the equation, expressing its value relation to another commodity of a different kind, or in its exchange relation to the same.", + "links": "https://en.wikipedia.org/wiki/Joni_Mitchell\nhttps://en.wikipedia.org/wiki/Srinivasa_Ramanujan" }, - "rapid": { - "games": 134, - "rating": 1021, - "rd": 70, - "prog": 26 + "seenAt": 1744677685927, + "playTime": { + "total": 14336, + "tv": 0 }, - "classical": { - "games": 451, - "rating": 1136, - "rd": 78, - "prog": -1 + "url": "http://localhost:8080/@/Mary", + "count": { + "all": 5251, + "rated": 4200, + "ai": 0, + "draw": 250, + "drawH": 250, + "loss": 2418, + "lossH": 2418, + "win": 2583, + "winH": 2583, + "bookmark": 0, + "playing": 0, + "import": 0, + "me": 1 }, - "correspondence": { - "games": 35, - "rating": 1049, - "rd": 45, - "prog": 15 + "streamer": { + "twitch": { + "channel": "https://www.twitch.tv/lichessdotorg" + } }, - "chess960": { - "games": 52, - "rating": 996, - "rd": 72, - "prog": -9 - }, - "kingOfTheHill": { - "games": 1998, - "rating": 1169, - "rd": 79, - "prog": -13 - }, - "threeCheck": { - "games": 6, - "rating": 946, - "rd": 52, - "prog": 32 - }, - "antichess": { - "games": 79, - "rating": 1143, - "rd": 48, - "prog": 61 - }, - "atomic": { - "games": 239, - "rating": 978, - "rd": 76, - "prog": 22 - }, - "horde": { - "games": 246, - "rating": 1031, - "rd": 108, - "prog": -28 - }, - "crazyhouse": { - "games": 473, - "rating": 1063, - "rd": 88, - "prog": 2 - }, - "puzzle": { - "games": 37, - "rating": 977, - "rd": 86, - "prog": 26 - } - }, - "flair": "food-drink.coconut", - "createdAt": 1744526339498, - "profile": { - "location": "Mary City", - "cfcRating": 1173, - "rcfRating": 897, - "flag": "MF", - "dsbRating": 1110, - "fideRating": 1050, - "ecfRating": 1249, - "uscfRating": 1217, - "bio": "The elementary form of value of a commodity is contained in the equation, expressing its value relation to another commodity of a different kind, or in its exchange relation to the same.", - "links": "https://en.wikipedia.org/wiki/Joni_Mitchell\nhttps://en.wikipedia.org/wiki/Srinivasa_Ramanujan" - }, - "seenAt": 1744677685927, - "playTime": { - "total": 14336, - "tv": 0 - }, - "url": "http://localhost:8080/@/Mary", - "count": { - "all": 5251, - "rated": 4200, - "ai": 0, - "draw": 250, - "drawH": 250, - "loss": 2418, - "lossH": 2418, - "win": 2583, - "winH": 2583, - "bookmark": 0, - "playing": 0, - "import": 0, - "me": 1 - }, - "streamer": { - "twitch": { - "channel": "https://www.twitch.tv/lichessdotorg" - } - }, - "followable": true, - "following": false, - "blocking": false + "followable": true, + "following": false, + "blocking": false } \ No newline at end of file diff --git a/lib/tests/data/response/user_performance.json b/lib/tests/data/response/user_performance.json index 86ab0b6..3306b78 100644 --- a/lib/tests/data/response/user_performance.json +++ b/lib/tests/data/response/user_performance.json @@ -1,250 +1,250 @@ { - "user": { - "name": "Tarr3n" - }, - "perf": { - "glicko": { - "rating": 1955.89, - "deviation": 45.0 + "user": { + "name": "Tarr3n" }, - "nb": 14632, - "progress": -18 - }, - "rank": 502, - "percentile": 92.1, - "stat": { - "count": { - "berserk": 904, - "win": 8152, - "all": 15249, - "seconds": 1387450, - "opAvg": 1824.61, - "draw": 233, - "tour": 3273, - "disconnects": 0, - "rated": 14632, - "loss": 6864 - }, - "resultStreak": { - "win": { - "cur": { - "v": 0 - }, - "max": { - "v": 45, - "from": { - "at": "2020-07-03T12:45:38.028Z", - "gameId": "sUHkFZ2t" - }, - "to": { - "at": "2020-07-04T15:19:09.255Z", - "gameId": "HwEaczVF" - } - } - }, - "loss": { - "cur": { - "v": 2, - "from": { - "at": "2024-09-10T16:56:56.388Z", - "gameId": "YuVvrANS" - }, - "to": { - "at": "2024-09-10T17:00:05.579Z", - "gameId": "6qi1yLYU" - } + "perf": { + "glicko": { + "rating": 1955.89, + "deviation": 45.0 }, - "max": { - "v": 41, - "from": { - "at": "2019-11-27T19:02:45.016Z", - "gameId": "tiwQsw9t" - }, - "to": { - "at": "2019-11-27T19:46:03.585Z", - "gameId": "SK2uSsGQ" - } - } - } - }, - "lowest": { - "int": 1201, - "at": "2019-11-23T08:37:47.855Z", - "gameId": "qeMz4KvC" + "nb": 14632, + "progress": -18 }, - "worstLosses": { - "results": [ - { - "opRating": 1113, - "opId": { - "id": "m_guzel", - "name": "M_Guzel", - "title": null - }, - "at": "2020-03-29T09:01:27.789Z", - "gameId": "01k3dvDL" + "rank": 502, + "percentile": 92.1, + "stat": { + "count": { + "berserk": 904, + "win": 8152, + "all": 15249, + "seconds": 1387450, + "opAvg": 1824.61, + "draw": 233, + "tour": 3273, + "disconnects": 0, + "rated": 14632, + "loss": 6864 }, - { - "opRating": 1158, - "opId": { - "id": "lilyschirmbeck", - "name": "Lilyschirmbeck", - "title": "WCM" - }, - "at": "2020-06-25T20:57:54.333Z", - "gameId": "nciW5Rb4" + "resultStreak": { + "win": { + "cur": { + "v": 0 + }, + "max": { + "v": 45, + "from": { + "at": "2020-07-03T12:45:38.028Z", + "gameId": "sUHkFZ2t" + }, + "to": { + "at": "2020-07-04T15:19:09.255Z", + "gameId": "HwEaczVF" + } + } + }, + "loss": { + "cur": { + "v": 2, + "from": { + "at": "2024-09-10T16:56:56.388Z", + "gameId": "YuVvrANS" + }, + "to": { + "at": "2024-09-10T17:00:05.579Z", + "gameId": "6qi1yLYU" + } + }, + "max": { + "v": 41, + "from": { + "at": "2019-11-27T19:02:45.016Z", + "gameId": "tiwQsw9t" + }, + "to": { + "at": "2019-11-27T19:46:03.585Z", + "gameId": "SK2uSsGQ" + } + } + } }, - { - "opRating": 1176, - "opId": { - "id": "nirvan1234", - "name": "nirvan1234", - "title": null - }, - "at": "2020-06-13T14:56:44.945Z", - "gameId": "IrS6dhQY" + "lowest": { + "int": 1201, + "at": "2019-11-23T08:37:47.855Z", + "gameId": "qeMz4KvC" }, - { - "opRating": 1201, - "opId": { - "id": "khodavedk", - "name": "khodavedk", - "title": null - }, - "at": "2020-03-28T10:23:20.719Z", - "gameId": "3imrI2kk" + "worstLosses": { + "results": [ + { + "opRating": 1113, + "opId": { + "id": "m_guzel", + "name": "M_Guzel", + "title": null + }, + "at": "2020-03-29T09:01:27.789Z", + "gameId": "01k3dvDL" + }, + { + "opRating": 1158, + "opId": { + "id": "lilyschirmbeck", + "name": "Lilyschirmbeck", + "title": "WCM" + }, + "at": "2020-06-25T20:57:54.333Z", + "gameId": "nciW5Rb4" + }, + { + "opRating": 1176, + "opId": { + "id": "nirvan1234", + "name": "nirvan1234", + "title": null + }, + "at": "2020-06-13T14:56:44.945Z", + "gameId": "IrS6dhQY" + }, + { + "opRating": 1201, + "opId": { + "id": "khodavedk", + "name": "khodavedk", + "title": null + }, + "at": "2020-03-28T10:23:20.719Z", + "gameId": "3imrI2kk" + }, + { + "opRating": 1206, + "opId": { + "id": "white__killer1", + "name": "white__killer1", + "title": null + }, + "at": "2020-05-08T11:18:38.937Z", + "gameId": "Zj2VjkWL" + } + ] }, - { - "opRating": 1206, - "opId": { - "id": "white__killer1", - "name": "white__killer1", - "title": null - }, - "at": "2020-05-08T11:18:38.937Z", - "gameId": "Zj2VjkWL" - } - ] - }, - "perfType": { - "key": "antichess", - "name": "Antichess" - }, - "id": "tarr3n/13", - "bestWins": { - "results": [ - { - "opRating": 2449, - "opId": { - "id": "antichess_valentino", - "name": "Antichess_Valentino", - "title": null - }, - "at": "2024-08-09T21:26:10.033Z", - "gameId": "FwhIplpv" + "perfType": { + "key": "antichess", + "name": "Antichess" }, - { - "opRating": 2409, - "opId": { - "id": "antichess_valentino", - "name": "Antichess_Valentino", - "title": null - }, - "at": "2024-03-10T18:53:29.285Z", - "gameId": "a9mpQZ6A" + "id": "tarr3n/13", + "bestWins": { + "results": [ + { + "opRating": 2449, + "opId": { + "id": "antichess_valentino", + "name": "Antichess_Valentino", + "title": null + }, + "at": "2024-08-09T21:26:10.033Z", + "gameId": "FwhIplpv" + }, + { + "opRating": 2409, + "opId": { + "id": "antichess_valentino", + "name": "Antichess_Valentino", + "title": null + }, + "at": "2024-03-10T18:53:29.285Z", + "gameId": "a9mpQZ6A" + }, + { + "opRating": 2392, + "opId": { + "id": "changeopening", + "name": "ChangeOpening", + "title": null + }, + "at": "2024-02-19T18:43:05.66Z", + "gameId": "JnDNs0EN" + }, + { + "opRating": 2390, + "opId": { + "id": "allegro_moon", + "name": "Allegro_Moon", + "title": null + }, + "at": "2024-03-05T18:37:32.635Z", + "gameId": "VcgEbatU" + }, + { + "opRating": 2387, + "opId": { + "id": "fins-love", + "name": "Fins-Love", + "title": null + }, + "at": "2024-08-02T18:26:58.501Z", + "gameId": "Eo0PFFsj" + } + ] }, - { - "opRating": 2392, - "opId": { - "id": "changeopening", - "name": "ChangeOpening", + "userId": { + "id": "tarr3n", + "name": "Tarr3n", "title": null - }, - "at": "2024-02-19T18:43:05.66Z", - "gameId": "JnDNs0EN" }, - { - "opRating": 2390, - "opId": { - "id": "allegro_moon", - "name": "Allegro_Moon", - "title": null - }, - "at": "2024-03-05T18:37:32.635Z", - "gameId": "VcgEbatU" + "playStreak": { + "nb": { + "cur": { + "v": 8, + "from": { + "at": "2024-09-10T16:40:57.636Z", + "gameId": "Mq9gSZLi" + }, + "to": { + "at": "2024-09-10T17:00:05.579Z", + "gameId": "6qi1yLYU" + } + }, + "max": { + "v": 128, + "from": { + "at": "2020-04-23T10:05:24.651Z", + "gameId": "NqG48jAx" + }, + "to": { + "at": "2020-04-23T16:16:23.075Z", + "gameId": "Y2kixNMn" + } + } + }, + "time": { + "cur": { + "v": 857, + "from": { + "at": "2024-09-10T16:40:57.636Z", + "gameId": "Mq9gSZLi" + }, + "to": { + "at": "2024-09-10T17:00:05.579Z", + "gameId": "6qi1yLYU" + } + }, + "max": { + "v": 16894, + "from": { + "at": "2020-04-23T10:05:24.651Z", + "gameId": "NqG48jAx" + }, + "to": { + "at": "2020-04-23T16:16:23.075Z", + "gameId": "Y2kixNMn" + } + } + }, + "lastDate": "2024-09-10T17:00:05.579Z" }, - { - "opRating": 2387, - "opId": { - "id": "fins-love", - "name": "Fins-Love", - "title": null - }, - "at": "2024-08-02T18:26:58.501Z", - "gameId": "Eo0PFFsj" + "highest": { + "int": 2087, + "at": "2024-06-19T18:22:51.442Z", + "gameId": "zzGA5X63" } - ] - }, - "userId": { - "id": "tarr3n", - "name": "Tarr3n", - "title": null - }, - "playStreak": { - "nb": { - "cur": { - "v": 8, - "from": { - "at": "2024-09-10T16:40:57.636Z", - "gameId": "Mq9gSZLi" - }, - "to": { - "at": "2024-09-10T17:00:05.579Z", - "gameId": "6qi1yLYU" - } - }, - "max": { - "v": 128, - "from": { - "at": "2020-04-23T10:05:24.651Z", - "gameId": "NqG48jAx" - }, - "to": { - "at": "2020-04-23T16:16:23.075Z", - "gameId": "Y2kixNMn" - } - } - }, - "time": { - "cur": { - "v": 857, - "from": { - "at": "2024-09-10T16:40:57.636Z", - "gameId": "Mq9gSZLi" - }, - "to": { - "at": "2024-09-10T17:00:05.579Z", - "gameId": "6qi1yLYU" - } - }, - "max": { - "v": 16894, - "from": { - "at": "2020-04-23T10:05:24.651Z", - "gameId": "NqG48jAx" - }, - "to": { - "at": "2020-04-23T16:16:23.075Z", - "gameId": "Y2kixNMn" - } - } - }, - "lastDate": "2024-09-10T17:00:05.579Z" - }, - "highest": { - "int": 2087, - "at": "2024-06-19T18:22:51.442Z", - "gameId": "zzGA5X63" } - } -} +} \ No newline at end of file diff --git a/lib/tests/data/response/user_statuses.json b/lib/tests/data/response/user_statuses.json index fe8f0d5..b7f4129 100644 --- a/lib/tests/data/response/user_statuses.json +++ b/lib/tests/data/response/user_statuses.json @@ -1,13 +1,13 @@ [ - { - "name": "Mary", - "flair": "food-drink.coconut", - "id": "mary" - }, - { - "name": "Ana", - "title": "GM", - "flair": "symbols.japanese-no-vacancy-button", - "id": "ana" - } + { + "name": "Mary", + "flair": "food-drink.coconut", + "id": "mary" + }, + { + "name": "Ana", + "title": "GM", + "flair": "symbols.japanese-no-vacancy-button", + "id": "ana" + } ] \ No newline at end of file diff --git a/lib/tests/offline.rs b/lib/tests/offline.rs index 8b8d2a1..11499b3 100644 --- a/lib/tests/offline.rs +++ b/lib/tests/offline.rs @@ -18,39 +18,30 @@ pub fn response() { #[test] pub fn board_event_stream() { - test_response_model::<board::stream::events::Event>("challenge"); - test_response_model::<board::stream::events::Event>("challenge_canceled"); - test_response_model::<board::stream::events::Event>("challenge_declined"); - test_response_model::<board::stream::events::Event>("game_start"); - test_response_model::<board::stream::events::Event>("game_finish"); + test_response_model::<board::stream::events::Event>("game_start_event"); + test_response_model::<board::stream::events::Event>("game_start_ai_event"); + test_response_model::<board::stream::events::Event>("game_finish_event"); + test_response_model::<board::stream::events::Event>("game_finish_ai_event"); + test_response_model::<board::stream::events::Event>("challenge_event1"); + test_response_model::<board::stream::events::Event>("challenge_event2"); + test_response_model::<board::stream::events::Event>("challenge_declined_event1"); + test_response_model::<board::stream::events::Event>("challenge_declined_event2"); + test_response_model::<board::stream::events::Event>("challenge_canceled_event1"); + test_response_model::<board::stream::events::Event>("challenge_canceled_event2"); } #[test] pub fn board_game_stream() { - test_response_model::<board::stream::game::Event>("game_full_human"); - test_response_model::<board::stream::game::Event>("game_state"); + test_response_model::<board::stream::game::Event>("game_full_event"); + test_response_model::<board::stream::game::Event>("game_state_event"); test_response_model::<board::stream::game::Event>("game_state_resign"); - test_response_model::<board::stream::game::Event>("chat_line"); - test_response_model::<board::stream::game::Event>("chat_line_spectator"); - test_response_model::<board::stream::game::Event>("opponent_gone_false"); - test_response_model::<board::stream::game::Event>("opponent_gone_true"); + test_response_model::<board::stream::game::Event>("chat_line_event"); + test_response_model::<board::stream::game::Event>("opponent_gone_event"); } #[test] -pub fn challenge_ai() { - test_response_model::<games::stream::moves::Move>("challenge_ai"); - test_response_model::<board::stream::game::Event>("game_full_ai"); -} - -#[test] -pub fn challenge_anonymous() { - test_response_model::<board::stream::events::Event>("challenge_anonymous"); - test_response_model::<board::stream::game::Event>("game_full_anonymous"); -} - -#[test] -pub fn games_export() { - test_response_model::<games::GameJson>("game_json"); +pub fn board_chat() { + test_response_model::<Vec<board::chat::ChatLine>>("game_chat"); } #[test] @@ -117,9 +108,6 @@ pub fn challenges() { test_response_model::<challenges::ChallengeJson>("challenge_json"); test_response_model::<challenges::ChallengeOpenJson>("challenge_open_json"); test_response_model::<challenges::ChallengeDeclinedJson>("challenge_declined_json"); - test_response_model::<challenges::ChallengeEvent>("challenge_event"); - test_response_model::<challenges::ChallengeCanceledEvent>("challenge_canceled_event"); - test_response_model::<challenges::ChallengeDeclinedEvent>("challenge_declined_event"); } fn test_response_model<Model: Serialize + DeserializeOwned>(file_name: &str) {