Application.scala 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  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. val defaultHeader = Http.HeaderNames.SERVER -> "Play Framework"
  16. private def worldCollection: JSONCollection = reactiveMongoApi.db.collection[JSONCollection]("world")
  17. private def fortuneCollection: JSONCollection = reactiveMongoApi.db.collection[JSONCollection]("fortune")
  18. private val projection = Json.obj("_id" -> 0)
  19. def getRandomWorlds(queries: Int): Future[Seq[Option[JsObject]]] = {
  20. val futureWorlds: Seq[Future[Option[JsObject]]] = for {
  21. _ <- 1 to queries
  22. } yield { worldCollection
  23. .find(Json.obj("_id" -> getNextRandom), projection)
  24. .one[JsObject]
  25. }
  26. Future.sequence(futureWorlds)
  27. }
  28. def getRandomWorld = {
  29. val futureWorld = worldCollection
  30. .find(Json.obj("id" -> getNextRandom), projection)
  31. .one[JsValue]
  32. futureWorld
  33. }
  34. def getFortunes: Future[List[JsObject]] = {
  35. val futureFortunes: Future[List[JsObject]] =
  36. fortuneCollection.find(Json.obj())
  37. .cursor[JsObject](ReadPreference.primaryPreferred, false).collect[List]()
  38. futureFortunes
  39. }
  40. def updateWorlds(queries: Int): Future[Seq[Option[JsObject]]] = {
  41. val futureWorlds: Future[Seq[Option[JsObject]]] = getRandomWorlds(queries)
  42. val futureNewWorlds: Future[Seq[Option[JsObject]]] = futureWorlds.map( worlds => {
  43. worlds.map(worldOption => {
  44. worldOption.map(world => {
  45. val newWorld = world ++ Json.obj("randomNumber" -> getNextRandom)
  46. worldCollection.update(world, newWorld)
  47. newWorld
  48. })
  49. })
  50. })
  51. futureNewWorlds
  52. }
  53. def getNextRandom: Int = {
  54. ThreadLocalRandom.current().nextInt(TestDatabaseRows) + 1
  55. }
  56. case class HelloWorld(message: String)
  57. def getJsonMessage = Action {
  58. val helloWorld = HelloWorld(message = "Hello, World!")
  59. Ok(Json.toJson(helloWorld)(Json.writes[HelloWorld])).withHeaders(defaultHeader)
  60. }
  61. val plaintext = Action {
  62. Ok("Hello, World!").withHeaders(defaultHeader).as("text/plain")
  63. }
  64. // Semi-Common code between Scala database code
  65. protected val TestDatabaseRows = 10000
  66. def doDb = Action.async {
  67. getRandomWorld.map { worlds =>
  68. Ok(Json.toJson(worlds.head)).withHeaders(defaultHeader)
  69. }
  70. }
  71. def queries(countString: String) = Action.async {
  72. val n = parseCount(countString)
  73. getRandomWorlds(n).map { worlds =>
  74. Ok(Json.toJson(worlds)).withHeaders(defaultHeader)
  75. }
  76. }
  77. private def byMessage(item: JsValue): String = {
  78. (item \ "message").as[String]
  79. }
  80. def fortunes() = Action.async {
  81. getFortunes.map { dbFortunes =>
  82. val appendedFortunes = Json.obj("_id" -> 0, "message" -> "Additional fortune added at request time.") :: dbFortunes
  83. val sorted = appendedFortunes.sortBy(byMessage(_))
  84. Ok(views.html.fortune(sorted)).withHeaders(defaultHeader).as(HTML)
  85. }
  86. }
  87. def update(queries: String) = Action.async {
  88. val n = parseCount(queries)
  89. updateWorlds(n).map { worlds =>
  90. Ok(Json.toJson(worlds)).withHeaders(defaultHeader)
  91. }
  92. }
  93. private def parseCount(s: String): Int = {
  94. try {
  95. val parsed = java.lang.Integer.parseInt(s, 10)
  96. parsed match {
  97. case i if i < 1 => 1
  98. case i if i > 500 => 500
  99. case i => i
  100. }
  101. } catch {
  102. case _: NumberFormatException => 1
  103. }
  104. }
  105. }