From 148fb73f7f3883217561d7dda7ebb99f74124569 Mon Sep 17 00:00:00 2001 From: deadvey Date: Tue, 26 May 2026 21:41:36 +0100 Subject: [PATCH] added support for instring variables and made character IDs be always stored in lowercase --- server/Cargo.lock | 1 + server/Cargo.toml | 1 + server/src/character.rs | 7 ++-- server/src/main.rs | 1 + server/src/parsing/identifier_parse.rs | 3 ++ server/src/parsing/keyword_parse.rs | 13 ++++++-- server/src/tokenise.rs | 43 +++++++++++++++++++++++-- stories/about.json | 4 --- stories/characters.json | 27 ---------------- stories/story.ha | 27 ---------------- stories/test.zip | Bin 962 -> 0 bytes test-client/main.py | 12 ++++--- 12 files changed, 69 insertions(+), 70 deletions(-) delete mode 100644 stories/about.json delete mode 100644 stories/characters.json delete mode 100644 stories/story.ha delete mode 100644 stories/test.zip diff --git a/server/Cargo.lock b/server/Cargo.lock index 18f0a8a..1c1cdda 100644 --- a/server/Cargo.lock +++ b/server/Cargo.lock @@ -461,6 +461,7 @@ version = "0.0.3" dependencies = [ "env_logger", "log", + "regex", "serde", "serde-patch", "serde_json", diff --git a/server/Cargo.toml b/server/Cargo.toml index ec40ec5..6f7aa47 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -25,6 +25,7 @@ unwrap_used = "warn" [dependencies] env_logger = "0.11.10" log = "0.4.29" +regex = "1.12.3" serde = { version = "1.0.228", features = ["derive"] } serde-patch = "0.2.3" serde_json = "1.0.149" diff --git a/server/src/character.rs b/server/src/character.rs index f9f08a6..473ab5a 100644 --- a/server/src/character.rs +++ b/server/src/character.rs @@ -71,8 +71,11 @@ pub fn character_parse(archive: &mut ZipArchive) // Serialise this to a HashMap let characters: HashMap = - serde_json::from_str(&file_contents) - .map_err (|err| format!("Invalid JSON in characters.json: {err}"))?; + serde_json::from_str::>(&file_contents) + .map_err (|err| format!("Invalid JSON in characters.json: {err}"))? + .into_iter() + .map(|(k,v)| (k.to_lowercase(), v)) + .collect(); info!("Parsed characters from characters.json"); debug!("{characters:?}"); Ok(Arc::new(Mutex::new(characters))) diff --git a/server/src/main.rs b/server/src/main.rs index e718b78..fa9d2be 100644 --- a/server/src/main.rs +++ b/server/src/main.rs @@ -40,6 +40,7 @@ use crate:: { traits::UnwrapOrExit, }; +use regex::Regex; #[tokio::main] async fn main() diff --git a/server/src/parsing/identifier_parse.rs b/server/src/parsing/identifier_parse.rs index a5ac09d..dc0ad61 100644 --- a/server/src/parsing/identifier_parse.rs +++ b/server/src/parsing/identifier_parse.rs @@ -10,6 +10,7 @@ use crate:: VecDeque, warn, debug, + info, mpsc::Receiver, }; use super::keyword_parse; @@ -62,6 +63,7 @@ pub fn identifier_parse "input" => { api::modify_data(happening_queue, "input".to_string(), String::new(), String::new(), Vec::new()); + info!("Waiting for client input"); let input = match rx.recv() { Ok((_,input)) => input, @@ -72,6 +74,7 @@ pub fn identifier_parse } }; variables.insert(identifier.to_owned(), tokenise::Value::String(input)); + sum_index += 1; }, _ => { diff --git a/server/src/parsing/keyword_parse.rs b/server/src/parsing/keyword_parse.rs index d75ad30..f20acf3 100644 --- a/server/src/parsing/keyword_parse.rs +++ b/server/src/parsing/keyword_parse.rs @@ -89,6 +89,7 @@ pub fn keyword_parse( // Jump to a particular index based on a label eg GOTO character_check "goto" => { + info!("GOTO command, jumping there"); index += 1; let label = tokenise::get_keyword_token(tokens, index)?; index = if let Some(label_index) = labels.get(&label) { *label_index } @@ -98,10 +99,17 @@ pub fn keyword_parse( index + 1 }; debug!("Jumping to {index}"); - } + }, + "pan" => + { + info!("PAN command, informing client"); + index += 1; + let location = tokenise::get_keyword_token(tokens, index)?; + api::modify_data(happening_queue, "pan".to_string(), location, String::new(), Vec::new()); + }, _ => { - warn!("Invalid command: {token}"); + warn!("Invalid command: {token}, index {index}"); index += 1; } } @@ -142,6 +150,7 @@ pub fn choice_parse } }; api::modify_data(happening_queue, "choice".to_string(), String::new(), String::new(), choices.clone()); + info!("Waiting for client choice"); debug!("{choice_indeces:?}"); let choice = match rx.recv() { diff --git a/server/src/tokenise.rs b/server/src/tokenise.rs index ef53d64..b2f534c 100644 --- a/server/src/tokenise.rs +++ b/server/src/tokenise.rs @@ -1,6 +1,7 @@ use crate:: { HashMap, + Regex, }; #[derive(Debug, Clone)] @@ -49,6 +50,19 @@ pub enum Comparison LessOrEqual, } +impl Value +{ + pub fn as_string(&self) -> String + { + match self + { + Value::String(s) => s.clone(), + Value::Integer(i) => i.to_string(), + Value::Bool(b) => b.to_string(), + Value::Null => "".to_string(), + } + } +} // TODO error reporting for all of these pub fn get_operator_token(tokens: &[Token], index: usize) @@ -105,7 +119,11 @@ pub fn get_string_token(tokens: &[Token], index: usize, variables: &HashMap Ok(s.clone()), + Value::String(s) => + { + let string = insert_variables_into_string(s, variables); + Ok(string) + }, _ => Err("Unexpected value type".to_string()), } }, @@ -116,7 +134,11 @@ pub fn get_string_token(tokens: &[Token], index: usize, variables: &HashMap Ok(s.clone()), + Value::String(s) => + { + let string = insert_variables_into_string(s, variables); + Ok(string) + }, _ => Err("Unexpected value type".to_string()), } }, @@ -125,6 +147,19 @@ pub fn get_string_token(tokens: &[Token], index: usize, variables: &HashMap) +-> String +{ + let re = Regex::new(r"\$([A-Za-z0-9-_]*)").unwrap(); + re.replace_all(string, |caps: ®ex::Captures| { + let key = &caps[1].to_lowercase(); + variables.get(key) + .map(|v| v.as_string()) + .unwrap_or_else(|| caps[0].to_string()) // leave unchanged if missing + }) + .to_string() +} + // Tokenise the story to Vec // It can contain sub-objects (using recursive calls) // TODO check for END @@ -165,7 +200,7 @@ pub fn tokenise(file_contents: &str) { let mut chars = item.chars(); chars.next(); - tokenised_data.push(Token::Character(chars.as_str().to_string())); + tokenised_data.push(Token::Character(chars.as_str().to_lowercase().to_string())); // Force character to be lowecase } // Strings else if item.starts_with('"') // TODO support ' @@ -227,6 +262,8 @@ pub fn tokenise(file_contents: &str) Ok((tokenised_data, labels)) } + +// TODO support strings that contain " in them by using a backslash fn tokenise_string(space_seperated: &[&str], mut index: usize) -> Option<(usize, String)> { diff --git a/stories/about.json b/stories/about.json deleted file mode 100644 index 65f3ce7..0000000 --- a/stories/about.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "title": "Once upon a Test", - "description": "This story is for testing purposes" -} diff --git a/stories/characters.json b/stories/characters.json deleted file mode 100644 index 62f85f5..0000000 --- a/stories/characters.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "tim": { - "name": "Timothy Sharpshooter", - "gender": "Male", - "skin_color": [0,0,0], - "eye_color": [0,0,0], - "hair_color": [0,0,0], - "pronoun_subject": "He", - "pronoun_object": "Him", - "pronoun_deppos": "His", - "pronoun_indpos": "His", - "pronoun_reflex": "Himself", - "head_shape": "normal-male", - "hair_style": "", - "torso_shape": "", - "arm_shape": "", - "leg_shape": "", - "clothing": { - "top": "", - "bottom": "", - "shoes": "", - "hat": "", - "gloves": "", - "neck": "" - } - } -} diff --git a/stories/story.ha b/stories/story.ha deleted file mode 100644 index 2c7237f..0000000 --- a/stories/story.ha +++ /dev/null @@ -1,27 +0,0 @@ -$name = input -@tim says "hello" -@tim says $name -$x = 3 -$x + 1 -if $x == 4 { - @tim says "5" -} -elif $x < 5 { - - @tim says "<5" -} -else { - @tim says "whar" -} -label: -$choice_string = choice "choice numero uno" { - @tim says "super sad" -} -or "choice numero duo" { - @tim says "super unsad" -} -or "choice numero tres" { - @tim says "hola mi amigos" - goto label -} -END diff --git a/stories/test.zip b/stories/test.zip deleted file mode 100644 index 39ffe691c02aad03daa57b855e1c62c987f6d29c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 962 zcmWIWW@Zs#U|`^2Fpk(2b17JS;#LL*hG<5RhzvtzoS?_Lu- z;^e=1_vZU=#2n2(Ec*Olt5Ms9NybIYvSD&eq7z$0WYb>?yT4(JOg{ZZ_V9xa+c+J~ zIz`F!{AFieJU>zO`~3Oktn1SfqPfi@-0n=V+^}Vh=k!;vnlEpA<==1nV~LsBDZxdm zcHEynE{uskt=M~K&V<6ojf4Ezi-49OXZMTyBJsYS(lS;hHzVBbGFBbo)m=)RwLFz=87Puuyo z!3*ZhJTg=LMyh(*?10p$%Pf;Dy3TIl`uNU!GGEk@DKc;V7r(i&@7h$M$5+Zq*RJ-e zESQn=HB+WjF3g(OaD$pqPnNCQmlwNJme1hd5Mg2`eSb?z=9T?suS>p3K4{P{HYq`*-#}zr%Do!B}rrKuXmfO(mD_I+1VYFTJ*`Qu@Asw?uKP_1Y_qE+@{mY!QAk zbG>6)T>i`IM%!)A->AJ0TVB1oo)HmP)0#HLSl{Ai31nbk2xnkm;9`(rNKDEvEkT5n zj~;hckRCUBDiJ-kk+;Et!{Oqs*-Zh~jovrzFg` z3?RVBz`(Gi5yV0yWL8K*MvF#d(=by6vT5HL7%BMs=~y85{|44 a%%E_@a3m`m$TQ3g%nY9y7#Makfp`G>&Qe(b diff --git a/test-client/main.py b/test-client/main.py index 699213a..88d9b58 100644 --- a/test-client/main.py +++ b/test-client/main.py @@ -2,11 +2,11 @@ import requests import os import time import sys -debug = False +debug = True try: - if sys.argv[1] == "debug": debug = True + if sys.argv[1] == "silent": debug = False except: - debug = False + debug = True # Loop and get new api def main(): @@ -22,7 +22,9 @@ def main(): output(character, response["content"]) case "choice": user_choice = choice(response["choices"]) - time.sleep(0.5) + continue + case "input": + get_input() continue case "end": print("Exitting successfully") @@ -46,7 +48,7 @@ def choice(choices): def get_input(): api_url = "http://localhost:20264/input" - input_string = input() + input_string = input("Input: ") requests.post(api_url, json=input_string);