Skip to content

Commit

Permalink
add a stats endpoint
Browse files Browse the repository at this point in the history
  • Loading branch information
pschichtel committed Oct 7, 2024
1 parent a3c84de commit daff178
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 13 deletions.
22 changes: 20 additions & 2 deletions app/controllers/Ld56C2Controller.scala
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,15 @@ import org.apache.pekko.stream.Materializer
import play.api.Logger
import play.api.libs.json.{Format, JsError, JsObject, JsResult, JsString, JsValue, Json}
import play.api.libs.streams.ActorFlow
import play.api.mvc.{ControllerComponents, WebSocket}
import play.api.mvc.{AbstractController, AnyContent, ControllerComponents, WebSocket}

import java.net.InetAddress
import java.time.{Duration, Instant}
import java.util.UUID
import java.util.concurrent.{ConcurrentHashMap, ConcurrentMap}
import scala.collection.mutable.ArrayBuffer
import scala.concurrent.Future
import scala.jdk.CollectionConverters.CollectionHasAsScala
import scala.math.Ordering.Implicits.infixOrderingOps

private val logger = Logger(classOf[Ld56C2Controller])
Expand Down Expand Up @@ -64,12 +66,27 @@ object JoinerMessage {
implicit val joinerFormat: Format[JoinerMessage] = Json.format
}

final case class StatsResponse(servers: Int, latestServer: Option[Instant], players: Int, latestPlayer: Option[Instant])
object StatsResponse {
implicit val format: Format[StatsResponse] = Json.format
}

final case class GameHost(id: UUID, playerCount: Int, lastUpdated: Instant, inceptionTime: Instant)

class Ld56C2Controller(cc: ControllerComponents)(implicit system: ActorSystem, mat: Materializer) {
class Ld56C2Controller(cc: ControllerComponents)(implicit system: ActorSystem, mat: Materializer) extends AbstractController(cc) {
private val hosterConnections = ConcurrentHashMap[UUID, ActorRef]()
private val joinerConnections = ConcurrentHashMap[UUID, ActorRef]()
private val hosts = ConcurrentHashMap[UUID, GameHost]()
private var lastJoinTime: Instant = _

def stats() = Action.async { request =>
val gameHosts = hosts.values().asScala.toVector
val latestHost =
if (hosts.isEmpty) None
else Some(gameHosts.map(_.inceptionTime).max)

Future.successful(Ok(Json.toJson(StatsResponse(gameHosts.length, latestHost, gameHosts.map(_.playerCount).sum, Option(lastJoinTime)))))
}

def signalHost(id: String) = WebSocket.accept[String, String] { request =>
val clientId = UUID.fromString(id)
Expand All @@ -78,6 +95,7 @@ class Ld56C2Controller(cc: ControllerComponents)(implicit system: ActorSystem, m

def signalJoin(id: String) = WebSocket.accept[String, String] { request =>
val clientId = UUID.fromString(id)
lastJoinTime = Instant.now()
ActorFlow.actorRef { out => Props(JoinHandler(out, hosterConnections, joinerConnections, clientId, request.connection.remoteAddress, hosts)) }
}
}
Expand Down
23 changes: 12 additions & 11 deletions conf/routes
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,19 @@
# ~~~~

# Home page
GET / controllers.MainController.index()
GET /blog controllers.BlogController.firstBlogPage()
GET /blog/:service/:id controllers.BlogController.showPost(service: String, id: Long)
GET /projects controllers.MainController.projects()
GET /project/:jam/:slug controllers.MainController.project(jam: String, slug: String)
GET /about controllers.MainController.about()
GET /search controllers.MainController.search(query: String)
GET / controllers.MainController.index()
GET /blog controllers.BlogController.firstBlogPage()
GET /blog/:service/:id controllers.BlogController.showPost(service: String, id: Long)
GET /projects controllers.MainController.projects()
GET /project/:jam/:slug controllers.MainController.project(jam: String, slug: String)
GET /about controllers.MainController.about()
GET /search controllers.MainController.search(query: String)

# Map static resources from the /public folder to the /assets URL path
GET /assets/*file controllers.Assets.versioned(path="/public", file: Asset)
GET /assets/*file controllers.Assets.versioned(path="/public", file: Asset)

GET /dev controllers.MainController.dev()
GET /dev controllers.MainController.dev()

GET /ld56/signal/:id/host controllers.Ld56C2Controller.signalHost(id)
GET /ld56/signal/:id/join controllers.Ld56C2Controller.signalJoin(id)
GET /ld56/signal/:id/host controllers.Ld56C2Controller.signalHost(id)
GET /ld56/signal/:id/join controllers.Ld56C2Controller.signalJoin(id)
GET /ld56/stats controllers.Ld56C2Controller.stats()

0 comments on commit daff178

Please sign in to comment.