room joining reuqires sender
parent
3e9ce3edff
commit
3859f29a75
|
|
@ -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,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -55,11 +55,11 @@ 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\"}}"
|
||||
|
|
@ -72,7 +72,7 @@ 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\"}}"
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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,7 +112,7 @@ 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 {
|
||||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue