Application.scala 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. package controllers
  2. import java.util.concurrent.ThreadLocalRandom
  3. import scala.concurrent.{Future, ExecutionContext}
  4. import play.api.libs.json.{JsObject, Json, JsValue}
  5. import play.api.mvc._
  6. import play.mvc.Http
  7. import reactivemongo.api.ReadPreference
  8. import reactivemongo.play.json.collection.JSONCollection
  9. import play.modules.reactivemongo.{
  10. ReactiveMongoApi, ReactiveMongoComponents, MongoController
  11. }
  12. import play.modules.reactivemongo.json._
  13. class Application (val controllerComponents: ControllerComponents, reactiveMongoApi: ReactiveMongoApi)(implicit ec: ExecutionContext)
  14. extends BaseController {
  15. private def worldCollection: JSONCollection = reactiveMongoApi.db.collection[JSONCollection]("world")
  16. private def fortuneCollection: JSONCollection = reactiveMongoApi.db.collection[JSONCollection]("fortune")
  17. private val projection = Json.obj("_id" -> 0)
  18. def getRandomWorlds(queries: Int): Future[Seq[Option[JsObject]]] = {
  19. val futureWorlds: Seq[Future[Option[JsObject]]] = for {
  20. _ <- 1 to queries
  21. } yield { worldCollection
  22. .find(Json.obj("_id" -> getNextRandom), projection)
  23. .one[JsObject]
  24. }
  25. Future.sequence(futureWorlds)
  26. }
  27. def getRandomWorld = {
  28. val futureWorld = worldCollection
  29. .find(Json.obj("id" -> getNextRandom), projection)
  30. .one[JsValue]
  31. futureWorld
  32. }
  33. def getFortunes: Future[List[JsObject]] = {
  34. val futureFortunes: Future[List[JsObject]] =
  35. fortuneCollection.find(Json.obj())
  36. .cursor[JsObject](ReadPreference.primaryPreferred, false).collect[List]()
  37. futureFortunes
  38. }
  39. def updateWorlds(queries: Int): Future[Seq[Option[JsObject]]] = {
  40. val futureWorlds: Future[Seq[Option[JsObject]]] = getRandomWorlds(queries)
  41. val futureNewWorlds: Future[Seq[Option[JsObject]]] = futureWorlds.map( worlds => {
  42. worlds.map(worldOption => {
  43. worldOption.map(world => {
  44. val newWorld = world ++ Json.obj("randomNumber" -> getNextRandom)
  45. worldCollection.update(world, newWorld)
  46. newWorld
  47. })
  48. })
  49. })
  50. futureNewWorlds
  51. }
  52. def getNextRandom: Int = {
  53. ThreadLocalRandom.current().nextInt(TestDatabaseRows) + 1
  54. }
  55. // Semi-Common code between Scala database code
  56. protected val TestDatabaseRows = 10000
  57. def db = Action.async {
  58. getRandomWorld.map { worlds =>
  59. Ok(Json.toJson(worlds.head))
  60. }
  61. }
  62. def queries(countString: String) = Action.async {
  63. val n = parseCount(countString)
  64. getRandomWorlds(n).map { worlds =>
  65. Ok(Json.toJson(worlds))
  66. }
  67. }
  68. private def byMessage(item: JsValue): String = {
  69. (item \ "message").as[String]
  70. }
  71. def fortunes() = Action.async {
  72. getFortunes.map { dbFortunes =>
  73. val appendedFortunes = Json.obj("_id" -> 0, "message" -> "Additional fortune added at request time.") :: dbFortunes
  74. val sorted = appendedFortunes.sortBy(byMessage(_))
  75. Ok(views.html.fortune(sorted))
  76. }
  77. }
  78. def update(queries: String) = Action.async {
  79. val n = parseCount(queries)
  80. updateWorlds(n).map { worlds =>
  81. Ok(Json.toJson(worlds))
  82. }
  83. }
  84. private def parseCount(s: String): Int = {
  85. try {
  86. val parsed = java.lang.Integer.parseInt(s, 10)
  87. parsed match {
  88. case i if i < 1 => 1
  89. case i if i > 500 => 500
  90. case i => i
  91. }
  92. } catch {
  93. case _: NumberFormatException => 1
  94. }
  95. }
  96. }