master
Elnu 2 years ago
parent ed11799bf5
commit c4eece7ffd

@ -13,11 +13,11 @@
use crate::room::Room;
use std::cmp::{PartialEq, Eq};
use simple_websockets::{Message, Responder};
use std::cell::RefCell;
use std::cmp::{Eq, PartialEq};
use std::hash::{Hash, Hasher};
use std::rc::Rc;
use std::cell::RefCell;
use simple_websockets::{Responder, Message};
pub struct DiscordInfo {
pub username: String,
@ -47,7 +47,9 @@ pub enum ClientInfo {
impl ClientInfo {
fn id(&self) -> u64 {
match self {
Self::Ws { id, discord_info, .. } => match discord_info {
Self::Ws {
id, discord_info, ..
} => match discord_info {
// Discord-verified websocket connection
Some(discord_info) => discord_info.id,
// Anonymous websocket connection
@ -93,7 +95,9 @@ impl Client {
pub fn send(&self, message: Message) -> bool {
match &self.info {
ClientInfo::Ws { responder, .. } => responder.send(message),
ClientInfo::Discord { .. } => unimplemented!("no networking implementation for Discord connections"),
ClientInfo::Discord { .. } => {
unimplemented!("no networking implementation for Discord connections")
}
}
}
}

@ -1,8 +1,8 @@
use crate::word::Word;
use derive_more::From;
use rusqlite::{params, Connection, Result};
use std::path::PathBuf;
use rusqlite::{Connection, Result, params};
pub struct Database {
conn: Connection,
@ -46,7 +46,8 @@ impl Database {
.prepare("SELECT id FROM word ORDER BY id DESC LIMIT 1")?
.query_map(params![], |row| row.get(0))?
.collect::<Result<Vec<i64>>>()?
.first() {
.first()
{
Some(id) => *id,
None => 0, // first database entry is id 1
};
@ -70,10 +71,7 @@ impl Database {
pub fn add_word(&mut self, word: &Word) -> Result<()> {
self.conn.execute(
"INSERT INTO word (word, reading) VALUES (?1, ?2)",
params![
word.word,
word.reading,
],
params![word.word, word.reading,],
)?;
self.last_word_id += 1;
Ok(())

@ -2,7 +2,8 @@ use wana_kana::{ConvertJapanese, IsJapaneseStr};
fn raw_lookup(input: &str) -> Option<&jisho::Entry> {
let input = input.trim();
jisho::lookup(input).into_iter().find(|&word| (
jisho::lookup(input).into_iter().find(|&word| {
(
// If input has no kanji,
// we can just compare the input to the reading verbatim
// ensuring both are hiragana
@ -11,7 +12,9 @@ fn raw_lookup(input: &str) -> Option<&jisho::Entry> {
// is verbosely the same.
// However, this will cause problems for some words.
// For example, 照り焼き will be accepted but 照焼 won't.
(input == word.kanji)))
(input == word.kanji)
)
})
}
pub fn lookup(query: &str) -> Option<jisho::Entry> {

@ -11,7 +11,11 @@ use crate::server::{Server, ServerSettings};
fn main() {
let settings = ServerSettings::default();
let mut server = Server::new(&settings)
.unwrap_or_else(|error| panic!("Failed to start server at port {}: {:?}", settings.port, error));
let mut server = Server::new(&settings).unwrap_or_else(|error| {
panic!(
"Failed to start server at port {}: {:?}",
settings.port, error
)
});
server.run();
}

@ -11,10 +11,10 @@
use crate::database::{Database, DatabaseCreationError, DatabaseSettings};
use crate::dictionary::lookup;
use crate::response::MessageResponseData;
use crate::utils::{get_starting_mora, get_final_mora};
use crate::utils::{get_final_mora, get_starting_mora};
use crate::word::Word;
use wana_kana::{IsJapaneseStr, ConvertJapanese};
use wana_kana::{ConvertJapanese, IsJapaneseStr};
#[derive(Default)]
pub struct RoomSettings {
@ -41,11 +41,16 @@ impl Room {
}
pub fn get_history(&self) -> rusqlite::Result<Vec<Word>> {
self.database.load_words_before(self.database.last_word_id + 1)
self.database
.load_words_before(self.database.last_word_id + 1)
}
// Err(&str) will be converted to MessageResponseData::Error
pub fn handle_query(&mut self, query: &str, client_id: u64) -> Result<MessageResponseData, &str> {
pub fn handle_query(
&mut self,
query: &str,
client_id: u64,
) -> Result<MessageResponseData, &str> {
// Ensure query isn't from last player
if Some(client_id) == self.last_client_id {
return Err("It's not your turn!");
@ -70,9 +75,19 @@ impl Room {
// Send result
match dictionary_result {
Some(entry) => {
if entry.reading.chars().last().unwrap().to_string().to_hiragana() == "ん" {
if entry
.reading
.chars()
.last()
.unwrap()
.to_string()
.to_hiragana()
== "ん"
{
Err("Can't end with ん!")
} else if self.next_mora.is_none() || get_starting_mora(&entry.reading).eq(self.next_mora.as_deref().unwrap()) {
} else if self.next_mora.is_none()
|| get_starting_mora(&entry.reading).eq(self.next_mora.as_deref().unwrap())
{
let word: Word = entry.clone().into();
self.next_mora = Some(get_final_mora(&word.reading));
self.database.add_word(&word).unwrap(); // TODO: replace .unwrap() with ?

@ -1,13 +1,13 @@
use crate::client::{Client, ClientInfo};
use crate::database::{DatabaseSettings, DatabaseType, DatabaseCreationError};
use crate::database::{DatabaseCreationError, DatabaseSettings, DatabaseType};
use crate::response::MessageResponseData;
use crate::room::{Room, RoomSettings};
use derive_more::From;
use simple_websockets::{Event, EventHub, Message, Responder};
use std::cell::RefCell;
use std::collections::HashMap;
use std::rc::Rc;
use std::cell::RefCell;
use simple_websockets::{Event, Responder, Message, EventHub};
use derive_more::From;
#[derive(From, Debug)]
pub enum ServerCreationError {
@ -66,27 +66,36 @@ impl Server {
pub fn run(&mut self) {
loop {
match match self.event_hub.poll_event() {
Event::Connect(client_id, responder) => self.handle_connection(client_id, responder),
Event::Connect(client_id, responder) => {
self.handle_connection(client_id, responder)
}
Event::Disconnect(client_id) => self.handle_disconnection(client_id),
Event::Message(client_id, message) => self.handle_message(client_id, message),
} {
Ok(()) => {},
Ok(()) => {}
Err(error) => println!("{:?}", error),
}
}
}
fn new_client(&mut self, client_id: u64, responder: Responder) -> &Client {
let client = Client::new(ClientInfo::Ws {
let client = Client::new(
ClientInfo::Ws {
id: client_id,
responder,
discord_info: None,
}, self.lobby.clone());
},
self.lobby.clone(),
);
self.clients.insert(client_id, client);
self.clients.get(&client_id).unwrap()
}
fn handle_connection(&mut self, client_id: u64, responder: Responder) -> Result<(), ServerError> {
fn handle_connection(
&mut self,
client_id: u64,
responder: Responder,
) -> Result<(), ServerError> {
// Debug
println!("A client connected with id #{}", client_id);
@ -98,15 +107,21 @@ impl Server {
let room = client.room.borrow();
// Send client greeting
client.send(MessageResponseData::Greeting {
client.send(
MessageResponseData::Greeting {
id: client_id,
next_mora: room.next_mora().clone(),
}.into_message());
}
.into_message(),
);
// Sent recent message history
client.send(MessageResponseData::History {
client.send(
MessageResponseData::History {
words: room.get_history()?,
}.into_message());
}
.into_message(),
);
}
// Number of clients on Rc<RefCell<Room>> reference counter will be one more
@ -133,7 +148,11 @@ impl Server {
}
fn for_client_in_room(&self, room: &Rc<RefCell<Room>>, mut closure: impl FnMut(&Client) -> ()) {
for (_id, client) in self.clients.iter().filter(|(_id, client)| Rc::<RefCell<Room>>::ptr_eq(room, &client.room)) {
for (_id, client) in self
.clients
.iter()
.filter(|(_id, client)| Rc::<RefCell<Room>>::ptr_eq(room, &client.room))
{
closure(client);
}
}
@ -145,7 +164,10 @@ impl Server {
}
fn broadcast_player_count(&self, room: &Rc<RefCell<Room>>) {
let response = MessageResponseData::PlayerCount { players: self.client_count_in_room(room) as u64 }.into_response();
let response = MessageResponseData::PlayerCount {
players: self.client_count_in_room(room) as u64,
}
.into_response();
for (_id, client) in self.clients.iter() {
client.send(response.to_message());
}
@ -163,13 +185,19 @@ impl Server {
let message = match message {
Message::Text(message) => {
// Debug
println!("Received a message from client #{}: {:?}", client_id, message);
println!(
"Received a message from client #{}: {:?}",
client_id, message
);
message
}
Message::Binary(message) => {
// Debug
println!("Received a binary message from client #{}: {:?}", client_id, message);
println!(
"Received a binary message from client #{}: {:?}",
client_id, message
);
return Ok(());
}
@ -182,7 +210,12 @@ impl Server {
Ok(response) => self.announce_to_room(&client.room, response),
// Send errors to only this client
Err(message) => {
client.send(MessageResponseData::Error { message: message.to_string() }.into_message());
client.send(
MessageResponseData::Error {
message: message.to_string(),
}
.into_message(),
);
}
};
Ok(())

@ -38,10 +38,13 @@ pub fn get_final_mora(word: &str) -> String {
let mut iter = word.chars().rev();
let final_char = iter.next().unwrap();
match final_char {
'ゃ' | 'ゅ' | 'ょ' => format!("{}{final_char}", match iter.next() {
'ゃ' | 'ゅ' | 'ょ' => format!(
"{}{final_char}",
match iter.next() {
Some(c) => c.to_string(),
None => String::from(""),
}),
}
),
_ => final_char.to_string(),
}
}

@ -1,6 +1,6 @@
use chrono::{DateTime, Utc};
use serde::Serialize;
use jisho::Entry;
use serde::Serialize;
use std::convert::From;
#[derive(Serialize)]

Loading…
Cancel
Save