aboutsummaryrefslogtreecommitdiff
path: root/src/scalevalapokalypsi/Server/Clients.scala
diff options
context:
space:
mode:
authorJoel Kronqvist <joel.kronqvist@iki.fi>2024-11-17 13:45:44 +0200
committerJoel Kronqvist <joel.kronqvist@iki.fi>2024-11-17 13:45:44 +0200
commit4de67b497e0e229fe4a42f66f833640b6e50fd5a (patch)
tree34fb5b0e776f7cd3adcb4556f4d6a7c8ad66de39 /src/scalevalapokalypsi/Server/Clients.scala
parent8595e892abc0e0554f589ed2eb88c351a347fbd4 (diff)
downloadscalevalapokalypsi-4de67b497e0e229fe4a42f66f833640b6e50fd5a.tar.gz
scalevalapokalypsi-4de67b497e0e229fe4a42f66f833640b6e50fd5a.zip
Moved the project to an IDEA project & wrote part of README.txt
Diffstat (limited to 'src/scalevalapokalypsi/Server/Clients.scala')
-rw-r--r--src/scalevalapokalypsi/Server/Clients.scala82
1 files changed, 82 insertions, 0 deletions
diff --git a/src/scalevalapokalypsi/Server/Clients.scala b/src/scalevalapokalypsi/Server/Clients.scala
new file mode 100644
index 0000000..377050d
--- /dev/null
+++ b/src/scalevalapokalypsi/Server/Clients.scala
@@ -0,0 +1,82 @@
+package scalevalapokalypsi.Server
+
+import scala.util.Try
+import scala.util.Random
+
+class Clients(maxClients: Int):
+ private val clients: Array[Option[Client]] = Array.fill(maxClients)(None)
+
+ /** Adds `client` to this collection of clients.
+ *
+ * @param client the Client to add
+ * @return true if there was room for the client
+ * i.e. fewer clients than `maxClients`, false otherwise
+ */
+ def addClient(client: Client): Boolean =
+ val i = this.clients.indexOf(None)
+ if i == -1 then
+ false
+ else
+ this.clients(i) = Some(client)
+ true
+
+ /** Returns all the clients.
+ *
+ * @return an iterable of all the clients
+ */
+ def allClients: Iterable[Client] = clients.toVector.flatten
+
+ /** Applies the function `f` to all the clients for its side effects. */
+ def foreach(f: Client => Any): Unit = this.clients.flatten.foreach(f)
+
+ /** Executes the function `f` for all clients in a pseudorandom order. */
+ def inRandomOrder(f: Client => Any): Unit =
+ Random.shuffle(this
+ .clients
+ .flatten)
+ .foreach(f)
+
+ /** Returns true if the predicate `f` stands for all clients,
+ * false otherwise
+ *
+ * @param f the predicate to check for all clients
+ * @return whether `f` stands for all clients
+ */
+ def forall(f: Client => Boolean): Boolean = this.clients.flatten.forall(f)
+
+ /** Gets the names of all the clients stored by this object.
+ *
+ * @return the names of the clients
+ */
+ def names: Vector[String] = this.clients.flatten.flatMap(_.getName).toVector
+
+ def isEmpty: Boolean = this.clients.flatten.isEmpty
+
+ /** Applies the function `f` to all the clients for its side effects
+ * and removes all the clients for which `f([client])` returns false.
+ * This is useful for doing IO with the client and removing clients
+ * with stale sockets.
+ *
+ * @param f the function to apply to all the clients and filter them with
+ */
+ def removeNonSatisfying(f: Client => Boolean): Unit =
+ for i <- this.clients.indices do
+ this.clients(i) match
+ case Some(c) =>
+ if !f(c) then
+ this.clients(i) = None
+ case None =>
+
+ /** Removes clients that have not behaved according to protocol */
+ def removeNonCompliant(): Unit =
+ this.removeNonSatisfying(_.isIntactProtocolWise)
+
+ /** Applies the function f to all clients for its side effects.
+ * If the function throws an exception, the client is removed.
+ * Probably a more concise alternative to `removeNonSatisfying`,
+ * but might catch exceptions unintentionally.
+ *
+ * @param f the function to apply for its side effects to each client
+ */
+ def mapAndRemove(f: Client => Unit): Unit =
+ this.removeNonSatisfying(c => Try(f(c)).isSuccess)