added support for instring variables and made character IDs
be always stored in lowercase
This commit is contained in:
Generated
+1
@@ -461,6 +461,7 @@ version = "0.0.3"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"env_logger",
|
"env_logger",
|
||||||
"log",
|
"log",
|
||||||
|
"regex",
|
||||||
"serde",
|
"serde",
|
||||||
"serde-patch",
|
"serde-patch",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ unwrap_used = "warn"
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
env_logger = "0.11.10"
|
env_logger = "0.11.10"
|
||||||
log = "0.4.29"
|
log = "0.4.29"
|
||||||
|
regex = "1.12.3"
|
||||||
serde = { version = "1.0.228", features = ["derive"] }
|
serde = { version = "1.0.228", features = ["derive"] }
|
||||||
serde-patch = "0.2.3"
|
serde-patch = "0.2.3"
|
||||||
serde_json = "1.0.149"
|
serde_json = "1.0.149"
|
||||||
|
|||||||
@@ -71,8 +71,11 @@ pub fn character_parse(archive: &mut ZipArchive<File>)
|
|||||||
|
|
||||||
// Serialise this to a HashMap
|
// Serialise this to a HashMap
|
||||||
let characters: HashMap<String, Character> =
|
let characters: HashMap<String, Character> =
|
||||||
serde_json::from_str(&file_contents)
|
serde_json::from_str::<HashMap<String,Character>>(&file_contents)
|
||||||
.map_err (|err| format!("Invalid JSON in characters.json: {err}"))?;
|
.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");
|
info!("Parsed characters from characters.json");
|
||||||
debug!("{characters:?}");
|
debug!("{characters:?}");
|
||||||
Ok(Arc::new(Mutex::new(characters)))
|
Ok(Arc::new(Mutex::new(characters)))
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ use crate::
|
|||||||
{
|
{
|
||||||
traits::UnwrapOrExit,
|
traits::UnwrapOrExit,
|
||||||
};
|
};
|
||||||
|
use regex::Regex;
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main()
|
async fn main()
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ use crate::
|
|||||||
VecDeque,
|
VecDeque,
|
||||||
warn,
|
warn,
|
||||||
debug,
|
debug,
|
||||||
|
info,
|
||||||
mpsc::Receiver,
|
mpsc::Receiver,
|
||||||
};
|
};
|
||||||
use super::keyword_parse;
|
use super::keyword_parse;
|
||||||
@@ -62,6 +63,7 @@ pub fn identifier_parse
|
|||||||
"input" =>
|
"input" =>
|
||||||
{
|
{
|
||||||
api::modify_data(happening_queue, "input".to_string(), String::new(), String::new(), Vec::new());
|
api::modify_data(happening_queue, "input".to_string(), String::new(), String::new(), Vec::new());
|
||||||
|
info!("Waiting for client input");
|
||||||
let input = match rx.recv()
|
let input = match rx.recv()
|
||||||
{
|
{
|
||||||
Ok((_,input)) => input,
|
Ok((_,input)) => input,
|
||||||
@@ -72,6 +74,7 @@ pub fn identifier_parse
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
variables.insert(identifier.to_owned(), tokenise::Value::String(input));
|
variables.insert(identifier.to_owned(), tokenise::Value::String(input));
|
||||||
|
sum_index += 1;
|
||||||
},
|
},
|
||||||
_ =>
|
_ =>
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -89,6 +89,7 @@ pub fn keyword_parse(
|
|||||||
// Jump to a particular index based on a label eg GOTO character_check
|
// Jump to a particular index based on a label eg GOTO character_check
|
||||||
"goto" =>
|
"goto" =>
|
||||||
{
|
{
|
||||||
|
info!("GOTO command, jumping there");
|
||||||
index += 1;
|
index += 1;
|
||||||
let label = tokenise::get_keyword_token(tokens, index)?;
|
let label = tokenise::get_keyword_token(tokens, index)?;
|
||||||
index = if let Some(label_index) = labels.get(&label) { *label_index }
|
index = if let Some(label_index) = labels.get(&label) { *label_index }
|
||||||
@@ -98,10 +99,17 @@ pub fn keyword_parse(
|
|||||||
index + 1
|
index + 1
|
||||||
};
|
};
|
||||||
debug!("Jumping to {index}");
|
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;
|
index += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -142,6 +150,7 @@ pub fn choice_parse
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
api::modify_data(happening_queue, "choice".to_string(), String::new(), String::new(), choices.clone());
|
api::modify_data(happening_queue, "choice".to_string(), String::new(), String::new(), choices.clone());
|
||||||
|
info!("Waiting for client choice");
|
||||||
debug!("{choice_indeces:?}");
|
debug!("{choice_indeces:?}");
|
||||||
let choice = match rx.recv()
|
let choice = match rx.recv()
|
||||||
{
|
{
|
||||||
|
|||||||
+40
-3
@@ -1,6 +1,7 @@
|
|||||||
use crate::
|
use crate::
|
||||||
{
|
{
|
||||||
HashMap,
|
HashMap,
|
||||||
|
Regex,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
@@ -49,6 +50,19 @@ pub enum Comparison
|
|||||||
LessOrEqual,
|
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
|
// TODO error reporting for all of these
|
||||||
pub fn get_operator_token(tokens: &[Token], index: usize)
|
pub fn get_operator_token(tokens: &[Token], index: usize)
|
||||||
@@ -105,7 +119,11 @@ pub fn get_string_token(tokens: &[Token], index: usize, variables: &HashMap<Stri
|
|||||||
{
|
{
|
||||||
match val
|
match val
|
||||||
{
|
{
|
||||||
Value::String(s) => Ok(s.clone()),
|
Value::String(s) =>
|
||||||
|
{
|
||||||
|
let string = insert_variables_into_string(s, variables);
|
||||||
|
Ok(string)
|
||||||
|
},
|
||||||
_ => Err("Unexpected value type".to_string()),
|
_ => Err("Unexpected value type".to_string()),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -116,7 +134,11 @@ pub fn get_string_token(tokens: &[Token], index: usize, variables: &HashMap<Stri
|
|||||||
.ok_or(format!("Variable {iden} not initialised"))?;
|
.ok_or(format!("Variable {iden} not initialised"))?;
|
||||||
match val
|
match val
|
||||||
{
|
{
|
||||||
Value::String(s) => Ok(s.clone()),
|
Value::String(s) =>
|
||||||
|
{
|
||||||
|
let string = insert_variables_into_string(s, variables);
|
||||||
|
Ok(string)
|
||||||
|
},
|
||||||
_ => Err("Unexpected value type".to_string()),
|
_ => Err("Unexpected value type".to_string()),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -125,6 +147,19 @@ pub fn get_string_token(tokens: &[Token], index: usize, variables: &HashMap<Stri
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn insert_variables_into_string(string: &str, variables: &HashMap<String, Value>)
|
||||||
|
-> 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<Token>
|
// Tokenise the story to Vec<Token>
|
||||||
// It can contain sub-objects (using recursive calls)
|
// It can contain sub-objects (using recursive calls)
|
||||||
// TODO check for END
|
// TODO check for END
|
||||||
@@ -165,7 +200,7 @@ pub fn tokenise(file_contents: &str)
|
|||||||
{
|
{
|
||||||
let mut chars = item.chars();
|
let mut chars = item.chars();
|
||||||
chars.next();
|
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
|
// Strings
|
||||||
else if item.starts_with('"') // TODO support '
|
else if item.starts_with('"') // TODO support '
|
||||||
@@ -227,6 +262,8 @@ pub fn tokenise(file_contents: &str)
|
|||||||
Ok((tokenised_data, labels))
|
Ok((tokenised_data, labels))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// TODO support strings that contain " in them by using a backslash
|
||||||
fn tokenise_string(space_seperated: &[&str], mut index: usize)
|
fn tokenise_string(space_seperated: &[&str], mut index: usize)
|
||||||
-> Option<(usize, String)>
|
-> Option<(usize, String)>
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,4 +0,0 @@
|
|||||||
{
|
|
||||||
"title": "Once upon a Test",
|
|
||||||
"description": "This story is for testing purposes"
|
|
||||||
}
|
|
||||||
@@ -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": ""
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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
|
|
||||||
Binary file not shown.
+7
-5
@@ -2,11 +2,11 @@ import requests
|
|||||||
import os
|
import os
|
||||||
import time
|
import time
|
||||||
import sys
|
import sys
|
||||||
debug = False
|
debug = True
|
||||||
try:
|
try:
|
||||||
if sys.argv[1] == "debug": debug = True
|
if sys.argv[1] == "silent": debug = False
|
||||||
except:
|
except:
|
||||||
debug = False
|
debug = True
|
||||||
|
|
||||||
# Loop and get new api
|
# Loop and get new api
|
||||||
def main():
|
def main():
|
||||||
@@ -22,7 +22,9 @@ def main():
|
|||||||
output(character, response["content"])
|
output(character, response["content"])
|
||||||
case "choice":
|
case "choice":
|
||||||
user_choice = choice(response["choices"])
|
user_choice = choice(response["choices"])
|
||||||
time.sleep(0.5)
|
continue
|
||||||
|
case "input":
|
||||||
|
get_input()
|
||||||
continue
|
continue
|
||||||
case "end":
|
case "end":
|
||||||
print("Exitting successfully")
|
print("Exitting successfully")
|
||||||
@@ -46,7 +48,7 @@ def choice(choices):
|
|||||||
|
|
||||||
def get_input():
|
def get_input():
|
||||||
api_url = "http://localhost:20264/input"
|
api_url = "http://localhost:20264/input"
|
||||||
input_string = input()
|
input_string = input("Input: ")
|
||||||
requests.post(api_url, json=input_string);
|
requests.post(api_url, json=input_string);
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user