Thomas Dy 10 лет назад
Родитель
Сommit
f59da4c461
7 измененных файлов с 88 добавлено и 8 удалено
  1. 29 0
      app/controllers/Cards.scala
  2. 31 0
      app/models/Card.scala
  3. 1 3
      app/models/Taboo.scala
  4. 4 0
      build.sbt
  5. 4 5
      conf/application.conf
  6. 17 0
      conf/evolutions/default/1.sql
  7. 2 0
      conf/routes

+ 29 - 0
app/controllers/Cards.scala

@@ -0,0 +1,29 @@
+package controllers
+
+import play.api._
+import play.api.mvc._
+
+import play.api.data._
+import play.api.data.Forms._
+import play.api.libs.json._
+
+import models._
+
+object Cards extends Controller {
+
+  val cardForm = Form(mapping(
+    "word" -> text,
+    "taboos" -> seq(text).transform(_.toSet, (set: Set[String]) => set.toSeq)
+  )(Card.apply)(Card.unapply))
+
+  def add = Action(parse.json) { implicit request =>
+    cardForm.bindFromRequest.fold(
+      { case error => BadRequest("invalid format") },
+      { case card =>
+        Card.add(card)
+        Ok("ok")
+      }
+    )
+  }
+
+}

+ 31 - 0
app/models/Card.scala

@@ -1,6 +1,10 @@
 package models
 
+import anorm._
+import anorm.SqlParser._
+import play.api.db._
 import play.api.libs.json._
+import play.api.Play.current
 
 object Card {
   implicit val writes = new Writes[Card] {
@@ -9,8 +13,35 @@ object Card {
       "taboo" -> o.taboo
     )
   }
+
+  def add(card: Card) = DB.withTransaction { implicit c =>
+    val id = SQL("insert into words values (default, {word})")
+      .on('word -> card.word)
+      .executeInsert()
+    id.map { id =>
+      card.taboo.map { word =>
+        SQL("insert into taboo values (default, {id}, {word})")
+          .on('id -> id, 'word -> word)
+          .executeInsert()
+      }
+    }
+  }
+
+  def getRandom() = DB.withConnection { implicit c =>
+    SQL("""
+      with rand as (
+        select * from words offset random() * (select count(*) from words) limit 1
+      )
+      select rand.word as word, taboo.word as taboo from taboo, rand where word_id = rand.id
+    """)
+    .list(str("word") ~ str("taboo") map flatten)
+    .groupBy(_._1)
+    .map { case (word, taboos) => Card(word, taboos.map(_._2).toSet) }
+    .head
+  }
 }
 
+
 case class Card(word: String, taboo: Set[String]) {
 
   def isTaboo(text: String) = {

+ 1 - 3
app/models/Taboo.scala

@@ -142,7 +142,7 @@ class TabooGame(val chatActor: ActorRef) extends Actor {
       self ! NextCard
 
     case NextCard =>
-      val card = randomCard()
+      val card = Card.getRandom()
       roundActor ! card
 
       val message = Json.obj(
@@ -198,8 +198,6 @@ class TabooGame(val chatActor: ActorRef) extends Actor {
 
   def player = round.get.team.player
 
-  def randomCard() = Card("test", Set("a", "b", "c", "d", "e"))
-
   def announceStatus(kind: String = "status", user: String = "*GM") {
     chatActor ! Announce(Json.obj(
       "kind" -> kind,

+ 4 - 0
build.sbt

@@ -4,4 +4,8 @@ name := "gamenchat"
 
 version := "1.0"
 
+libraryDependencies ++= Seq(jdbc, anorm)
+
+libraryDependencies += "postgresql" % "postgresql" % "9.1-901.jdbc4"
+
 playScalaSettings

+ 4 - 5
conf/application.conf

@@ -14,14 +14,13 @@ application.secret="fXYT0c[h_gT_ZtlDbpJESb=22p;R62HO5nvwgN3RI<3ZsIVu04UsP;HiMeFb
 # global=Global
 
 # Database configuration
-# ~~~~~ 
+# ~~~~~
 # You can declare as many datasources as you want.
 # By convention, the default datasource is named `default`
 #
-# db.default.driver=org.h2.Driver
-# db.default.url="jdbc:h2:mem:play"
-# db.default.user=sa
-# db.default.password=""
+db.default.driver=org.postgresql.Driver
+db.default.url="jdbc:postgresql:gamenchat"
+db.default.user=postgres
 
 # Evolutions
 # ~~~~~

+ 17 - 0
conf/evolutions/default/1.sql

@@ -0,0 +1,17 @@
+# --- !Ups
+
+CREATE TABLE words (
+  id serial PRIMARY KEY,
+  word text NOT NULL
+);
+
+CREATE TABLE taboo (
+  id serial PRIMARY KEY,
+  word_id integer NOT NULL REFERENCES words(id),
+  word text NOT NULL
+);
+
+# --- !Downs
+
+DROP TABLE taboo;
+DROP TABLE words;

+ 2 - 0
conf/routes

@@ -7,5 +7,7 @@ GET     /                                controllers.Application.index
 GET     /room/chat                       controllers.Application.chat(username)
 GET     /jsRoutes                        controllers.Application.javascriptRoutes
 
+POST    /cards                           controllers.Cards.add
+
 # Map static resources from the /public folder to the /assets URL path
 GET     /assets/*file                    controllers.Assets.at(path="/public", file)