Changed the data_to_send to be a stack so many lines of code can
be pre-processed before the user interacts. When the /happening api is called it just dequeues the front item
This commit is contained in:
+18
-16
@@ -1,6 +1,12 @@
|
|||||||
import requests
|
import requests
|
||||||
import os
|
import os
|
||||||
import time
|
import time
|
||||||
|
import sys
|
||||||
|
debug = False
|
||||||
|
try:
|
||||||
|
if sys.argv[1] == "debug": debug = True
|
||||||
|
except:
|
||||||
|
debug = False
|
||||||
|
|
||||||
# Loop and get new api
|
# Loop and get new api
|
||||||
def main():
|
def main():
|
||||||
@@ -9,22 +15,18 @@ def main():
|
|||||||
while True:
|
while True:
|
||||||
try:
|
try:
|
||||||
response = api_get()
|
response = api_get()
|
||||||
if response["id"] != id:
|
if debug: print(response)
|
||||||
id = response["id"]
|
match response["action_type"]:
|
||||||
print(response)
|
case "output":
|
||||||
match response["action_type"]:
|
character = get_character(response["character"])
|
||||||
case "output":
|
output(character, response["content"])
|
||||||
character = get_character(response["character"])
|
case "choice":
|
||||||
output(character, response["content"])
|
user_choice = choice(response["choices"])
|
||||||
case "choice":
|
time.sleep(0.5)
|
||||||
user_choice = choice(response["choices"])
|
continue
|
||||||
time.sleep(0.5)
|
case "end":
|
||||||
continue
|
print("Exitting successfully")
|
||||||
case "end":
|
os._exit(0)
|
||||||
print("Exitting successfully")
|
|
||||||
os._exit(0)
|
|
||||||
else:
|
|
||||||
continue
|
|
||||||
except:
|
except:
|
||||||
print("Server not up or cannot be reached")
|
print("Server not up or cannot be reached")
|
||||||
input() # Enter to go to next loop (testing)
|
input() # Enter to go to next loop (testing)
|
||||||
|
|||||||
+24
-22
@@ -9,6 +9,7 @@ use crate::
|
|||||||
HashMap,
|
HashMap,
|
||||||
Arc,
|
Arc,
|
||||||
Mutex,
|
Mutex,
|
||||||
|
VecDeque,
|
||||||
config,
|
config,
|
||||||
mpsc::Sender,
|
mpsc::Sender,
|
||||||
info,
|
info,
|
||||||
@@ -18,9 +19,8 @@ use crate::
|
|||||||
Deserialize,
|
Deserialize,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Serialize, Clone)]
|
#[derive(Debug, Deserialize, Serialize, Clone, Default)]
|
||||||
pub struct DataToSend {
|
pub struct DataToSend {
|
||||||
pub id: u32,
|
|
||||||
pub action_type: String,
|
pub action_type: String,
|
||||||
pub content: String,
|
pub content: String,
|
||||||
pub character: String,
|
pub character: String,
|
||||||
@@ -32,13 +32,13 @@ pub struct DataToSend {
|
|||||||
// tx to allow the program executor to move onto the next bit of code
|
// tx to allow the program executor to move onto the next bit of code
|
||||||
pub async fn api_process
|
pub async fn api_process
|
||||||
(
|
(
|
||||||
data_to_send: Arc<Mutex<DataToSend>>,
|
happening_queue: Arc<Mutex<VecDeque<DataToSend>>>,
|
||||||
characters: Arc<Mutex<HashMap::<String,character::Character>>>,
|
characters: Arc<Mutex<HashMap::<String,character::Character>>>,
|
||||||
tx: Sender<(bool, usize, String)>,
|
tx: Sender<(usize, String)>,
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
// This data must be passed through to the api route in order to be used
|
// This data must be passed through to the api route in order to be used
|
||||||
let data_filter = warp::any().map(move || Arc::clone(&data_to_send));
|
let happening_queue_filter = warp::any().map(move || Arc::clone(&happening_queue));
|
||||||
let characters_filter = warp::any().map(move || Arc::clone(&characters));
|
let characters_filter = warp::any().map(move || Arc::clone(&characters));
|
||||||
let tx_filter = warp::any().map(move || tx.clone());
|
let tx_filter = warp::any().map(move || tx.clone());
|
||||||
let tx_filter2 = tx_filter.clone();
|
let tx_filter2 = tx_filter.clone();
|
||||||
@@ -49,14 +49,14 @@ pub async fn api_process
|
|||||||
// The server route is loaded at address:port/happening
|
// The server route is loaded at address:port/happening
|
||||||
let main = warp::path("happening")
|
let main = warp::path("happening")
|
||||||
.and(warp::get())
|
.and(warp::get())
|
||||||
.and(data_filter)
|
.and(happening_queue_filter)
|
||||||
.and(tx_filter)
|
.and(tx_filter)
|
||||||
// Perform this code on a GET request
|
// Perform this code on a GET request
|
||||||
.map(|state: Arc<Mutex<DataToSend>>, tx_handle: Sender<(bool,usize,String)>|
|
.map(|queue: Arc<Mutex<VecDeque<DataToSend>>>, tx_handle: Sender<(usize,String)>|
|
||||||
{
|
{
|
||||||
//debug!("GET: {state:?}");
|
//debug!("GET: {state:?}");
|
||||||
let reply = state.as_ref();
|
let mut queue = queue.lock().unwrap();
|
||||||
let _ = tx_handle.send((true,0,String::new()));
|
let reply = queue.pop_front().unwrap_or_default();
|
||||||
warp::reply::json(&reply) // Send the reply data (data_to_send formatted as JSON)
|
warp::reply::json(&reply) // Send the reply data (data_to_send formatted as JSON)
|
||||||
}).boxed();
|
}).boxed();
|
||||||
let characters = warp::path("character")
|
let characters = warp::path("character")
|
||||||
@@ -91,9 +91,9 @@ pub async fn api_process
|
|||||||
.and(warp::post())
|
.and(warp::post())
|
||||||
.and(warp::body::json())
|
.and(warp::body::json())
|
||||||
.and(tx_filter2)
|
.and(tx_filter2)
|
||||||
.map(|index: usize, tx_handle: Sender<(bool,usize,String)>| {
|
.map(|index: usize, tx_handle: Sender<(usize,String)>| {
|
||||||
debug!("Choice: {index}");
|
debug!("Choice: {index}");
|
||||||
let _ = tx_handle.send((true,index,String::new()));
|
let _ = tx_handle.send((index,String::new()));
|
||||||
let reply = "ack";
|
let reply = "ack";
|
||||||
warp::reply::json(&reply)
|
warp::reply::json(&reply)
|
||||||
}).boxed();
|
}).boxed();
|
||||||
@@ -101,9 +101,9 @@ pub async fn api_process
|
|||||||
.and(warp::post())
|
.and(warp::post())
|
||||||
.and(warp::body::json())
|
.and(warp::body::json())
|
||||||
.and(tx_filter3)
|
.and(tx_filter3)
|
||||||
.map(|input: String, tx_handle: Sender<(bool, usize, String)>|
|
.map(|input: String, tx_handle: Sender<(usize, String)>|
|
||||||
{
|
{
|
||||||
let _ = tx_handle.send((true,0,input));
|
let _ = tx_handle.send((0,input));
|
||||||
let reply = "ack";
|
let reply = "ack";
|
||||||
warp::reply::json(&reply)
|
warp::reply::json(&reply)
|
||||||
}).boxed();
|
}).boxed();
|
||||||
@@ -117,20 +117,22 @@ pub async fn api_process
|
|||||||
|
|
||||||
// On fail, quit safely
|
// On fail, quit safely
|
||||||
// If successful, return nothing
|
// If successful, return nothing
|
||||||
pub fn modify_data
|
pub fn modify_data // TODO rename
|
||||||
(
|
(
|
||||||
data_to_send: &Arc<Mutex<DataToSend>>,
|
happening_queue: &Arc<Mutex<VecDeque<DataToSend>>>,
|
||||||
action_type: String,
|
action_type: String,
|
||||||
content: String,
|
content: String,
|
||||||
character_name: String,
|
character_name: String,
|
||||||
choices: Vec<String>,
|
choices: Vec<String>,
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
let mut data = data_to_send.lock().unwrap_or_exit("Data to send Mutex was poisoned",2);
|
let mut queue = happening_queue.lock().unwrap_or_exit("Data to send Mutex was poisoned",2);
|
||||||
data.id += 1;
|
let new_data = DataToSend {
|
||||||
data.action_type = action_type;
|
action_type: action_type,
|
||||||
data.content = content;
|
content: content,
|
||||||
data.character = character_name;
|
character: character_name,
|
||||||
data.choices = choices;
|
choices: choices,
|
||||||
drop(data);
|
};
|
||||||
|
queue.push_back(new_data);
|
||||||
|
drop(queue);
|
||||||
}
|
}
|
||||||
|
|||||||
+19
-14
@@ -11,7 +11,11 @@ use std::
|
|||||||
env::args,
|
env::args,
|
||||||
fs::File,
|
fs::File,
|
||||||
io::Read,
|
io::Read,
|
||||||
collections::HashMap,
|
collections::
|
||||||
|
{
|
||||||
|
HashMap,
|
||||||
|
VecDeque,
|
||||||
|
},
|
||||||
sync::{Arc, Mutex, mpsc},
|
sync::{Arc, Mutex, mpsc},
|
||||||
};
|
};
|
||||||
use log::
|
use log::
|
||||||
@@ -70,25 +74,26 @@ async fn main()
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
// Initialise the data strcut that will be sent out during API GET requests
|
// Initialise the data strcut that will be sent out during API GET requests
|
||||||
let data_to_send = Arc::new(Mutex::new(api::DataToSend
|
let happening_stack = Arc::new(Mutex::new(
|
||||||
{
|
VecDeque::from([api::DataToSend{
|
||||||
id: 0,
|
action_type: "begin".to_owned(),
|
||||||
action_type: "begin".to_owned(),
|
content: String::new(), // TODO send title and description
|
||||||
content: String::new(), // TODO send title and description
|
character: String::new(),
|
||||||
character: String::new(),
|
choices: vec![],
|
||||||
choices: vec![],
|
}])
|
||||||
}));
|
));
|
||||||
|
|
||||||
// setup the api stuff //
|
// setup the api stuff //
|
||||||
|
|
||||||
// Make clones of the data Arc for the two processes
|
// Make clones of the data Arc for the two processes
|
||||||
let data_clone1 = Arc::clone(&data_to_send);
|
//let data_clone1 = Arc::clone(&data_to_send);
|
||||||
|
let happening_stack1 = Arc::clone(&happening_stack);
|
||||||
let characters_clone1 = Arc::clone(&characters);
|
let characters_clone1 = Arc::clone(&characters);
|
||||||
let tx_clone = tx;
|
let tx_clone = tx;
|
||||||
// Spawn a thread for warp api server
|
// Spawn a thread for warp api server
|
||||||
tokio::spawn(
|
tokio::spawn(
|
||||||
async move {
|
async move {
|
||||||
api::api_process(data_clone1, characters_clone1, tx_clone).await;
|
api::api_process(happening_stack1, characters_clone1, tx_clone).await;
|
||||||
});
|
});
|
||||||
|
|
||||||
// setup the parsing stuff //
|
// setup the parsing stuff //
|
||||||
@@ -106,16 +111,16 @@ async fn main()
|
|||||||
let (tokens, labels) = tokenise::tokenise(&file_contents)
|
let (tokens, labels) = tokenise::tokenise(&file_contents)
|
||||||
.unwrap_or_exit("Unable to tokenise data", 15);
|
.unwrap_or_exit("Unable to tokenise data", 15);
|
||||||
debug!("{tokens:?}\n{labels:?}");
|
debug!("{tokens:?}\n{labels:?}");
|
||||||
let data_clone2 = Arc::clone(&data_to_send);
|
|
||||||
let characters_clone2 = Arc::clone(&characters);
|
let characters_clone2 = Arc::clone(&characters);
|
||||||
|
let happening_stack2 = Arc::clone(&happening_stack);
|
||||||
// Run the parsing process for the DSL
|
// Run the parsing process for the DSL
|
||||||
info!("DSL parsing begun");
|
info!("DSL parsing begun");
|
||||||
match parsing::token_parse(&tokens, &labels, &characters_clone2, &data_clone2, &rx)
|
match parsing::token_parse(&tokens, &labels, &characters_clone2, &happening_stack2, &rx)
|
||||||
{
|
{
|
||||||
// Exit with error or success
|
// Exit with error or success
|
||||||
Ok(()) =>
|
Ok(()) =>
|
||||||
{
|
{
|
||||||
api::modify_data(&data_to_send, "end".to_string(), String::new(), String::new(), vec![]);
|
api::modify_data(&happening_stack, "end".to_string(), String::new(), String::new(), vec![]);
|
||||||
// TODO fix quitting instantly
|
// TODO fix quitting instantly
|
||||||
let _ = rx.recv(); // Wait for the client to respond
|
let _ = rx.recv(); // Wait for the client to respond
|
||||||
info!("Program exited successfully");
|
info!("Program exited successfully");
|
||||||
|
|||||||
+11
-92
@@ -10,12 +10,14 @@ use crate::
|
|||||||
mpsc::Receiver,
|
mpsc::Receiver,
|
||||||
Arc,
|
Arc,
|
||||||
Mutex,
|
Mutex,
|
||||||
|
VecDeque,
|
||||||
info,
|
info,
|
||||||
debug,
|
debug,
|
||||||
warn,
|
warn,
|
||||||
};
|
};
|
||||||
|
|
||||||
mod character_parse;
|
mod character_parse;
|
||||||
|
mod keyword_parse;
|
||||||
|
|
||||||
// Parse the tokens in a file
|
// Parse the tokens in a file
|
||||||
// Returns success or an error string
|
// Returns success or an error string
|
||||||
@@ -23,16 +25,11 @@ pub fn token_parse(
|
|||||||
tokens: &[tokenise::Token],
|
tokens: &[tokenise::Token],
|
||||||
labels: &HashMap<String,usize>,
|
labels: &HashMap<String,usize>,
|
||||||
characters: &Arc<Mutex<HashMap::<String, character::Character>>>,
|
characters: &Arc<Mutex<HashMap::<String, character::Character>>>,
|
||||||
data_to_send: &Arc<Mutex<api::DataToSend>>,
|
happening_queue: &Arc<Mutex<VecDeque<api::DataToSend>>>,
|
||||||
rx: &Receiver<(bool,usize,String)>,
|
rx: &Receiver<(usize,String)>,
|
||||||
) -> Result<(),String>
|
) -> Result<(),String>
|
||||||
{
|
{
|
||||||
let mut index: usize = 0;
|
let mut index: usize = 0;
|
||||||
if rx.recv().is_err()
|
|
||||||
{
|
|
||||||
warn!("Some issue with api");
|
|
||||||
// TODO eh?
|
|
||||||
}
|
|
||||||
info!("Client has connected");
|
info!("Client has connected");
|
||||||
// Run an infinite loop
|
// Run an infinite loop
|
||||||
'parse_loop: loop
|
'parse_loop: loop
|
||||||
@@ -41,7 +38,12 @@ pub fn token_parse(
|
|||||||
// Get the next token
|
// Get the next token
|
||||||
let token: String = match tokens.get(index)
|
let token: String = match tokens.get(index)
|
||||||
{
|
{
|
||||||
Some(tokenise::Token::Keyword(s)) => s.clone(),
|
Some(tokenise::Token::Keyword(token)) =>
|
||||||
|
{
|
||||||
|
if token.to_lowercase().as_str() == "end" { return Ok(()); };
|
||||||
|
index = keyword_parse::keyword_parse(tokens, token.to_string(), index, characters, happening_queue, labels, rx).unwrap();
|
||||||
|
continue 'parse_loop;
|
||||||
|
},
|
||||||
// Ignore closing braces and jump over opening brace blocks
|
// Ignore closing braces and jump over opening brace blocks
|
||||||
Some(tokenise::Token::Bracket((bracket,new_index))) =>
|
Some(tokenise::Token::Bracket((bracket,new_index))) =>
|
||||||
{
|
{
|
||||||
@@ -56,7 +58,7 @@ pub fn token_parse(
|
|||||||
// Handle a character
|
// Handle a character
|
||||||
Some(tokenise::Token::Character(character_name)) => // TODO add support for narrator
|
Some(tokenise::Token::Character(character_name)) => // TODO add support for narrator
|
||||||
{
|
{
|
||||||
index = match character_parse::character_parse(index+1,tokens,character_name.clone(),characters,data_to_send)
|
index = match character_parse::character_parse(index+1,tokens,character_name.clone(),characters,happening_queue)
|
||||||
{
|
{
|
||||||
Ok(increment) => increment,
|
Ok(increment) => increment,
|
||||||
Err((err,increment)) =>
|
Err((err,increment)) =>
|
||||||
@@ -65,7 +67,6 @@ pub fn token_parse(
|
|||||||
increment
|
increment
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
if rx.recv().is_err() { warn!("Some issue with api"); }
|
|
||||||
continue 'parse_loop
|
continue 'parse_loop
|
||||||
}
|
}
|
||||||
Some(_) =>
|
Some(_) =>
|
||||||
@@ -78,88 +79,6 @@ pub fn token_parse(
|
|||||||
};
|
};
|
||||||
debug!("{index}: {token}");
|
debug!("{index}: {token}");
|
||||||
// The instructions are related to characters
|
// The instructions are related to characters
|
||||||
match token.to_lowercase().as_str()
|
|
||||||
{
|
|
||||||
"end" =>
|
|
||||||
{
|
|
||||||
info!("END command, exiting");
|
|
||||||
return Ok(()) // quit successfully
|
|
||||||
},
|
|
||||||
"choice" =>
|
|
||||||
{
|
|
||||||
let choice_indeces = choice_parse(tokens, index, data_to_send)?;
|
|
||||||
debug!("{choice_indeces:?}");
|
|
||||||
if rx.recv().is_err() { warn!("Error sending choices to client"); }
|
|
||||||
let choice = match rx.recv()
|
|
||||||
{
|
|
||||||
Ok((_,choice,_)) => choice_indeces[choice],
|
|
||||||
Err(err) =>
|
|
||||||
{
|
|
||||||
warn!("Error receiving choice from client, defaulting to choice 0 {err}");
|
|
||||||
0
|
|
||||||
}
|
|
||||||
};
|
|
||||||
index = choice;
|
|
||||||
continue 'parse_loop
|
|
||||||
},
|
|
||||||
"or" =>
|
|
||||||
{
|
|
||||||
info!("OR command, jumping over");
|
|
||||||
index += 2;
|
|
||||||
let new_index = tokenise::get_closing_index(tokens, index)?;
|
|
||||||
index = new_index;
|
|
||||||
continue 'parse_loop
|
|
||||||
},
|
|
||||||
// Jump to a particular index based on a label eg GOTO character_check
|
|
||||||
"goto" =>
|
|
||||||
{
|
|
||||||
index += 1;
|
|
||||||
let label = tokenise::get_keyword_token(tokens, index)?;
|
|
||||||
index = if let Some(label_index) = labels.get(&label) { *label_index }
|
|
||||||
else
|
|
||||||
{
|
|
||||||
warn!("Label {label} does not exist");
|
|
||||||
index + 1
|
|
||||||
};
|
|
||||||
debug!("Jumping to {index}");
|
|
||||||
continue 'parse_loop
|
|
||||||
}
|
|
||||||
_ =>
|
|
||||||
{
|
|
||||||
warn!("Invalid command: {token}");
|
|
||||||
index += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if rx.recv().is_err() { warn!("Some issue with api"); }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn choice_parse(tokens: &[tokenise::Token], mut index: usize, data_to_send: &Arc<Mutex<api::DataToSend>>,)
|
|
||||||
-> Result<Vec<usize>, String>
|
|
||||||
{
|
|
||||||
let mut next_token: String = "or".to_string();
|
|
||||||
let mut choices: Vec<String> = Vec::new();
|
|
||||||
let mut choice_indeces: Vec<usize> = Vec::new();
|
|
||||||
while next_token == "or"
|
|
||||||
{
|
|
||||||
index += 1;
|
|
||||||
choices.push
|
|
||||||
(
|
|
||||||
tokenise::get_string_token(tokens, index)?
|
|
||||||
);
|
|
||||||
index += 1;
|
|
||||||
choice_indeces.push(index+1);
|
|
||||||
index = match tokenise::get_closing_index(tokens,index)
|
|
||||||
{
|
|
||||||
Ok(new_index) => new_index + 1,
|
|
||||||
Err(_) => break,
|
|
||||||
};
|
|
||||||
next_token = match tokenise::get_keyword_token(tokens, index)
|
|
||||||
{
|
|
||||||
Ok(string) => string,
|
|
||||||
Err(_) => break,
|
|
||||||
}
|
|
||||||
};
|
|
||||||
api::modify_data(data_to_send, "choice".to_string(), String::new(), String::new(), choices);
|
|
||||||
Ok(choice_indeces)
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ use crate::
|
|||||||
Mutex,
|
Mutex,
|
||||||
Arc,
|
Arc,
|
||||||
HashMap,
|
HashMap,
|
||||||
|
VecDeque,
|
||||||
info,
|
info,
|
||||||
warn,
|
warn,
|
||||||
debug,
|
debug,
|
||||||
@@ -23,7 +24,7 @@ pub fn character_parse
|
|||||||
tokens: &[tokenise::Token],
|
tokens: &[tokenise::Token],
|
||||||
character_name: String,
|
character_name: String,
|
||||||
characters: &Arc<Mutex<HashMap::<String, character::Character>>>,
|
characters: &Arc<Mutex<HashMap::<String, character::Character>>>,
|
||||||
data_to_send: &Arc<Mutex<api::DataToSend>>,
|
happening_queue: &Arc<Mutex<VecDeque<api::DataToSend>>>,
|
||||||
) -> Result<usize,(String,usize)>
|
) -> Result<usize,(String,usize)>
|
||||||
{
|
{
|
||||||
let mut sum_index: usize = index;
|
let mut sum_index: usize = index;
|
||||||
@@ -47,7 +48,7 @@ pub fn character_parse
|
|||||||
let output = tokenise::get_string_token(tokens, sum_index)
|
let output = tokenise::get_string_token(tokens, sum_index)
|
||||||
.map_err(|err| (err, index))?;
|
.map_err(|err| (err, index))?;
|
||||||
debug!("Saying {output}");
|
debug!("Saying {output}");
|
||||||
api::modify_data(data_to_send, "output".to_string(), output, character_name, vec![]);
|
api::modify_data(happening_queue, "output".to_string(), output, character_name, vec![]);
|
||||||
},
|
},
|
||||||
// Change the property of the selected character eg @tim CHANGE name "Bill Buffins"
|
// Change the property of the selected character eg @tim CHANGE name "Bill Buffins"
|
||||||
// will change the character with ID tim to "Bill Buffins"; a character's ID cannot change
|
// will change the character with ID tim to "Bill Buffins"; a character's ID cannot change
|
||||||
@@ -65,7 +66,7 @@ pub fn character_parse
|
|||||||
&& character.set_field(&feature, &string)
|
&& character.set_field(&feature, &string)
|
||||||
.is_err() { warn!("Feature {feature} does not exist") }
|
.is_err() { warn!("Feature {feature} does not exist") }
|
||||||
drop(characters);
|
drop(characters);
|
||||||
api::modify_data(data_to_send, "change".to_string(), String::new(), character_name, vec![]);
|
api::modify_data(happening_queue, "change".to_string(), String::new(), character_name, vec![]);
|
||||||
},
|
},
|
||||||
// These two are mainly just actions performed by the frontend client, so just tell the client to move/animate
|
// These two are mainly just actions performed by the frontend client, so just tell the client to move/animate
|
||||||
// the character and not much other processing needed on the serverside
|
// the character and not much other processing needed on the serverside
|
||||||
@@ -74,7 +75,7 @@ pub fn character_parse
|
|||||||
sum_index += 1;
|
sum_index += 1;
|
||||||
let content = tokenise::get_keyword_token(tokens, sum_index)
|
let content = tokenise::get_keyword_token(tokens, sum_index)
|
||||||
.map_err(|err| (err, index))?;
|
.map_err(|err| (err, index))?;
|
||||||
api::modify_data(data_to_send, keyword.to_lowercase(), content, character_name, vec![]);
|
api::modify_data(happening_queue, keyword.to_lowercase(), content, character_name, vec![]);
|
||||||
},
|
},
|
||||||
// Catch all condition, if the instruction is unrecognised as a
|
// Catch all condition, if the instruction is unrecognised as a
|
||||||
// character command
|
// character command
|
||||||
|
|||||||
@@ -0,0 +1,103 @@
|
|||||||
|
use crate::
|
||||||
|
{
|
||||||
|
tokenise,
|
||||||
|
character,
|
||||||
|
api,
|
||||||
|
|
||||||
|
HashMap,
|
||||||
|
Arc,
|
||||||
|
Mutex,
|
||||||
|
VecDeque,
|
||||||
|
warn,
|
||||||
|
debug,
|
||||||
|
info,
|
||||||
|
mpsc::Receiver,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub fn keyword_parse(
|
||||||
|
tokens: &[tokenise::Token],
|
||||||
|
token: String,
|
||||||
|
mut index: usize,
|
||||||
|
characters: &Arc<Mutex<HashMap::<String, character::Character>>>,
|
||||||
|
happening_queue: &Arc<Mutex<VecDeque<api::DataToSend>>>,
|
||||||
|
labels: &HashMap<String, usize>,
|
||||||
|
rx: &Receiver<(usize,String)>,
|
||||||
|
)
|
||||||
|
-> Result<usize, String>
|
||||||
|
{
|
||||||
|
|
||||||
|
match token.to_lowercase().as_str()
|
||||||
|
{
|
||||||
|
"choice" =>
|
||||||
|
{
|
||||||
|
let choice_indeces = choice_parse(tokens, index, happening_queue)?;
|
||||||
|
debug!("{choice_indeces:?}");
|
||||||
|
let choice = match rx.recv()
|
||||||
|
{
|
||||||
|
Ok((choice,_)) => choice_indeces[choice],
|
||||||
|
Err(err) =>
|
||||||
|
{
|
||||||
|
warn!("Error receiving choice from client, defaulting to choice 0 {err}");
|
||||||
|
0
|
||||||
|
}
|
||||||
|
};
|
||||||
|
index = choice;
|
||||||
|
},
|
||||||
|
"or" =>
|
||||||
|
{
|
||||||
|
info!("OR command, jumping over");
|
||||||
|
index += 2;
|
||||||
|
let new_index = tokenise::get_closing_index(tokens, index)?;
|
||||||
|
index = new_index;
|
||||||
|
},
|
||||||
|
// Jump to a particular index based on a label eg GOTO character_check
|
||||||
|
"goto" =>
|
||||||
|
{
|
||||||
|
index += 1;
|
||||||
|
let label = tokenise::get_keyword_token(tokens, index)?;
|
||||||
|
index = if let Some(label_index) = labels.get(&label) { *label_index }
|
||||||
|
else
|
||||||
|
{
|
||||||
|
warn!("Label {label} does not exist");
|
||||||
|
index + 1
|
||||||
|
};
|
||||||
|
debug!("Jumping to {index}");
|
||||||
|
}
|
||||||
|
_ =>
|
||||||
|
{
|
||||||
|
warn!("Invalid command: {token}");
|
||||||
|
index += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(index)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn choice_parse(tokens: &[tokenise::Token], mut index: usize, happening_queue: &Arc<Mutex<VecDeque<api::DataToSend>>>,)
|
||||||
|
-> Result<Vec<usize>, String>
|
||||||
|
{
|
||||||
|
let mut next_token: String = "or".to_string();
|
||||||
|
let mut choices: Vec<String> = Vec::new();
|
||||||
|
let mut choice_indeces: Vec<usize> = Vec::new();
|
||||||
|
while next_token == "or"
|
||||||
|
{
|
||||||
|
index += 1;
|
||||||
|
choices.push
|
||||||
|
(
|
||||||
|
tokenise::get_string_token(tokens, index)?
|
||||||
|
);
|
||||||
|
index += 1;
|
||||||
|
choice_indeces.push(index+1);
|
||||||
|
index = match tokenise::get_closing_index(tokens,index)
|
||||||
|
{
|
||||||
|
Ok(new_index) => new_index + 1,
|
||||||
|
Err(_) => break,
|
||||||
|
};
|
||||||
|
next_token = match tokenise::get_keyword_token(tokens, index)
|
||||||
|
{
|
||||||
|
Ok(string) => string,
|
||||||
|
Err(_) => break,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
api::modify_data(happening_queue, "choice".to_string(), String::new(), String::new(), choices);
|
||||||
|
Ok(choice_indeces)
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user