From 247e29ce139e2beb0aced09954d3158b84174af2 Mon Sep 17 00:00:00 2001 From: bel Date: Sun, 3 May 2020 08:14:29 -0600 Subject: [PATCH] Implement message types and lobby join --- secert-hitler/Cargo.lock | 7 + secert-hitler/Cargo.toml | 1 + .../src/controller/gamemaster/gamemaster.rs | 39 +++++- .../src/controller/gamemaster/lobby.rs | 70 ++++++++++ .../src/controller/gamemaster/mod.rs | 2 + .../src/controller/gamemaster/player.rs | 22 ++++ secert-hitler/src/model/state/event.rs | 123 +++++++++++++++++- testdata/matrix-sandbox/build.sh | 11 +- testdata/matrix-sandbox/synapse-test-log.yaml | 2 +- 9 files changed, 270 insertions(+), 7 deletions(-) create mode 100644 secert-hitler/src/controller/gamemaster/lobby.rs create mode 100644 secert-hitler/src/controller/gamemaster/player.rs diff --git a/secert-hitler/Cargo.lock b/secert-hitler/Cargo.lock index 6d19f0b..c637209 100644 --- a/secert-hitler/Cargo.lock +++ b/secert-hitler/Cargo.lock @@ -44,6 +44,12 @@ dependencies = [ "wasi", ] +[[package]] +name = "json" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "078e285eafdfb6c4b434e0d31e8cfcb5115b651496faca5749b88fafd4f23bfd" + [[package]] name = "lazy_static" version = "1.4.0" @@ -114,6 +120,7 @@ name = "secert-hitler" version = "0.1.0" dependencies = [ "crossbeam-channel", + "json", "rand", ] diff --git a/secert-hitler/Cargo.toml b/secert-hitler/Cargo.toml index bb12c43..c115ed5 100644 --- a/secert-hitler/Cargo.toml +++ b/secert-hitler/Cargo.toml @@ -9,3 +9,4 @@ edition = "2018" [dependencies] rand = "*" crossbeam-channel = "*" +json = "*" diff --git a/secert-hitler/src/controller/gamemaster/gamemaster.rs b/secert-hitler/src/controller/gamemaster/gamemaster.rs index 710892a..53b6b48 100644 --- a/secert-hitler/src/controller/gamemaster/gamemaster.rs +++ b/secert-hitler/src/controller/gamemaster/gamemaster.rs @@ -1,3 +1,4 @@ +/* use super::super::super::model::state::room::Room; pub struct GameMaster { @@ -10,6 +11,24 @@ impl GameMaster { room: room, } } + + fn run(&self) -> Result { + self.run_lobby()?; + self.run_game_setup()?; + self.run_game() + } + + fn run_lobby(&self) -> Result { + Err("not impl".to_string()) + } + + fn run_game_setup(&self) -> Result { + Err("not impl".to_string()) + } + + fn run_game(&self) -> Result { + Err("not impl".to_string()) + } } #[cfg(test)] @@ -36,11 +55,29 @@ mod tests { let _ = GameMaster::new(r); } - #[test] fn new_mockrooms() { let mut mrs = MockRooms::new(); let r = mrs.create(); let _ = GameMaster::new(r); } + + #[test] + fn gm_run_lobby_fail() { + let gm = GameMaster::new(Box::new(MockRoom::create())); + panic!("not impl"); + } + + #[test] + fn gm_run_game_setup_fail() { + let gm = GameMaster::new(Box::new(MockRoom::create())); + panic!("not impl"); + } + + #[test] + fn gm_run_game_fail() { + let gm = GameMaster::new(Box::new(MockRoom::create())); + panic!("not impl"); + } } +*/ diff --git a/secert-hitler/src/controller/gamemaster/lobby.rs b/secert-hitler/src/controller/gamemaster/lobby.rs new file mode 100644 index 0000000..5ba5d7e --- /dev/null +++ b/secert-hitler/src/controller/gamemaster/lobby.rs @@ -0,0 +1,70 @@ +use super::player::Player; +use super::super::super::model::state::event::Event; + +use std::collections::HashMap; + +pub struct Lobby { + players: HashMap, +} + +impl Lobby { + fn new() -> Lobby { + Lobby{ + players: HashMap::new(), + } + } + + fn eat(&mut self, message: Event) { + let j = message.join(); + if j.is_none() { + return; + } + let id = j.unwrap(); + self.players.insert(id.clone(), Player::new(id)); + } +} + +#[cfg(test)] +mod tests { + use super::*; + + fn _dummy_event(m: &str) -> Event { + Event{ + body: m.to_string(), + next: "a".to_string(), + sender: "b".to_string(), + } + } + + #[test] + fn new_lobby() { + let _ = Lobby::new(); + } + + #[test] + fn eat_join() { + let mut l = Lobby::new(); + let e = _dummy_event(r#"{"membership": "join", "displayname": "a"}"#); + let was = l.players.len(); + l.eat(e); + assert!(was+1 == l.players.len(), "want {}, got {}: {:?}", was+1, l.players.len(), l.players); + } + + #[test] + fn eat_join_malformatted() { + let mut l = Lobby::new(); + let e = _dummy_event(r#"{"membership": "join"}"#); + let was = l.players.len(); + l.eat(e); + assert!(was == l.players.len()); + } + + #[test] + fn eat_null() { + let mut l = Lobby::new(); + let e = _dummy_event(r#"{"hello": "world"}"#); + let was = l.players.len(); + l.eat(e); + assert!(was == l.players.len()); + } +} diff --git a/secert-hitler/src/controller/gamemaster/mod.rs b/secert-hitler/src/controller/gamemaster/mod.rs index 2d0280a..bcb677e 100644 --- a/secert-hitler/src/controller/gamemaster/mod.rs +++ b/secert-hitler/src/controller/gamemaster/mod.rs @@ -1 +1,3 @@ pub mod gamemaster; +pub mod player; +pub mod lobby; diff --git a/secert-hitler/src/controller/gamemaster/player.rs b/secert-hitler/src/controller/gamemaster/player.rs new file mode 100644 index 0000000..cd96c6a --- /dev/null +++ b/secert-hitler/src/controller/gamemaster/player.rs @@ -0,0 +1,22 @@ +#[derive(Clone, Debug)] +pub struct Player { + id: String, +} + +impl Player { + pub fn new(id: String) -> Player { + Player { + id: id, + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn new_player() { + let _ = Player::new("id".to_string()); + } +} diff --git a/secert-hitler/src/model/state/event.rs b/secert-hitler/src/model/state/event.rs index b8f5492..e4f6a61 100644 --- a/secert-hitler/src/model/state/event.rs +++ b/secert-hitler/src/model/state/event.rs @@ -1,3 +1,5 @@ +use json; + #[derive(Clone, Debug)] pub struct Event { pub sender: String, @@ -5,15 +7,134 @@ pub struct Event { pub next: String, } +#[derive(PartialEq, Eq, Debug)] +pub enum EventType { + Null, + Join, + Create, + Message, +} + +impl Event { + pub fn mode(&self) -> EventType { + let d = json::parse(&self.body).unwrap(); + if d["membership"].is_string() { + return match d["membership"].as_str().unwrap().to_string().as_ref() { + "join" => EventType::Join, + _ => EventType::Null, + }; + } + if d["creator"].is_string() { + return EventType::Create; + } + if d["msgtype"].is_string() { + return match d["msgtype"].as_str().unwrap().to_string().as_ref() { + "m.text" => EventType::Message, + _ => EventType::Null, + }; + } + EventType::Null + } + + pub fn join(&self) -> Option { + let d = json::parse(&self.body).unwrap(); + match self.mode() { + EventType::Join => true, + _ => return None, + }; + let o = d["displayname"].as_str(); + if o.is_none() { + return None; + } + Some(o.unwrap().to_string()) + } +} + #[cfg(test)] mod tests { + use super::*; + + fn _dummy() -> Event { + Event{ + sender: "sender".to_string(), + body: r#"{}"#.to_string(), + next: "next".to_string(), + } + } + #[test] fn event() { - let e = super::Event{ + let e = Event{ sender: "sender".to_string(), body: "body".to_string(), next: "next".to_string(), }; println!("{:?}", e); } + + #[test] + fn mode_null() { + let mut e = _dummy(); + e.body = r#"{ + }"#.to_string(); + assert!(e.mode() == EventType::Null); + } + + #[test] + fn mode_create() { + let mut e = _dummy(); + e.body = r#"{ + "creator": "abc" + }"#.to_string(); + assert!(e.mode() == EventType::Create); + } + + #[test] + fn mode_msgtype() { + let mut e = _dummy(); + e.body = r#"{ + "msgtype": "m.text" + }"#.to_string(); + assert!(e.mode() == EventType::Message); + } + + #[test] + fn mode_join() { + let mut e = _dummy(); + e.body = r#"{ + "membership": "join" + }"#.to_string(); + assert!(e.mode() == EventType::Join); + } + + #[test] + fn join_some() { + let mut e = _dummy(); + e.body = r#"{ + "displayname": "hi", + "membership": "join" + }"#.to_string(); + let j = e.join(); + assert!(j.is_some()); + } + + #[test] + fn join_some_bad() { + let mut e = _dummy(); + e.body = r#"{ + "membership": "join" + }"#.to_string(); + let j = e.join(); + assert!(j.is_none()); + } + + #[test] + fn join_none() { + let mut e = _dummy(); + e.body = r#"{ + "a": "b" + }"#.to_string(); + let j = e.join(); + assert!(j.is_none()); + } } diff --git a/testdata/matrix-sandbox/build.sh b/testdata/matrix-sandbox/build.sh index dc4e997..afe6a3c 100644 --- a/testdata/matrix-sandbox/build.sh +++ b/testdata/matrix-sandbox/build.sh @@ -82,10 +82,12 @@ out="$( -H 'content-type: application/json' \ -H 'Authorization: Bearer '"$access_token" \ | jq '{"timeline": .rooms.join[].timeline.events[], "next": .next_batch}' \ - | jq '{"content": .timeline.content.body, "sender": .timeline.sender, "next": .next}' + | jq '{"content": .timeline.content, "sender": .timeline.sender, "next": .next}' \ )" -printf "%s\n" "$out" -since="$(echo "$out" | jq -r .next | tail -n 1)" +printf "%s\n" "$out" | jq . +since="$( + echo "$out" \ + | jq -r .next | tail -n 1)" # send new message txid="$(cat /proc/sys/kernel/random/uuid)" @@ -112,5 +114,6 @@ curl -sS "http://localhost:39487/_matrix/client/r0/sync?since=$since" \ -H 'content-type: application/json' \ -H 'Authorization: Bearer '"$access_token" \ | jq '{"timeline": .rooms.join[].timeline.events[], "next": .next_batch}' \ - | jq '{"content": .timeline.content.body, "sender": .timeline.sender, "next": .next}' + | jq '{"content": .timeline.content, "sender": .timeline.sender, "next": .next}' \ + | jq . diff --git a/testdata/matrix-sandbox/synapse-test-log.yaml b/testdata/matrix-sandbox/synapse-test-log.yaml index 91633e4..b8bb22f 100644 --- a/testdata/matrix-sandbox/synapse-test-log.yaml +++ b/testdata/matrix-sandbox/synapse-test-log.yaml @@ -20,7 +20,7 @@ handlers: file: class: logging.handlers.RotatingFileHandler formatter: precise - filename: /home/bel/Go/src/local/containers/secret-hitler-via-matrix/testdata/matrix-sandbox/homeserver.log + filename: /tmp/synapse-test-real.log maxBytes: 104857600 backupCount: 10 filters: [context]