implement stats message
authoralfadur
Thu, 11 Apr 2019 21:20:41 +0300
changeset 14810 18240b308505
parent 14809 6dea1ca64992
child 14811 e94fbf6cad2b
implement stats message
rust/hedgewars-server/src/server/core.rs
rust/hedgewars-server/src/server/handlers.rs
rust/hedgewars-server/src/server/handlers/common.rs
rust/hedgewars-server/src/server/handlers/inroom.rs
rust/hedgewars-server/src/server/handlers/lobby.rs
--- a/rust/hedgewars-server/src/server/core.rs	Thu Apr 11 19:30:22 2019 +0300
+++ b/rust/hedgewars-server/src/server/core.rs	Thu Apr 11 21:20:41 2019 +0300
@@ -158,11 +158,29 @@
             .find_map(|(_, c)| Some(c).filter(|c| c.nick == nick))
     }
 
+    pub fn all_clients(&self) -> impl Iterator<Item = ClientId> + '_ {
+        self.clients.iter().map(|(id, _)| id)
+    }
+
+    pub fn filter_clients<'a, F>(&'a self, f: F) -> impl Iterator<Item = ClientId> + 'a
+    where
+        F: Fn(&(usize, &HWClient)) -> bool + 'a,
+    {
+        self.clients.iter().filter(f).map(|(_, c)| c.id)
+    }
+
+    pub fn filter_rooms<'a, F>(&'a self, f: F) -> impl Iterator<Item = RoomId> + 'a
+    where
+        F: Fn(&(usize, &HWRoom)) -> bool + 'a,
+    {
+        self.rooms.iter().filter(f).map(|(_, c)| c.id)
+    }
+
     pub fn collect_clients<F>(&self, f: F) -> Vec<ClientId>
     where
         F: Fn(&(usize, &HWClient)) -> bool,
     {
-        self.clients.iter().filter(f).map(|(_, c)| c.id).collect()
+        self.filter_clients(f).collect()
     }
 
     pub fn collect_nicks<F>(&self, f: F) -> Vec<String>
@@ -176,16 +194,20 @@
             .collect()
     }
 
-    pub fn collect_lobby_clients(&self) -> Vec<ClientId> {
-        self.collect_clients(|(_, c)| c.room_id == None)
+    pub fn lobby_clients(&self) -> impl Iterator<Item = ClientId> + '_ {
+        self.filter_clients(|(_, c)| c.room_id == None)
     }
 
-    pub fn collect_room_clients(&self, room_id: RoomId) -> Vec<ClientId> {
-        self.collect_clients(|(_, c)| c.room_id == Some(room_id))
+    pub fn room_clients(&self, room_id: RoomId) -> impl Iterator<Item = ClientId> + '_ {
+        self.filter_clients(move |(_, c)| c.room_id == Some(room_id))
     }
 
