diff --git a/benchmark/src/main/scala/Benchmark.scala b/benchmark/src/main/scala/Benchmark.scala new file mode 100644 index 0000000000..e4c7ef9e2a --- /dev/null +++ b/benchmark/src/main/scala/Benchmark.scala @@ -0,0 +1,82 @@ +package lila.benchmark + +import annotation.tailrec +import com.google.caliper.Param + +// a caliper benchmark is a class that extends com.google.caliper.Benchmark +// the SimpleScalaBenchmark trait does it and also adds some convenience functionality +class Benchmark extends SimpleScalaBenchmark { + + // to make your benchmark depend on one or more parameterized values, create fields with the name you want + // the parameter to be known by, and add this annotation (see @Param javadocs for more details) + // caliper will inject the respective value at runtime and make sure to run all combinations + @Param(Array("10")) + val length: Int = 0 + + var array: Array[Int] = _ + + override def setUp() { + // set up all your benchmark data here + array = new Array(length) + } + + // the actual code you'd like to test needs to live in one or more methods + // whose names begin with 'time' and which accept a single 'reps: Int' parameter + // the body of the method simply executes the code we wish to measure, 'reps' times + // you can use the 'repeat' method from the SimpleScalaBenchmark trait to repeat with relatively low overhead + // however, if your code snippet is very fast you might want to implement the reps loop directly with 'while' + def timeForeach(reps: Int) = repeat(reps) { + //////////////////// CODE SNIPPET ONE //////////////////// + + var result = 0 + array.foreach { + result += _ + } + result // always have your snippet return a value that cannot easily be "optimized away" + + ////////////////////////////////////////////////////////// + } + + // a second benchmarking code snippet + def timeTFor(reps: Int) = repeat(reps) { + //////////////////// CODE SNIPPET TWO //////////////////// + + var result = 0 + tfor(0)(_ < array.length, _ + 1) { i => + result += array(i) + } + result + + ////////////////////////////////////////////////////////// + } + + // and a third benchmarking code snippet + def timeWhile(reps: Int) = repeat(reps) { + //////////////////// CODE SNIPPET THREE //////////////////// + + var result = 0 + var i = 0 + while (i < array.length) { + result += array(i) + i = i + 1 + } + result + + ////////////////////////////////////////////////////////// + } + + // this is a scala version of Javas "for" loop, we test it against the array.foreach and a plain "while" loop + @tailrec + final def tfor[@specialized T](i: T)(test: T => Boolean, inc: T => T)(f: T => Unit) { + if(test(i)) { + f(i) + tfor(inc(i))(test, inc)(f) + } + } + + override def tearDown() { + // clean up after yourself if required + } + +} + diff --git a/benchmark/src/main/scala/Runner.scala b/benchmark/src/main/scala/Runner.scala new file mode 100644 index 0000000000..e103538e3e --- /dev/null +++ b/benchmark/src/main/scala/Runner.scala @@ -0,0 +1,15 @@ +package lila.benchmark + +import com.google.caliper.{Runner => CaliperRunner} + +object Runner { + + // main method for IDEs, from the CLI you can also run the caliper Runner directly + // or simply use SBTs "run" action + def main(args: Array[String]) { + // we simply pass in the CLI args, + // we could of course also just pass hardcoded arguments to the caliper Runner + CaliperRunner.main(classOf[Benchmark], args: _*) + } + +} diff --git a/benchmark/src/main/scala/SimpleScalaBenchmark.scala b/benchmark/src/main/scala/SimpleScalaBenchmark.scala new file mode 100644 index 0000000000..dffa913977 --- /dev/null +++ b/benchmark/src/main/scala/SimpleScalaBenchmark.scala @@ -0,0 +1,21 @@ +package lila.benchmark + +import com.google.caliper.SimpleBenchmark + +trait SimpleScalaBenchmark extends SimpleBenchmark { + + // helper method to keep the actual benchmarking methods a bit cleaner + // your code snippet should always return a value that cannot be "optimized away" + def repeat[@specialized A](reps: Int)(snippet: => A) = { + val zero = 0.asInstanceOf[A] // looks wierd but does what it should: init w/ default value in a fully generic way + var i = 0 + var result = zero + while (i < reps) { + val res = snippet + if (res != zero) result = res // make result depend on the benchmarking snippet result + i = i + 1 + } + result + } + +} diff --git a/src/main/scala/format/Format.scala b/chess/src/main/scala/format/Format.scala similarity index 82% rename from src/main/scala/format/Format.scala rename to chess/src/main/scala/format/Format.scala index 681e520559..c169972228 100644 --- a/src/main/scala/format/Format.scala +++ b/chess/src/main/scala/format/Format.scala @@ -1,4 +1,4 @@ -package lila +package lila.chess package format trait Format[A] { diff --git a/src/main/scala/format/Visual.scala b/chess/src/main/scala/format/Visual.scala similarity index 98% rename from src/main/scala/format/Visual.scala rename to chess/src/main/scala/format/Visual.scala index 6a6a579373..ae583664d8 100644 --- a/src/main/scala/format/Visual.scala +++ b/chess/src/main/scala/format/Visual.scala @@ -1,4 +1,4 @@ -package lila +package lila.chess package format import model._ diff --git a/src/main/scala/model/Actor.scala b/chess/src/main/scala/model/Actor.scala similarity index 99% rename from src/main/scala/model/Actor.scala rename to chess/src/main/scala/model/Actor.scala index d5aa245b4b..310a4a5d68 100644 --- a/src/main/scala/model/Actor.scala +++ b/chess/src/main/scala/model/Actor.scala @@ -1,4 +1,4 @@ -package lila +package lila.chess package model import Pos.makePos diff --git a/src/main/scala/model/Board.scala b/chess/src/main/scala/model/Board.scala similarity index 99% rename from src/main/scala/model/Board.scala rename to chess/src/main/scala/model/Board.scala index 65f6bc2e9b..a251813e65 100644 --- a/src/main/scala/model/Board.scala +++ b/chess/src/main/scala/model/Board.scala @@ -1,4 +1,4 @@ -package lila +package lila.chess package model import Pos._ diff --git a/src/main/scala/model/Color.scala b/chess/src/main/scala/model/Color.scala similarity index 96% rename from src/main/scala/model/Color.scala rename to chess/src/main/scala/model/Color.scala index 62e6e5fc33..a7135c945c 100644 --- a/src/main/scala/model/Color.scala +++ b/chess/src/main/scala/model/Color.scala @@ -1,4 +1,4 @@ -package lila +package lila.chess package model sealed trait Color { diff --git a/src/main/scala/model/Game.scala b/chess/src/main/scala/model/Game.scala similarity index 90% rename from src/main/scala/model/Game.scala rename to chess/src/main/scala/model/Game.scala index 30f583c795..dd258ec06c 100644 --- a/src/main/scala/model/Game.scala +++ b/chess/src/main/scala/model/Game.scala @@ -1,4 +1,4 @@ -package lila +package lila.chess package model case class Game( diff --git a/src/main/scala/model/History.scala b/chess/src/main/scala/model/History.scala similarity index 98% rename from src/main/scala/model/History.scala rename to chess/src/main/scala/model/History.scala index 042097531c..da36588060 100644 --- a/src/main/scala/model/History.scala +++ b/chess/src/main/scala/model/History.scala @@ -1,4 +1,4 @@ -package lila +package lila.chess package model case class History( diff --git a/src/main/scala/model/Piece.scala b/chess/src/main/scala/model/Piece.scala similarity index 93% rename from src/main/scala/model/Piece.scala rename to chess/src/main/scala/model/Piece.scala index f8d846d438..76471dd327 100644 --- a/src/main/scala/model/Piece.scala +++ b/chess/src/main/scala/model/Piece.scala @@ -1,4 +1,4 @@ -package lila +package lila.chess package model case class Piece(color: Color, role: Role) { diff --git a/src/main/scala/model/Pos.scala b/chess/src/main/scala/model/Pos.scala similarity index 99% rename from src/main/scala/model/Pos.scala rename to chess/src/main/scala/model/Pos.scala index b1554abb16..9a796ec945 100644 --- a/src/main/scala/model/Pos.scala +++ b/chess/src/main/scala/model/Pos.scala @@ -1,4 +1,4 @@ -package lila +package lila.chess package model import scala.math.{ abs, min, max } diff --git a/src/main/scala/model/Role.scala b/chess/src/main/scala/model/Role.scala similarity index 98% rename from src/main/scala/model/Role.scala rename to chess/src/main/scala/model/Role.scala index bd146ba5a1..30a28dd248 100644 --- a/src/main/scala/model/Role.scala +++ b/chess/src/main/scala/model/Role.scala @@ -1,4 +1,4 @@ -package lila +package lila.chess package model import Pos._ diff --git a/src/main/scala/model/Side.scala b/chess/src/main/scala/model/Side.scala similarity index 97% rename from src/main/scala/model/Side.scala rename to chess/src/main/scala/model/Side.scala index 2ca9a0b671..322f5bc553 100644 --- a/src/main/scala/model/Side.scala +++ b/chess/src/main/scala/model/Side.scala @@ -1,4 +1,4 @@ -package lila +package lila.chess package model sealed trait Side { diff --git a/src/main/scala/model/Situation.scala b/chess/src/main/scala/model/Situation.scala similarity index 98% rename from src/main/scala/model/Situation.scala rename to chess/src/main/scala/model/Situation.scala index 656660778d..d3196bd77f 100644 --- a/src/main/scala/model/Situation.scala +++ b/chess/src/main/scala/model/Situation.scala @@ -1,4 +1,4 @@ -package lila +package lila.chess package model case class Situation(board: Board, color: Color) { diff --git a/src/main/scala/model/package.scala b/chess/src/main/scala/model/package.scala similarity index 90% rename from src/main/scala/model/package.scala rename to chess/src/main/scala/model/package.scala index 9d577b1cb7..ced1c44aa8 100644 --- a/src/main/scala/model/package.scala +++ b/chess/src/main/scala/model/package.scala @@ -1,4 +1,4 @@ -package lila +package lila.chess package object model { diff --git a/src/main/scala/package.scala b/chess/src/main/scala/package.scala similarity index 91% rename from src/main/scala/package.scala rename to chess/src/main/scala/package.scala index a9ff097655..0c07f03c38 100644 --- a/src/main/scala/package.scala +++ b/chess/src/main/scala/package.scala @@ -1,9 +1,10 @@ +package lila + import ornicar.scalalib._ -package object lila +package object chess extends OrnicarValidation with OrnicarCommon - //with DateTime with scalaz.Identitys with scalaz.Equals with scalaz.MABs diff --git a/src/test/scala/LilaSpec.scala b/chess/src/test/scala/LilaSpec.scala similarity index 100% rename from src/test/scala/LilaSpec.scala rename to chess/src/test/scala/LilaSpec.scala diff --git a/src/test/scala/format/FormatVisualTest.scala b/chess/src/test/scala/format/FormatVisualTest.scala similarity index 100% rename from src/test/scala/format/FormatVisualTest.scala rename to chess/src/test/scala/format/FormatVisualTest.scala diff --git a/src/test/scala/model/BishopTest.scala b/chess/src/test/scala/model/BishopTest.scala similarity index 100% rename from src/test/scala/model/BishopTest.scala rename to chess/src/test/scala/model/BishopTest.scala diff --git a/src/test/scala/model/BoardTest.scala b/chess/src/test/scala/model/BoardTest.scala similarity index 100% rename from src/test/scala/model/BoardTest.scala rename to chess/src/test/scala/model/BoardTest.scala diff --git a/src/test/scala/model/CastleTest.scala b/chess/src/test/scala/model/CastleTest.scala similarity index 100% rename from src/test/scala/model/CastleTest.scala rename to chess/src/test/scala/model/CastleTest.scala diff --git a/src/test/scala/model/ColorTest.scala b/chess/src/test/scala/model/ColorTest.scala similarity index 100% rename from src/test/scala/model/ColorTest.scala rename to chess/src/test/scala/model/ColorTest.scala diff --git a/src/test/scala/model/KingSafetyTest.scala b/chess/src/test/scala/model/KingSafetyTest.scala similarity index 100% rename from src/test/scala/model/KingSafetyTest.scala rename to chess/src/test/scala/model/KingSafetyTest.scala diff --git a/src/test/scala/model/KingTest.scala b/chess/src/test/scala/model/KingTest.scala similarity index 100% rename from src/test/scala/model/KingTest.scala rename to chess/src/test/scala/model/KingTest.scala diff --git a/src/test/scala/model/KnightTest.scala b/chess/src/test/scala/model/KnightTest.scala similarity index 100% rename from src/test/scala/model/KnightTest.scala rename to chess/src/test/scala/model/KnightTest.scala diff --git a/src/test/scala/model/PawnTest.scala b/chess/src/test/scala/model/PawnTest.scala similarity index 100% rename from src/test/scala/model/PawnTest.scala rename to chess/src/test/scala/model/PawnTest.scala diff --git a/src/test/scala/model/PieceTest.scala b/chess/src/test/scala/model/PieceTest.scala similarity index 100% rename from src/test/scala/model/PieceTest.scala rename to chess/src/test/scala/model/PieceTest.scala diff --git a/src/test/scala/model/PlayTest.scala b/chess/src/test/scala/model/PlayTest.scala similarity index 100% rename from src/test/scala/model/PlayTest.scala rename to chess/src/test/scala/model/PlayTest.scala diff --git a/src/test/scala/model/PosTest.scala b/chess/src/test/scala/model/PosTest.scala similarity index 100% rename from src/test/scala/model/PosTest.scala rename to chess/src/test/scala/model/PosTest.scala diff --git a/src/test/scala/model/QueenTest.scala b/chess/src/test/scala/model/QueenTest.scala similarity index 100% rename from src/test/scala/model/QueenTest.scala rename to chess/src/test/scala/model/QueenTest.scala diff --git a/src/test/scala/model/RookTest.scala b/chess/src/test/scala/model/RookTest.scala similarity index 100% rename from src/test/scala/model/RookTest.scala rename to chess/src/test/scala/model/RookTest.scala diff --git a/src/test/scala/model/SituationTest.scala b/chess/src/test/scala/model/SituationTest.scala similarity index 100% rename from src/test/scala/model/SituationTest.scala rename to chess/src/test/scala/model/SituationTest.scala diff --git a/src/main/scala/Cli.scala b/http/src/main/scala/Cli.scala similarity index 96% rename from src/main/scala/Cli.scala rename to http/src/main/scala/Cli.scala index 27eb6252ce..4fd3f74d21 100644 --- a/src/main/scala/Cli.scala +++ b/http/src/main/scala/Cli.scala @@ -1,4 +1,4 @@ -package lila +package lila.http object Cli { diff --git a/src/main/scala/Env.scala b/http/src/main/scala/Env.scala similarity index 97% rename from src/main/scala/Env.scala rename to http/src/main/scala/Env.scala index 7880d63e0a..73553ac7af 100644 --- a/src/main/scala/Env.scala +++ b/http/src/main/scala/Env.scala @@ -1,4 +1,4 @@ -package lila +package lila.http import repo._ import com.mongodb.casbah.MongoConnection diff --git a/src/main/scala/repo/Game.scala b/http/src/main/scala/repo/Game.scala similarity index 100% rename from src/main/scala/repo/Game.scala rename to http/src/main/scala/repo/Game.scala diff --git a/src/main/scala/repo/GameRepo.scala b/http/src/main/scala/repo/GameRepo.scala similarity index 100% rename from src/main/scala/repo/GameRepo.scala rename to http/src/main/scala/repo/GameRepo.scala diff --git a/src/main/scala/repo/Player.scala b/http/src/main/scala/repo/Player.scala similarity index 100% rename from src/main/scala/repo/Player.scala rename to http/src/main/scala/repo/Player.scala diff --git a/project/Build.scala b/project/Build.scala index c24a6a4850..45e1538833 100644 --- a/project/Build.scala +++ b/project/Build.scala @@ -3,36 +3,72 @@ import Keys._ trait Resolvers { val codahale = "repo.codahale.com" at "http://repo.codahale.com/" - //val twitter = "twitter.com" at "http://maven.twttr.com/" val typesafe = "typesafe.com" at "http://repo.typesafe.com/typesafe/releases/" - val typesafeSnapshot = "typesafe.com snapshots" at "http://repo.typesafe.com/typesafe/snapshots/" + val typesafeS = "typesafe.com snapshots" at "http://repo.typesafe.com/typesafe/snapshots/" val iliaz = "iliaz.com" at "http://scala.iliaz.com/" val sonatype = "sonatype" at "http://oss.sonatype.org/content/repositories/releases" + val sonatypeS = "sonatype snapshots" at "http://oss.sonatype.org/content/repositories/snapshots" } trait Dependencies { - val twitterUtilVersion = "1.12.12" - - val twitterCore = "com.twitter" % "util-core" % twitterUtilVersion - val slf4jNop = "org.slf4j" % "slf4j-nop" % "1.6.4" val scalaz = "org.scalaz" %% "scalaz-core" % "6.0.4" val specs2 = "org.specs2" %% "specs2" % "1.8.2" val redis = "net.debasishg" %% "redisclient" % "2.4.2" val json = "net.liftweb" %% "lift-json" % "2.4-RC1" val casbah = "com.mongodb.casbah" %% "casbah" % "2.1.5-1" val salat = "com.novus" %% "salat-core" % "0.0.8-SNAPSHOT" + val slf4jNop = "org.slf4j" % "slf4j-nop" % "1.6.4" + val instrumenter = "com.google.code.java-allocation-instrumenter" % "java-allocation-instrumenter" % "2.0" + val gson = "com.google.code.gson" % "gson" % "1.7.1" } object ApplicationBuild extends Build with Resolvers with Dependencies { - val lila = Project("lila", file("."), settings = Project.defaultSettings).settings( - libraryDependencies := Seq(scalaz, specs2, redis, json, casbah, salat), - resolvers := Seq(codahale, typesafe, typesafeSnapshot, iliaz, sonatype), + lazy val chess = Project("chess", file("chess"), settings = Project.defaultSettings).settings( + libraryDependencies := Seq(scalaz, specs2), + resolvers := Seq(codahale, sonatype), shellPrompt := ShellPrompt.buildShellPrompt, scalacOptions := Seq("-deprecation", "-unchecked") ) dependsOn (ornicarScalalib) + lazy val http = Project("http", file("http"), settings = Project.defaultSettings).settings( + libraryDependencies := Seq(scalaz, specs2, redis, json, casbah, salat), + resolvers := Seq(codahale, typesafe, typesafeS, iliaz, sonatype), + shellPrompt := ShellPrompt.buildShellPrompt, + scalacOptions := Seq("-deprecation", "-unchecked") + ) dependsOn (chess, ornicarScalalib) + + lazy val benchmark = Project("benchmark", file("benchmark"), settings = Project.defaultSettings).settings( + fork in run := true, + libraryDependencies := Seq(instrumenter, gson), + resolvers := Seq(codahale, sonatype), + shellPrompt := ShellPrompt.buildShellPrompt, + scalacOptions := Seq("-deprecation", "-unchecked"), + // we need to add the runtime classpath as a "-cp" argument + // to the `javaOptions in run`, otherwise caliper + // will not see the right classpath and die with a ConfigurationException + // unfortunately `javaOptions` is a SettingsKey and + // `fullClasspath in Runtime` is a TaskKey, so we need to + // jump through these hoops here in order to + // feed the result of the latter into the former + onLoad in Global ~= { previous => state => + previous { + state get key match { + case None => + // get the runtime classpath, turn into a colon-delimited string + val classPath = Project.runTask(fullClasspath in Runtime, state).get._2.toEither.right.get.files.mkString(":") + // return a state with javaOptionsPatched = true and javaOptions set correctly + Project.extract(state).append(Seq(javaOptions in run ++= Seq("-cp", classPath)), state.put(key, true)) + case Some(_) => state // the javaOptions are already patched + } + } + } + ) dependsOn (chess) + lazy val ornicarScalalib = uri("git://github.com/ornicar/scalalib#1.6") + + // attribute key to prevent circular onLoad hook + val key = AttributeKey[Boolean]("javaOptionsPatched") } object ShellPrompt { diff --git a/routes b/routes new file mode 100644 index 0000000000..ad5d824abb --- /dev/null +++ b/routes @@ -0,0 +1,16 @@ +lichess_move ANY /move/{id} +lichess_say ANY /talk/{id} +lichess_resign ANY /resign/{id} +lichess_abort ANY /abort/{id} +lichess_outoftime ANY /outoftime/{id} +lichess_rematch ANY /rematch/{id} +lichess_force_resignation ANY /force-resign/{id} +lichess_claim_draw ANY /claim-draw/{id} +lichess_offer_draw ANY /offer-draw/{id} +lichess_cancel_draw_offer ANY /cancel-draw-offer/{id} +lichess_accept_draw_offer ANY /accept-draw-offer/{id} +lichess_decline_draw_offer ANY /decline-draw-offer/{id} +lichess_moretime ANY /moretime/{id} +lichess_status ANY /status +lichess_ping ANY /ping +lichess_sync ANY /sync/{id}/{color}/{version}/{playerFullId}