From f4ae44b1d9e7c9a8eca07f8c132cbfbe60ae9883 Mon Sep 17 00:00:00 2001 From: Julian Raufelder Date: Wed, 2 May 2018 19:25:58 +0200 Subject: [PATCH] Enahnce akka implementation --- build.sbt | 2 + src/main/scala/de/htwg/se/sudoku/Sudoku.scala | 11 ++- .../de/htwg/se/sudoku/aview/HttpServer.scala | 73 +++++++++++++++++++ 3 files changed, 82 insertions(+), 4 deletions(-) create mode 100644 src/main/scala/de/htwg/se/sudoku/aview/HttpServer.scala diff --git a/build.sbt b/build.sbt index 55cfbaf..6076c0b 100755 --- a/build.sbt +++ b/build.sbt @@ -20,3 +20,5 @@ libraryDependencies += "com.typesafe.play" %% "play-json" % "2.6.6" libraryDependencies += "ch.qos.logback" % "logback-classic" % "1.2.3" libraryDependencies += "com.typesafe.scala-logging" %% "scala-logging" % "3.7.2" + +libraryDependencies += "com.typesafe.akka" %% "akka-http" % "10.0.0" \ No newline at end of file diff --git a/src/main/scala/de/htwg/se/sudoku/Sudoku.scala b/src/main/scala/de/htwg/se/sudoku/Sudoku.scala index 8e5926a..f873ee4 100755 --- a/src/main/scala/de/htwg/se/sudoku/Sudoku.scala +++ b/src/main/scala/de/htwg/se/sudoku/Sudoku.scala @@ -1,17 +1,19 @@ package de.htwg.se.sudoku -import com.google.inject.Guice -import de.htwg.se.sudoku.aview.Tui +import com.google.inject.{Guice, Injector} import de.htwg.se.sudoku.aview.gui.SwingGui +import de.htwg.se.sudoku.aview.{HttpServer, Tui} import de.htwg.se.sudoku.controller.controllerComponent.ControllerInterface import scala.io.StdIn.readLine object Sudoku { - val injector = Guice.createInjector(new SudokuModule) - val controller = injector.getInstance(classOf[ControllerInterface]) + val injector: Injector = Guice.createInjector(new SudokuModule) + val controller: ControllerInterface = injector.getInstance(classOf[ControllerInterface]) val tui = new Tui(controller) val gui = new SwingGui(controller) + val webserver = new HttpServer(controller) + controller.createNewGrid def main(args: Array[String]): Unit = { @@ -21,5 +23,6 @@ object Sudoku { input = readLine() tui.processInputLine(input) } while (input != "q") + webserver.unbind() } } diff --git a/src/main/scala/de/htwg/se/sudoku/aview/HttpServer.scala b/src/main/scala/de/htwg/se/sudoku/aview/HttpServer.scala new file mode 100644 index 0000000..838b663 --- /dev/null +++ b/src/main/scala/de/htwg/se/sudoku/aview/HttpServer.scala @@ -0,0 +1,73 @@ +package de.htwg.se.sudoku.aview + +import akka.actor.ActorSystem +import akka.http.scaladsl.Http +import akka.http.scaladsl.model.{ContentTypes, HttpEntity, StatusCodes} +import akka.http.scaladsl.server.Directives._ +import akka.http.scaladsl.server.{Route, StandardRoute} +import akka.stream.ActorMaterializer +import de.htwg.se.sudoku.controller.controllerComponent.ControllerInterface + +import scala.concurrent.{ExecutionContextExecutor, Future} + +class HttpServer(controller: ControllerInterface) { + + implicit val system: ActorSystem = ActorSystem("system") + implicit val materializer: ActorMaterializer = ActorMaterializer() + // needed for the future flatMap/onComplete in the end + implicit val executionContext: ExecutionContextExecutor = system.dispatcher + + val route: Route = get { + pathSingleSlash { + complete(HttpEntity(ContentTypes.`text/plain(UTF-8)`, "

HTWG Sudoku

")) + } + pathPrefix("sudoku" / "rest" / "v1") { + pathEnd { + gridtoHtml + } ~ + path("new") { + controller.createEmptyGrid + gridtoHtml + } ~ + path("solve") { + controller.solve + gridtoHtml + } ~ + path("undo") { + controller.undo + gridtoHtml + } ~ + path("redo") { + controller.redo + gridtoHtml + } + } + } ~ + post { + pathPrefix("sudoku" / "rest" / "v1") { + path(Segment) { command => { + if (processInputLine(command)) complete(StatusCodes.NoContent) else complete(StatusCodes.BadRequest) + } + } + } + } + + def gridtoHtml: StandardRoute = { + complete(HttpEntity(ContentTypes.`text/html(UTF-8)`, "

HTWG Sudoku

" + controller.gridToString)) + } + + val bindingFuture: Future[Http.ServerBinding] = Http().bindAndHandle(route, "localhost", 8080) + + def unbind(): Unit = { + bindingFuture + .flatMap(_.unbind()) // trigger unbinding from the port + .onComplete(_ => system.terminate()) // and shutdown when done + } + + def processInputLine(input: String): Boolean = { + input.toList.filter(c => c != ' ').map(c => c.toString.toInt) match { + case row :: column :: value :: Nil => controller.set(row, column, value); true + case _ => false + } + } +}