diff --git a/README.md b/README.md index 9f5dd98..56c6ac6 100644 --- a/README.md +++ b/README.md @@ -199,4 +199,4 @@ GOTO label | 12 | Failed to open archive | Make sure the story file is a zip archive. | | 13 | Unable to setup the characters hashmap. | Make sure the characters.json file exists, is valid JSON and contains valid characters. | | 14 | Unable to read the main story file. | Make sure the story.ha file exists and is readable. | -| 15 | | | \ No newline at end of file +| 15 | | | diff --git a/server/src/api.rs b/server/src/api.rs index cca0e7e..ee4d661 100644 --- a/server/src/api.rs +++ b/server/src/api.rs @@ -33,7 +33,7 @@ pub async fn api_process ( data_to_send: Arc>, characters: Arc>>, - tx: Sender<(bool, usize)>, + tx: Sender<(bool, usize, String)>, ) { // This data must be passed through to the api route in order to be used @@ -41,6 +41,7 @@ pub async fn api_process let characters_filter = warp::any().map(move || Arc::clone(&characters)); let tx_filter = warp::any().map(move || tx.clone()); let tx_filter2 = tx_filter.clone(); + let tx_filter3 = tx_filter.clone(); info!("Running server"); @@ -50,11 +51,11 @@ pub async fn api_process .and(data_filter) .and(tx_filter) // Perform this code on a GET request - .map(|state: Arc>, tx_handle: Sender<(bool,usize)>| + .map(|state: Arc>, tx_handle: Sender<(bool,usize,String)>| { debug!("GET: {state:?}"); let reply = state.as_ref(); - let _ = tx_handle.send((true,0)); + let _ = tx_handle.send((true,0,String::new())); warp::reply::json(&reply) // Send the reply data (data_to_send formatted as JSON) }).boxed(); let characters = warp::path("character") @@ -89,14 +90,24 @@ pub async fn api_process .and(warp::post()) .and(warp::body::json()) .and(tx_filter2) - .map(|index: usize, tx_handle: Sender<(bool,usize)>| { + .map(|index: usize, tx_handle: Sender<(bool,usize,String)>| { debug!("Choice: {index}"); - let _ = tx_handle.send((true,index)); + let _ = tx_handle.send((true,index,String::new())); + let reply = "ack"; + warp::reply::json(&reply) + }).boxed(); + let input = warp::path("input") + .and(warp::post()) + .and(warp::body::json()) + .and(tx_filter3) + .map(|input: String, tx_handle: Sender<(bool, usize, String)>| + { + let _ = tx_handle.send((true,0,input)); let reply = "ack"; warp::reply::json(&reply) }).boxed(); - let routes = main.or(characters).or(choice); + let routes = main.or(characters).or(choice).or(input); // Start the server warp::serve(routes) .run(([127, 0, 0, 1],config::API_PORT)) diff --git a/server/src/character.rs b/server/src/character.rs index 53196ab..47996f9 100644 --- a/server/src/character.rs +++ b/server/src/character.rs @@ -39,25 +39,26 @@ pub struct Clothing shoes: String, } impl Character { + // Big ass ugly function because rust doesn't support referencing struct entries by string pub fn set_field(&mut self, field: &str, value: &str) -> Result<(), ()> { match field { - "name" => self.name = value.to_string(), - "gender" => self.gender = value.to_string(), - "eye_color" => self.eye_color = value.to_string(), - "pronoun_subject" => self.pronoun_subject = value.to_string(), - "pronoun_object" => self.pronoun_object = value.to_string(), - "pronoun_deppos" => self.pronoun_deppos = value.to_string(), - "pronoun_indpos" => self.pronoun_indpos = value.to_string(), - "pronoun_reflex" => self.pronoun_reflex = value.to_string(), - "head_shape" => self.head_shape = value.to_string(), - "hair_style" => self.hair_style = value.to_string(), - "torso_shape" => self.torso_shape = value.to_string(), - "arm_shape" => self.arm_shape = value.to_string(), - "leg_shape" => self.leg_shape = value.to_string(), - "hair_color" => self.hair_color = value.to_string(), - "clothing.top" => self.clothing.top = value.to_string(), - "clothing.bottom" => self.clothing.bottom = value.to_string(), - "clothing.shoes" => self.clothing.shoes = value.to_string(), + "name" => self.name = value.to_string(), + "gender" => self.gender = value.to_string(), + "eye_color" => self.eye_color = value.to_string(), + "pronoun_subject" => self.pronoun_subject = value.to_string(), + "pronoun_object" => self.pronoun_object = value.to_string(), + "pronoun_deppos" => self.pronoun_deppos = value.to_string(), + "pronoun_indpos" => self.pronoun_indpos = value.to_string(), + "pronoun_reflex" => self.pronoun_reflex = value.to_string(), + "head_shape" => self.head_shape = value.to_string(), + "hair_style" => self.hair_style = value.to_string(), + "torso_shape" => self.torso_shape = value.to_string(), + "arm_shape" => self.arm_shape = value.to_string(), + "leg_shape" => self.leg_shape = value.to_string(), + "hair_color" => self.hair_color = value.to_string(), + "clothing.top" => self.clothing.top = value.to_string(), + "clothing.bottom" => self.clothing.bottom = value.to_string(), + "clothing.shoes" => self.clothing.shoes = value.to_string(), _ => return Err(()), } diff --git a/server/src/main.rs b/server/src/main.rs index 6b5edd6..4122a57 100644 --- a/server/src/main.rs +++ b/server/src/main.rs @@ -3,6 +3,7 @@ mod character; mod config; mod api; mod traits; +mod tokenise; use std:: { @@ -96,7 +97,6 @@ async fn main() api::api_process(data_clone1, characters_clone1, tx_clone).await; }); - // setup the parsing stuff // // Read the file and split it into tokens // file read from a zip file /story.ha @@ -114,6 +114,7 @@ async fn main() exit(14); }); // Tokenise story file + /* let tokens: Vec<&str> = file_contents .split_whitespace() .collect(); @@ -121,8 +122,13 @@ async fn main() { warn!("No END statement, story may exit unexpectedly"); } + */ + let space_seperated: Vec<&str> = file_contents + .split_whitespace() + .collect(); + let (tokens, labels,_) = tokenise::tokenise(&space_seperated, 0).unwrap(); debug!("{tokens:?}"); - +/* let data_clone2 = Arc::clone(&data_to_send); let characters_clone2 = Arc::clone(&characters); // Run the parsing process for the DSL @@ -142,4 +148,5 @@ async fn main() exit(1); }, } +*/ } diff --git a/server/src/parsing.rs b/server/src/parsing.rs index 9b769d4..0c4e7dc 100644 --- a/server/src/parsing.rs +++ b/server/src/parsing.rs @@ -23,7 +23,7 @@ pub fn token_parse( tokens: &Vec<&str>, characters: &Arc>>, data_to_send: &Arc>, - rx: &Receiver<(bool,usize)>, + rx: &Receiver<(bool,usize,String)>, ) -> Result<(),String> { info!("DSL parsing begun"); @@ -76,13 +76,13 @@ pub fn token_parse( Err(error) => return Err(error), }; if rx.recv().is_err() { warn!("Error sending choices to client"); } - let (_, choice) = match rx.recv() + let (_, choice, _) = match rx.recv() { - Ok((_,choice)) => (None::, choice), + Ok((_,choice,_)) => (None::, choice, None::), Err(err) => { warn!("Error receiving choice from client, defaulting to choice 0 {err}"); - (None::, 0) + (None::, 0, None::) } }; index = jump_points[choice]; diff --git a/server/src/tokenise.rs b/server/src/tokenise.rs new file mode 100644 index 0000000..e34d189 --- /dev/null +++ b/server/src/tokenise.rs @@ -0,0 +1,76 @@ +use crate:: +{ + debug, + exit, +}; + +#[derive(Debug)] +pub enum Token +{ + Null, + String(String), + Object(Vec), +} + +pub fn tokenise(space_seperated: &Vec<&str>, mut index: usize) +-> Result<(Vec,Vec<(String,usize)>,usize),String> +{ + let mut tokenised_data: Vec = Vec::new(); + let mut labels: Vec<(String,usize)> = Vec::new(); + while index < space_seperated.len() + { + let mut item = space_seperated[index].to_string(); + let mut object: Vec = Vec::new(); + debug!("{item}"); + if item.starts_with("\"") + { + (index, item) = match tokenise_string(&space_seperated, index) + { + Some((index,item)) => (index, item), + None => exit(1), + }; + tokenised_data.push(Token::String(item)); + } + else if item == "{" + { + (object, labels, index) = match tokenise(&space_seperated, index+1) // !WARNING! recursive call + { + Ok((object,labels,index)) => (object,labels,index), + Err(err) => return Err(err), + }; + tokenised_data.push(Token::Object(object)); + } + else if item == "}" + { + return Ok((tokenised_data,labels,index)); + } + else { tokenised_data.push(Token::String(item)); } + index += 1; + } + return Ok((tokenised_data, labels, 0)); +} + +fn tokenise_string(space_seperated: &Vec<&str>, mut index: usize) +-> Option<(usize, String)> +{ + let mut string = String::new(); + let mut chars = space_seperated[index].chars(); + chars.next(); + string += chars.as_str(); + for item in &space_seperated[index+1..] + { + if item.ends_with("\"") + { + let mut chars = item.chars(); + chars.next_back(); + string += format!(" {}", chars.as_str()).as_str(); + break + } + else + { + string += format!(" {}", item).as_str(); + } + index += 1; + } + return Some((index+1,string)) +}