use crate::{ types::{AppState, Config, ConfigOption, DatabasePath, GameState, Player, Rank}, ui::{configuration, home, playing_field, ConfigurationView, HomeView, PlayingFieldView}, }; use serde::{Deserialize, Serialize}; use std::{ path::PathBuf, sync::{Arc, RwLock}, }; use typeshare::typeshare; #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] #[typeshare] #[serde(tag = "type", content = "content")] pub enum CoreRequest { ChangeSetting(ChangeSettingRequest), CreateGame(CreateGameRequest), Home, OpenConfiguration, PlayingField, PlayStone(PlayStoneRequest), StartGame, } #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] #[typeshare] #[serde(tag = "type", content = "content")] pub enum ChangeSettingRequest { LibraryPath(String), } #[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, } impl From 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 { ConfigurationView(ConfigurationView), HomeView(HomeView), PlayingFieldView(PlayingFieldView), UpdatedConfigurationView(ConfigurationView), } #[derive(Clone, Debug)] pub struct CoreApp { config: Arc>, state: Arc>, } impl CoreApp { pub fn new(config_path: std::path::PathBuf) -> Self { let config = Config::from_path(config_path).expect("configuration to open"); let db_path: DatabasePath = config.get().unwrap(); let state = Arc::new(RwLock::new(AppState::new(db_path))); Self { config: Arc::new(RwLock::new(config)), state, } } pub async fn dispatch(&self, request: CoreRequest) -> CoreResponse { match request { CoreRequest::ChangeSetting(request) => match request { ChangeSettingRequest::LibraryPath(path) => { let mut config = self.config.write().unwrap(); config.set(ConfigOption::DatabasePath(DatabasePath(PathBuf::from( path, )))); CoreResponse::UpdatedConfigurationView(configuration(&config)) } }, 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::OpenConfiguration => { CoreResponse::ConfigurationView(configuration(&self.config.read().unwrap())) } 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) {} }