Set up the game review page along with #229
|
@ -17,19 +17,11 @@ You should have received a copy of the GNU General Public License along with On
|
||||||
use crate::{
|
use crate::{
|
||||||
database::Database,
|
database::Database,
|
||||||
library, settings,
|
library, settings,
|
||||||
types::{AppState, Config, ConfigOption, GameState, LibraryPath, Player, Rank},
|
types::{Config, LibraryPath},
|
||||||
};
|
|
||||||
use async_std::{
|
|
||||||
channel::{Receiver, Sender},
|
|
||||||
stream,
|
|
||||||
task::spawn,
|
|
||||||
};
|
};
|
||||||
|
use async_std::channel::{Receiver, Sender};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::{
|
use std::sync::{Arc, RwLock, RwLockReadGuard};
|
||||||
future::Future,
|
|
||||||
path::PathBuf,
|
|
||||||
sync::{Arc, RwLock, RwLockReadGuard},
|
|
||||||
};
|
|
||||||
|
|
||||||
pub trait Observable<T> {
|
pub trait Observable<T> {
|
||||||
fn subscribe(&self) -> Receiver<T>;
|
fn subscribe(&self) -> Receiver<T>;
|
||||||
|
@ -168,14 +160,14 @@ impl Core {
|
||||||
*self.library.write().unwrap() = Some(db);
|
*self.library.write().unwrap() = Some(db);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn library<'a>(&'a self) -> RwLockReadGuard<'_, Option<Database>> {
|
pub fn library(&self) -> RwLockReadGuard<'_, Option<Database>> {
|
||||||
self.library.read().unwrap()
|
self.library.read().unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn dispatch(&self, request: CoreRequest) -> CoreResponse {
|
pub async fn dispatch(&self, request: CoreRequest) -> CoreResponse {
|
||||||
match request {
|
match request {
|
||||||
CoreRequest::Library(request) => library::handle(&self, request).await.into(),
|
CoreRequest::Library(request) => library::handle(self, request).await.into(),
|
||||||
CoreRequest::Settings(request) => settings::handle(&self, request).await.into(),
|
CoreRequest::Settings(request) => settings::handle(self, request).await.into(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -42,13 +42,10 @@ impl Database {
|
||||||
.unwrap();
|
.unwrap();
|
||||||
match parse_sgf(&buffer) {
|
match parse_sgf(&buffer) {
|
||||||
Ok(sgfs) => {
|
Ok(sgfs) => {
|
||||||
for sgf in sgfs {
|
let mut sgfs = sgfs.into_iter().flatten().collect::<Vec<sgf::GameRecord>>();
|
||||||
if let Ok(sgf) = sgf {
|
games.append(&mut sgfs);
|
||||||
games.push(sgf);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Err(err) => println!("Error parsing {:?}", entry.path()),
|
Err(err) => println!("Error parsing {:?}: {:?}", entry.path(), err),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -95,7 +95,7 @@ impl Goban {
|
||||||
/// This would not work at all if we wanted to set up an impossible board state, given that
|
/// This would not work at all if we wanted to set up an impossible board state, given that
|
||||||
/// groups of stones get automatically removed once surrounded.
|
/// groups of stones get automatically removed once surrounded.
|
||||||
pub fn from_coordinates(
|
pub fn from_coordinates(
|
||||||
mut coordinates: impl IntoIterator<Item = (Coordinate, Color)>,
|
coordinates: impl IntoIterator<Item = (Coordinate, Color)>,
|
||||||
) -> Result<Self, BoardError> {
|
) -> Result<Self, BoardError> {
|
||||||
coordinates.into_iter().try_fold(Self::new(), |board, (coordinate, color)| {
|
coordinates.into_iter().try_fold(Self::new(), |board, (coordinate, color)| {
|
||||||
board.place_stone(coordinate, color)
|
board.place_stone(coordinate, color)
|
|
@ -19,8 +19,8 @@ extern crate config_derive;
|
||||||
mod api;
|
mod api;
|
||||||
pub use api::{Core, CoreNotification, CoreRequest, CoreResponse, Observable};
|
pub use api::{Core, CoreNotification, CoreRequest, CoreResponse, Observable};
|
||||||
|
|
||||||
mod board;
|
mod goban;
|
||||||
pub use board::*;
|
pub use goban::*;
|
||||||
|
|
||||||
mod database;
|
mod database;
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,7 @@ General Public License for more details.
|
||||||
You should have received a copy of the GNU General Public License along with On the Grid. If not, see <https://www.gnu.org/licenses/>.
|
You should have received a copy of the GNU General Public License along with On the Grid. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
use crate::{Core, Config};
|
use crate::{Core};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use sgf::GameRecord;
|
use sgf::GameRecord;
|
||||||
|
|
||||||
|
@ -32,7 +32,7 @@ async fn handle_list_games(model: &Core) -> LibraryResponse {
|
||||||
let library = model.library();
|
let library = model.library();
|
||||||
match *library {
|
match *library {
|
||||||
Some(ref library) => {
|
Some(ref library) => {
|
||||||
let info = library.all_games().map(|g| g.clone()).collect::<Vec<GameRecord>>();
|
let info = library.all_games().cloned().collect::<Vec<GameRecord>>();
|
||||||
LibraryResponse::Games(info)
|
LibraryResponse::Games(info)
|
||||||
}
|
}
|
||||||
None => LibraryResponse::Games(vec![]),
|
None => LibraryResponse::Games(vec![]),
|
||||||
|
|
|
@ -14,7 +14,7 @@ GNU General Public License for more details.
|
||||||
You should have received a copy of the GNU General Public License along with On the Grid. If not, see <https://www.gnu.org/licenses/>.
|
You should have received a copy of the GNU General Public License along with On the Grid. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
use crate::{types::LibraryPath, Core, Config};
|
use crate::{Core, Config};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||||
|
|
|
@ -1,7 +1,4 @@
|
||||||
use crate::{
|
use crate::goban::{Coordinate, Goban};
|
||||||
board::{Coordinate, Goban},
|
|
||||||
database::Database,
|
|
||||||
};
|
|
||||||
use config::define_config;
|
use config::define_config;
|
||||||
use config_derive::ConfigOption;
|
use config_derive::ConfigOption;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
@ -70,6 +67,32 @@ impl Default for Size {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// AppState stores all of the important state to a full running version of the application.
|
||||||
|
/// However, this version of AppState is in pretty sorry shape.
|
||||||
|
///
|
||||||
|
/// What are the states of the app?
|
||||||
|
///
|
||||||
|
/// - in review
|
||||||
|
/// - in a game
|
||||||
|
/// - connections to the internet
|
||||||
|
/// - connections to local applications, such as Leela Zero
|
||||||
|
/// - the current configuration
|
||||||
|
/// - the games database
|
||||||
|
/// - If in a game, the current state of the game. Delegated to GameState.
|
||||||
|
/// - If in review, the current state of the review.
|
||||||
|
///
|
||||||
|
/// Some of these states are concurrent. It's quite possible to have online connections running and
|
||||||
|
/// to be reviewing a game while, for instance, waiting for an opponent on OGS to make a move.
|
||||||
|
///
|
||||||
|
/// I get to ignore a lot of these things for now. Not playing online. Not playing at all,
|
||||||
|
/// actually. We'll come back to that.
|
||||||
|
///
|
||||||
|
/// Plus, it gets more fuzzy, because some of the application state is really UI state. For
|
||||||
|
/// instance, the state of a game review is purely UI.
|
||||||
|
///
|
||||||
|
/// So... AppState probably isn't great for now, but maybe it will become so later. I think I'm
|
||||||
|
/// going to ignore it until I need it.
|
||||||
|
/*
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct AppState {
|
pub struct AppState {
|
||||||
pub game: Option<GameState>,
|
pub game: Option<GameState>,
|
||||||
|
@ -95,9 +118,11 @@ impl AppState {
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
pub enum Rank {
|
pub enum Rank {
|
||||||
|
|
||||||
Kyu(u8),
|
Kyu(u8),
|
||||||
Dan(u8),
|
Dan(u8),
|
||||||
Pro(u8),
|
Pro(u8),
|
||||||
|
@ -164,6 +189,9 @@ impl Default for GameState {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl GameState {
|
impl GameState {
|
||||||
|
// Legacy code. I recall that this is no longer used (but will be used again) because I
|
||||||
|
// commented out so much code when I was overhauling the architecture of this app.
|
||||||
|
#[allow(dead_code)]
|
||||||
fn place_stone(&mut self, coordinate: Coordinate) -> Result<(), BoardError> {
|
fn place_stone(&mut self, coordinate: Coordinate) -> Result<(), BoardError> {
|
||||||
let board = self.board.clone();
|
let board = self.board.clone();
|
||||||
let new_board = board.place_stone(coordinate, self.current_player)?;
|
let new_board = board.place_stone(coordinate, self.current_player)?;
|
||||||
|
|
Loading…
Reference in New Issue