Use mora instead of characters, e.g. しゅ

master
Elnu 2 years ago
parent 4076a4c556
commit 96b97ca820

@ -25,7 +25,7 @@ ws.onmessage = e => {
case "word": case "word":
let waiting = data.author === id; let waiting = data.author === id;
displayWord(data.word, true); displayWord(data.word, true);
input.placeholder = waiting ? "Waiting for other players..." : `${data.next_char}`; input.placeholder = waiting ? "Waiting for other players..." : `${data.next_mora}`;
input.disabled = waiting; input.disabled = waiting;
if (!waiting) input.focus(); if (!waiting) input.focus();
break; break;

@ -47,7 +47,6 @@ impl Database {
} }
pub fn load_words_before(&self, before_id: i64) -> Result<Vec<Word>> { pub fn load_words_before(&self, before_id: i64) -> Result<Vec<Word>> {
println!("{}", before_id);
self.conn self.conn
.prepare("SELECT id, word, reading, timestamp FROM word WHERE id < ? ORDER BY id DESC LIMIT 10")? .prepare("SELECT id, word, reading, timestamp FROM word WHERE id < ? ORDER BY id DESC LIMIT 10")?
.query_map(params![before_id], |row| { .query_map(params![before_id], |row| {

@ -30,7 +30,7 @@ enum MessageResponseData {
Word { Word {
author: u64, author: u64,
word: Word, word: Word,
next_char: char, next_mora: String,
}, },
History { History {
words: Vec<Word>, words: Vec<Word>,
@ -70,7 +70,7 @@ pub struct Server {
event_hub: EventHub, event_hub: EventHub,
database: Database, database: Database,
clients: HashMap<u64, Responder>, clients: HashMap<u64, Responder>,
next_char: Option<char>, next_mora: Option<String>,
last_client_id: Option<u64>, last_client_id: Option<u64>,
} }
@ -85,13 +85,59 @@ pub enum ServerError {
DatabaseError(rusqlite::Error), DatabaseError(rusqlite::Error),
} }
fn get_starting_mora(word: &str) -> String {
if word.is_empty() {
return String::from("");
}
let word = word.to_hiragana();
let mut iter = word.chars();
let starting_char = iter.next().unwrap();
let second_char = iter.next().unwrap();
match second_char {
'ゃ' | 'ゅ' | 'ょ' => format!("{starting_char}{second_char}"),
_ => starting_char.to_string(),
}
}
// Trim off lengtheners and non-kana that are irrelevant to shiritori
// TODO: Use slices
fn trim_irrelevant_chars(word: &str) -> String {
let mut iter = word.chars().rev().peekable();
while let Some(c) = iter.peek() {
if *c == 'ー' || !c.to_string().is_kana() {
iter.next();
} else {
break;
}
}
iter.rev().collect()
}
// Get final mora, which could be multiple chars e.g. しゃ
// TODO: Use slices
fn get_final_mora(word: &str) -> String {
let word = trim_irrelevant_chars(word).to_hiragana();
if word.is_empty() {
return String::from("");
}
let mut iter = word.chars().rev();
let final_char = iter.next().unwrap();
match final_char {
'ゃ' | 'ゅ' | 'ょ' => format!("{}{final_char}", match iter.next() {
Some(c) => c.to_string(),
None => String::from(""),
}),
_ => final_char.to_string(),
}
}
impl Server { impl Server {
pub fn new(port: u16, testing: bool) -> Result<Self, ServerCreationError> { pub fn new(port: u16, testing: bool) -> Result<Self, ServerCreationError> {
Ok(Server { Ok(Server {
event_hub: simple_websockets::launch(port)?, event_hub: simple_websockets::launch(port)?,
database: Database::new(testing)?, database: Database::new(testing)?,
clients: HashMap::new(), clients: HashMap::new(),
next_char: None, next_mora: None,
last_client_id: None, last_client_id: None,
}) })
} }
@ -153,32 +199,23 @@ impl Server {
} else { } else {
match lookup(&message) { match lookup(&message) {
Some(entry) => { Some(entry) => {
println!("{}, {:?}", get_starting_mora(&entry.reading), self.next_mora);
if entry.reading.chars().last().unwrap().to_string().to_hiragana() == "ん" { if entry.reading.chars().last().unwrap().to_string().to_hiragana() == "ん" {
MessageResponseData::Error { MessageResponseData::Error {
message: String::from("Can't end with ん!"), message: String::from("Can't end with ん!"),
} }
} else if self.next_char.is_none() || entry.reading.chars().next().unwrap().to_string().to_hiragana().chars().next().unwrap() == self.next_char.unwrap() { } else if self.next_mora.is_none() || get_starting_mora(&entry.reading).eq(self.next_mora.as_deref().unwrap()) {
self.next_char = {
// If final character is lengthener or not kana
// Use semifinal
let mut final_chars = entry.reading.chars().rev();
let final_char = final_chars.next().unwrap();
Some(if final_char == 'ー' || !final_char.to_string().is_kana() {
final_chars.next().unwrap()
} else {
final_char
}.to_string().to_hiragana().chars().next().unwrap())
};
let word: Word = entry.clone().into(); let word: Word = entry.clone().into();
self.next_mora = Some(get_final_mora(&word.reading));
self.database.add_word(&word)?; self.database.add_word(&word)?;
MessageResponseData::Word { MessageResponseData::Word {
author: client_id, author: client_id,
word, word,
next_char: self.next_char.unwrap(), next_mora: self.next_mora.as_deref().unwrap().to_owned(),
} }
} else { } else {
MessageResponseData::Error { MessageResponseData::Error {
message: String::from("Wrong starting kana!"), message: String::from("Wrong starting mora!"),
} }
} }
} }

Loading…
Cancel
Save