blob: 64874461f2eca2b76bef2fb9823668ef07957959 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
|
package o1game.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)
|