2024-03-21 23:20:09 +00:00
|
|
|
/*
|
|
|
|
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/>.
|
|
|
|
*/
|
|
|
|
|
2023-06-15 03:49:03 +00:00
|
|
|
use crate::{
|
2024-02-28 00:03:13 +00:00
|
|
|
database::Database,
|
2024-03-19 14:08:43 +00:00
|
|
|
types::{AppState, Config, ConfigOption, GameState, LibraryPath, Player, Rank},
|
2024-03-21 23:20:09 +00:00
|
|
|
settings,
|
2024-03-19 14:08:43 +00:00
|
|
|
};
|
|
|
|
use async_std::{
|
|
|
|
channel::{Receiver, Sender},
|
|
|
|
stream,
|
|
|
|
task::spawn,
|
2023-06-15 03:49:03 +00:00
|
|
|
};
|
2023-04-21 02:50:48 +00:00
|
|
|
use serde::{Deserialize, Serialize};
|
2023-08-25 00:52:27 +00:00
|
|
|
use std::{
|
2024-03-19 14:08:43 +00:00
|
|
|
future::Future,
|
2023-08-25 00:52:27 +00:00
|
|
|
path::PathBuf,
|
2024-03-15 14:49:25 +00:00
|
|
|
sync::{Arc, RwLock, RwLockReadGuard},
|
2023-08-25 00:52:27 +00:00
|
|
|
};
|
2024-02-28 03:36:35 +00:00
|
|
|
|
|
|
|
pub trait Observable<T> {
|
|
|
|
fn subscribe(&self) -> Receiver<T>;
|
|
|
|
}
|
|
|
|
|
2024-03-21 23:20:09 +00:00
|
|
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
2023-05-11 13:39:31 +00:00
|
|
|
pub enum CoreRequest {
|
2024-03-21 23:20:09 +00:00
|
|
|
Settings(settings::SettingsRequest)
|
|
|
|
/*
|
2023-08-25 00:52:27 +00:00
|
|
|
ChangeSetting(ChangeSettingRequest),
|
2023-06-15 03:49:03 +00:00
|
|
|
CreateGame(CreateGameRequest),
|
2023-07-24 23:43:22 +00:00
|
|
|
Home,
|
2023-08-25 00:24:41 +00:00
|
|
|
OpenConfiguration,
|
2023-03-20 12:16:20 +00:00
|
|
|
PlayingField,
|
2023-06-15 03:49:03 +00:00
|
|
|
PlayStone(PlayStoneRequest),
|
2023-05-26 04:16:40 +00:00
|
|
|
StartGame,
|
2024-03-21 23:20:09 +00:00
|
|
|
*/
|
2023-03-20 12:16:20 +00:00
|
|
|
}
|
|
|
|
|
2023-08-25 00:52:27 +00:00
|
|
|
#[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
|
|
|
}
|
|
|
|
|
2023-06-15 03:49:03 +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,
|
2023-06-15 03:49:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
|
|
|
pub enum PlayerInfoRequest {
|
|
|
|
Hotseat(HotseatPlayerRequest),
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
|
|
|
pub struct HotseatPlayerRequest {
|
2023-06-16 02:20:59 +00:00
|
|
|
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-06-15 03:49:03 +00:00
|
|
|
}
|
|
|
|
|
2023-04-21 02:50:48 +00:00
|
|
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
2023-05-11 13:39:31 +00:00
|
|
|
pub enum CoreResponse {
|
2024-03-21 23:20:09 +00:00
|
|
|
Settings(settings::SettingsResponse)
|
|
|
|
/*
|
2023-08-25 00:24:41 +00:00
|
|
|
ConfigurationView(ConfigurationView),
|
2023-07-24 23:43:22 +00:00
|
|
|
HomeView(HomeView),
|
2023-03-20 12:16:20 +00:00
|
|
|
PlayingFieldView(PlayingFieldView),
|
2023-08-25 00:52:27 +00:00
|
|
|
UpdatedConfigurationView(ConfigurationView),
|
2024-03-15 14:49:25 +00:00
|
|
|
*/
|
2024-03-21 23:20:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl From<settings::SettingsResponse> for CoreResponse {
|
|
|
|
fn from(r: settings::SettingsResponse) -> Self {
|
|
|
|
Self::Settings(r)
|
|
|
|
}
|
|
|
|
}
|
2023-03-20 12:16:20 +00:00
|
|
|
|
2024-03-19 14:08:43 +00:00
|
|
|
#[derive(Clone, Debug)]
|
2024-02-27 12:49:10 +00:00
|
|
|
pub enum CoreNotification {
|
2024-03-19 14:08:43 +00:00
|
|
|
ConfigurationUpdated(Config),
|
2024-02-27 12:49:10 +00:00
|
|
|
BoardUpdated,
|
|
|
|
}
|
|
|
|
|
2023-04-21 13:25:21 +00:00
|
|
|
#[derive(Clone, Debug)]
|
2024-02-27 13:34:17 +00:00
|
|
|
pub struct Core {
|
2024-03-19 14:08:43 +00:00
|
|
|
config: Arc<RwLock<Config>>,
|
2024-02-27 00:06:41 +00:00
|
|
|
// state: Arc<RwLock<AppState>>,
|
2024-03-15 14:49:25 +00:00
|
|
|
library: Arc<RwLock<Option<Database>>>,
|
2024-02-28 00:09:21 +00:00
|
|
|
subscribers: Arc<RwLock<Vec<Sender<CoreNotification>>>>,
|
2023-03-20 12:16:20 +00:00
|
|
|
}
|
|
|
|
|
2024-02-27 13:34:17 +00:00
|
|
|
impl Core {
|
2024-03-19 14:08:43 +00:00
|
|
|
pub fn new(config: Config) -> Self {
|
2024-03-21 23:20:09 +00:00
|
|
|
println!("config: {:?}", config);
|
2023-08-25 00:52:27 +00:00
|
|
|
Self {
|
2024-03-19 14:08:43 +00:00
|
|
|
config: Arc::new(RwLock::new(config)),
|
2024-02-27 00:06:41 +00:00
|
|
|
// state,
|
2024-03-15 14:49:25 +00:00
|
|
|
library: Arc::new(RwLock::new(None)),
|
2024-02-28 00:09:21 +00:00
|
|
|
subscribers: Arc::new(RwLock::new(vec![])),
|
2023-08-25 00:52:27 +00:00
|
|
|
}
|
2023-03-20 12:16:20 +00:00
|
|
|
}
|
|
|
|
|
2024-03-19 14:08:43 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-03-15 14:49:25 +00:00
|
|
|
pub fn library<'a>(&'a self) -> RwLockReadGuard<'_, Option<Database>> {
|
|
|
|
self.library.read().unwrap()
|
|
|
|
}
|
|
|
|
|
2024-03-21 23:20:09 +00:00
|
|
|
pub async fn dispatch(&self, request: CoreRequest) -> CoreResponse {
|
|
|
|
match request {
|
|
|
|
CoreRequest::Settings(request) => settings::handle(&self, request).await.into(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-02-27 12:49:10 +00:00
|
|
|
/*
|
2023-05-11 13:39:31 +00:00
|
|
|
pub async fn dispatch(&self, request: CoreRequest) -> CoreResponse {
|
2023-03-20 12:16:20 +00:00
|
|
|
match request {
|
2023-08-25 00:52:27 +00:00
|
|
|
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!()
|
2023-08-25 00:52:27 +00:00
|
|
|
}
|
|
|
|
},
|
2023-06-16 02:20:59 +00:00
|
|
|
CoreRequest::CreateGame(create_request) => {
|
2024-02-27 00:06:41 +00:00
|
|
|
/*
|
2023-06-16 02:20:59 +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()
|
2023-06-16 02:20:59 +00:00
|
|
|
});
|
|
|
|
let game_state = app_state.game.as_ref().unwrap();
|
|
|
|
CoreResponse::PlayingFieldView(playing_field(game_state))
|
2024-02-27 00:06:41 +00:00
|
|
|
*/
|
|
|
|
unimplemented!()
|
2023-06-15 03:49:03 +00:00
|
|
|
}
|
2023-07-26 03:27:36 +00:00
|
|
|
CoreRequest::Home => {
|
2024-02-27 00:06:41 +00:00
|
|
|
// CoreResponse::HomeView(home(self.state.read().unwrap().database.all_games()))
|
|
|
|
unimplemented!()
|
2023-07-26 03:27:36 +00:00
|
|
|
}
|
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
|
|
|
}
|
2023-06-15 03:49:03 +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!()
|
|
|
|
}
|
2023-03-20 12:16:20 +00:00
|
|
|
}
|
|
|
|
}
|
2024-02-27 12:49:10 +00:00
|
|
|
*/
|
2023-03-20 12:16:20 +00:00
|
|
|
|
2024-02-27 12:49:10 +00:00
|
|
|
// pub async fn run(&self) {}
|
2023-03-20 12:16:20 +00:00
|
|
|
}
|
2024-02-28 03:36:35 +00:00
|
|
|
|
|
|
|
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
|
|
|
|
}
|
|
|
|
}
|