room joining reuqires sender

master^2
Bel LaPointe 2020-05-07 07:46:43 -06:00
parent 3e9ce3edff
commit 3859f29a75
9 changed files with 177 additions and 54 deletions

View File

@ -61,7 +61,7 @@ impl GameEventType {
params: [],
}.dump(),
};
GameEvent::new(Event{sender: "<generated>".to_string(), body: d.dump(), since: "".to_string()})
GameEvent::new(Event{sender: "__gm__".to_string(), body: d.dump(), since: "".to_string()})
}
}
@ -75,9 +75,15 @@ impl GameEvent {
if !top_level["body"].is_string() {
return GameEvent{d: json::Null, sender: event.sender.clone()};
}
let body = top_level["body"].as_str().unwrap();
let d = json::parse(&body).unwrap_or(json::Null);
let sender = event.sender.clone();
if d.is_object() && d.has_key("sender") && d["sender"].is_string() {
// sender = d["sender"].as_str().unwrap();
}
GameEvent{
d: json::parse(&top_level["body"].as_str().unwrap()).unwrap_or(json::Null),
sender: event.sender.clone(),
d: d,
sender: sender,
}
}

View File

@ -6,6 +6,7 @@ use super::super::role::Role;
use log::debug;
use json;
use std::collections::HashMap;
impl GameMaster {
pub fn game_is_over(&mut self) -> Result<GameEvent, Role> {
@ -30,6 +31,7 @@ impl GameMaster {
pub fn game_election(&mut self) -> Result<GameEvent, Role> {
let mut ge = GameEventType::ElectionPend.build();
let president_candidate = self.candidate_presidents.pop().unwrap();
self.president = Some(president_candidate.clone());
ge.d["targets"] = json::array![president_candidate.clone()];
ge.d["params"] = json::array!["president"];
if self.room.send(ge.serialize()).is_err() {
@ -51,11 +53,55 @@ impl GameMaster {
debug!("invalid chancellor candidates found in election set");
return self.game_election();
}
self.chancellor = Some(chancellor_candidate.clone());
Ok(chancellor_candidate_event)
}
pub fn game_election_vote(&mut self) -> Result<GameEvent, Role> {
Err(Role::Null)
let mut votes: HashMap<String, bool> = HashMap::new();
while votes.len() < self.players().len() {
debug!("votes: {:?}", votes);
let events = self.scrape_until_gameeventtype(GameEventType::VoteSet).unwrap();
debug!("scrape until vote set found {:?}", events);
if events.len() > 0 {
let ge = GameEvent::new(events.last().unwrap().clone());
let sources = ge.sources();
if sources.len() > 0 {
let player = sources.first().unwrap();
if self.player(player.clone()).is_some() {
let params = ge.params();
if params.len() > 0 {
votes.insert(player.clone(), params.first().unwrap() == "y");
}
}
}
}
}
debug!("game election vote yielded: {:?}", votes);
let mut ge = GameEventType::VoteSet.build();
ge.d["sources"] = json::array!["__gm__"];
let mut yays = 0;
for (player, vote) in &votes {
if *vote {
yays += 1;
}
}
let gm_vote = yays > self.players().len() / 2;
ge.d["params"] = json::array![format!("{:?}", gm_vote)];
for (player, vote) in &votes {
ge.d["sources"].push(player.clone());
ge.d["params"].push(format!("{:?}", vote));
}
self.room.send(ge.serialize());
if gm_vote {
return Ok(GameEventType::Null.build()); // todo how to emit continue?
} else {
self.president = None;
self.chancellor = None;
return Ok(GameEventType::VoteFailed.build());
}
}
pub fn game_policy_select_random(&mut self) -> Result<GameEvent, Role> {
@ -100,13 +146,13 @@ mod tests {
fn dummy() -> GameMaster {
init();
let mut mrs = MockRooms::new();
let r = mrs.create();
let r = mrs.create("__gm__".to_string());
let room_id = r.room_id().clone();
let mut gm = GameMaster::new(r);
for _ in 0..config::MIN_PLAYERS-2 {
assert!(mrs.join(room_id.clone()).is_ok());
for i in 0..config::MIN_PLAYERS-2 {
assert!(mrs.join(i.to_string(), room_id.clone()).is_ok());
}
mrs.join(room_id).unwrap().send(format!(r#"{{
mrs.join((config::MIN_PLAYERS-1).to_string(), room_id).unwrap().send(format!(r#"{{
"msgtype": "m.text",
"body": "{{\"GameEventType\": \"GameStart\"}}"
}}"#)).unwrap();
@ -235,4 +281,65 @@ mod tests {
let election_pends = gm.room.sync();
assert!(election_pends.len() == 6, "election_pends: {:?}", election_pends);
}
#[test]
fn game_election_vote() {
let mut gm = dummy();
gm.lobby.players = HashMap::new();
debug!("sending a null event");
let ge = GameEventType::Null.build();
assert!(ge.mode() == GameEventType::Null);
assert!(gm.room.send(ge.serialize()).is_ok());
debug!("sent: {}", ge.serialize());
debug!("sending a valid vote from a valid player");
let mut ge = GameEventType::VoteSet.build();
assert!(ge.mode() == GameEventType::VoteSet);
ge.d["sources"] = json::array!["1"];
ge.d["params"] = json::array!["n"];
assert!(gm.room.send(ge.serialize()).is_ok());
debug!("sent: {}", ge.serialize());
gm.lobby.players.insert("1".to_string(), Player::new("1".to_string()));
debug!("sending a valid repeat vote from a valid player");
let mut ge = GameEventType::VoteSet.build();
assert!(ge.mode() == GameEventType::VoteSet);
ge.d["sources"] = json::array!["1"];
ge.d["params"] = json::array!["y"];
assert!(gm.room.send(ge.serialize()).is_ok());
debug!("sent: {}", ge.serialize());
debug!("sending an invalid vote from a valid player");
let mut ge = GameEventType::VoteSet.build();
assert!(ge.mode() == GameEventType::VoteSet);
ge.d["sources"] = json::array![];
ge.d["params"] = json::array!["n"];
assert!(gm.room.send(ge.serialize()).is_ok());
debug!("sent: {}", ge.serialize());
gm.lobby.players.insert("2".to_string(), Player::new("2".to_string()));
debug!("correcting an invalid vote from a valid player");
let mut ge = GameEventType::VoteSet.build();
assert!(ge.mode() == GameEventType::VoteSet);
ge.d["sources"] = json::array!["2"];
ge.d["params"] = json::array!["y"];
assert!(gm.room.send(ge.serialize()).is_ok());
debug!("sent: {}", ge.serialize());
let ge = gm.game_election_vote();
debug!("game election vote result: {:?}", ge);
assert!(ge.is_ok());
let events = gm.room.sync();
assert!(events.len() == 1);
let e = events.last().unwrap().clone();
let ge = GameEvent::new(e.clone());
assert!(ge.sender == "__gm__", "post-game election vote ge: {:?} from {:?}", ge, e);
assert!(ge.mode() == GameEventType::VoteSet);
assert!(ge.sources()[0] == "__gm__");
assert!(ge.params()[0] == "true");
assert!(ge.params()[1] == "true");
assert!(ge.params()[2] == "true");
}
}

View File

@ -51,14 +51,18 @@ impl GameMaster {
pub fn run_game(&mut self) -> Result<GameEvent, Role> {
loop {
self.game_is_over()?;
self.game_election()?;
self.game_is_over()?;
let ge = self.game_is_over()?;
self.room.send(ge.serialize());
let ge = self.game_election()?;
self.room.send(ge.serialize());
let ge = self.game_is_over()?;
self.room.send(ge.serialize());
let p = match self.game_election_vote().unwrap_or(GameEventType::GameStop.build()).mode() {
GameEventType::VoteFailed => self.game_policy_select_random(),
GameEventType::GameStop => self.game_is_over(),
_ => self.game_policy_select(),
}?;
self.room.send(p.serialize());
if p.mode() != GameEventType::PolicySet {
error!("unexpected game event type after election vote followup: {:?}", p);
return Err(Role::Null);
@ -71,9 +75,12 @@ impl GameMaster {
}
let param = param.unwrap();
let policy = Policy::from_string(param.to_string());
self.game_policy_veto(policy.clone())?;
self.game_ends_with(policy.clone())?;
self.game_policy_enact(policy.clone())?;
let ge = self.game_policy_veto(policy.clone())?;
self.room.send(ge.serialize());
let ge = self.game_ends_with(policy.clone())?;
self.room.send(ge.serialize());
let ge = self.game_policy_enact(policy.clone())?;
self.room.send(ge.serialize());
}
}
@ -117,7 +124,7 @@ mod tests {
#[test]
fn new_mockroom() {
let _ = GameMaster::new(Box::new(MockRoom::create()));
let _ = GameMaster::new(Box::new(MockRoom::create("__gm__".to_string())));
}
#[test]
@ -127,23 +134,23 @@ mod tests {
mrs
}
let mut mrs = get();
let r = mrs.create();
let r = mrs.create("__gm__".to_string());
let _ = GameMaster::new(r);
}
#[test]
fn new_mockrooms() {
let mut mrs = MockRooms::new();
let r = mrs.create();
let r = mrs.create("__gm__".to_string());
let _ = GameMaster::new(r);
}
#[test]
fn scrape_until_get() {
let mut mrs = MockRooms::new();
let r = mrs.create();
let r = mrs.create("__gm__".to_string());
let room_id = r.room_id().clone();
let r2 = mrs.join(room_id);
let r2 = mrs.join("r2".to_string(), room_id);
assert!(r2.is_ok());
let mut r2 = r2.unwrap();
let mut gm = GameMaster::new(r);

View File

@ -55,15 +55,15 @@ mod tests {
fn run_lobby() {
init();
let mut mrs = MockRooms::new();
let r1 = mrs.create();
let r1 = mrs.create("__gm__".to_string());
let room_id = r1.room_id();
let mut gm = GameMaster::new(r1);
for i in 0..config::MIN_PLAYERS-1 {
let mut r2 = mrs.join(room_id.clone()).unwrap();
let mut r2 = mrs.join(i.to_string(), room_id.clone()).unwrap();
r2.send(format!(r#"{{
"msgtype": "m.text",
"body": "{{\"GameEventType\": \"GameStart\"}}"
}}"#)).unwrap();
}}"#)).unwrap();
let ready = gm.run_lobby();
assert!(ready.is_err() == (i != 3), "want {:?} for ready.is_err #{:?}, which is {:?}", i != 3, i, ready.is_err());
}
@ -72,12 +72,12 @@ mod tests {
for k in gm.lobby.players.keys() {
players1.push(k.clone());
}
let mut r2 = mrs.join(room_id.clone()).unwrap();
let mut r2 = mrs.join("r2".to_string(), room_id.clone()).unwrap();
r2.send(format!(r#"{{
"msgtype": "m.text",
"body": "{{\"GameEventType\": \"GameStart\"}}"
}}"#)).unwrap();
assert!(gm.run_lobby().is_ok());
}}"#)).unwrap();
assert!(gm.run_lobby().is_ok());
assert!(gm.lobby.players.len() == 5, "secnd run_lobby players: {:?}, sync: {:?}", gm.lobby.players, gm.room.sync());
let players2 = gm.lobby.players.keys();
assert!(format!("{:?}", players1) == format!("{:?}", players2));

View File

@ -110,7 +110,7 @@ mod tests {
fn run_game_setup() {
init();
let mut mrs = MockRooms::new();
let r1 = mrs.create();
let r1 = mrs.create("__gm__".to_string());
let mut gm = GameMaster::new(r1);
let r = gm.run_game_setup();
assert!(!r.is_ok());
@ -128,7 +128,7 @@ mod tests {
fn setup_gather_candidates() {
init();
let mut mrs = MockRooms::new();
let r1 = mrs.create();
let r1 = mrs.create("__gm__".to_string());
let mut gm = GameMaster::new(r1);
assert!(gm.setup_gather_candidates().is_ok());
for i in 0..config::MIN_PLAYERS {
@ -147,7 +147,7 @@ mod tests {
fn setup_set_roles() {
init();
let mut mrs = MockRooms::new();
let r1 = mrs.create();
let r1 = mrs.create("__gm__".to_string());
let mut gm = GameMaster::new(r1);
assert!(gm.setup_set_roles().is_err());
for i in 0..config::MIN_PLAYERS {
@ -168,7 +168,7 @@ mod tests {
fn setup_order_candidates() {
init();
let mut mrs = MockRooms::new();
let r1 = mrs.create();
let r1 = mrs.create("__gm__".to_string());
let mut gm = GameMaster::new(r1);
assert!(gm.setup_order_candidates().is_ok());
gm.candidate_presidents = ["1".to_string()].to_vec();

View File

@ -11,14 +11,15 @@ pub struct MockRoom {
room_id: String,
events_s: Sender<Vec<Event>>,
events_r: Receiver<Vec<Event>>,
pub sender: String,
}
impl MockRoom {
pub fn create() -> MockRoom {
MockRoom::join(rands())
pub fn create(sender: String) -> MockRoom {
MockRoom::join(sender, rands())
}
pub fn join(room_id: String) -> MockRoom {
pub fn join(sender: String, room_id: String) -> MockRoom {
let (s, r) = unbounded();
s.send(vec![]).ok().unwrap();
let mut mr = MockRoom {
@ -26,12 +27,12 @@ impl MockRoom {
room_id: room_id.clone(),
events_s: s,
events_r: r,
sender: sender,
};
let id = rands();
mr.send_as(id.clone(), format!(r#"{{
mr.send_as(mr.sender.clone(), format!(r#"{{
"displayname": "{}",
"membership": "join"
}}"#, id.clone())).unwrap();
}}"#, mr.sender.clone())).unwrap();
mr
}
@ -111,13 +112,13 @@ mod tests {
use super::rands;
fn _dummy() -> MockRoom {
let mut r = MockRoom::create();
let mut r = MockRoom::create(rands());
r.since = "1".to_string();
let mut events = r.events_r.recv().ok().unwrap();
for i in 0..5 {
events.push(Event{
sender: i.to_string(),
since: i.to_string(),
sender: i.to_string(),
since: i.to_string(),
body: i.to_string(),
});
}
@ -134,14 +135,14 @@ mod tests {
#[test]
fn create() {
let mut r: MockRoom = MockRoom::create();
let mut r: MockRoom = MockRoom::create(rands());
println!("{:?}", r.sync());
}
#[test]
fn join() {
let rid = "a".to_string();
let mut r: MockRoom = MockRoom::join(rid.to_string());
let mut r: MockRoom = MockRoom::join(rands(), rid.to_string());
assert!(r.room_id == rid);
let events = r.sync();
let mut found = false;

View File

@ -17,16 +17,18 @@ impl MockRooms {
}
impl Rooms for MockRooms {
fn create(&mut self) -> Box<dyn Room> {
let room = MockRoom::create();
fn create(&mut self, sender: String) -> Box<dyn Room> {
let room = MockRoom::create(sender);
let _room = room.room();
self.rooms.push(room);
Box::new(_room)
}
fn join(&self, room_id: String) -> Result<Box<dyn Room>, &str> {
fn join(&self, sender: String, room_id: String) -> Result<Box<dyn Room>, &str> {
for r in &self.rooms {
if r.room_id() == room_id {
let mut r = r.clone();
r.sender = sender;
let mut r = r.room();
r.send(format!(r#"{{
"displayname": "{}",
@ -48,9 +50,9 @@ mod tests {
fn _dummy() -> MockRooms {
let mut mrs = MockRooms::new();
for i in 0..5 {
let random = MockRoom::create();
let random = MockRoom::create(i.to_string());
mrs.rooms.push(random);
let joined = MockRoom::join(i.to_string());
let joined = MockRoom::join(i.to_string(), i.to_string());
mrs.rooms.push(joined);
}
assert!(mrs.rooms.len() == 10);
@ -67,7 +69,7 @@ mod tests {
fn create() {
let mut mrs = _dummy();
let was = mrs.rooms.len();
let _ = mrs.create();
let _ = mrs.create("abc".to_string());
let is = mrs.rooms.len();
assert!(was+1 == is, "was {} rooms, want {} rooms, got {} rooms", was, was+1, is);
}
@ -76,7 +78,7 @@ mod tests {
fn join_404() {
let mrs = _dummy();
let was = mrs.rooms.len();
let r = mrs.join("does not exist".to_string());
let r = mrs.join("?".to_string(), "does not exist".to_string());
let is = mrs.rooms.len();
assert!(was == is, "was {} rooms, want {} rooms, got {} rooms", was, was+1, is);
assert!(!r.is_ok());
@ -86,7 +88,7 @@ mod tests {
fn join_found() {
let mrs = _dummy();
let was = mrs.rooms.len();
let r = mrs.join("0".to_string());
let r = mrs.join("?".to_string(), "0".to_string());
let is = mrs.rooms.len();
assert!(was == is, "was {} rooms, want {} rooms, got {} rooms", was, was+1, is);
assert!(r.is_ok());
@ -96,8 +98,8 @@ mod tests {
#[test]
fn join_clobber() {
let mrs = _dummy();
let mut a = mrs.join("0".to_string()).ok().unwrap();
let mut b = mrs.join("0".to_string()).ok().unwrap();
let mut a = mrs.join("?".to_string(), "0".to_string()).ok().unwrap();
let mut b = mrs.join("?".to_string(), "0".to_string()).ok().unwrap();
assert!(a.room_id() == b.room_id());

View File

@ -18,7 +18,7 @@ mod tests {
#[test]
fn mockroom() {
fn gen() -> impl Room {
let r = MockRoom::create();
let r = MockRoom::create("123".to_string());
r
}
gen();

View File

@ -1,8 +1,8 @@
use super::room::Room;
pub trait Rooms {
fn create(&mut self) -> Box<dyn Room>;
fn join(&self, room_id: String) -> Result<Box<dyn Room>, &str>;
fn create(&mut self, sender: String) -> Box<dyn Room>;
fn join(&self, sender: String, room_id: String) -> Result<Box<dyn Room>, &str>;
}
#[cfg(test)]
@ -18,7 +18,7 @@ mod tests {
r
}
let mut rooms = gen();
let mut room_ptr: Box<dyn Room> = rooms.create();
let mut room_ptr: Box<dyn Room> = rooms.create("abc".to_string());
assert!(room_ptr.send("hi".to_string()).is_ok());
}
}