Application.scala 3.2 KB

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