implement choice selection
This commit is contained in:
parent
8df6914dba
commit
e7df698225
87
src/chat.rs
87
src/chat.rs
|
@ -113,7 +113,14 @@ impl ChatDB {
|
|||
return Err(format!("No chat with the conversation ID `{id}` was found."));
|
||||
}
|
||||
|
||||
fn search_choice(&self, yaml: Option<&Value>) -> Option<String> {
|
||||
// For a given Value, check whether it's a Value::Mapping and whether it
|
||||
// contains a choice. Mappings that will be detected as choices:
|
||||
// - `{"What's up?": [...]}`
|
||||
// - `{"What's up?": [...], "if": "value > 3"}`
|
||||
// Not acceptable:
|
||||
// - `"What's up?"`
|
||||
// - `{"goto": "foo"}`
|
||||
fn search_choice(&self, yaml: Option<&Value>) -> Option<(String, Value)> {
|
||||
let non_choice_tokens = NON_CHOICE_TOKENS.to_vec();
|
||||
if let Some(Value::Mapping(hash)) = yaml {
|
||||
for key in hash.keys() {
|
||||
|
@ -121,7 +128,7 @@ impl ChatDB {
|
|||
if non_choice_tokens.contains(&key.as_str()) {
|
||||
continue;
|
||||
}
|
||||
return Some(key.into());
|
||||
return Some((key.into(), hash[key].clone()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -130,23 +137,33 @@ impl ChatDB {
|
|||
|
||||
// returns false if the advanced pointer is out of bounds
|
||||
fn advance_pointer(&self, chat: &mut Chat) -> bool {
|
||||
let index = chat.position.len() - 1;
|
||||
chat.position[index] += 1;
|
||||
let len = chat.position.len();
|
||||
if len == 0 {
|
||||
return false;
|
||||
}
|
||||
chat.position[len - 1] += 1;
|
||||
|
||||
while chat.position.len() > 0 {
|
||||
dbg!(&chat.position);
|
||||
dbg!(self.at(chat.id, &chat.position));
|
||||
match self.at(chat.id, &chat.position) {
|
||||
None => {
|
||||
dbg!("Pop.");
|
||||
chat.position.pop();
|
||||
if chat.position.len() > 0 {
|
||||
let index = chat.position.len() - 1;
|
||||
chat.position[index] += 1;
|
||||
}
|
||||
},
|
||||
Some(_) => {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if chat.position.len() == 0 {
|
||||
// out of bounds, return false.
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -156,22 +173,47 @@ impl ChatDB {
|
|||
position[index] += 1;
|
||||
}
|
||||
|
||||
fn at(&self, id: usize, position: &Vec<usize>) -> Option<&Value> {
|
||||
// Returns the Value at the given ID/position, as-is.
|
||||
// If it's a choice, it returns the entire {"choice text": [...]} mapping.
|
||||
fn at(&self, id: usize, position: &Vec<usize>) -> Option<Value> {
|
||||
if position.len() == 0 {
|
||||
return None;
|
||||
}
|
||||
let mut pointer: Option<&Value> = Some(&self.0[id]);
|
||||
let mut result: Option<Value> = None;
|
||||
let mut pointer: Option<Value> = Some(self.0[id].clone());
|
||||
let mut next_pointer: Option<Value> = None;
|
||||
for index in position {
|
||||
if let Some(Value::Sequence(seq)) = self.0.get(id) {
|
||||
// TODO: handle mappings
|
||||
if let Some(value) = seq.get(*index) {
|
||||
pointer = Some(value);
|
||||
if let Some(Value::Sequence(seq)) = &pointer {
|
||||
let value = seq.get(*index);
|
||||
match value {
|
||||
Some(Value::String(value_string)) => {
|
||||
result = Some(Value::String(value_string.into()));
|
||||
}
|
||||
Some(Value::Mapping(mapping)) => {
|
||||
if let Some((_choicetext, subconversation)) = self.search_choice(value) {
|
||||
result = Some(Value::Mapping(mapping.clone()));
|
||||
next_pointer = Some(subconversation);
|
||||
}
|
||||
else {
|
||||
result = Some(Value::Mapping(mapping.clone()));
|
||||
}
|
||||
}
|
||||
None => {
|
||||
// Out of bounds.
|
||||
return None;
|
||||
}
|
||||
_ => {
|
||||
error!("Could not handle YAML value {value:?}");
|
||||
return None;
|
||||
}
|
||||
}
|
||||
pointer = next_pointer;
|
||||
next_pointer = None;
|
||||
} else {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
return pointer;
|
||||
return result;
|
||||
}
|
||||
|
||||
pub fn advance_chat(&self, chat: &mut Chat, event: &mut EventWriter<ChatEvent>) {
|
||||
|
@ -188,7 +230,7 @@ impl ChatDB {
|
|||
event.send(ChatEvent::DespawnAllChats);
|
||||
return;
|
||||
}
|
||||
else if let Some(_) = self.search_choice(self.at(chat.id, &chat.position)) {
|
||||
else if let Some(_) = self.search_choice(self.at(chat.id, &chat.position).as_ref()) {
|
||||
is_skipping_through = true;
|
||||
}
|
||||
else if let Some(Value::String(message)) = self.at(chat.id, &chat.position) {
|
||||
|
@ -203,7 +245,11 @@ impl ChatDB {
|
|||
if is_skipping_through /*|| pos[0] >= conv.len()*/ { // TODO: out of bounds checking
|
||||
break;
|
||||
}
|
||||
if let Some(choice) = self.search_choice(self.at(chat.id, &pos)) {
|
||||
dbg!(&pos);
|
||||
dbg!(self.at(chat.id, &pos));
|
||||
let choice = self.search_choice(self.at(chat.id, &pos).as_ref());
|
||||
dbg!(&choice);
|
||||
if let Some((choice, _)) = choice {
|
||||
let mut goto: Vec<usize> = pos.clone();
|
||||
goto.push(0);
|
||||
event.send(ChatEvent::SpawnChoice(choice, key, goto));
|
||||
|
@ -246,6 +292,21 @@ pub fn load_chats(mut chatdb: ResMut<ChatDB>) {
|
|||
error!("Could not load chat definitions. Validate files in `src/chats/` path.");
|
||||
}
|
||||
}
|
||||
// let mut chat = Chat {
|
||||
// id: 2,
|
||||
// position: vec![0],
|
||||
// timer: 0.0,
|
||||
// talker: Talker {
|
||||
// conv_id: "Icarus".to_string(),
|
||||
// name: None,
|
||||
// pronoun: None,
|
||||
// talking_speed: 1.0,
|
||||
// }
|
||||
// };
|
||||
dbg!(chatdb.at(2, &vec![0]));
|
||||
dbg!(chatdb.at(2, &vec![1]));
|
||||
dbg!(chatdb.at(2, &vec![2]));
|
||||
dbg!(chatdb.at(2, &vec![3]));
|
||||
}
|
||||
|
||||
pub fn handle_new_conversations(
|
||||
|
|
Loading…
Reference in a new issue