Set up a database and serve character sheets from it #277
|
@ -3,6 +3,7 @@ use std::{
|
|||
thread::JoinHandle,
|
||||
};
|
||||
|
||||
use async_std::channel::{bounded, Receiver, Sender};
|
||||
use async_trait::async_trait;
|
||||
use include_dir::{include_dir, Dir};
|
||||
use lazy_static::lazy_static;
|
||||
|
@ -10,7 +11,6 @@ use rusqlite::Connection;
|
|||
use rusqlite_migration::Migrations;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use thiserror::Error;
|
||||
use async_std::channel::{Sender, Receiver, bounded};
|
||||
use uuid::Uuid;
|
||||
|
||||
static MIGRATIONS_DIR: Dir = include_dir!("$CARGO_MANIFEST_DIR/migrations");
|
||||
|
@ -29,7 +29,7 @@ pub enum Error {
|
|||
MessageMismatch,
|
||||
|
||||
#[error("No response to request")]
|
||||
NoResponse
|
||||
NoResponse,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
|
@ -82,10 +82,7 @@ pub struct CharsheetRow {
|
|||
|
||||
#[async_trait]
|
||||
pub trait Database: Send + Sync {
|
||||
async fn charsheet(
|
||||
&mut self,
|
||||
id: CharacterId,
|
||||
) -> Result<Option<CharsheetRow>, Error>;
|
||||
async fn charsheet(&mut self, id: CharacterId) -> Result<Option<CharsheetRow>, Error>;
|
||||
}
|
||||
|
||||
pub struct DiskDb {
|
||||
|
@ -102,6 +99,20 @@ impl DiskDb {
|
|||
Some(path) => Connection::open(path).expect("to create connection"),
|
||||
};
|
||||
MIGRATIONS.to_latest(&mut conn).expect("to run migrations");
|
||||
|
||||
{
|
||||
let mut stmt = conn.prepare("SELECT count(*) FROM charsheet").unwrap();
|
||||
let mut sheets = stmt.query([]).unwrap();
|
||||
if sheets.next().unwrap().unwrap().get::<usize, usize>(0) == Ok(0) {
|
||||
let char_id = CharacterId::new();
|
||||
let mut stmt = conn
|
||||
.prepare("INSERT INTO charsheet VALUES (?, ?, ?)")
|
||||
.unwrap();
|
||||
stmt.execute((char_id.as_str(), "Candela", r#"{ "type_": "Candela", "name": "Soren Jensen", "pronouns": "he/him", "circle": "Circle of the Bluest Sky", "style": "dapper gentleman", "catalyst": "a cursed book", "question": "What were the contents of that book?", "nerve": { "type_": "nerve", "drives": { "current": 1, "max": 2 }, "resistances": { "current": 0, "max": 3 }, "move": { "gilded": false, "score": 2 }, "strike": { "gilded": false, "score": 1 }, "control": { "gilded": true, "score": 0 } }, "cunning": { "type_": "cunning", "drives": { "current": 1, "max": 1 }, "resistances": { "current": 0, "max": 3 }, "sway": { "gilded": false, "score": 0 }, "read": { "gilded": false, "score": 0 }, "hide": { "gilded": false, "score": 0 } }, "intuition": { "type_": "intuition", "drives": { "current": 0, "max": 0 }, "resistances": { "current": 0, "max": 3 }, "survey": { "gilded": false, "score": 0 }, "focus": { "gilded": false, "score": 0 }, "sense": { "gilded": false, "score": 0 } }, "role": "Slink", "role_abilities": [ "Scout: If you have time to observe a location, you can spend 1 Intuition to ask a question: What do I notice here that others do not see? What in this place might be of use to us? What path should we follow?" ], "specialty": "Detective", "specialty_abilities": [ "Mind Palace: When you want to figure out how two clues might relate or what path they should point you towards, burn 1 Intution resistance. The GM will give you the information you have deduced." ] }"#))
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
Ok(DiskDb { conn })
|
||||
}
|
||||
|
||||
|
@ -163,7 +174,7 @@ impl DiskDb {
|
|||
|
||||
async fn db_handler(db: DiskDb, mut requestor: Receiver<DatabaseRequest>) {
|
||||
println!("Starting db_handler");
|
||||
while let Ok(DatabaseRequest{ tx, req }) = requestor.recv().await {
|
||||
while let Ok(DatabaseRequest { tx, req }) = requestor.recv().await {
|
||||
println!("Request received: {:?}", req);
|
||||
match req {
|
||||
Request::Charsheet(id) => {
|
||||
|
@ -172,7 +183,7 @@ async fn db_handler(db: DiskDb, mut requestor: Receiver<DatabaseRequest>) {
|
|||
match sheet {
|
||||
Ok(sheet) => {
|
||||
tx.send(DatabaseResponse::Charsheet(sheet)).await.unwrap();
|
||||
},
|
||||
}
|
||||
_ => unimplemented!(),
|
||||
}
|
||||
}
|
||||
|
@ -194,7 +205,9 @@ impl DbConn {
|
|||
let (tx, rx) = bounded::<DatabaseRequest>(5);
|
||||
let db = DiskDb::new(path).unwrap();
|
||||
|
||||
let handle = tokio::spawn(async move { db_handler(db, rx).await; });
|
||||
let handle = tokio::spawn(async move {
|
||||
db_handler(db, rx).await;
|
||||
});
|
||||
|
||||
Self { conn: tx, handle }
|
||||
}
|
||||
|
@ -202,13 +215,10 @@ impl DbConn {
|
|||
|
||||
#[async_trait]
|
||||
impl Database for DbConn {
|
||||
async fn charsheet(
|
||||
&mut self,
|
||||
id: CharacterId,
|
||||
) -> Result<Option<CharsheetRow>, Error> {
|
||||
async fn charsheet(&mut self, id: CharacterId) -> Result<Option<CharsheetRow>, Error> {
|
||||
let (tx, rx) = bounded::<DatabaseResponse>(1);
|
||||
|
||||
let request = DatabaseRequest{
|
||||
let request = DatabaseRequest {
|
||||
tx,
|
||||
req: Request::Charsheet(id),
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue