implement choice selection
This commit is contained in:
parent
8df6914dba
commit
e7df698225
91
src/chat.rs
91
src/chat.rs
|
@ -113,7 +113,14 @@ impl ChatDB {
|
||||||
return Err(format!("No chat with the conversation ID `{id}` was found."));
|
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();
|
let non_choice_tokens = NON_CHOICE_TOKENS.to_vec();
|
||||||
if let Some(Value::Mapping(hash)) = yaml {
|
if let Some(Value::Mapping(hash)) = yaml {
|
||||||
for key in hash.keys() {
|
for key in hash.keys() {
|
||||||
|
@ -121,7 +128,7 @@ impl ChatDB {
|
||||||
if non_choice_tokens.contains(&key.as_str()) {
|
if non_choice_tokens.contains(&key.as_str()) {
|
||||||
continue;
|
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
|
// returns false if the advanced pointer is out of bounds
|
||||||
fn advance_pointer(&self, chat: &mut Chat) -> bool {
|
fn advance_pointer(&self, chat: &mut Chat) -> bool {
|
||||||
let index = chat.position.len() - 1;
|
let len = chat.position.len();
|
||||||
chat.position[index] += 1;
|
if len == 0 {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
chat.position[len - 1] += 1;
|
||||||
|
|
||||||
while chat.position.len() > 0 {
|
while chat.position.len() > 0 {
|
||||||
|
dbg!(&chat.position);
|
||||||
dbg!(self.at(chat.id, &chat.position));
|
dbg!(self.at(chat.id, &chat.position));
|
||||||
match self.at(chat.id, &chat.position) {
|
match self.at(chat.id, &chat.position) {
|
||||||
None => {
|
None => {
|
||||||
dbg!("Pop.");
|
dbg!("Pop.");
|
||||||
chat.position.pop();
|
chat.position.pop();
|
||||||
let index = chat.position.len() - 1;
|
if chat.position.len() > 0 {
|
||||||
chat.position[index] += 1;
|
let index = chat.position.len() - 1;
|
||||||
|
chat.position[index] += 1;
|
||||||
|
}
|
||||||
},
|
},
|
||||||
Some(_) => {
|
Some(_) => {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if chat.position.len() == 0 {
|
||||||
|
// out of bounds, return false.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -156,22 +173,47 @@ impl ChatDB {
|
||||||
position[index] += 1;
|
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 {
|
if position.len() == 0 {
|
||||||
return None;
|
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 {
|
for index in position {
|
||||||
if let Some(Value::Sequence(seq)) = self.0.get(id) {
|
if let Some(Value::Sequence(seq)) = &pointer {
|
||||||
// TODO: handle mappings
|
let value = seq.get(*index);
|
||||||
if let Some(value) = seq.get(*index) {
|
match value {
|
||||||
pointer = Some(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 {
|
} else {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return pointer;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn advance_chat(&self, chat: &mut Chat, event: &mut EventWriter<ChatEvent>) {
|
pub fn advance_chat(&self, chat: &mut Chat, event: &mut EventWriter<ChatEvent>) {
|
||||||
|
@ -188,7 +230,7 @@ impl ChatDB {
|
||||||
event.send(ChatEvent::DespawnAllChats);
|
event.send(ChatEvent::DespawnAllChats);
|
||||||
return;
|
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;
|
is_skipping_through = true;
|
||||||
}
|
}
|
||||||
else if let Some(Value::String(message)) = self.at(chat.id, &chat.position) {
|
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
|
if is_skipping_through /*|| pos[0] >= conv.len()*/ { // TODO: out of bounds checking
|
||||||
break;
|
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();
|
let mut goto: Vec<usize> = pos.clone();
|
||||||
goto.push(0);
|
goto.push(0);
|
||||||
event.send(ChatEvent::SpawnChoice(choice, key, goto));
|
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.");
|
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(
|
pub fn handle_new_conversations(
|
||||||
|
|
Loading…
Reference in a new issue