-    pub fn protocol_clients(&self, protocol: u16) -> Vec<ClientId> {
-        self.collect_clients(|(_, c)| c.protocol_number == protocol)
+    pub fn protocol_clients(&self, protocol: u16) -> impl Iterator<Item = ClientId> + '_ {
+        self.filter_clients(move |(_, c)| c.protocol_number == protocol)
+    }
+
+    pub fn protocol_rooms(&self, protocol: u16) -> impl Iterator<Item = RoomId> + '_ {
+        self.filter_rooms(move |(_, r)| r.protocol_number == protocol)
     }
 
     pub fn other_clients_in_room(&self, self_id: ClientId) -> Vec<ClientId> {
--- a/rust/hedgewars-server/src/server/handlers.rs	Thu Apr 11 19:30:22 2019 +0300
+++ b/rust/hedgewars-server/src/server/handlers.rs	Thu Apr 11 21:20:41 2019 +0300
@@ -166,11 +166,11 @@
         Destination::ToId(id) => vec![id],
         Destination::ToIds(ids) => ids,
         Destination::ToAll { group, skip_self } => {
-            let mut ids = match group {
-                DestinationGroup::All => server.clients.iter().map(|(id, _)| id).collect(),
-                DestinationGroup::Lobby => server.collect_lobby_clients(),
-                DestinationGroup::Protocol(proto) => server.protocol_clients(proto),
-                DestinationGroup::Room(id) => server.collect_room_clients(id),
+            let mut ids: Vec<_> = match group {
+                DestinationGroup::All => server.all_clients().collect(),
+                DestinationGroup::Lobby => server.lobby_clients().collect(),
+                DestinationGroup::Protocol(proto) => server.protocol_clients(proto).collect(),
+                DestinationGroup::Room(id) => server.room_clients(id).collect(),
             };
 
             if skip_self {
--- a/rust/hedgewars-server/src/server/handlers/common.rs	Thu Apr 11 19:30:22 2019 +0300
+++ b/rust/hedgewars-server/src/server/handlers/common.rs	Thu Apr 11 21:20:41 2019 +0300
@@ -227,7 +227,8 @@
         remove_client_from_room(client, room, response, msg);
 
         if !room.is_fixed() && room.master_id == None {
-            if let Some(new_master_id) = server.collect_room_clients(room_id).first().cloned() {
+            let new_master_id = server.room_clients(room_id).next();
+            if let Some(new_master_id) = new_master_id {
                 let new_master_nick = server.clients[new_master_id].nick.clone();
                 let room = &mut server.rooms[room_id];
                 room.master_id = Some(new_master_id);
--- a/rust/hedgewars-server/src/server/handlers/inroom.rs	Thu Apr 11 19:30:22 2019 +0300
+++ b/rust/hedgewars-server/src/server/handlers/inroom.rs	Thu Apr 11 21:20:41 2019 +0300
@@ -446,7 +446,7 @@
             match error {
                 None => {
                     let msg = voting_description(&kind);
-                    let voting = Voting::new(kind, server.collect_room_clients(client_id));
+                    let voting = Voting::new(kind, server.room_clients(client_id).collect());
                     let room = &mut server.rooms[room_id];
                     room.voting = Some(voting);
                     response.add(server_chat(msg).send_all().in_room(room_id));
--- a/rust/hedgewars-server/src/server/handlers/lobby.rs	Thu Apr 11 19:30:22 2019 +0300
+++ b/rust/hedgewars-server/src/server/handlers/lobby.rs	Thu Apr 11 21:20:41 2019 +0300
@@ -3,7 +3,8 @@
 use super::common::rnd_reply;
 use crate::{
     protocol::messages::{
-        add_flags, remove_flags, HWProtocolMessage, HWServerMessage::*, ProtocolFlags as Flags,
+        add_flags, remove_flags, server_chat, HWProtocolMessage, HWServerMessage::*,
+        ProtocolFlags as Flags,
     },
     server::{
         client::HWClient,
@@ -13,6 +14,7 @@
     utils::is_name_illegal,
 };
 use log::*;
+use std::{collections::HashSet, convert::identity};
 
 pub fn handle(
     server: &mut HWServer,
@@ -130,6 +132,31 @@
         Rnd(v) => {
             response.add(rnd_reply(&v).send_self());
         }
+        Stats => {
+            let mut protocols: HashSet<_> = server
+                .clients
+                .iter()
+                .map(|(_, c)| c.protocol_number)
+                .chain(server.rooms.iter().map(|(_, r)| r.protocol_number))
+                .collect();
+            let mut protocols: Vec<_> = protocols.drain().collect();
+            protocols.sort();
+
+            let mut html = Vec::with_capacity(protocols.len() + 2);
+
+            html.push("<table>".to_string());
+            for protocol in protocols {
+                html.push(format!(
+                    "<tr><td>{}</td><td>{}</td><td>{}</td></tr>",
+                    super::utils::protocol_version_string(protocol),
+                    server.protocol_clients(protocol).count(),
+                    server.protocol_rooms(protocol).count()
+                ));
+            }
+            html.push("</table>".to_string());
+
+            response.add(Warning(html.join("")).send_self());
+        }
         List => warn!("Deprecated LIST message received"),
         _ => warn!("Incorrect command in lobby state"),
     }