monorepo/kifu/core/src/api.rs

238 lines
7.5 KiB
Rust
Raw Normal View History

/*
Copyright 2024, Savanni D'Gerinel <savanni@luminescent-dreams.com>
This file is part of Kifu.
Kifu is free software: you can redistribute it and/or modify it under the terms of the GNU
General Public License as published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
Kifu is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License along with Kifu. If not, see <https://www.gnu.org/licenses/>.
*/
use crate::{
2024-02-28 00:03:13 +00:00
database::Database,
types::{AppState, Config, ConfigOption, GameState, LibraryPath, Player, Rank},
settings,
};
use async_std::{
channel::{Receiver, Sender},
stream,
task::spawn,
};
2023-04-21 02:50:48 +00:00
use serde::{Deserialize, Serialize};
use std::{
future::Future,
path::PathBuf,
sync::{Arc, RwLock, RwLockReadGuard},
};
pub trait Observable<T> {
fn subscribe(&self) -> Receiver<T>;
}
#[derive(Clone, Debug, Serialize, Deserialize)]
2023-05-11 13:39:31 +00:00
pub enum CoreRequest {
Settings(settings::SettingsRequest)
/*
ChangeSetting(ChangeSettingRequest),
CreateGame(CreateGameRequest),
2023-07-24 23:43:22 +00:00
Home,
2023-08-25 00:24:41 +00:00
OpenConfiguration,
PlayingField,
PlayStone(PlayStoneRequest),
2023-05-26 04:16:40 +00:00
StartGame,
*/
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub enum ChangeSettingRequest {
LibraryPath(String),
}
2023-04-21 02:50:48 +00:00
#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
2023-04-07 01:52:39 +00:00
pub struct PlayStoneRequest {
2023-05-11 13:39:31 +00:00
pub column: u8,
pub row: u8,
2023-04-07 01:52:39 +00:00
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub struct CreateGameRequest {
2023-06-15 04:09:50 +00:00
pub black_player: PlayerInfoRequest,
pub white_player: PlayerInfoRequest,
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub enum PlayerInfoRequest {
Hotseat(HotseatPlayerRequest),
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
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()),
}
}
}
2023-04-21 02:50:48 +00:00
#[derive(Clone, Debug, Serialize, Deserialize)]
2023-05-11 13:39:31 +00:00
pub enum CoreResponse {
Settings(settings::SettingsResponse)
/*
2023-08-25 00:24:41 +00:00
ConfigurationView(ConfigurationView),
2023-07-24 23:43:22 +00:00
HomeView(HomeView),
PlayingFieldView(PlayingFieldView),
UpdatedConfigurationView(ConfigurationView),
*/
}
impl From<settings::SettingsResponse> for CoreResponse {
fn from(r: settings::SettingsResponse) -> Self {
Self::Settings(r)
}
}
#[derive(Clone, Debug)]
pub enum CoreNotification {
ConfigurationUpdated(Config),
BoardUpdated,
}
2023-04-21 13:25:21 +00:00
#[derive(Clone, Debug)]
pub struct Core {
config: Arc<RwLock<Config>>,
2024-02-27 00:06:41 +00:00
// state: Arc<RwLock<AppState>>,
library: Arc<RwLock<Option<Database>>>,
subscribers: Arc<RwLock<Vec<Sender<CoreNotification>>>>,
}
impl Core {
pub fn new(config: Config) -> Self {
println!("config: {:?}", config);
Self {
config: Arc::new(RwLock::new(config)),
2024-02-27 00:06:41 +00:00
// state,
library: Arc::new(RwLock::new(None)),
subscribers: Arc::new(RwLock::new(vec![])),
}
}
pub fn get_config(&self) -> Config {
self.config.read().unwrap().clone()
}
/// Change the configuration of the Core. This function will update any relevant core
/// functions, especially the contents of the library, and it will notify any subscribed objects
/// that the configuration has changed.
///
/// It will not handle persisting the new configuration, as the backing store for the
/// configuration is not a decision for the core library.
pub async fn set_config(&self, config: Config) {
*self.config.write().unwrap() = config.clone();
let subscribers = self.subscribers.read().unwrap().clone();
for subscriber in subscribers {
let subscriber = subscriber.clone();
let _ = subscriber.send(CoreNotification::ConfigurationUpdated(config.clone())).await;
}
}
pub fn library<'a>(&'a self) -> RwLockReadGuard<'_, Option<Database>> {
self.library.read().unwrap()
}
pub async fn dispatch(&self, request: CoreRequest) -> CoreResponse {
match request {
CoreRequest::Settings(request) => settings::handle(&self, request).await.into(),
}
}
/*
2023-05-11 13:39:31 +00:00
pub async fn dispatch(&self, request: CoreRequest) -> CoreResponse {
match request {
CoreRequest::ChangeSetting(request) => match request {
ChangeSettingRequest::LibraryPath(path) => {
2024-02-27 00:06:41 +00:00
// let mut config = self.config.write().unwrap();
// config.set(ConfigOption::DatabasePath(DatabasePath(PathBuf::from(
// path,
// ))));
// CoreResponse::UpdatedConfigurationView(configuration(&config))
unimplemented!()
}
},
CoreRequest::CreateGame(create_request) => {
2024-02-27 00:06:41 +00:00
/*
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,
2023-10-05 16:19:57 +00:00
..GameState::default()
});
let game_state = app_state.game.as_ref().unwrap();
CoreResponse::PlayingFieldView(playing_field(game_state))
2024-02-27 00:06:41 +00:00
*/
unimplemented!()
}
CoreRequest::Home => {
2024-02-27 00:06:41 +00:00
// CoreResponse::HomeView(home(self.state.read().unwrap().database.all_games()))
unimplemented!()
}
2023-08-25 00:24:41 +00:00
CoreRequest::OpenConfiguration => {
2024-02-27 00:06:41 +00:00
// CoreResponse::ConfigurationView(configuration(&self.config.read().unwrap()))
unimplemented!()
2023-08-25 00:24:41 +00:00
}
2023-05-11 13:39:31 +00:00
CoreRequest::PlayingField => {
2024-02-27 00:06:41 +00:00
// let app_state = self.state.read().unwrap();
// let game = app_state.game.as_ref().unwrap();
// CoreResponse::PlayingFieldView(playing_field(game))
unimplemented!()
2023-04-07 01:52:39 +00:00
}
CoreRequest::PlayStone(request) => {
2024-02-27 00:06:41 +00:00
// let mut app_state = self.state.write().unwrap();
// app_state.place_stone(request);
2023-04-07 01:52:39 +00:00
2024-02-27 00:06:41 +00:00
// let game = app_state.game.as_ref().unwrap();
// CoreResponse::PlayingFieldView(playing_field(game))
unimplemented!()
2023-04-07 01:52:39 +00:00
}
2023-05-26 04:16:40 +00:00
CoreRequest::StartGame => {
unimplemented!()
}
}
}
*/
// pub async fn run(&self) {}
}
impl Observable<CoreNotification> for Core {
fn subscribe(&self) -> Receiver<CoreNotification> {
let mut subscribers = self.subscribers.write().unwrap();
let (sender, receiver) = async_std::channel::unbounded();
subscribers.push(sender);
receiver
}
}