I've been playing around with akka-streams and seem to be stuck with one problem that I cannot find a clean way to handle this in a stream.
I have events coming from 1..* players with their corresponding positions on the board. I want to check if any given time players collide. For this I need to handle group of events of all currently connected players in 1 action. I could only come up with something like this which could work for 2 players and most likely groupby is not needed given events flow sequentially.
import akka.actor.ActorSystem
import akka.stream.ActorMaterializer
import akka.stream.scaladsl.{Flow, Keep, Sink, Source}
import akka.testkit.TestKit
import org.scalatest.{MustMatchers, WordSpecLike}
import scala.concurrent.Await
import scala.concurrent.duration._
case class PlayerPosition(x: Int, y: Int)
case class PlayerState(playerName: String, positions: List[PlayerPosition])
class GameLogicSpec
extends TestKit(ActorSystem("test-filter"))
with WordSpecLike
with MustMatchers {
val psa = PlayerState("A", List(PlayerPosition(0, 1)))
val psb = PlayerState("B", List(PlayerPosition(0, 1)))
implicit val materializer = ActorMaterializer()
"game flow logic" must {
"returns handles collision" in {
val flow =
Flow[PlayerState]
.groupBy(2, _.playerName)
.mergeSubstreams
.sliding(2, 1)
.map(evts =>
evts.size > 1 && evts.head.positions == evts.last.positions)
val gameLogicGraph = Source(List(psa, psb))
.via(flow)
.toMat(Sink.seq[Boolean])(Keep.right)
Await
.result(gameLogicGraph.run(), 10 seconds) must be(
List(true)
)
}
}
}
Ideally I would like the sliding window to publish events for each player evenly in distinct groups depending on the number of players currently connected. Of course the question is if 1 player is producing events faster than others would some kind of throttling would be needed, but for the sake of education I think assumption can be made they publish at the same rate.