monorepo/kifu/core/src/api.rs

144 lines
5.0 KiB
Rust

use crate::{
types::{AppState, GameState, Player, Rank},
ui::{home, playing_field, HomeView, PlayingFieldView},
Config, DatabasePath,
};
use serde::{Deserialize, Serialize};
use std::sync::{Arc, RwLock};
use typeshare::typeshare;
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
#[typeshare]
#[serde(tag = "type", content = "content")]
pub enum CoreRequest {
CreateGame(CreateGameRequest),
Home,
PlayingField,
PlayStone(PlayStoneRequest),
StartGame,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
#[typeshare]
pub struct PlayStoneRequest {
pub column: u8,
pub row: u8,
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
#[typeshare]
pub struct CreateGameRequest {
pub black_player: PlayerInfoRequest,
pub white_player: PlayerInfoRequest,
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
#[typeshare]
pub enum PlayerInfoRequest {
Hotseat(HotseatPlayerRequest),
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
#[typeshare]
pub struct HotseatPlayerRequest {
pub name: String,
pub rank: Option<String>,
}
impl From<HotseatPlayerRequest> for Player {
fn from(p: HotseatPlayerRequest) -> Self {
Self {
name: p.name,
rank: p.rank.and_then(|r| Rank::try_from(r.as_ref()).ok()),
}
}
}
#[derive(Clone, Debug, Serialize, Deserialize)]
#[typeshare]
#[serde(tag = "type", content = "content")]
pub enum CoreResponse {
HomeView(HomeView),
PlayingFieldView(PlayingFieldView),
}
#[derive(Clone, Debug)]
pub struct CoreApp {
config: Config,
state: Arc<RwLock<AppState>>,
}
impl CoreApp {
pub fn new(config_path: std::path::PathBuf) -> Self {
println!("config_path: {:?}", config_path);
let config = Config::from_path(config_path).expect("configuration to open");
let db_path: DatabasePath = config.get();
let state = Arc::new(RwLock::new(AppState::new(db_path)));
println!("config: {:?}", config);
println!("games database: {:?}", state.read().unwrap().database.len());
Self { config, state }
}
pub async fn dispatch(&self, request: CoreRequest) -> CoreResponse {
match request {
/*
CoreRequest::LaunchScreen => {
let app_state = self.state.read().unwrap();
At launch, I want to either show a list of games in progress, the current game, or the game creation screen.
- if a live game is in progress, immmediately go to that game. Such a game will be classified at game creation, so it should be persisted to the state.
- if no live games are in progress, but there are slow games in progress, show a list of the slow games and let the player choose which one to jump into.
- if no games are in progress, show only the game creation screen
- game creation menu should be present both when there are only slow games and when there are no games
- the UI returned here will always be available in other places, such as when the user is viewing a game and wants to return to this page
For the initial version, I want only to show the game creation screen. Then I will backtrack record application state so that the only decisions can be made.
}
*/
CoreRequest::CreateGame(create_request) => {
let mut app_state = self.state.write().unwrap();
let white_player = {
match create_request.white_player {
PlayerInfoRequest::Hotseat(request) => Player::from(request),
}
};
let black_player = {
match create_request.black_player {
PlayerInfoRequest::Hotseat(request) => Player::from(request),
}
};
app_state.game = Some(GameState {
white_player,
black_player,
..GameState::new()
});
let game_state = app_state.game.as_ref().unwrap();
CoreResponse::PlayingFieldView(playing_field(game_state))
}
CoreRequest::Home => {
CoreResponse::HomeView(home(self.state.read().unwrap().database.all_games()))
}
CoreRequest::PlayingField => {
let app_state = self.state.read().unwrap();
let game = app_state.game.as_ref().unwrap();
CoreResponse::PlayingFieldView(playing_field(game))
}
CoreRequest::PlayStone(request) => {
let mut app_state = self.state.write().unwrap();
app_state.place_stone(request);
let game = app_state.game.as_ref().unwrap();
CoreResponse::PlayingFieldView(playing_field(game))
}
CoreRequest::StartGame => {
unimplemented!()
}
}
}
pub async fn run(&self) {}
}