From b0ecc5841e78625b9961a3f430441628d2f4a00f Mon Sep 17 00:00:00 2001 From: Enrico Siboni Date: Mon, 23 Jul 2018 18:29:17 +0200 Subject: [PATCH 001/193] Added messages that GUI can send to GameViewActor notifying for user actions --- .../cwmp/client/view/game/GameViewActor.scala | 35 ++++++++++++++++--- 1 file changed, 31 insertions(+), 4 deletions(-) diff --git a/client/src/main/scala/it/cwmp/client/view/game/GameViewActor.scala b/client/src/main/scala/it/cwmp/client/view/game/GameViewActor.scala index 17257422..de00f1de 100644 --- a/client/src/main/scala/it/cwmp/client/view/game/GameViewActor.scala +++ b/client/src/main/scala/it/cwmp/client/view/game/GameViewActor.scala @@ -1,8 +1,9 @@ package it.cwmp.client.view.game -import akka.actor.{Actor, ActorLogging, Cancellable} +import akka.actor.{Actor, Cancellable} import it.cwmp.client.controller.game.GameEngine -import it.cwmp.client.model.game.impl.CellWorld +import it.cwmp.client.model.game.impl.{CellWorld, Point} +import it.cwmp.utils.Logging import scala.concurrent.duration._ @@ -17,6 +18,22 @@ object GameViewActor { case object UpdateLocalWorld + + /** + * A message stating that an attack has been launched from one point to another + * + * @param from the point from which attack is starting + * @param to the point to which the attack is going + */ + case class AddAttack(from: Point, to: Point) + + /** + * A message stating that an attack has been removed + * + * @param pointOnAttackView the point clicked by the player to remove the attack + */ + case class RemoveAttack(pointOnAttackView: Point) + } import it.cwmp.client.view.game.GameViewActor._ @@ -24,7 +41,7 @@ import it.cwmp.client.view.game.GameViewActor._ /** * @author contributor Enrico Siboni */ -class GameViewActor extends Actor with ActorLogging { +class GameViewActor extends Actor with Logging { private val gameFX: GameFX = GameFX() private val FRAME_RATE: FiniteDuration = 50.millis @@ -54,10 +71,20 @@ class GameViewActor extends Actor with ActorLogging { UpdateLocalWorld)(context.dispatcher) case UpdateLocalWorld => - log.info(s"World to paint: Characters=${tempWorld.characters} Attacks=${tempWorld.attacks} Instant=${tempWorld.instant}") + // log.info(s"World to paint: Characters=${tempWorld.characters} Attacks=${tempWorld.attacks} Instant=${tempWorld.instant}") gameFX.updateWorld(tempWorld) // is that to heavy computation here ??? tempWorld = GameEngine(tempWorld, java.time.Duration.ofMillis(FRAME_RATE.toMillis)) + + case AddAttack(from, to) => + log.info(s"AddAttack from:$from to:$to") + // TODO: convert those points (implementing a utility method in GeometricUtils) in an attack + // TODO: discovering to which cell are near the points provided + + case RemoveAttack(pointOnAttackView) => + log.info(s"RemoveAttack pointOnView:$pointOnAttackView") + // TODO: convert point on attack view to the corresponding tentacle, calculating the distance of this point + // TODO: from the straight line passing through the tentacle "from" and "to" points } } From e63e3a7612ebc3752228230af35197a683871f0f Mon Sep 17 00:00:00 2001 From: Enrico Siboni Date: Mon, 23 Jul 2018 19:00:11 +0200 Subject: [PATCH 002/193] Moved GameViewActor Companion object below class --- .../cwmp/client/view/game/GameViewActor.scala | 63 ++++++++++--------- .../model/game/impl/GeometricUtilsTest.scala | 2 + 2 files changed, 34 insertions(+), 31 deletions(-) diff --git a/client/src/main/scala/it/cwmp/client/view/game/GameViewActor.scala b/client/src/main/scala/it/cwmp/client/view/game/GameViewActor.scala index de00f1de..a6229116 100644 --- a/client/src/main/scala/it/cwmp/client/view/game/GameViewActor.scala +++ b/client/src/main/scala/it/cwmp/client/view/game/GameViewActor.scala @@ -3,41 +3,11 @@ package it.cwmp.client.view.game import akka.actor.{Actor, Cancellable} import it.cwmp.client.controller.game.GameEngine import it.cwmp.client.model.game.impl.{CellWorld, Point} +import it.cwmp.client.view.game.GameViewActor._ import it.cwmp.utils.Logging import scala.concurrent.duration._ -object GameViewActor { - def apply(): GameViewActor = new GameViewActor - - case object ShowGUI - - case object HideGUI - - case class NewWorld(world: CellWorld) - - case object UpdateLocalWorld - - - /** - * A message stating that an attack has been launched from one point to another - * - * @param from the point from which attack is starting - * @param to the point to which the attack is going - */ - case class AddAttack(from: Point, to: Point) - - /** - * A message stating that an attack has been removed - * - * @param pointOnAttackView the point clicked by the player to remove the attack - */ - case class RemoveAttack(pointOnAttackView: Point) - -} - -import it.cwmp.client.view.game.GameViewActor._ - /** * @author contributor Enrico Siboni */ @@ -88,3 +58,34 @@ class GameViewActor extends Actor with Logging { // TODO: from the straight line passing through the tentacle "from" and "to" points } } + +/** + * Companion object, containing actor messages + */ +object GameViewActor { + def apply(): GameViewActor = new GameViewActor + + case object ShowGUI + + case object HideGUI + + case class NewWorld(world: CellWorld) + + case object UpdateLocalWorld + + + /** + * A message stating that an attack has been launched from one point to another + * + * @param from the point from which attack is starting + * @param to the point to which the attack is going + */ + case class AddAttack(from: Point, to: Point) + + /** + * A message stating that an attack has been removed + * + * @param pointOnAttackView the point clicked by the player to remove the attack + */ + case class RemoveAttack(pointOnAttackView: Point) +} diff --git a/client/src/test/scala/it/cwmp/client/model/game/impl/GeometricUtilsTest.scala b/client/src/test/scala/it/cwmp/client/model/game/impl/GeometricUtilsTest.scala index e1666539..7b61ed2c 100644 --- a/client/src/test/scala/it/cwmp/client/model/game/impl/GeometricUtilsTest.scala +++ b/client/src/test/scala/it/cwmp/client/model/game/impl/GeometricUtilsTest.scala @@ -6,6 +6,8 @@ import org.scalatest.{Matchers, PropSpec} /** * A test class for GeometricUtils + * + * @author Enrico Siboni */ class GeometricUtilsTest extends PropSpec with PropertyChecks with Matchers { From 9d20595075db474f9781d3d15ef107a8acacd1fd Mon Sep 17 00:00:00 2001 From: Davide Borficchia Date: Tue, 24 Jul 2018 11:01:03 +0200 Subject: [PATCH 003/193] Iniziata rifattorizzazione Authentication DAO --- .../AuthenticationServiceVerticle.scala | 7 +- .../authentication/StorageLoaclDAO.scala | 147 ++++++++++++++++++ .../authentication/storage/StorageAsync.scala | 112 ------------- 3 files changed, 150 insertions(+), 116 deletions(-) create mode 100644 services/authentication/src/main/scala/it/cwmp/services/authentication/StorageLoaclDAO.scala delete mode 100644 services/authentication/src/main/scala/it/cwmp/services/authentication/storage/StorageAsync.scala diff --git a/services/authentication/src/main/scala/it/cwmp/services/authentication/AuthenticationServiceVerticle.scala b/services/authentication/src/main/scala/it/cwmp/services/authentication/AuthenticationServiceVerticle.scala index bde9a54f..158d3153 100644 --- a/services/authentication/src/main/scala/it/cwmp/services/authentication/AuthenticationServiceVerticle.scala +++ b/services/authentication/src/main/scala/it/cwmp/services/authentication/AuthenticationServiceVerticle.scala @@ -2,7 +2,6 @@ package it.cwmp.services.authentication import io.vertx.core.Handler import io.vertx.scala.ext.web.{Router, RoutingContext} -import it.cwmp.services.authentication.storage.StorageAsync import it.cwmp.utils.{HttpUtils, Logging, VertxServer} import scala.concurrent.Future @@ -16,7 +15,7 @@ case class AuthenticationServiceVerticle() extends VertxServer with Logging { import it.cwmp.services.authentication.ServerParameters._ - private var storageFuture: Future[StorageAsync] = _ + private var storageFuture: Future[StorageDAO] = _ override protected def initRouter(router: Router): Unit = { router post API_SIGNUP handler handlerSignup @@ -26,8 +25,8 @@ case class AuthenticationServiceVerticle() extends VertxServer with Logging { } override protected def initServer: Future[_] = { - val storage = StorageAsync() - storageFuture = storage.init().map(_ => storage) + val storage = StorageLoaclDAO() + storageFuture = storage.initialize().map(_ => storage) storageFuture } diff --git a/services/authentication/src/main/scala/it/cwmp/services/authentication/StorageLoaclDAO.scala b/services/authentication/src/main/scala/it/cwmp/services/authentication/StorageLoaclDAO.scala new file mode 100644 index 00000000..c95b5ea9 --- /dev/null +++ b/services/authentication/src/main/scala/it/cwmp/services/authentication/StorageLoaclDAO.scala @@ -0,0 +1,147 @@ +package it.cwmp.services.authentication + +import com.typesafe.scalalogging.Logger +import io.vertx.core.json.JsonArray +import it.cwmp.services.authentication.StorageLoaclDAO._ +import it.cwmp.utils.{VertxInstance, VertxJDBC} +import scala.concurrent._ + +trait StorageDAO { + + def signupFuture(username: String, password: String): Future[Unit] + + def signoutFuture(username: String): Future[Unit] + + def loginFuture(username: String, password: String): Future[Unit] + + def existsFuture(username: String): Future[Unit] +} + +case class StorageLoaclDAO(override val configurationPath: String = "authentication/database.json") extends StorageDAO with VertxInstance with VertxJDBC { + private var notInitialized = true + + def initialize(): Future[Unit] = { + logger.info("Initializing RoomLocalDAO...") + + (for ( + connection <- openConnection(); + result <- connection.executeFuture( + createStorageTableSql) + ) yield { + result + notInitialized = false + }).closeConnections + } + + + override def signupFuture(usernameP: String, passwordP: String): Future[Unit] = { + logger.debug(s"signup() username:$usernameP, password:$passwordP") + (for ( + // Controllo l'input + username <- Option(usernameP) if username.nonEmpty; + password <- Option(passwordP) if password.nonEmpty; + future <- checkInitialization(notInitialized) + ) yield { + (for ( + // Eseguo operazioni sul db in maniera sequenziale + connection <- openConnection(); + _ <- connection.updateWithParamsFuture( + insertNewUserSql, new JsonArray().add(username).add(password).add("SALT")) + ) yield { + logger.debug("inizialized") + }).closeConnections + }).getOrElse(Future.failed(new IllegalArgumentException())) + } + + + override def signoutFuture(usernameP: String): Future[Unit] = { + logger.debug(s"signoutFuture() username:$usernameP") + (for ( + // Controllo l'input + username <- Option(usernameP) if username.nonEmpty + ) yield { + (for ( + // Eseguo operazioni sul db in maniera sequenziale + connection <- openConnection(); + result <- connection.updateWithParamsFuture( + signoutUserSql, new JsonArray().add(username)) if result.getUpdated > 0 + ) yield ()).closeConnections + }).getOrElse(Future.failed(new IllegalArgumentException())) + } + + + override def loginFuture(usernameP: String, passwordP: String): Future[Unit] = { + logger.debug(s"loginFuture() username:$usernameP, password:$passwordP") + (for ( + // Controllo l'input + username <- Option(usernameP) if username.nonEmpty; + password <- Option(passwordP) if password.nonEmpty + ) yield { + (for ( + // Eseguo operazioni sul db in maniera sequenziale + connection <- openConnection(); + result <- connection.queryWithParamsFuture( + loginUserSql, new JsonArray().add(username).add(password)) if result.getResults.nonEmpty + ) yield ()).closeConnections + }).getOrElse(Future.failed(new IllegalArgumentException())) + } + + + override def existsFuture(usernameP: String): Future[Unit] = { + logger.debug(s"existsFuture() username:$usernameP") + (for ( + // Controllo l'input + username <- Option(usernameP) if username.nonEmpty + ) yield { + (for ( + // Eseguo operazioni sul db in maniera sequenziale + connection <- openConnection(); + result <- connection.queryWithParamsFuture( + existFutureUserSql, new JsonArray().add(username)) if result.getResults.nonEmpty + ) yield ()).closeConnections + }).getOrElse(Future.failed(new IllegalArgumentException())) + } + + +} + +object StorageLoaclDAO { + private val logger: Logger = Logger[StorageLoaclDAO] + private val FIELD_AUTH_USERNAME = "auth_username" + private val FIELD_AUTH_PASSWORD = "auth_password" + private val FIELD_AUTH_SALT = "auth_salt" + + /** + * Utility method to check if DAO is initialized + */ + private def checkInitialization(notInitialized: Boolean): Option[Future[Unit]] = { + //if (notInitialized) Future.failed(new IllegalStateException("Not initialized, you should first call initialize()")) + if (notInitialized) None //TODO implementare eccezione della riga sopra + else Some(Future.successful(Unit)) + } + + private val createStorageTableSql = + s""" + CREATE TABLE IF NOT EXISTS authorization ( + $FIELD_AUTH_USERNAME VARCHAR(45) NOT NULL, + $FIELD_AUTH_PASSWORD VARCHAR(45) NOT NULL, + $FIELD_AUTH_SALT CHAR(32) NOT NULL, + PRIMARY KEY ($FIELD_AUTH_USERNAME)) + """ + + private val insertNewUserSql = "INSERT INTO authorization VALUES (?, ?, ?)" + private val signoutUserSql = "DELETE FROM authorization WHERE auth_username = ?" + private val loginUserSql = + s""" + SELECT * + FROM authorization + WHERE $FIELD_AUTH_USERNAME = ? + AND $FIELD_AUTH_PASSWORD = ? + """ + private val existFutureUserSql = + s""" + SELECT * + FROM authorization + WHERE $FIELD_AUTH_USERNAME = ? + """ +} \ No newline at end of file diff --git a/services/authentication/src/main/scala/it/cwmp/services/authentication/storage/StorageAsync.scala b/services/authentication/src/main/scala/it/cwmp/services/authentication/storage/StorageAsync.scala deleted file mode 100644 index 0c3ac756..00000000 --- a/services/authentication/src/main/scala/it/cwmp/services/authentication/storage/StorageAsync.scala +++ /dev/null @@ -1,112 +0,0 @@ -package it.cwmp.services.authentication.storage - -import io.vertx.core.json.JsonArray -import it.cwmp.utils.{VertxInstance, VertxJDBC} - -import scala.concurrent._ - -trait StorageAsync { - - def init(): Future[Unit] - - def signupFuture(username: String, password: String): Future[Unit] - - def signoutFuture(username: String): Future[Unit] - - def loginFuture(username: String, password: String): Future[Unit] - - def existsFuture(username: String): Future[Unit] -} - -object StorageAsync { - - def apply(): StorageAsync = new StorageAsyncImpl() - - def apply(configurationPath: String): StorageAsync = new StorageAsyncImpl(configurationPath) - - class StorageAsyncImpl(override val configurationPath: String = "authentication/database.json") extends StorageAsync with VertxInstance with VertxJDBC { - - override def init(): Future[Unit] = - (for ( - connection <- openConnection(); - result <- connection.executeFuture( - """ - CREATE TABLE IF NOT EXISTS authorization ( - auth_username VARCHAR(45) NOT NULL, - auth_password VARCHAR(45) NOT NULL, - auth_salt CHAR(32) NOT NULL, - PRIMARY KEY (auth_username)) - """) - ) yield result).closeConnections - - override def signupFuture(usernameP: String, passwordP: String): Future[Unit] = - (for ( - // Controllo l'input - username <- Option(usernameP) if username.nonEmpty; - password <- Option(passwordP) if password.nonEmpty - ) yield { - (for ( - // Eseguo operazioni sul db in maniera sequenziale - connection <- openConnection(); - _ <- connection.updateWithParamsFuture( - """ - INSERT INTO authorization values (?, ?, ?) - """, new JsonArray().add(username).add(password).add("SALT")) - ) yield ()).closeConnections - }).getOrElse(Future.failed(new IllegalArgumentException())) - - override def signoutFuture(usernameP: String): Future[Unit] = - (for ( - // Controllo l'input - username <- Option(usernameP) if username.nonEmpty - ) yield { - (for ( - // Eseguo operazioni sul db in maniera sequenziale - connection <- openConnection(); - result <- connection.updateWithParamsFuture( - """ - DELETE FROM authorization WHERE auth_username = ? - """, new JsonArray().add(username)) if result.getUpdated > 0 - ) yield ()).closeConnections - }).getOrElse(Future.failed(new IllegalArgumentException())) - - override def loginFuture(usernameP: String, passwordP: String): Future[Unit] = - (for ( - // Controllo l'input - username <- Option(usernameP) if username.nonEmpty; - password <- Option(passwordP) if password.nonEmpty - ) yield { - (for ( - // Eseguo operazioni sul db in maniera sequenziale - connection <- openConnection(); - result <- connection.queryWithParamsFuture( - """ - SELECT * - FROM authorization - WHERE auth_username = ? - AND auth_password = ? - """, new JsonArray().add(username).add(password)) if result.getResults.nonEmpty - ) yield ()).closeConnections - }).getOrElse(Future.failed(new IllegalArgumentException())) - - - override def existsFuture(usernameP: String): Future[Unit] = - (for ( - // Controllo l'input - username <- Option(usernameP) if username.nonEmpty - ) yield { - (for ( - // Eseguo operazioni sul db in maniera sequenziale - connection <- openConnection(); - result <- connection.queryWithParamsFuture( - """ - SELECT * - FROM authorization - WHERE auth_username = ? - """, new JsonArray().add(username)) if result.getResults.nonEmpty - ) yield ()).closeConnections - }).getOrElse(Future.failed(new IllegalArgumentException())) - - } - -} \ No newline at end of file From fc1d46914bf4eb540b932853181c8acc0ce31ed7 Mon Sep 17 00:00:00 2001 From: Davide Borficchia Date: Tue, 24 Jul 2018 11:03:02 +0200 Subject: [PATCH 004/193] rifattorizzato test --- ...{StorageAsyncTest.scala => StorageLocalDAOTest.scala} | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) rename services/authentication/src/test/scala/it/cwmp/services/authentication/storage/{StorageAsyncTest.scala => StorageLocalDAOTest.scala} (92%) diff --git a/services/authentication/src/test/scala/it/cwmp/services/authentication/storage/StorageAsyncTest.scala b/services/authentication/src/test/scala/it/cwmp/services/authentication/storage/StorageLocalDAOTest.scala similarity index 92% rename from services/authentication/src/test/scala/it/cwmp/services/authentication/storage/StorageAsyncTest.scala rename to services/authentication/src/test/scala/it/cwmp/services/authentication/storage/StorageLocalDAOTest.scala index 84f17419..e9d00891 100644 --- a/services/authentication/src/test/scala/it/cwmp/services/authentication/storage/StorageAsyncTest.scala +++ b/services/authentication/src/test/scala/it/cwmp/services/authentication/storage/StorageLocalDAOTest.scala @@ -1,19 +1,20 @@ package it.cwmp.services.authentication.storage +import it.cwmp.services.authentication.{StorageDAO, StorageLoaclDAO} import it.cwmp.testing.{FutureMatchers, VertxTest} import it.cwmp.utils.Utils import org.scalatest.{BeforeAndAfterEach, Matchers} import scala.concurrent.Future -class StorageAsyncTest extends VertxTest with Matchers with FutureMatchers with BeforeAndAfterEach { +class StorageLocalDAOTest extends VertxTest with Matchers with FutureMatchers with BeforeAndAfterEach { - var storageFuture: Future[StorageAsync] = _ + var storageFuture: Future[StorageDAO] = _ override def beforeEach(): Unit = { super.beforeEach() - val storage = StorageAsync() - storageFuture = storage.init().map(_ => storage) + val storage = StorageLoaclDAO() + storageFuture = storage.initialize().map(_ => storage) } describe("Storage manager") { From 4fcf17598be7cec829350fad4fe48df82eefd98b Mon Sep 17 00:00:00 2001 From: Davide Borficchia Date: Tue, 24 Jul 2018 13:08:52 +0200 Subject: [PATCH 005/193] Aggiunta documentazione --- .../authentication/StorageLoaclDAO.scala | 45 +++++++++++++++---- 1 file changed, 37 insertions(+), 8 deletions(-) diff --git a/services/authentication/src/main/scala/it/cwmp/services/authentication/StorageLoaclDAO.scala b/services/authentication/src/main/scala/it/cwmp/services/authentication/StorageLoaclDAO.scala index c95b5ea9..fef10f0e 100644 --- a/services/authentication/src/main/scala/it/cwmp/services/authentication/StorageLoaclDAO.scala +++ b/services/authentication/src/main/scala/it/cwmp/services/authentication/StorageLoaclDAO.scala @@ -6,17 +6,52 @@ import it.cwmp.services.authentication.StorageLoaclDAO._ import it.cwmp.utils.{VertxInstance, VertxJDBC} import scala.concurrent._ +/** + * Trait che descrive l' Authentication Data Access Object + * + * @author Davide Borficchia + */ trait StorageDAO { - + /** + * Registra un nuovo utente all'interno dello storage + * + * @param username username del nuovo utente + * @param password password del nuovo utente + * @return ritorna un Future vuoto + */ def signupFuture(username: String, password: String): Future[Unit] + /** + * Fa sloggare un utente che ha precedentemente fatto login + * + * @param username username dell'utente che si vuole fare sloggare + * @return ritorna un Future vuoto + */ def signoutFuture(username: String): Future[Unit] + /** + * Permette di far loggare un utente precedentemente registrato nel sistema + * + * @param username username dell'utente + * @param password password dell'utente + * @return ritorna un Future vuoto + */ def loginFuture(username: String, password: String): Future[Unit] + /** + * controlla se un utente è presente nel sistema + * + * @param username utente da controllare + * @return ritorna un Future vuoto + */ def existsFuture(username: String): Future[Unit] } +/** + * Wrapper per accedere allo storage Vertex locale per l'autenticazione + * + * @author Davide Borficchia + */ case class StorageLoaclDAO(override val configurationPath: String = "authentication/database.json") extends StorageDAO with VertxInstance with VertxJDBC { private var notInitialized = true @@ -33,7 +68,6 @@ case class StorageLoaclDAO(override val configurationPath: String = "authenticat }).closeConnections } - override def signupFuture(usernameP: String, passwordP: String): Future[Unit] = { logger.debug(s"signup() username:$usernameP, password:$passwordP") (for ( @@ -53,7 +87,6 @@ case class StorageLoaclDAO(override val configurationPath: String = "authenticat }).getOrElse(Future.failed(new IllegalArgumentException())) } - override def signoutFuture(usernameP: String): Future[Unit] = { logger.debug(s"signoutFuture() username:$usernameP") (for ( @@ -69,7 +102,6 @@ case class StorageLoaclDAO(override val configurationPath: String = "authenticat }).getOrElse(Future.failed(new IllegalArgumentException())) } - override def loginFuture(usernameP: String, passwordP: String): Future[Unit] = { logger.debug(s"loginFuture() username:$usernameP, password:$passwordP") (for ( @@ -86,7 +118,6 @@ case class StorageLoaclDAO(override val configurationPath: String = "authenticat }).getOrElse(Future.failed(new IllegalArgumentException())) } - override def existsFuture(usernameP: String): Future[Unit] = { logger.debug(s"existsFuture() username:$usernameP") (for ( @@ -101,8 +132,6 @@ case class StorageLoaclDAO(override val configurationPath: String = "authenticat ) yield ()).closeConnections }).getOrElse(Future.failed(new IllegalArgumentException())) } - - } object StorageLoaclDAO { @@ -112,7 +141,7 @@ object StorageLoaclDAO { private val FIELD_AUTH_SALT = "auth_salt" /** - * Utility method to check if DAO is initialized + * Utility method per controlloare se il DAO è stato inizializzato */ private def checkInitialization(notInitialized: Boolean): Option[Future[Unit]] = { //if (notInitialized) Future.failed(new IllegalStateException("Not initialized, you should first call initialize()")) From 22064f853f2b453c38cb6dfdb622e29e99fcd85e Mon Sep 17 00:00:00 2001 From: Enrico Siboni Date: Tue, 24 Jul 2018 14:31:54 +0200 Subject: [PATCH 006/193] - Added methods in GeometricUtils to calculate distance from a straight line and to answer if a point is inside a circumference - Added method tests --- .../model/game/impl/GeometricUtils.scala | 35 +++++++++ .../model/game/impl/GeometricUtilsTest.scala | 71 +++++++++++++++++-- 2 files changed, 99 insertions(+), 7 deletions(-) diff --git a/client/src/main/scala/it/cwmp/client/model/game/impl/GeometricUtils.scala b/client/src/main/scala/it/cwmp/client/model/game/impl/GeometricUtils.scala index 51f0d711..9aa6aa0b 100644 --- a/client/src/main/scala/it/cwmp/client/model/game/impl/GeometricUtils.scala +++ b/client/src/main/scala/it/cwmp/client/model/game/impl/GeometricUtils.scala @@ -76,6 +76,41 @@ object GeometricUtils { (deltaX, deltaY) } + /** + * A method returning the distance of a point from a straight line passing through two points + * + * @param myPoint the point from which to calculate the distance + * @param point1 the first point from which the straight line is passing through + * @param point2 the second point from which the straight line is passing through + * @return the distance of first point from this straight line + */ + def pointDistanceFromStraightLine(myPoint: Point, + point1: Point, + point2: Point): Double = { + val angularCoefficient = GeometricUtils.angularCoefficient(point1, point2) + + if (angularCoefficient.isPosInfinity) Math.abs(myPoint.x - point1.x) // if the straight line is vertical, the distance is the difference from myPoint X and a point on straight line X + else + Math.abs(myPoint.y - (angularCoefficient * myPoint.x + ordinateAtOrigin(point1, point2))) / + Math.sqrt(angularCoefficient.squared + 1) + } + + /** + * A method that says if provided point is inside the circumference with provided center and radius + * + * @param point the point to verify inside circumference + * @param center the center of the circumference + * @param radius the radius of the circumference + * @return true if the point is inside or on the circumference, false otherwise + */ + def isWithinCircumference(point: Point, + center: Point, + radius: Double): Boolean = { + require(radius >= 0, "Circumference radius must be positive") + + (point.x - center.x).squared + (point.y - center.y).squared <= radius.squared + } + /** * A class that makes possible to square numbers * diff --git a/client/src/test/scala/it/cwmp/client/model/game/impl/GeometricUtilsTest.scala b/client/src/test/scala/it/cwmp/client/model/game/impl/GeometricUtilsTest.scala index 7b61ed2c..b13d556d 100644 --- a/client/src/test/scala/it/cwmp/client/model/game/impl/GeometricUtilsTest.scala +++ b/client/src/test/scala/it/cwmp/client/model/game/impl/GeometricUtilsTest.scala @@ -79,7 +79,7 @@ class GeometricUtilsTest extends PropSpec with PropertyChecks with Matchers { assert(GeometricUtils.deltaXYFromFirstPoint(firstPoint, Point(-3, -4), 2.5) == (-1.5, -2)) forAnyTwoPoints { (point1, point2) => - forAll { (distance: Int) => + forAll { (distance: Double) => whenever(distance > 0) { val deltaXY = GeometricUtils.deltaXYFromFirstPoint(point1, point2, distance) @@ -105,18 +105,75 @@ class GeometricUtilsTest extends PropSpec with PropertyChecks with Matchers { } } + property("Method pointDistanceFromStraightLine() should calculate the distance of a point from a straight line " + + "passing through two other points") { + + val myPoint = Point(3, 4) + assert(GeometricUtils.pointDistanceFromStraightLine(myPoint, Point(5, 2), Point(8, 2)) == 2) + + forAnyPoint { myPoint => + forAnyTwoPoints { (point1, point2) => + + if (point1.x == point2.x) { + assert(GeometricUtils.pointDistanceFromStraightLine(myPoint, point1, point2) == Math.abs(point2.x - myPoint.x)) + } else { + val angularCoefficient = GeometricUtils.angularCoefficient(point1, point2) + val distanceFromStraightLine = + Math.abs(myPoint.y.toDouble - (angularCoefficient * myPoint.x.toDouble + GeometricUtils.ordinateAtOrigin(point1, point2))) / + Math.sqrt(angularCoefficient.squared + 1) + + assert(GeometricUtils.pointDistanceFromStraightLine(myPoint, point1, point2) == distanceFromStraightLine) + } + } + } + + } + + property("Method isWithinCircumference() should tell if a point is inside a circumference") { + + val myPoint = Point(1, 1) + val centerPoint = Point(0, 0) + val myRadius = 1 + + intercept[IllegalArgumentException](GeometricUtils.isWithinCircumference(myPoint, centerPoint, -1)) + + assert(!GeometricUtils.isWithinCircumference(myPoint, centerPoint, myRadius)) + assert(GeometricUtils.isWithinCircumference(Point(1, 0), centerPoint, myRadius)) + assert(GeometricUtils.isWithinCircumference(myPoint, centerPoint, 2)) + + forAnyTwoPoints { (myPoint, centerPoint) => + forAll { (radius: Double) => + whenever(radius > 0) { + if ((myPoint.x - centerPoint.x).squared + (myPoint.y - centerPoint.y).squared <= radius.squared) + assert(GeometricUtils.isWithinCircumference(myPoint, centerPoint, radius)) + else + assert(!GeometricUtils.isWithinCircumference(myPoint, centerPoint, radius)) + } + } + } + } + /** - * A property check that should be valid for any two points that satisfy the provided condition + * A property check that should be valid for any two points * * @param test the test to run */ private def forAnyTwoPoints(test: (Point, Point) => Unit): Unit = { - forAll { (x1: Int, y1: Int, x2: Int, y2: Int) => - val firstPoint = Point(x1, y1) - val secondPoint = Point(x2, y2) - - test(firstPoint, secondPoint) + forAnyPoint { firstPoint => + forAnyPoint { secondPoint => + test(firstPoint, secondPoint) + } } } + /** + * A property check that should be valid for any point + * + * @param test the test to run + */ + private def forAnyPoint(test: Point => Unit): Unit = { + forAll { (x1: Int, y1: Int) => + test(Point(x1, y1)) + } + } } From cc95ccddabf0cb4272d13b73f33821b803a2b834 Mon Sep 17 00:00:00 2001 From: Enrico Siboni Date: Tue, 24 Jul 2018 15:04:48 +0200 Subject: [PATCH 007/193] - Added GameViewActor behaviour on reception of AddAttack message - Modified CellView to hold it's radius --- .../cwmp/client/view/game/GameViewActor.scala | 26 ++++++++++++++++--- .../cwmp/client/view/game/ObjectDrawer.scala | 10 +++---- .../client/view/game/model/CellView.scala | 15 +++++------ 3 files changed, 35 insertions(+), 16 deletions(-) diff --git a/client/src/main/scala/it/cwmp/client/view/game/GameViewActor.scala b/client/src/main/scala/it/cwmp/client/view/game/GameViewActor.scala index a6229116..30726b90 100644 --- a/client/src/main/scala/it/cwmp/client/view/game/GameViewActor.scala +++ b/client/src/main/scala/it/cwmp/client/view/game/GameViewActor.scala @@ -2,8 +2,9 @@ package it.cwmp.client.view.game import akka.actor.{Actor, Cancellable} import it.cwmp.client.controller.game.GameEngine -import it.cwmp.client.model.game.impl.{CellWorld, Point} +import it.cwmp.client.model.game.impl._ import it.cwmp.client.view.game.GameViewActor._ +import it.cwmp.client.view.game.model.CellView import it.cwmp.utils.Logging import scala.concurrent.duration._ @@ -49,8 +50,17 @@ class GameViewActor extends Actor with Logging { case AddAttack(from, to) => log.info(s"AddAttack from:$from to:$to") - // TODO: convert those points (implementing a utility method in GeometricUtils) in an attack - // TODO: discovering to which cell are near the points provided + val worldCharacters = tempWorld.characters + val fromCell = findCellNearTo(from, worldCharacters) + val toCell = findCellNearTo(to, worldCharacters) + log.debug(s"Attack detected from $fromCell to $toCell") + (fromCell, toCell) match { + case (Some(attacker), Some(attacked)) => + tempWorld = tempWorld ++ Tentacle(attacker, attacked, tempWorld.instant) + // TODO: tell playerActor that world has changed + case tmp@_ => log.debug(s"No attack detected... $tmp") + } + case RemoveAttack(pointOnAttackView) => log.info(s"RemoveAttack pointOnView:$pointOnAttackView") @@ -88,4 +98,14 @@ object GameViewActor { * @param pointOnAttackView the point clicked by the player to remove the attack */ case class RemoveAttack(pointOnAttackView: Point) + + /** + * A method to find a cell near to a clicked point on view, according to actual cell sizing + * + * @param clickedPoint the clicked point on view + * @param cells the collection of cells on screen + * @return optionally the cell near the clicked point + */ + private def findCellNearTo(clickedPoint: Point, cells: Seq[Cell]): Option[Cell] = + cells.find(cell => GeometricUtils.isWithinCircumference(clickedPoint, cell.position, CellView.sizingStrategy(cell))) } diff --git a/client/src/main/scala/it/cwmp/client/view/game/ObjectDrawer.scala b/client/src/main/scala/it/cwmp/client/view/game/ObjectDrawer.scala index f33e5c19..8c281570 100644 --- a/client/src/main/scala/it/cwmp/client/view/game/ObjectDrawer.scala +++ b/client/src/main/scala/it/cwmp/client/view/game/ObjectDrawer.scala @@ -30,12 +30,12 @@ trait ObjectDrawer { val svgShape = new Region svgShape.setShape(svg) // TODO: the cell size is not drawn according to size value!!!! - svgShape.setMinSize(cell.size, cell.size) - svgShape.setPrefSize(cell.size, cell.size) - svgShape.setMaxSize(cell.size, cell.size) + svgShape.setMinSize(cell.radius, cell.radius) + svgShape.setPrefSize(cell.radius, cell.radius) // TODO: la cellula ora fornisce il suo raggio, rivedere il dimensionamento (fare raggio * 2?) + svgShape.setMaxSize(cell.radius, cell.radius) svgShape.setStyle("-fx-background-color: " + "#" + Integer.toHexString(cell.color.getRGB).substring(2)) - svgShape.setLayoutX(cell.center.x - cell.size / 2) - svgShape.setLayoutY(cell.center.y - cell.size / 2) + svgShape.setLayoutX(cell.center.x - cell.radius / 2) + svgShape.setLayoutY(cell.center.y - cell.radius / 2) svgShape } diff --git a/client/src/main/scala/it/cwmp/client/view/game/model/CellView.scala b/client/src/main/scala/it/cwmp/client/view/game/model/CellView.scala index 60a1941f..ea5e109e 100644 --- a/client/src/main/scala/it/cwmp/client/view/game/model/CellView.scala +++ b/client/src/main/scala/it/cwmp/client/view/game/model/CellView.scala @@ -3,10 +3,9 @@ package it.cwmp.client.view.game.model import java.awt.Color import com.github.tkqubo.colorHash.ColorHash -import it.cwmp.client.model.game.impl.{Cell, Point} import it.cwmp.client.model.game.SizingStrategy +import it.cwmp.client.model.game.impl.{Cell, Point} import it.cwmp.client.view.game.ColoringStrategy -import it.cwmp.client.view.game.GameViewConstants._ import scala.language.implicitConversions @@ -16,9 +15,9 @@ import scala.language.implicitConversions * @author Davide Borficchia * @author Eugenio Pierfederici * @param center punto nel quale verrà disegnata la cella - * @param size dimensione della cella + * @param radius dimensione della cella */ -case class CellView(center: Point, color: Color, size: Int) +case class CellView(center: Point, radius: Double, color: Color) /** * Companion object @@ -28,7 +27,7 @@ object CellView { /** * @return the ViewCell corresponding to the given Cell */ - implicit def cellToViewCell(cell: Cell): CellView = CellView(cell.position, coloringStrategy(cell), sizingStrategy(cell)) + implicit def cellToViewCell(cell: Cell): CellView = CellView(cell.position, sizingStrategy(cell), coloringStrategy(cell)) /** * Default cell coloring strategy @@ -41,9 +40,9 @@ object CellView { } /** - * The default sizing strategy + * The default sizing strategy; returns the radius that the cellView should have * - * Maps size to energy + * Maps energy to radius */ - val sizingStrategy: SizingStrategy[Cell, Int] = _.energy.toInt + val sizingStrategy: SizingStrategy[Cell, Double] = _.energy } From 0ac92a51e52ed726107b46e9f07da1027f14cf49 Mon Sep 17 00:00:00 2001 From: Enrico Siboni Date: Tue, 24 Jul 2018 15:17:49 +0200 Subject: [PATCH 008/193] - Added constructor parameter in GameViewActor to make possible to have a reference of parentActor - Now receiving an ADdAttack message makes GameViewActor tell PlayerActor to update distributed state --- .../main/scala/it/cwmp/client/model/PlayerActor.scala | 2 +- .../scala/it/cwmp/client/view/game/GameViewActor.scala | 9 +++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/client/src/main/scala/it/cwmp/client/model/PlayerActor.scala b/client/src/main/scala/it/cwmp/client/model/PlayerActor.scala index 3fb8b34d..9ee4b26d 100644 --- a/client/src/main/scala/it/cwmp/client/model/PlayerActor.scala +++ b/client/src/main/scala/it/cwmp/client/model/PlayerActor.scala @@ -54,7 +54,7 @@ class PlayerActor(system: ActorSystem) extends Actor with Logging { override def preStart(): Unit = { log.info(s"Initializing the game-view actor...") - gameViewActor = system.actorOf(Props[GameViewActor], "game-view") + gameViewActor = system.actorOf(Props(classOf[GameViewActor], self), "game-view") log.info(s"Subscribing to cluster changes...") cluster.subscribe(self, initialStateMode = InitialStateAsEvents, classOf[MemberEvent], classOf[UnreachableMember]) diff --git a/client/src/main/scala/it/cwmp/client/view/game/GameViewActor.scala b/client/src/main/scala/it/cwmp/client/view/game/GameViewActor.scala index 30726b90..e042dec9 100644 --- a/client/src/main/scala/it/cwmp/client/view/game/GameViewActor.scala +++ b/client/src/main/scala/it/cwmp/client/view/game/GameViewActor.scala @@ -1,7 +1,8 @@ package it.cwmp.client.view.game -import akka.actor.{Actor, Cancellable} +import akka.actor.{Actor, ActorRef, Cancellable} import it.cwmp.client.controller.game.GameEngine +import it.cwmp.client.model.DistributedStateMessages import it.cwmp.client.model.game.impl._ import it.cwmp.client.view.game.GameViewActor._ import it.cwmp.client.view.game.model.CellView @@ -12,7 +13,7 @@ import scala.concurrent.duration._ /** * @author contributor Enrico Siboni */ -class GameViewActor extends Actor with Logging { +class GameViewActor(parentActor: ActorRef) extends Actor with Logging { private val gameFX: GameFX = GameFX() private val FRAME_RATE: FiniteDuration = 50.millis @@ -57,7 +58,7 @@ class GameViewActor extends Actor with Logging { (fromCell, toCell) match { case (Some(attacker), Some(attacked)) => tempWorld = tempWorld ++ Tentacle(attacker, attacked, tempWorld.instant) - // TODO: tell playerActor that world has changed + parentActor ! DistributedStateMessages.UpdateWorld(tempWorld) case tmp@_ => log.debug(s"No attack detected... $tmp") } @@ -73,7 +74,7 @@ class GameViewActor extends Actor with Logging { * Companion object, containing actor messages */ object GameViewActor { - def apply(): GameViewActor = new GameViewActor + def apply(parentActor: ActorRef): GameViewActor = new GameViewActor(parentActor) case object ShowGUI From dae26931e54bbd259b9ccb62b3ed0c930cdaede9 Mon Sep 17 00:00:00 2001 From: Enrico Siboni Date: Tue, 24 Jul 2018 15:25:16 +0200 Subject: [PATCH 009/193] Added GameViewActor documentation --- .../cwmp/client/view/game/GameViewActor.scala | 20 +++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/client/src/main/scala/it/cwmp/client/view/game/GameViewActor.scala b/client/src/main/scala/it/cwmp/client/view/game/GameViewActor.scala index e042dec9..61740448 100644 --- a/client/src/main/scala/it/cwmp/client/view/game/GameViewActor.scala +++ b/client/src/main/scala/it/cwmp/client/view/game/GameViewActor.scala @@ -11,6 +11,8 @@ import it.cwmp.utils.Logging import scala.concurrent.duration._ /** + * The actor that deals with Game View + * * @author contributor Enrico Siboni */ class GameViewActor(parentActor: ActorRef) extends Actor with Logging { @@ -54,9 +56,9 @@ class GameViewActor(parentActor: ActorRef) extends Actor with Logging { val worldCharacters = tempWorld.characters val fromCell = findCellNearTo(from, worldCharacters) val toCell = findCellNearTo(to, worldCharacters) - log.debug(s"Attack detected from $fromCell to $toCell") (fromCell, toCell) match { case (Some(attacker), Some(attacked)) => + log.debug(s"Attack detected from $attacker to $attacked") tempWorld = tempWorld ++ Tentacle(attacker, attacked, tempWorld.instant) parentActor ! DistributedStateMessages.UpdateWorld(tempWorld) case tmp@_ => log.debug(s"No attack detected... $tmp") @@ -65,6 +67,7 @@ class GameViewActor(parentActor: ActorRef) extends Actor with Logging { case RemoveAttack(pointOnAttackView) => log.info(s"RemoveAttack pointOnView:$pointOnAttackView") + // TODO: convert point on attack view to the corresponding tentacle, calculating the distance of this point // TODO: from the straight line passing through the tentacle "from" and "to" points } @@ -76,15 +79,28 @@ class GameViewActor(parentActor: ActorRef) extends Actor with Logging { object GameViewActor { def apply(parentActor: ActorRef): GameViewActor = new GameViewActor(parentActor) + /** + * Shows the GUI + */ case object ShowGUI + /** + * Hides the GUI + */ case object HideGUI + /** + * Sets a new world to display + * + * @param world the newWorld from which to compute new evolution + */ case class NewWorld(world: CellWorld) + /** + * Updates local version of the world making it "move" + */ case object UpdateLocalWorld - /** * A message stating that an attack has been launched from one point to another * From b3d6f61443723d3b524a4d4ad833fab193ceacf7 Mon Sep 17 00:00:00 2001 From: Enrico Siboni Date: Tue, 24 Jul 2018 15:45:56 +0200 Subject: [PATCH 010/193] - Added a thickness strategy in TentacleView - Implemented Remove Attack message reception in GameViewActor --- .../controller/game/GameConstants.scala | 2 +- .../client/controller/game/GameEngine.scala | 2 +- .../cwmp/client/view/game/GameViewActor.scala | 29 ++++++++++++++----- .../client/view/game/GameViewConstants.scala | 13 +++------ .../cwmp/client/view/game/ObjectDrawer.scala | 2 +- .../client/view/game/model/TentacleView.scala | 11 ++++++- 6 files changed, 39 insertions(+), 20 deletions(-) diff --git a/client/src/main/scala/it/cwmp/client/controller/game/GameConstants.scala b/client/src/main/scala/it/cwmp/client/controller/game/GameConstants.scala index 57f0a325..9dfebd7e 100644 --- a/client/src/main/scala/it/cwmp/client/controller/game/GameConstants.scala +++ b/client/src/main/scala/it/cwmp/client/controller/game/GameConstants.scala @@ -12,7 +12,7 @@ object GameConstants { * * The energy that a cell has when it's born */ - val cellWhenBornEnergy = 20d + val CELL_ENERGY_WHEN_BORN = 20d /** * ==Cell== diff --git a/client/src/main/scala/it/cwmp/client/controller/game/GameEngine.scala b/client/src/main/scala/it/cwmp/client/controller/game/GameEngine.scala index c7157517..5febda40 100644 --- a/client/src/main/scala/it/cwmp/client/controller/game/GameEngine.scala +++ b/client/src/main/scala/it/cwmp/client/controller/game/GameEngine.scala @@ -86,7 +86,7 @@ object GameEngine extends EvolutionStrategy[CellWorld, Duration] { allTentacles: Seq[Tentacle], maturedEnergy: Double): Cell = { val firstAttackerOfCell = allTentacles.min(Tentacle.orderByLaunchInstant).from.owner - Cell(firstAttackerOfCell, cell.position, GameConstants.cellWhenBornEnergy + maturedEnergy) + Cell(firstAttackerOfCell, cell.position, GameConstants.CELL_ENERGY_WHEN_BORN + maturedEnergy) } /** diff --git a/client/src/main/scala/it/cwmp/client/view/game/GameViewActor.scala b/client/src/main/scala/it/cwmp/client/view/game/GameViewActor.scala index 61740448..d2081c92 100644 --- a/client/src/main/scala/it/cwmp/client/view/game/GameViewActor.scala +++ b/client/src/main/scala/it/cwmp/client/view/game/GameViewActor.scala @@ -5,7 +5,7 @@ import it.cwmp.client.controller.game.GameEngine import it.cwmp.client.model.DistributedStateMessages import it.cwmp.client.model.game.impl._ import it.cwmp.client.view.game.GameViewActor._ -import it.cwmp.client.view.game.model.CellView +import it.cwmp.client.view.game.model.{CellView, TentacleView} import it.cwmp.utils.Logging import scala.concurrent.duration._ @@ -58,18 +58,22 @@ class GameViewActor(parentActor: ActorRef) extends Actor with Logging { val toCell = findCellNearTo(to, worldCharacters) (fromCell, toCell) match { case (Some(attacker), Some(attacked)) => - log.debug(s"Attack detected from $attacker to $attacked") + log.debug(s"Adding attack from $attacker to $attacked ...") tempWorld = tempWorld ++ Tentacle(attacker, attacked, tempWorld.instant) parentActor ! DistributedStateMessages.UpdateWorld(tempWorld) - case tmp@_ => log.debug(s"No attack detected... $tmp") + case tmp@_ => log.debug(s"No cells detected $tmp") } - case RemoveAttack(pointOnAttackView) => log.info(s"RemoveAttack pointOnView:$pointOnAttackView") - - // TODO: convert point on attack view to the corresponding tentacle, calculating the distance of this point - // TODO: from the straight line passing through the tentacle "from" and "to" points + val attack = findTentacleNearTo(pointOnAttackView, tempWorld.attacks) + attack match { + case Some(tentacle) => + log.debug(s"Removing this attack: $tentacle ...") + tempWorld = tempWorld -- tentacle + parentActor ! DistributedStateMessages.UpdateWorld(tempWorld) + case tmp@_ => log.debug(s"No attack detected $tmp") + } } } @@ -125,4 +129,15 @@ object GameViewActor { */ private def findCellNearTo(clickedPoint: Point, cells: Seq[Cell]): Option[Cell] = cells.find(cell => GeometricUtils.isWithinCircumference(clickedPoint, cell.position, CellView.sizingStrategy(cell))) + + /** + * A method to find the tentacle near to a clicked point on view, according to actual tentacle sizing + * + * @param clickedPoint the cliked point on view + * @param tentacles the collection of attacks on screen + * @return optionally the tentacle near the clicked point + */ + private def findTentacleNearTo(clickedPoint: Point, tentacles: Seq[Tentacle]): Option[Tentacle] = + tentacles.find(tentacle => GeometricUtils. + pointDistanceFromStraightLine(clickedPoint, tentacle.from.position, tentacle.to.position) <= TentacleView.thicknessStrategy(tentacle)) } diff --git a/client/src/main/scala/it/cwmp/client/view/game/GameViewConstants.scala b/client/src/main/scala/it/cwmp/client/view/game/GameViewConstants.scala index 3cad8aae..31964261 100644 --- a/client/src/main/scala/it/cwmp/client/view/game/GameViewConstants.scala +++ b/client/src/main/scala/it/cwmp/client/view/game/GameViewConstants.scala @@ -1,19 +1,14 @@ package it.cwmp.client.view.game -import java.awt.Color - /** * An object where to put constants about the game visual + * + * @author Enrico Siboni */ object GameViewConstants { /** - * @return the cell Size - */ - def cellSize: Int = 20 - - /** - * @return the default color + * Provides default value for tentacle thickness */ - def defaultColor: Color = Color.BLACK + val DEFAULT_TENTACLE_THICKNESS = 3d } diff --git a/client/src/main/scala/it/cwmp/client/view/game/ObjectDrawer.scala b/client/src/main/scala/it/cwmp/client/view/game/ObjectDrawer.scala index 8c281570..3114d56d 100644 --- a/client/src/main/scala/it/cwmp/client/view/game/ObjectDrawer.scala +++ b/client/src/main/scala/it/cwmp/client/view/game/ObjectDrawer.scala @@ -46,7 +46,7 @@ trait ObjectDrawer { */ def drawArch(tentacle: Tentacle, actualInstant: Instant)(implicit graphicsContext: GraphicsContext): Unit = { graphicsContext.setStroke(TentacleView.coloringStrategy(tentacle)) - graphicsContext.setLineWidth(3.0) + graphicsContext.setLineWidth(TentacleView.thicknessStrategy(tentacle)) val attackerPosition = tentacle.from.position val tentacleReachedPoint = TentacleView.reachedPoint(tentacle, actualInstant) diff --git a/client/src/main/scala/it/cwmp/client/view/game/model/TentacleView.scala b/client/src/main/scala/it/cwmp/client/view/game/model/TentacleView.scala index 52dc35fb..6190c265 100644 --- a/client/src/main/scala/it/cwmp/client/view/game/model/TentacleView.scala +++ b/client/src/main/scala/it/cwmp/client/view/game/model/TentacleView.scala @@ -3,8 +3,9 @@ package it.cwmp.client.view.game.model import java.awt.Color import java.time.{Duration, Instant} +import it.cwmp.client.model.game.SizingStrategy import it.cwmp.client.model.game.impl.{GeometricUtils, Point, Tentacle} -import it.cwmp.client.view.game.ColoringStrategy +import it.cwmp.client.view.game.{ColoringStrategy, GameViewConstants} /** @@ -22,6 +23,14 @@ object TentacleView { val coloringStrategy: ColoringStrategy[Tentacle, Color] = (tentacle: Tentacle) => CellView.coloringStrategy(tentacle.from) + /** + * Default tentacle thickness strategy + * + * Returns always same thickness + */ + val thicknessStrategy: SizingStrategy[Tentacle, Double] = // TODO: make thickness vary with attackers cell energy + (_: Tentacle) => GameViewConstants.DEFAULT_TENTACLE_THICKNESS + /** * A method returning the Point reached actually by the tentacle * From a8238545799a6a49b7f16b316ed9fce4b16caeb2 Mon Sep 17 00:00:00 2001 From: Enrico Siboni Date: Tue, 24 Jul 2018 16:01:44 +0200 Subject: [PATCH 011/193] - Moved companion object in PlayerActor below class behaviour - Added some doc and made fields private --- .../cwmp/client/model/DistributedState.scala | 2 +- .../it/cwmp/client/model/PlayerActor.scala | 79 ++++++++++--------- 2 files changed, 44 insertions(+), 37 deletions(-) diff --git a/client/src/main/scala/it/cwmp/client/model/DistributedState.scala b/client/src/main/scala/it/cwmp/client/model/DistributedState.scala index 7adb115d..dd048522 100644 --- a/client/src/main/scala/it/cwmp/client/model/DistributedState.scala +++ b/client/src/main/scala/it/cwmp/client/model/DistributedState.scala @@ -11,7 +11,7 @@ import it.cwmp.utils.Logging object DistributedStateMessages { /** - * The message received when the user do something in the GUI + * The message received when the user does something in the GUI * * @param world The world to update in the GUI * @tparam W Type of the world diff --git a/client/src/main/scala/it/cwmp/client/model/PlayerActor.scala b/client/src/main/scala/it/cwmp/client/model/PlayerActor.scala index 9ee4b26d..9d18bd78 100644 --- a/client/src/main/scala/it/cwmp/client/model/PlayerActor.scala +++ b/client/src/main/scala/it/cwmp/client/model/PlayerActor.scala @@ -5,28 +5,13 @@ import akka.cluster.Cluster import akka.cluster.ClusterEvent._ import akka.cluster.ddata.DistributedData import it.cwmp.client.GameMain +import it.cwmp.client.model.PlayerActor._ import it.cwmp.client.model.game.impl.CellWorld import it.cwmp.client.view.game.GameViewActor import it.cwmp.client.view.game.GameViewActor._ import it.cwmp.model.Address import it.cwmp.utils.Logging -object PlayerActor { - - def apply(system: ActorSystem): PlayerActor = new PlayerActor(system) - - // Incoming messages - case object RetrieveAddress - - case class StartGame(participantList: List[Address]) - - case object EndGame - - // Outgoing messages - case class RetrieveAddressResponse(address: String) - -} - /** * Questo attore è quello che si occupa di gestire l'esecuzione del gioco distribuito. * Innanzi tutto all'avvio della partita crea un cluster con gli altri partecipanti; poi @@ -34,23 +19,20 @@ object PlayerActor { * * @author Eugenio Pierfederici */ - -import it.cwmp.client.model.PlayerActor._ - class PlayerActor(system: ActorSystem) extends Actor with Logging { // View actor - var gameViewActor: ActorRef = _ + private var gameViewActor: ActorRef = _ // Cluster info - var roomSize: Int = _ + private var roomSize: Int = _ // distributed replica system - val replicator: ActorRef = DistributedData(context.system).replicator - implicit val cluster: Cluster = Cluster(context.system) + private val replicator: ActorRef = DistributedData(context.system).replicator + private implicit val cluster: Cluster = Cluster(context.system) // Distributed world - val distributedState: DistributedState[CellWorld] = DistributedState(this, println) + private val distributedState: DistributedState[CellWorld] = DistributedState(this, println) override def preStart(): Unit = { log.info(s"Initializing the game-view actor...") @@ -64,43 +46,68 @@ class PlayerActor(system: ActorSystem) extends Actor with Logging { override def receive: Receive = clusterBehaviour orElse lobbyBehaviour + /** + * @return the behaviour of an actor in a cluster + */ private def clusterBehaviour: Receive = { case MemberUp(member) => log.info("Member is Up: {}", member.address) log.debug("Cluster size: " + cluster.state.members.size) - if (cluster.state.members.size == roomSize) enterGame + if (cluster.state.members.size == roomSize) enterGameAction() case UnreachableMember(member) => log.info("Member detected as unreachable: {}", member) case MemberRemoved(member, previousStatus) => - log.info( - "Member is Removed: {} after {}", - member.address, previousStatus) + log.info("Member is Removed: {} after {}", member.address, previousStatus) case _: MemberEvent => // ignore } - private def backToLobby: Unit = context.become(clusterBehaviour orElse lobbyBehaviour) - + // TODO: add doc private def lobbyBehaviour: Receive = { case RetrieveAddress => sender() ! RetrieveAddressResponse(getAddress) case StartGame(participants) => - connectTo(participants) + join(participants) roomSize = participants.size } - private def enterGame: Unit = { + /** + * @return the behaviour of the actor when it's in game + */ + private def inGameBehaviour: Receive = + distributedState.stateBehaviour orElse { + case EndGame => backToLobbyAction() + } + + private def enterGameAction(): Unit = { context.become(clusterBehaviour orElse inGameBehaviour) gameViewActor ! ShowGUI gameViewActor ! NewWorld(GameMain.debugWorld) } - private def inGameBehaviour: Receive = distributedState.stateBehaviour orElse { - case EndGame => backToLobby - } + private def backToLobbyAction(): Unit = context.become(clusterBehaviour orElse lobbyBehaviour) - private def connectTo(participants: List[Address]): Unit = { + private def join(participants: List[Address]): Unit = { cluster.join(AddressFromURIString(participants.head.address)) } private def getAddress: String = cluster.selfAddress + self.path.toString.substring(self.path.address.toString.length) } + +/** + * Companion object, containing actor messages + */ +object PlayerActor { + + def apply(system: ActorSystem): PlayerActor = new PlayerActor(system) + + // Incoming messages + case object RetrieveAddress + + case class StartGame(participantList: List[Address]) + + case object EndGame + + // Outgoing messages + case class RetrieveAddressResponse(address: String) + +} From b937a13b9cace1d58d3263121d966abeae390afe Mon Sep 17 00:00:00 2001 From: Enrico Siboni Date: Tue, 24 Jul 2018 16:59:24 +0200 Subject: [PATCH 012/193] - Better generified DistributedState - Implemented specific CellWorld distributed state (removing annoying warnings on type erasure) --- .../model/CellWorldDistributedState.scala | 27 ++++++ .../cwmp/client/model/DistributedState.scala | 84 ++++++++++--------- .../it/cwmp/client/model/PlayerActor.scala | 4 +- .../cwmp/client/view/game/GameViewActor.scala | 6 +- 4 files changed, 76 insertions(+), 45 deletions(-) create mode 100644 client/src/main/scala/it/cwmp/client/model/CellWorldDistributedState.scala diff --git a/client/src/main/scala/it/cwmp/client/model/CellWorldDistributedState.scala b/client/src/main/scala/it/cwmp/client/model/CellWorldDistributedState.scala new file mode 100644 index 00000000..8c7517f5 --- /dev/null +++ b/client/src/main/scala/it/cwmp/client/model/CellWorldDistributedState.scala @@ -0,0 +1,27 @@ +package it.cwmp.client.model + +import akka.actor.Actor.Receive +import akka.actor.ActorRef +import akka.cluster.Cluster +import akka.cluster.ddata.{LWWRegister, Replicator} +import akka.cluster.ddata.Replicator.{Update, WriteLocal} +import it.cwmp.client.model.DistributedState.UpdateState +import it.cwmp.client.model.game.impl.CellWorld + +/** + * Distributed representation of the world and of his behaviours. + * + * @author Eugenio Pierfederici + * @author contributor Enrico Siboni + */ +case class CellWorldDistributedState(updateSubscriber: ActorRef, onWorldUpdate: CellWorld => Unit)(implicit replicatorActor: ActorRef, cluster: Cluster) + extends DistributedState[CellWorld](updateSubscriber, onWorldUpdate) { + + override def consistencyPolicy: Replicator.WriteConsistency = WriteLocal + + override protected def activeBehaviour: Receive = { + case UpdateState(state: CellWorld) => + log.debug("Updating distributed state") + replicatorActor ! Update(DistributedKey, LWWRegister[CellWorld](state), consistencyPolicy)(_.withValue(state)) + } +} diff --git a/client/src/main/scala/it/cwmp/client/model/DistributedState.scala b/client/src/main/scala/it/cwmp/client/model/DistributedState.scala index dd048522..12f31bfb 100644 --- a/client/src/main/scala/it/cwmp/client/model/DistributedState.scala +++ b/client/src/main/scala/it/cwmp/client/model/DistributedState.scala @@ -1,68 +1,72 @@ package it.cwmp.client.model import akka.actor.Actor.Receive -import akka.actor.{Actor, ActorRef} +import akka.actor.ActorRef import akka.cluster.Cluster import akka.cluster.ddata.Replicator._ import akka.cluster.ddata._ -import it.cwmp.client.model.game.World +import it.cwmp.client.model.DistributedState.DISTRIBUTED_KEY_NAME import it.cwmp.utils.Logging -object DistributedStateMessages { - - /** - * The message received when the user does something in the GUI - * - * @param world The world to update in the GUI - * @tparam W Type of the world - */ - case class UpdateWorld[W <: World[_, _, _]](world: W) - -} - /** - * Distributed representation of the world and of his behaviours. + * Distributed representation of data and attached behaviours. * * @param onWorldUpdate the update strategy when the world is changed * @author Eugenio Pierfederici + * @author contributor Enrico Siboni */ -case class DistributedState[WD <: World[_, _, _]] -(actor: Actor, onWorldUpdate: WD => Unit)(implicit replicator: ActorRef, cluster: Cluster) extends Logging { +abstract class DistributedState[T](updateSubscriber: ActorRef, onWorldUpdate: T => Unit)(implicit replicatorActor: ActorRef, cluster: Cluster) extends Logging { - import it.cwmp.client.model.DistributedStateMessages._ + protected val DistributedKey: LWWRegisterKey[T] = LWWRegisterKey[T](DISTRIBUTED_KEY_NAME) - private val WorldKey = LWWRegisterKey[WD]("world") - - def initState(): Unit = { - replicator ! Subscribe(WorldKey, actor.self) + /** + * Subscribes the provided actor to receive changes in this distributed state + * + * @param actorRef the actor to subscribe + */ + def subscribe(actorRef: ActorRef): Unit = { + replicatorActor ! Subscribe(DistributedKey, actorRef) } /** - * This behaviour provides an easy way to integrate the distributed state in the player actor. + * This behaviour provides an easy way to make the interested actor, + * able to receive updates and make changes in this distributed state */ - def stateBehaviour: Receive = userActionBehaviour orElse distributedActionBehaviour + def distributedStateBehaviour: Receive = passiveBehaviour orElse activeBehaviour /** - * All the behaviours needed to execute all the action requested from the user (the player on this client) - * - * @return + * @return the behaviour enabling to listen for modification in the distributed state */ - private def userActionBehaviour: Receive = { - // Called from the view/controller - case UpdateWorld(world: WD) => - log.debug("Requiring UpdateWorld DISTRIBUTED") - replicator ! Update(WorldKey, LWWRegister[WD](world), WriteLocal)(_.withValue(world)) + protected def passiveBehaviour: Receive = { + // Called when notified of the distributed data change + case c@Changed(DistributedKey) => + log.debug("Being notified that distributed state has changed") + onWorldUpdate(c.get(DistributedKey).getValue) } /** - * All the behaviours needed to manage the distribution of the state + * @return the behaviour enabling to modify distributed state + */ + protected def activeBehaviour: Receive + + /** + * @return the consistency policy to adopt when writing updates in distributed state + */ + protected def consistencyPolicy: Replicator.WriteConsistency +} + +/** + * Companion Object, containing actor messages + */ +object DistributedState { + + private val DISTRIBUTED_KEY_NAME = "distributedKey" + + /** + * The message to send to update distributed state * - * @return + * @param state the new state */ - private def distributedActionBehaviour: Receive = { - // Called when notified of the distributed data change - case c@Changed(WorldKey) => - log.debug("UpdateGUI from DISTRIBUTED because WorldKey was changed") - onWorldUpdate(c.get(WorldKey).getValue) - } + case class UpdateState[T](state: T) + } diff --git a/client/src/main/scala/it/cwmp/client/model/PlayerActor.scala b/client/src/main/scala/it/cwmp/client/model/PlayerActor.scala index 9d18bd78..c8761220 100644 --- a/client/src/main/scala/it/cwmp/client/model/PlayerActor.scala +++ b/client/src/main/scala/it/cwmp/client/model/PlayerActor.scala @@ -32,7 +32,7 @@ class PlayerActor(system: ActorSystem) extends Actor with Logging { private implicit val cluster: Cluster = Cluster(context.system) // Distributed world - private val distributedState: DistributedState[CellWorld] = DistributedState(this, println) + private val distributedState: DistributedState[CellWorld] = CellWorldDistributedState(self, println) override def preStart(): Unit = { log.info(s"Initializing the game-view actor...") @@ -74,7 +74,7 @@ class PlayerActor(system: ActorSystem) extends Actor with Logging { * @return the behaviour of the actor when it's in game */ private def inGameBehaviour: Receive = - distributedState.stateBehaviour orElse { + distributedState.distributedStateBehaviour orElse { case EndGame => backToLobbyAction() } diff --git a/client/src/main/scala/it/cwmp/client/view/game/GameViewActor.scala b/client/src/main/scala/it/cwmp/client/view/game/GameViewActor.scala index d2081c92..87082b3d 100644 --- a/client/src/main/scala/it/cwmp/client/view/game/GameViewActor.scala +++ b/client/src/main/scala/it/cwmp/client/view/game/GameViewActor.scala @@ -2,7 +2,7 @@ package it.cwmp.client.view.game import akka.actor.{Actor, ActorRef, Cancellable} import it.cwmp.client.controller.game.GameEngine -import it.cwmp.client.model.DistributedStateMessages +import it.cwmp.client.model.DistributedState import it.cwmp.client.model.game.impl._ import it.cwmp.client.view.game.GameViewActor._ import it.cwmp.client.view.game.model.{CellView, TentacleView} @@ -60,7 +60,7 @@ class GameViewActor(parentActor: ActorRef) extends Actor with Logging { case (Some(attacker), Some(attacked)) => log.debug(s"Adding attack from $attacker to $attacked ...") tempWorld = tempWorld ++ Tentacle(attacker, attacked, tempWorld.instant) - parentActor ! DistributedStateMessages.UpdateWorld(tempWorld) + parentActor ! DistributedState.UpdateState(tempWorld) case tmp@_ => log.debug(s"No cells detected $tmp") } @@ -71,7 +71,7 @@ class GameViewActor(parentActor: ActorRef) extends Actor with Logging { case Some(tentacle) => log.debug(s"Removing this attack: $tentacle ...") tempWorld = tempWorld -- tentacle - parentActor ! DistributedStateMessages.UpdateWorld(tempWorld) + parentActor ! DistributedState.UpdateState(tempWorld) case tmp@_ => log.debug(s"No attack detected $tmp") } } From a1dfd7840fad96e36bea151c12692b49ce4efeed Mon Sep 17 00:00:00 2001 From: Enrico Siboni Date: Tue, 24 Jul 2018 17:02:30 +0200 Subject: [PATCH 013/193] CellWorldDistributedState was taking as implicit input the "self" instance of actorRef in scope instead of replicator, now corrected --- client/src/main/scala/it/cwmp/client/model/PlayerActor.scala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/src/main/scala/it/cwmp/client/model/PlayerActor.scala b/client/src/main/scala/it/cwmp/client/model/PlayerActor.scala index c8761220..1bc6d832 100644 --- a/client/src/main/scala/it/cwmp/client/model/PlayerActor.scala +++ b/client/src/main/scala/it/cwmp/client/model/PlayerActor.scala @@ -29,10 +29,10 @@ class PlayerActor(system: ActorSystem) extends Actor with Logging { // distributed replica system private val replicator: ActorRef = DistributedData(context.system).replicator - private implicit val cluster: Cluster = Cluster(context.system) + private val cluster: Cluster = Cluster(context.system) // Distributed world - private val distributedState: DistributedState[CellWorld] = CellWorldDistributedState(self, println) + private val distributedState: DistributedState[CellWorld] = CellWorldDistributedState(self, println)(replicator, cluster) override def preStart(): Unit = { log.info(s"Initializing the game-view actor...") From 7ce749809ef069a957bb4923d8469bfb0e330201 Mon Sep 17 00:00:00 2001 From: Davide Borficchia Date: Tue, 24 Jul 2018 17:22:35 +0200 Subject: [PATCH 014/193] =?UTF-8?q?risolto=20bug=20della=20dimensione=20de?= =?UTF-8?q?lle=20celle=20e=20aggiunta=20energia=20celle=20in=20CellView=20?= =?UTF-8?q?Stampata=20nella=20GUI=20l'energia=20ma=20non=20=C3=A8=20ancora?= =?UTF-8?q?=20al=20centro=20della=20cella?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../it/cwmp/client/view/game/GameFX.scala | 6 ++-- .../cwmp/client/view/game/ObjectDrawer.scala | 29 ++++++++++++++----- .../client/view/game/model/CellView.scala | 5 ++-- 3 files changed, 28 insertions(+), 12 deletions(-) diff --git a/client/src/main/scala/it/cwmp/client/view/game/GameFX.scala b/client/src/main/scala/it/cwmp/client/view/game/GameFX.scala index 34b175cb..4c1c75b9 100644 --- a/client/src/main/scala/it/cwmp/client/view/game/GameFX.scala +++ b/client/src/main/scala/it/cwmp/client/view/game/GameFX.scala @@ -47,12 +47,12 @@ case class GameFX() extends ObjectDrawer { def updateWorld(world: CellWorld): Unit = { Platform.runLater(() => { implicit val graphicsContext: GraphicsContext = canvas.getGraphicsContext2D - graphicsContext.clearRect(0, 0, canvas.getWidth, canvas.getHeight) + root.getChildren.clear() import it.cwmp.client.view.game.model.CellView._ - world.attacks.foreach(tentacle => drawArch(tentacle, world.instant)) - // println(world.characters.map(_.size)) + world.attacks.foreach(tentacle => root.getChildren.add(drawArch(tentacle, world.instant))) world.characters.foreach(cell => root.getChildren.add(drawCell(cell))) + world.characters.foreach(cell => root.getChildren.add(drawCellEnergy(cell))) }) } } diff --git a/client/src/main/scala/it/cwmp/client/view/game/ObjectDrawer.scala b/client/src/main/scala/it/cwmp/client/view/game/ObjectDrawer.scala index f33e5c19..c587cdfe 100644 --- a/client/src/main/scala/it/cwmp/client/view/game/ObjectDrawer.scala +++ b/client/src/main/scala/it/cwmp/client/view/game/ObjectDrawer.scala @@ -6,8 +6,9 @@ import java.time.Instant import it.cwmp.client.model.game.impl.Tentacle import it.cwmp.client.view.game.model._ import javafx.scene.canvas.GraphicsContext -import javafx.scene.layout.Region -import javafx.scene.shape.SVGPath +import javafx.scene.layout._ +import javafx.scene.shape.{Line, SVGPath} +import javafx.scene.text.Text import scala.language.implicitConversions @@ -30,6 +31,8 @@ trait ObjectDrawer { val svgShape = new Region svgShape.setShape(svg) // TODO: the cell size is not drawn according to size value!!!! + svgShape.setBorder(new Border(new BorderStroke(Color.BLACK, + BorderStrokeStyle.SOLID, CornerRadii.EMPTY, BorderWidths.DEFAULT))) svgShape.setMinSize(cell.size, cell.size) svgShape.setPrefSize(cell.size, cell.size) svgShape.setMaxSize(cell.size, cell.size) @@ -39,19 +42,31 @@ trait ObjectDrawer { svgShape } + def drawCellEnergy(cell: CellView)(implicit graphicsContext: GraphicsContext): Text = { + val t = new Text(cell.center.x - cell.size / 2, cell.center.y - cell.size / 2, cell.energy.toInt.toString) + import javafx.scene.text.Font + t.setFont(Font.font("Verdana", 20)) + t.setFill(Color.BLACK) + t + } + /** * Metodo utilizato per disegnare l'arco che unisce due celle * * @param graphicsContext è l'oggetto che disenga l'arco */ - def drawArch(tentacle: Tentacle, actualInstant: Instant)(implicit graphicsContext: GraphicsContext): Unit = { - graphicsContext.setStroke(TentacleView.coloringStrategy(tentacle)) - graphicsContext.setLineWidth(3.0) + def drawArch(tentacle: Tentacle, actualInstant: Instant)(implicit graphicsContext: GraphicsContext): Line = { + val line = new Line() + line.setStroke(TentacleView.coloringStrategy(tentacle)) val attackerPosition = tentacle.from.position val tentacleReachedPoint = TentacleView.reachedPoint(tentacle, actualInstant) - graphicsContext.strokeLine(attackerPosition.x, attackerPosition.y, - tentacleReachedPoint.x, tentacleReachedPoint.y) + line.setStrokeWidth(3.0) + line.setStartX(attackerPosition.x) + line.setStartY(attackerPosition.y) + line.setEndX(tentacleReachedPoint.x) + line.setEndY(tentacleReachedPoint.y) + line } /** diff --git a/client/src/main/scala/it/cwmp/client/view/game/model/CellView.scala b/client/src/main/scala/it/cwmp/client/view/game/model/CellView.scala index 60a1941f..c1c1e3a0 100644 --- a/client/src/main/scala/it/cwmp/client/view/game/model/CellView.scala +++ b/client/src/main/scala/it/cwmp/client/view/game/model/CellView.scala @@ -17,8 +17,9 @@ import scala.language.implicitConversions * @author Eugenio Pierfederici * @param center punto nel quale verrà disegnata la cella * @param size dimensione della cella + * @param energy energia della cella */ -case class CellView(center: Point, color: Color, size: Int) +case class CellView(center: Point, color: Color, size: Int, energy: Double) /** * Companion object @@ -28,7 +29,7 @@ object CellView { /** * @return the ViewCell corresponding to the given Cell */ - implicit def cellToViewCell(cell: Cell): CellView = CellView(cell.position, coloringStrategy(cell), sizingStrategy(cell)) + implicit def cellToViewCell(cell: Cell): CellView = CellView(cell.position, coloringStrategy(cell), sizingStrategy(cell), cell.energy) /** * Default cell coloring strategy From 1e34b6d6a82b33dbf709aef20d2e2ed68d89fa70 Mon Sep 17 00:00:00 2001 From: Enrico Siboni Date: Tue, 24 Jul 2018 17:54:48 +0200 Subject: [PATCH 015/193] Made GameViewActor not to modify directly local world when a view action has been processed the action will be reflected back from PlayerActor when a newWorld notification comes --- .../scala/it/cwmp/client/view/game/GameViewActor.scala | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/client/src/main/scala/it/cwmp/client/view/game/GameViewActor.scala b/client/src/main/scala/it/cwmp/client/view/game/GameViewActor.scala index 87082b3d..40d0b40b 100644 --- a/client/src/main/scala/it/cwmp/client/view/game/GameViewActor.scala +++ b/client/src/main/scala/it/cwmp/client/view/game/GameViewActor.scala @@ -59,8 +59,9 @@ class GameViewActor(parentActor: ActorRef) extends Actor with Logging { (fromCell, toCell) match { case (Some(attacker), Some(attacked)) => log.debug(s"Adding attack from $attacker to $attacked ...") - tempWorld = tempWorld ++ Tentacle(attacker, attacked, tempWorld.instant) - parentActor ! DistributedState.UpdateState(tempWorld) + parentActor ! DistributedState.UpdateState( + tempWorld ++ Tentacle(attacker, attacked, tempWorld.instant) + ) case tmp@_ => log.debug(s"No cells detected $tmp") } @@ -70,8 +71,9 @@ class GameViewActor(parentActor: ActorRef) extends Actor with Logging { attack match { case Some(tentacle) => log.debug(s"Removing this attack: $tentacle ...") - tempWorld = tempWorld -- tentacle - parentActor ! DistributedState.UpdateState(tempWorld) + parentActor ! DistributedState.UpdateState( + tempWorld -- tentacle + ) case tmp@_ => log.debug(s"No attack detected $tmp") } } From 20d926cb7408bb4c5e10b95d29e1e1cb44d7497e Mon Sep 17 00:00:00 2001 From: Enrico Siboni Date: Tue, 24 Jul 2018 17:57:28 +0200 Subject: [PATCH 016/193] Added action on external distributed state update, notifying GameViewActor --- .../main/scala/it/cwmp/client/model/PlayerActor.scala | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/client/src/main/scala/it/cwmp/client/model/PlayerActor.scala b/client/src/main/scala/it/cwmp/client/model/PlayerActor.scala index 1bc6d832..d545be6b 100644 --- a/client/src/main/scala/it/cwmp/client/model/PlayerActor.scala +++ b/client/src/main/scala/it/cwmp/client/model/PlayerActor.scala @@ -32,7 +32,8 @@ class PlayerActor(system: ActorSystem) extends Actor with Logging { private val cluster: Cluster = Cluster(context.system) // Distributed world - private val distributedState: DistributedState[CellWorld] = CellWorldDistributedState(self, println)(replicator, cluster) + private val distributedState: DistributedState[CellWorld] = + CellWorldDistributedState(self, onWorldUpdatedAction)(replicator, cluster) override def preStart(): Unit = { log.info(s"Initializing the game-view actor...") @@ -86,6 +87,14 @@ class PlayerActor(system: ActorSystem) extends Actor with Logging { private def backToLobbyAction(): Unit = context.become(clusterBehaviour orElse lobbyBehaviour) + /** + * Action that will be executed every time the world will be updated + * + * @param world the updated world + */ + private def onWorldUpdatedAction(world: CellWorld): Unit = gameViewActor ! NewWorld(world) + + private def join(participants: List[Address]): Unit = { cluster.join(AddressFromURIString(participants.head.address)) } From 22855e46aa8528389349cbd91d55b3419ffc136b Mon Sep 17 00:00:00 2001 From: Enrico Siboni Date: Tue, 24 Jul 2018 18:05:52 +0200 Subject: [PATCH 017/193] Moved companion object of ClientControllerActor below class --- .../controller/ClientControllerActor.scala | 145 +++++++++--------- .../cwmp/client/view/game/GameViewActor.scala | 8 +- 2 files changed, 72 insertions(+), 81 deletions(-) diff --git a/client/src/main/scala/it/cwmp/client/controller/ClientControllerActor.scala b/client/src/main/scala/it/cwmp/client/controller/ClientControllerActor.scala index b0088ee1..b50c7e89 100644 --- a/client/src/main/scala/it/cwmp/client/controller/ClientControllerActor.scala +++ b/client/src/main/scala/it/cwmp/client/controller/ClientControllerActor.scala @@ -1,72 +1,17 @@ package it.cwmp.client.controller import akka.actor.{Actor, ActorRef, ActorSystem, Props} -import com.typesafe.scalalogging.Logger import it.cwmp.client.model.PlayerActor._ import it.cwmp.client.model._ import it.cwmp.client.view.AlertMessages import it.cwmp.client.view.authentication.{AuthenticationViewActor, AuthenticationViewMessages} import it.cwmp.client.view.room.{RoomViewActor, RoomViewMessages} import it.cwmp.model.{Address, Participant} +import it.cwmp.utils.Logging import scala.concurrent.Future import scala.util.{Failure, Success} -/** - * Questo oggetto contiene tutti i messaggi che questo attore può ricevere. - */ -object ClientControllerMessages { - - /** - * Message indicating the need to log into the system. - * When the system receives it, it sends the request to the authentication online service. - * - * @param username identification chosen by the player to access the system - * @param password password chosen during sign up - */ - case class AuthenticationPerformSignIn(username: String, password: String) - - /** - * Message indicating the need to create a new account. - * When the system receives it, it sends the request to the authentication online service. - * - * @param username identification chosen by the player to register in the system - * @param password password chosen to authenticate in the system - */ - case class AuthenticationPerformSignUp(username: String, password: String) - - - /** - * Questo messaggio gestisce la volontà di creare una nuova stanza privata. - * Quando lo ricevo, invio la richiesta all'attore che gestisce i servizi online delle stanze. - * - * @param name è il nome della stanza da creare - * @param nPlayer è il numero dei giocatori che potranno entrare nella stanza - */ - case class RoomCreatePrivate(name: String, nPlayer: Int) - - /** - * Questo messaggio gestisce la volontà di entrare in una stanza privata. - * Quando lo ricevo, invio la richiesta all'attore che gestisce i servizi online delle stanze. - * - * @param idRoom è l'id che identifica la stanza privata - */ - case class RoomEnterPrivate(idRoom: String) - - /** - * Questo messaggio gestisce la volontà di entrare in una stanza pubblica. - * Quando lo ricevo, invio la richiesta all'attore che gestisce i servizi online delle stanze. - * - * @param nPlayer è il numero dei partecipanti con i quali si vuole giocare - */ - case class RoomEnterPublic(nPlayer: Int) - -} - -object ClientControllerActor { - def apply(system: ActorSystem): ClientControllerActor = new ClientControllerActor(system) -} - /** * Questa classe rappresenta l'attore del controller del client che ha il compito * di fare da tramite tra le view e i model. @@ -75,10 +20,9 @@ object ClientControllerActor { * @author Davide Borficchia * @author Eugenio Pierfederici */ -class ClientControllerActor(system: ActorSystem) extends Actor with ParticipantListReceiver { +case class ClientControllerActor(system: ActorSystem) extends Actor with ParticipantListReceiver with Logging { private val UNKNOWN_ERROR = "Unknown Error" - private val logger: Logger = Logger[ClientControllerActor] // TODO: replace with our logging var jwtToken: String = _ @@ -113,19 +57,19 @@ class ClientControllerActor(system: ActorSystem) extends Actor with ParticipantL override def preStart(): Unit = { super.preStart() // Initialize all actors - logger.info(s"Initializing the player actor...") + log.info(s"Initializing the player actor...") playerActor = system.actorOf(Props(classOf[PlayerActor], system), "player") playerActor ! RetrieveAddress - logger.info(s"Initializing the API client actor...") + log.info(s"Initializing the API client actor...") apiClientActor = system.actorOf(Props[ApiClientActor], "roomAPIClient") //todo parametrizzare le stringhe - logger.info(s"Initializing the authentication view actor...") + log.info(s"Initializing the authentication view actor...") authenticationViewActor = system.actorOf(Props[AuthenticationViewActor], "authenticationView") authenticationViewActor ! AuthenticationViewMessages.InitController - logger.info(s"Initializing the room view actor...") + log.info(s"Initializing the room view actor...") roomViewActor = system.actorOf(Props[RoomViewActor], "roomView") roomViewActor ! RoomViewMessages.InitController - logger.info(s"Displaying the view...") + log.info(s"Displaying the view...") authenticationViewActor ! AuthenticationViewMessages.ShowGUI } @@ -142,7 +86,7 @@ class ClientControllerActor(system: ActorSystem) extends Actor with ParticipantL * Set the behavior of the [[ClientControllerActor]] in order to handle authentication processes */ def becomeAuthenticationManager(): Unit = { - logger.info(s"Setting the behaviour 'authentication-manager'") + log.info(s"Setting the behaviour 'authentication-manager'") context.become(apiClientReceiverBehaviour orElse authenticationManagerBehaviour) } @@ -150,13 +94,13 @@ class ClientControllerActor(system: ActorSystem) extends Actor with ParticipantL * Imposta il behavior del [[ClientControllerActor]] in modo da gestire solo la lobby delle stanze */ private def becomeRoomsManager(): Unit = { - logger.info(s"Setting the behaviour 'room-manager'") + log.info(s"Setting the behaviour 'room-manager'") context.become(apiClientReceiverBehaviour orElse roomManagerBehaviour) roomViewActor ! RoomViewMessages.ShowGUI } private def becomeInGame(participants: List[Participant]): Unit = { - logger.info(s"Setting the behaviour 'in-game'") + log.info(s"Setting the behaviour 'in-game'") context.become(inGameBehaviour) roomViewActor ! RoomViewMessages.HideGUI playerActor ! StartGame(participants) @@ -172,10 +116,10 @@ class ClientControllerActor(system: ActorSystem) extends Actor with ParticipantL */ def authenticationManagerBehaviour: Receive = { case AuthenticationPerformSignIn(username, password) => - logger.info(s"Signing in as $username") + log.info(s"Signing in as $username") apiClientActor ! ApiClientIncomingMessages.AuthenticationPerformSignIn(username, password) case AuthenticationPerformSignUp(username, password) => - logger.info(s"Signing up as $username") + log.info(s"Signing up as $username") apiClientActor ! ApiClientIncomingMessages.AuthenticationPerformSignUp(username, password) } @@ -189,16 +133,16 @@ class ClientControllerActor(system: ActorSystem) extends Actor with ParticipantL private def roomManagerBehaviour: Receive = { case RoomCreatePrivate(name, nPlayer) => - logger.info(s"Creating the room $name") + log.info(s"Creating the room $name") apiClientActor ! ApiClientIncomingMessages.RoomCreatePrivate(name, nPlayer, jwtToken) case RoomEnterPrivate(idRoom) => - logger.info(s"Entering the private room $idRoom") + log.info(s"Entering the private room $idRoom") enterRoom().map(url => apiClientActor ! ApiClientIncomingMessages.RoomEnterPrivate( idRoom, Address(playerAddress), url, jwtToken) ) case RoomEnterPublic(nPlayer) => - logger.info(s"Entering the public room with $nPlayer players") + log.info(s"Entering the public room with $nPlayer players") enterRoom().map(url => apiClientActor ! ApiClientIncomingMessages.RoomEnterPublic( nPlayer, Address(playerAddress), url, jwtToken) @@ -210,19 +154,19 @@ class ClientControllerActor(system: ActorSystem) extends Actor with ParticipantL } private def enterRoom(): Future[Address] = { - logger.debug(s"Starting the local one-time reception server...") + log.debug(s"Starting the local one-time reception server...") // Apre il server in ricezione per la lista dei partecipanti listenForParticipantListFuture( // Quando ha ricevuto la lista dei partecipanti dal server participants => { - logger.info(s"Participants list received!") + log.info(s"Participants list received!") becomeInGame(participants) } ).andThen({ // Una volta creato case Success(address) => - logger.debug(s"Server completely started listening at the address: $address") + log.debug(s"Server completely started listening at the address: $address") case Failure(error) => // Invia un messaggio di errore alla GUI - logger.error(s"Problem starting the server: ${error.getMessage}") + log.error(s"Problem starting the server: ${error.getMessage}") roomViewActor ! AlertMessages.Error("Error", error.getMessage) }) } @@ -267,4 +211,55 @@ class ClientControllerActor(system: ActorSystem) extends Actor with ParticipantL case RoomEnterPublicFailure(reason) => roomViewActor ! AlertMessages.Error("Problem", reason.getOrElse(UNKNOWN_ERROR)) // TODO parametrizzazione stringhe } +} + +/** + * Questo oggetto contiene tutti i messaggi che questo attore può ricevere. + */ +object ClientControllerMessages { + + /** + * Message indicating the need to log into the system. + * When the system receives it, it sends the request to the authentication online service. + * + * @param username identification chosen by the player to access the system + * @param password password chosen during sign up + */ + case class AuthenticationPerformSignIn(username: String, password: String) + + /** + * Message indicating the need to create a new account. + * When the system receives it, it sends the request to the authentication online service. + * + * @param username identification chosen by the player to register in the system + * @param password password chosen to authenticate in the system + */ + case class AuthenticationPerformSignUp(username: String, password: String) + + + /** + * Questo messaggio gestisce la volontà di creare una nuova stanza privata. + * Quando lo ricevo, invio la richiesta all'attore che gestisce i servizi online delle stanze. + * + * @param name è il nome della stanza da creare + * @param nPlayer è il numero dei giocatori che potranno entrare nella stanza + */ + case class RoomCreatePrivate(name: String, nPlayer: Int) + + /** + * Questo messaggio gestisce la volontà di entrare in una stanza privata. + * Quando lo ricevo, invio la richiesta all'attore che gestisce i servizi online delle stanze. + * + * @param idRoom è l'id che identifica la stanza privata + */ + case class RoomEnterPrivate(idRoom: String) + + /** + * Questo messaggio gestisce la volontà di entrare in una stanza pubblica. + * Quando lo ricevo, invio la richiesta all'attore che gestisce i servizi online delle stanze. + * + * @param nPlayer è il numero dei partecipanti con i quali si vuole giocare + */ + case class RoomEnterPublic(nPlayer: Int) + } \ No newline at end of file diff --git a/client/src/main/scala/it/cwmp/client/view/game/GameViewActor.scala b/client/src/main/scala/it/cwmp/client/view/game/GameViewActor.scala index 40d0b40b..44f907fd 100644 --- a/client/src/main/scala/it/cwmp/client/view/game/GameViewActor.scala +++ b/client/src/main/scala/it/cwmp/client/view/game/GameViewActor.scala @@ -59,9 +59,7 @@ class GameViewActor(parentActor: ActorRef) extends Actor with Logging { (fromCell, toCell) match { case (Some(attacker), Some(attacked)) => log.debug(s"Adding attack from $attacker to $attacked ...") - parentActor ! DistributedState.UpdateState( - tempWorld ++ Tentacle(attacker, attacked, tempWorld.instant) - ) + parentActor ! DistributedState.UpdateState(tempWorld ++ Tentacle(attacker, attacked, tempWorld.instant)) case tmp@_ => log.debug(s"No cells detected $tmp") } @@ -71,9 +69,7 @@ class GameViewActor(parentActor: ActorRef) extends Actor with Logging { attack match { case Some(tentacle) => log.debug(s"Removing this attack: $tentacle ...") - parentActor ! DistributedState.UpdateState( - tempWorld -- tentacle - ) + parentActor ! DistributedState.UpdateState(tempWorld -- tentacle) case tmp@_ => log.debug(s"No attack detected $tmp") } } From 5e9feacbd0b8a61e2e93419b82771f37eeb01635 Mon Sep 17 00:00:00 2001 From: Enrico Siboni Date: Tue, 24 Jul 2018 18:47:40 +0200 Subject: [PATCH 018/193] Added some doc to core classes and reorganized code --- .../it/cwmp/exceptions/HTTPException.scala | 3 +- .../authentication/ServerParameters.scala | 3 + .../roomreceiver/ServerParameters.scala | 3 + .../services/rooms/RoomApiWrapperUtils.scala | 59 +++++++-------- .../services/rooms/ServerParameters.scala | 3 + .../wrapper/AuthenticationApiWrapper.scala | 19 +++-- .../services/wrapper/RoomsApiWrapper.scala | 74 +++++++++++-------- 7 files changed, 93 insertions(+), 71 deletions(-) diff --git a/core/src/main/scala/it/cwmp/exceptions/HTTPException.scala b/core/src/main/scala/it/cwmp/exceptions/HTTPException.scala index e2957ba5..c611bf7b 100644 --- a/core/src/main/scala/it/cwmp/exceptions/HTTPException.scala +++ b/core/src/main/scala/it/cwmp/exceptions/HTTPException.scala @@ -6,8 +6,7 @@ package it.cwmp.exceptions * @param statusCode the HTTP code of error * @param getMessage the error message */ -sealed case class HTTPException(statusCode: Int, - override val getMessage: String = null) extends RuntimeException(getMessage) { +sealed case class HTTPException(statusCode: Int, override val getMessage: String = null) extends RuntimeException(getMessage) { /** * @return optionally the message of this Exception diff --git a/core/src/main/scala/it/cwmp/services/authentication/ServerParameters.scala b/core/src/main/scala/it/cwmp/services/authentication/ServerParameters.scala index f67ffed1..17ad8836 100644 --- a/core/src/main/scala/it/cwmp/services/authentication/ServerParameters.scala +++ b/core/src/main/scala/it/cwmp/services/authentication/ServerParameters.scala @@ -1,5 +1,8 @@ package it.cwmp.services.authentication +/** + * An object containing Authentication Service info + */ object ServerParameters { val DEFAULT_PORT = 8666 diff --git a/core/src/main/scala/it/cwmp/services/roomreceiver/ServerParameters.scala b/core/src/main/scala/it/cwmp/services/roomreceiver/ServerParameters.scala index beb6aa69..a567864f 100644 --- a/core/src/main/scala/it/cwmp/services/roomreceiver/ServerParameters.scala +++ b/core/src/main/scala/it/cwmp/services/roomreceiver/ServerParameters.scala @@ -1,5 +1,8 @@ package it.cwmp.services.roomreceiver +/** + * An object containing RoomReceiver Service info + */ object ServerParameters { def API_RECEIVE_PARTICIPANTS_URL(token: String) = s"/api/client/$token/room/participants" diff --git a/core/src/main/scala/it/cwmp/services/rooms/RoomApiWrapperUtils.scala b/core/src/main/scala/it/cwmp/services/rooms/RoomApiWrapperUtils.scala index 31fd527e..1a4946a4 100644 --- a/core/src/main/scala/it/cwmp/services/rooms/RoomApiWrapperUtils.scala +++ b/core/src/main/scala/it/cwmp/services/rooms/RoomApiWrapperUtils.scala @@ -3,21 +3,26 @@ package it.cwmp.services.rooms import io.vertx.core.buffer.Buffer import io.vertx.lang.scala.json.{Json, JsonArray, JsonObject} import io.vertx.scala.ext.web.client.{HttpResponse, WebClient} +import it.cwmp.model.Address.Converters._ import it.cwmp.model.{Address, Room} import it.cwmp.services.rooms.ServerParameters._ import it.cwmp.utils.VertxClient import scala.concurrent.Future +/** + * A trait that contains utility methods for a RoomApiWrapper + */ trait RoomApiWrapperUtils { this: VertxClient => /** * Wrapper method to do REST HTTP call to RoomsService createPrivateRoom API */ - protected def createPrivateRoomRequest(roomName: String, neededPlayers: Int)(implicit webClient: WebClient, userToken: String): Future[HttpResponse[Buffer]] = { - client.post(API_CREATE_PRIVATE_ROOM_URL).addAuthentication.sendJsonObjectFuture(roomForCreationJson(roomName, neededPlayers)) - } + protected def createPrivateRoomRequest(roomName: String, neededPlayers: Int) + (implicit webClient: WebClient, userToken: String): Future[HttpResponse[Buffer]] = + client.post(API_CREATE_PRIVATE_ROOM_URL).addAuthentication + .sendJsonObjectFuture(roomForCreationJson(roomName, neededPlayers)) /** * Handle method to create the JSON to use in creation API @@ -28,72 +33,60 @@ trait RoomApiWrapperUtils { /** * Wrapper method to do REST HTTP call to RoomsService enterPrivateRoom API */ - protected def enterPrivateRoomRequest(roomID: String, - userAddress: Address, - notificationAddress: Address) - (implicit webClient: WebClient, - userToken: String): Future[HttpResponse[Buffer]] = { + protected def enterPrivateRoomRequest(roomID: String, userAddress: Address, notificationAddress: Address) + (implicit webClient: WebClient, userToken: String): Future[HttpResponse[Buffer]] = client.put(API_ENTER_PRIVATE_ROOM_URL).addAuthentication - .setQueryParam(Room.FIELD_IDENTIFIER, roomID).sendJsonFuture(addressesForEnteringJson(userAddress, notificationAddress)) - } + .setQueryParam(Room.FIELD_IDENTIFIER, roomID) + .sendJsonFuture(addressesForEnteringJson(userAddress, notificationAddress)) /** * Wrapper method to do REST HTTP call to RoomsService privateRoomInfo API */ - protected def privateRoomInfoRequest(roomID: String)(implicit webClient: WebClient, userToken: String): Future[HttpResponse[Buffer]] = { + protected def privateRoomInfoRequest(roomID: String) + (implicit webClient: WebClient, userToken: String): Future[HttpResponse[Buffer]] = client.get(API_PRIVATE_ROOM_INFO_URL).addAuthentication .setQueryParam(Room.FIELD_IDENTIFIER, roomID).sendFuture() - } /** * Wrapper method to do REST HTTP call to RoomsService exitPrivateRoom API */ - protected def exitPrivateRoomRequest(roomID: String)(implicit webClient: WebClient, userToken: String): Future[HttpResponse[Buffer]] = { + protected def exitPrivateRoomRequest(roomID: String) + (implicit webClient: WebClient, userToken: String): Future[HttpResponse[Buffer]] = client.delete(API_EXIT_PRIVATE_ROOM_URL).addAuthentication .setQueryParam(Room.FIELD_IDENTIFIER, roomID).sendFuture() - } /** * Wrapper method to do REST HTTP call to RoomsService listPublicRooms API */ - protected def listPublicRoomsRequest()(implicit webClient: WebClient, userToken: String): Future[HttpResponse[Buffer]] = { - client.get(API_LIST_PUBLIC_ROOMS_URL).addAuthentication - .sendFuture() - } + protected def listPublicRoomsRequest()(implicit webClient: WebClient, userToken: String): Future[HttpResponse[Buffer]] = + client.get(API_LIST_PUBLIC_ROOMS_URL).addAuthentication.sendFuture() /** * Wrapper method to do REST HTTP call to RoomsService enterPublicRoom API */ - protected def enterPublicRoomRequest(playersNumber: Int, - userAddress: Address, - notificationAddress: Address) - (implicit webClient: WebClient, - userToken: String): Future[HttpResponse[Buffer]] = { + protected def enterPublicRoomRequest(playersNumber: Int, userAddress: Address, notificationAddress: Address) + (implicit webClient: WebClient, userToken: String): Future[HttpResponse[Buffer]] = client.put(API_ENTER_PUBLIC_ROOM_URL).addAuthentication - .setQueryParam(Room.FIELD_NEEDED_PLAYERS, playersNumber.toString).sendJsonFuture(addressesForEnteringJson(userAddress, notificationAddress)) - } + .setQueryParam(Room.FIELD_NEEDED_PLAYERS, playersNumber.toString) + .sendJsonFuture(addressesForEnteringJson(userAddress, notificationAddress)) /** * Handle method to create the JSON to use in entering API */ - protected def addressesForEnteringJson(playerAddress: Address, notificationAddress: Address): JsonArray = { - import Address.Converters._ - Json.arr(playerAddress.toJson, notificationAddress.toJson) - } + protected def addressesForEnteringJson(playerAddress: Address, notificationAddress: Address): JsonArray = + Json arr(playerAddress.toJson, notificationAddress.toJson) /** * Wrapper method to do REST HTTP call to RoomsService publicRoomInfo API */ - protected def publicRoomInfoRequest(playersNumber: Int)(implicit webClient: WebClient, userToken: String): Future[HttpResponse[Buffer]] = { + protected def publicRoomInfoRequest(playersNumber: Int)(implicit webClient: WebClient, userToken: String): Future[HttpResponse[Buffer]] = client.get(API_PUBLIC_ROOM_INFO_URL).addAuthentication .setQueryParam(Room.FIELD_NEEDED_PLAYERS, playersNumber.toString).sendFuture() - } /** * Wrapper method to do REST HTTP call to RoomsService exitPublicRoom API */ - protected def exitPublicRoomRequest(playersNumber: Int)(implicit webClient: WebClient, userToken: String): Future[HttpResponse[Buffer]] = { + protected def exitPublicRoomRequest(playersNumber: Int)(implicit webClient: WebClient, userToken: String): Future[HttpResponse[Buffer]] = client.delete(API_EXIT_PUBLIC_ROOM_URL).addAuthentication .setQueryParam(Room.FIELD_NEEDED_PLAYERS, playersNumber.toString).sendFuture() - } } diff --git a/core/src/main/scala/it/cwmp/services/rooms/ServerParameters.scala b/core/src/main/scala/it/cwmp/services/rooms/ServerParameters.scala index 066d4482..4eb4ae20 100644 --- a/core/src/main/scala/it/cwmp/services/rooms/ServerParameters.scala +++ b/core/src/main/scala/it/cwmp/services/rooms/ServerParameters.scala @@ -2,6 +2,9 @@ package it.cwmp.services.rooms import it.cwmp.model.Room +/** + * An object containing Rooms Service info + */ object ServerParameters { val DEFAULT_PORT = 8667 diff --git a/core/src/main/scala/it/cwmp/services/wrapper/AuthenticationApiWrapper.scala b/core/src/main/scala/it/cwmp/services/wrapper/AuthenticationApiWrapper.scala index f022c523..0643991a 100644 --- a/core/src/main/scala/it/cwmp/services/wrapper/AuthenticationApiWrapper.scala +++ b/core/src/main/scala/it/cwmp/services/wrapper/AuthenticationApiWrapper.scala @@ -3,34 +3,43 @@ package it.cwmp.services.wrapper import io.vertx.scala.ext.web.client.WebClientOptions import it.cwmp.exceptions.HTTPException import it.cwmp.model.User +import it.cwmp.services.authentication.ServerParameters._ import it.cwmp.utils.{Validation, VertxClient, VertxInstance} import scala.concurrent.Future +/** + * A trait describing the API wrapper for authentication service + */ trait AuthenticationApiWrapper extends Validation[String, User] { + // TODO: doc def signUp(username: String, password: String): Future[String] def login(username: String, password: String): Future[String] } +/** + * Companion object + */ object AuthenticationApiWrapper { val DEFAULT_HOST = "localhost" - import it.cwmp.services.authentication.ServerParameters._ - def apply(): AuthenticationApiWrapper = AuthenticationApiWrapper(DEFAULT_HOST, DEFAULT_PORT) + def apply(host: String): AuthenticationApiWrapper = + AuthenticationApiWrapper(host, DEFAULT_PORT) + def apply(host: String, port: Int): AuthenticationApiWrapper = new AuthenticationApiWrapperImpl(WebClientOptions() .setDefaultHost(host) .setDefaultPort(port)) - def apply(host: String): AuthenticationApiWrapper = - AuthenticationApiWrapper(host, DEFAULT_PORT) - + /** + * A default implementation class for Authentication API Wrapper + */ class AuthenticationApiWrapperImpl(override protected val clientOptions: WebClientOptions) extends AuthenticationApiWrapper with VertxInstance with VertxClient { diff --git a/core/src/main/scala/it/cwmp/services/wrapper/RoomsApiWrapper.scala b/core/src/main/scala/it/cwmp/services/wrapper/RoomsApiWrapper.scala index 55ac055e..fcd6c8d7 100644 --- a/core/src/main/scala/it/cwmp/services/wrapper/RoomsApiWrapper.scala +++ b/core/src/main/scala/it/cwmp/services/wrapper/RoomsApiWrapper.scala @@ -4,8 +4,10 @@ import io.vertx.core.buffer.Buffer import io.vertx.lang.scala.json.Json import io.vertx.scala.ext.web.client.{HttpResponse, WebClientOptions} import it.cwmp.exceptions.HTTPException +import it.cwmp.model.Room.Converters._ import it.cwmp.model.{Address, Room} import it.cwmp.services.rooms.RoomApiWrapperUtils +import it.cwmp.services.rooms.ServerParameters._ import it.cwmp.utils.{VertxClient, VertxInstance} import scala.concurrent.Future @@ -27,7 +29,8 @@ trait RoomsApiWrapper { * @return the future containing the identifier of the created room, * or fails if roomName is empty or playersNumber not correct */ - def createRoom(roomName: String, playersNumber: Int)(implicit userToken: String): Future[String] + def createRoom(roomName: String, playersNumber: Int) + (implicit userToken: String): Future[String] /** * Enters a room @@ -40,7 +43,8 @@ trait RoomsApiWrapper { * or fails if roomID not provided, not present * or user already inside a room, or room full */ - def enterRoom(roomID: String, userAddress: Address, notificationAddress: Address)(implicit userToken: String): Future[Unit] + def enterRoom(roomID: String, userAddress: Address, notificationAddress: Address) + (implicit userToken: String): Future[Unit] /** * Retrieves room information @@ -50,7 +54,8 @@ trait RoomsApiWrapper { * @return the future that completes when the room information is available, * or fails if room id not provided or not present */ - def roomInfo(roomID: String)(implicit userToken: String): Future[Room] + def roomInfo(roomID: String) + (implicit userToken: String): Future[Room] /** * Exits a room @@ -61,7 +66,8 @@ trait RoomsApiWrapper { * or fails if roomId is not provided or not present * or user is not inside that room */ - def exitRoom(roomID: String)(implicit userToken: String): Future[Unit] + def exitRoom(roomID: String) + (implicit userToken: String): Future[Unit] /** * retrieves a list of available public rooms @@ -82,7 +88,8 @@ trait RoomsApiWrapper { * or fails if players number is not correct, * or user already inside a room */ - def enterPublicRoom(playersNumber: Int, userAddress: Address, notificationAddress: Address)(implicit userToken: String): Future[Unit] + def enterPublicRoom(playersNumber: Int, userAddress: Address, notificationAddress: Address) + (implicit userToken: String): Future[Unit] /** * Retrieves information about a public room with specific number of players @@ -92,7 +99,8 @@ trait RoomsApiWrapper { * @return the future that completes when the information is available, * or fails if players number not correct */ - def publicRoomInfo(playersNumber: Int)(implicit userToken: String): Future[Room] + def publicRoomInfo(playersNumber: Int) + (implicit userToken: String): Future[Room] /** * Exits a public room @@ -103,7 +111,8 @@ trait RoomsApiWrapper { * or fails if players number is not correct, * or user not inside that room */ - def exitPublicRoom(playersNumber: Int)(implicit userToken: String): Future[Unit] + def exitPublicRoom(playersNumber: Int) + (implicit userToken: String): Future[Unit] } /** @@ -115,8 +124,6 @@ object RoomsApiWrapper { val DEFAULT_HOST = "localhost" - import it.cwmp.services.rooms.ServerParameters._ - def apply(): RoomsApiWrapper = RoomsApiWrapper(DEFAULT_HOST, DEFAULT_PORT) def apply(host: String): RoomsApiWrapper = RoomsApiWrapper(host, DEFAULT_PORT) @@ -134,22 +141,25 @@ object RoomsApiWrapper { private class RoomsApiWrapperDefault(override protected val clientOptions: WebClientOptions) extends RoomsApiWrapper with RoomApiWrapperUtils with VertxInstance with VertxClient { - override def createRoom(roomName: String, playersNumber: Int)(implicit userToken: String): Future[String] = + override def createRoom(roomName: String, playersNumber: Int) + (implicit userToken: String): Future[String] = createPrivateRoomRequest(roomName, playersNumber) .flatMap(implicit response => handleResponse(Future.successful(response.bodyAsString().get), 201)) - override def enterRoom(roomID: String, userAddress: Address, notificationAddress: Address)(implicit userToken: String): Future[Unit] = + override def enterRoom(roomID: String, userAddress: Address, notificationAddress: Address) + (implicit userToken: String): Future[Unit] = enterPrivateRoomRequest(roomID, userAddress, notificationAddress) .flatMap(implicit response => handleResponse(Future.successful(Unit), 200)) - override def roomInfo(roomID: String)(implicit userToken: String): Future[Room] = + override def roomInfo(roomID: String) + (implicit userToken: String): Future[Room] = privateRoomInfoRequest(roomID) .flatMap(implicit response => handleResponse({ - import Room.Converters._ Future.successful(Json.fromObjectString(response.bodyAsString().get).toRoom) }, 200)) - override def exitRoom(roomID: String)(implicit userToken: String): Future[Unit] = + override def exitRoom(roomID: String) + (implicit userToken: String): Future[Unit] = exitPrivateRoomRequest(roomID) .flatMap(implicit response => handleResponse(Future.successful(Unit), 200)) @@ -157,17 +167,34 @@ object RoomsApiWrapper { listPublicRoomsRequest() .flatMap(implicit response => handleResponse({ Future.successful { - import Room.Converters._ Json.fromArrayString(response.bodyAsString().get) .stream().toArray().toSeq.map(_.toString) .map(jsonString => Json.fromObjectString(jsonString).toRoom) } }, 200)) + override def enterPublicRoom(playersNumber: Int, userAddress: Address, notificationAddress: Address) + (implicit userToken: String): Future[Unit] = + enterPublicRoomRequest(playersNumber, userAddress, notificationAddress) + .flatMap(implicit response => handleResponse(Future.successful(Unit), 200)) + + override def publicRoomInfo(playersNumber: Int) + (implicit userToken: String): Future[Room] = + publicRoomInfoRequest(playersNumber) + .flatMap(implicit response => handleResponse({ + Future.successful(Json.fromObjectString(response.bodyAsString().get).toRoom) + }, 200)) + + override def exitPublicRoom(playersNumber: Int) + (implicit userToken: String): Future[Unit] = + exitPublicRoomRequest(playersNumber) + .flatMap(implicit response => handleResponse(Future.successful(Unit), 200)) + /** * Utility method to handle the Service response */ - private def handleResponse[T](onSuccessFuture: => Future[T], successHttpCodes: Int*)(implicit response: HttpResponse[Buffer]) = + private def handleResponse[T](onSuccessFuture: => Future[T], successHttpCodes: Int*) + (implicit response: HttpResponse[Buffer]) = successHttpCodes find (_ == response.statusCode) match { case Some(_) => onSuccessFuture case None => response.bodyAsString match { @@ -177,21 +204,6 @@ object RoomsApiWrapper { Future.failed(HTTPException(response.statusCode)) } } - - override def enterPublicRoom(playersNumber: Int, userAddress: Address, notificationAddress: Address)(implicit userToken: String): Future[Unit] = - enterPublicRoomRequest(playersNumber, userAddress, notificationAddress) - .flatMap(implicit response => handleResponse(Future.successful(Unit), 200)) - - override def publicRoomInfo(playersNumber: Int)(implicit userToken: String): Future[Room] = - publicRoomInfoRequest(playersNumber) - .flatMap(implicit response => handleResponse({ - import Room.Converters._ - Future.successful(Json.fromObjectString(response.bodyAsString().get).toRoom) - }, 200)) - - override def exitPublicRoom(playersNumber: Int)(implicit userToken: String): Future[Unit] = - exitPublicRoomRequest(playersNumber) - .flatMap(implicit response => handleResponse(Future.successful(Unit), 200)) } } \ No newline at end of file From aae17ea28678ce059e3bb4cfaa1011b7f473f280 Mon Sep 17 00:00:00 2001 From: Enrico Siboni Date: Tue, 24 Jul 2018 19:11:37 +0200 Subject: [PATCH 019/193] - Removed JsonFormat trait that wasn't used - Reformatted code and added doc --- .../src/main/scala/it/cwmp/testing/VertxTest.scala | 3 +-- .../main/scala/it/cwmp/utils/AdvancedLogging.scala | 12 ++++++++---- core/src/main/scala/it/cwmp/utils/JsonFormat.scala | 8 -------- core/src/main/scala/it/cwmp/utils/Utils.scala | 9 +++++++++ 4 files changed, 18 insertions(+), 14 deletions(-) delete mode 100644 core/src/main/scala/it/cwmp/utils/JsonFormat.scala diff --git a/core-testing/src/main/scala/it/cwmp/testing/VertxTest.scala b/core-testing/src/main/scala/it/cwmp/testing/VertxTest.scala index 1dd4592a..5e87dbbb 100644 --- a/core-testing/src/main/scala/it/cwmp/testing/VertxTest.scala +++ b/core-testing/src/main/scala/it/cwmp/testing/VertxTest.scala @@ -8,5 +8,4 @@ import org.scalatest.AsyncFunSpec * * @author Enrico Siboni */ -abstract class VertxTest extends AsyncFunSpec with VertxInstance { -} +abstract class VertxTest extends AsyncFunSpec with VertxInstance diff --git a/core/src/main/scala/it/cwmp/utils/AdvancedLogging.scala b/core/src/main/scala/it/cwmp/utils/AdvancedLogging.scala index bbe62d4e..9c449ef4 100644 --- a/core/src/main/scala/it/cwmp/utils/AdvancedLogging.scala +++ b/core/src/main/scala/it/cwmp/utils/AdvancedLogging.scala @@ -26,7 +26,8 @@ trait AdvancedLogging extends Logging { * @param executionContext the implicit execution context on which to execute the operation. * @return The future itself. */ - def logSuccessInfo(message: String)(implicit executionContext: ExecutionContext): Future[T] = + def logSuccessInfo(message: String) + (implicit executionContext: ExecutionContext): Future[T] = future.andThen { case Success(_) => log.info(message) } @@ -39,7 +40,8 @@ trait AdvancedLogging extends Logging { * @param executionContext the implicit execution context on which to execute the operation. * @return The future itself. */ - def logSuccessInfo(message: String, condition: T => Boolean)(implicit executionContext: ExecutionContext): Future[T] = + def logSuccessInfo(message: String, condition: T => Boolean) + (implicit executionContext: ExecutionContext): Future[T] = future.andThen { case Success(s) if condition(s) => log.info(message) } @@ -51,7 +53,8 @@ trait AdvancedLogging extends Logging { * @param executionContext the implicit execution context on which to execute the operation. * @return The future itself. */ - def logFailureInfo(message: String)(implicit executionContext: ExecutionContext): Future[T] = + def logFailureInfo(message: String) + (implicit executionContext: ExecutionContext): Future[T] = future.andThen { case Failure(e) => log.info(message, e) } @@ -64,7 +67,8 @@ trait AdvancedLogging extends Logging { * @param executionContext the implicit execution context on which to execute the operation. * @return The future itself. */ - def logFailureInfo[A <: Exception : ClassTag](message: String)(implicit executionContext: ExecutionContext): Future[T] = + def logFailureInfo[A <: Exception : ClassTag](message: String) + (implicit executionContext: ExecutionContext): Future[T] = future.andThen { case Failure(e) if classTag[A].runtimeClass.isInstance(e) => log.info(message, e) } diff --git a/core/src/main/scala/it/cwmp/utils/JsonFormat.scala b/core/src/main/scala/it/cwmp/utils/JsonFormat.scala deleted file mode 100644 index c24fd343..00000000 --- a/core/src/main/scala/it/cwmp/utils/JsonFormat.scala +++ /dev/null @@ -1,8 +0,0 @@ -package it.cwmp.utils - -import io.vertx.lang.scala.json.JsonObject - -trait JsonFormat { - - def toJson: JsonObject -} diff --git a/core/src/main/scala/it/cwmp/utils/Utils.scala b/core/src/main/scala/it/cwmp/utils/Utils.scala index 40e7d5fe..cf07be72 100644 --- a/core/src/main/scala/it/cwmp/utils/Utils.scala +++ b/core/src/main/scala/it/cwmp/utils/Utils.scala @@ -2,8 +2,17 @@ package it.cwmp.utils import java.text.ParseException +/** + * Generic utilities that can be used anywhere + */ object Utils { + /** + * Generates a random string of specified length + * + * @param length the length of the random String + * @return the random string + */ def randomString(length: Int): String = scala.util.Random.alphanumeric.take(length).mkString /** From b4c22ea31e152fec5dd0145b1318e71ffd806c10 Mon Sep 17 00:00:00 2001 From: Enrico Siboni Date: Tue, 24 Jul 2018 19:12:27 +0200 Subject: [PATCH 020/193] Solved Warnings of Vertx during tests, checking if a vertx instance is already present before creating another --- core/src/main/scala/it/cwmp/utils/VertxInstance.scala | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/core/src/main/scala/it/cwmp/utils/VertxInstance.scala b/core/src/main/scala/it/cwmp/utils/VertxInstance.scala index 70f50ae6..74e31a54 100644 --- a/core/src/main/scala/it/cwmp/utils/VertxInstance.scala +++ b/core/src/main/scala/it/cwmp/utils/VertxInstance.scala @@ -11,6 +11,8 @@ import io.vertx.scala.core.Vertx * @author Eugenio Pierfederici */ trait VertxInstance { - val vertx: Vertx = Vertx.vertx - implicit val vertxExecutionContext: VertxExecutionContext = VertxExecutionContext(vertx.getOrCreateContext()) + private val vertxContext = Vertx.currentContext().getOrElse(Vertx.vertx.getOrCreateContext()) + + val vertx: Vertx = vertxContext.owner() + implicit val vertxExecutionContext: VertxExecutionContext = VertxExecutionContext(vertxContext) } From acd2c7bd0b7639d27151bd869a52d53eb41cc9ec Mon Sep 17 00:00:00 2001 From: Enrico Siboni Date: Tue, 24 Jul 2018 19:36:47 +0200 Subject: [PATCH 021/193] - Moved a utility conversion from Seq to JsonArray in general VertxJDBC trait so it can be used in other parts of the project - Added our logging to RoomsLocalDAO and reformatted code --- .../scala/it/cwmp/utils/VertxClient.scala | 9 +- .../main/scala/it/cwmp/utils/VertxJDBC.scala | 24 ++++- .../cwmp/services/rooms/RoomsLocalDAO.scala | 95 +++++++++---------- 3 files changed, 70 insertions(+), 58 deletions(-) diff --git a/core/src/main/scala/it/cwmp/utils/VertxClient.scala b/core/src/main/scala/it/cwmp/utils/VertxClient.scala index dea4db6b..2d180f57 100644 --- a/core/src/main/scala/it/cwmp/utils/VertxClient.scala +++ b/core/src/main/scala/it/cwmp/utils/VertxClient.scala @@ -1,9 +1,11 @@ package it.cwmp.utils +import io.netty.handler.codec.http.HttpHeaderNames import io.vertx.scala.ext.web.client.{HttpRequest, HttpResponse, WebClient, WebClientOptions} import it.cwmp.exceptions.HTTPException import scala.concurrent.Future +import scala.language.implicitConversions import scala.util.{Failure, Success} /** @@ -52,10 +54,7 @@ trait VertxClient { /** * An implicit class to provide the [[HttpRequest]] with some more useful utilities. */ - - import io.netty.handler.codec.http.HttpHeaderNames - - implicit class richHttpRequest[T](request: HttpRequest[T]) { + implicit class RichHttpRequest[T](request: HttpRequest[T]) { /** * Simplified way to add the basic Authorization header with the provided username and password @@ -84,7 +83,7 @@ trait VertxClient { /** * An implicit class to provide the Future[HttpResponse] with some more useful utilities. */ - implicit class richHttpResponse[T](response: Future[HttpResponse[T]]) { + implicit class RichHttpResponse[T](response: Future[HttpResponse[T]]) { /** * Causes the future to fail if the status code if different from one of those passed diff --git a/core/src/main/scala/it/cwmp/utils/VertxJDBC.scala b/core/src/main/scala/it/cwmp/utils/VertxJDBC.scala index 5761bc82..ffe75184 100644 --- a/core/src/main/scala/it/cwmp/utils/VertxJDBC.scala +++ b/core/src/main/scala/it/cwmp/utils/VertxJDBC.scala @@ -1,10 +1,12 @@ package it.cwmp.utils +import io.vertx.lang.scala.json.JsonArray import io.vertx.scala.ext.jdbc.JDBCClient import io.vertx.scala.ext.sql.SQLConnection import scala.collection.mutable.ListBuffer import scala.concurrent.{ExecutionContext, Future} +import scala.language.implicitConversions import scala.util.Success /** @@ -21,7 +23,7 @@ trait VertxJDBC { private val clientFuture: Future[JDBCClient] = vertx.fileSystem.readFileFuture(configurationPath) - .recoverWith { case _ => vertx.fileSystem.readFileFuture("database/jdbc_config.json") } + .recoverWith { case _ => vertx.fileSystem.readFileFuture(DEFAULT_CONFIG_PATH) } .map(_.toJsonObject) .map(JDBCClient.createShared(vertx, _)) @@ -68,9 +70,23 @@ trait VertxJDBC { * @return the future itself */ def closeConnections(implicit executionContext: ExecutionContext): Future[F] = - future.andThen { - case _ => closeAllConnections() - } + future.andThen { case _ => closeAllConnections() } } } + + +/** + * Companion object + */ +object VertxJDBC { + + /** + * Implicit conversion to jsonArray + * + * @return the converted data + */ + implicit def stringsToJsonArray(arguments: Iterable[String]): JsonArray = { // TODO: import and use this in AuthDAO + arguments.foldLeft(new JsonArray)(_.add(_)) + } +} diff --git a/services/rooms/src/main/scala/it/cwmp/services/rooms/RoomsLocalDAO.scala b/services/rooms/src/main/scala/it/cwmp/services/rooms/RoomsLocalDAO.scala index 2cfc9392..4e579a30 100644 --- a/services/rooms/src/main/scala/it/cwmp/services/rooms/RoomsLocalDAO.scala +++ b/services/rooms/src/main/scala/it/cwmp/services/rooms/RoomsLocalDAO.scala @@ -1,11 +1,11 @@ package it.cwmp.services.rooms -import com.typesafe.scalalogging.Logger -import io.vertx.lang.scala.json.JsonArray import io.vertx.scala.ext.sql.{ResultSet, SQLConnection} import it.cwmp.model.{Address, Participant, Room, User} import it.cwmp.services.rooms.RoomsLocalDAO._ -import it.cwmp.utils.{Utils, VertxInstance, VertxJDBC} +import it.cwmp.utils.Utils.emptyString +import it.cwmp.utils.VertxJDBC.stringsToJsonArray +import it.cwmp.utils.{Logging, VertxInstance, VertxJDBC} import scala.collection.mutable import scala.concurrent.{ExecutionContext, Future} @@ -39,7 +39,8 @@ trait RoomDAO { * or fails if roomID not provided, not present * or user already inside a room, or room full */ - def enterRoom(roomID: String)(implicit user: Participant, notificationAddress: Address): Future[Unit] + def enterRoom(roomID: String) + (implicit user: Participant, notificationAddress: Address): Future[Unit] /** * Retrieves room information, and related user notification addresses @@ -59,7 +60,8 @@ trait RoomDAO { * or fails if roomId is not provided or not present * or user is not inside that room */ - def exitRoom(roomID: String)(implicit user: User): Future[Unit] + def exitRoom(roomID: String) + (implicit user: User): Future[Unit] /** * retrieves a list of available public rooms @@ -78,7 +80,8 @@ trait RoomDAO { * or fails if players number is not correct, * or user already inside a room */ - def enterPublicRoom(playersNumber: Int)(implicit user: Participant, notificationAddress: Address): Future[Unit] + def enterPublicRoom(playersNumber: Int) + (implicit user: Participant, notificationAddress: Address): Future[Unit] /** * Retrieves information about a public room with specific number of players, and relative user notification addresses @@ -98,7 +101,8 @@ trait RoomDAO { * or fails if players number is not correct, * or user not inside that room */ - def exitPublicRoom(playersNumber: Int)(implicit user: User): Future[Unit] + def exitPublicRoom(playersNumber: Int) + (implicit user: User): Future[Unit] /** * Deletes a room if it's full @@ -126,7 +130,9 @@ trait RoomDAO { * * @author Enrico Siboni */ -case class RoomsLocalDAO(override val configurationPath: String = "rooms/database.json") extends RoomDAO with VertxInstance with VertxJDBC { +case class RoomsLocalDAO(override val configurationPath: String = "rooms/database.json") extends RoomDAO + with VertxInstance with VertxJDBC with Logging { + private var notInitialized = true private val PUBLIC_ROOM_MAX_SIZE = 4 @@ -139,10 +145,8 @@ case class RoomsLocalDAO(override val configurationPath: String = "rooms/databas private val NOT_INSIDE_USER_ERROR = "The user is not inside that room: " private val DELETING_NON_FULL_ROOM_ERROR = "Cannot delete room if it's not full" - import RoomsLocalDAO.stringsToJsonArray - def initialize(): Future[Unit] = { - logger.info("Initializing RoomLocalDAO...") + log.info("Initializing RoomLocalDAO...") def createDefaultPublicRooms(conn: SQLConnection) = Future.sequence { // waits all creation future to end, or returns the failed one @@ -157,16 +161,16 @@ case class RoomsLocalDAO(override val configurationPath: String = "rooms/databas .flatMap(_ => listPublicRooms()) .filter(_.isEmpty) .flatMap(_ => { - logger.info(s"No public rooms found, creating public ones with players from 2 to $PUBLIC_ROOM_MAX_SIZE.") + log.info(s"No public rooms found, creating public ones with players from 2 to $PUBLIC_ROOM_MAX_SIZE.") createDefaultPublicRooms(conn) }) - .recover { case _: NoSuchElementException => logger.info("Room database already exists, skipping creation.") } + .recover { case _: NoSuchElementException => log.info("Room database already exists, skipping creation.") } .andThen { case _ => conn.close() }) .flatMap(_ => Future.successful(())) } override def createRoom(roomName: String, playersNumber: Int): Future[String] = { - logger.debug(s"createRoom() roomName:$roomName, playersNumber:$playersNumber") + log.debug(s"createRoom() roomName:$roomName, playersNumber:$playersNumber") checkInitialization(notInitialized) .flatMap(_ => stringCheckFuture(roomName, EMPTY_ROOM_NAME_ERROR)) .flatMap(_ => playersNumberCheck(playersNumber, s"$INVALID_PLAYERS_NUMBER$playersNumber")) @@ -178,8 +182,9 @@ case class RoomsLocalDAO(override val configurationPath: String = "rooms/databas ) } - override def enterRoom(roomID: String)(implicit user: Participant, notificationAddress: Address): Future[Unit] = { - logger.debug(s"enterRoom() roomID:$roomID, user:$user, notificationAddress:$notificationAddress") + override def enterRoom(roomID: String) + (implicit user: Participant, notificationAddress: Address): Future[Unit] = { + log.debug(s"enterRoom() roomID:$roomID, user:$user, notificationAddress:$notificationAddress") checkInitialization(notInitialized) .flatMap(_ => roomInfo(roomID)) .flatMap(_ => openConnection()) @@ -195,7 +200,7 @@ case class RoomsLocalDAO(override val configurationPath: String = "rooms/databas } override def roomInfo(roomID: String): Future[(Room, Seq[Address])] = { - logger.debug(s"roomInfo() roomID:$roomID") + log.debug(s"roomInfo() roomID:$roomID") checkInitialization(notInitialized) .flatMap(_ => stringCheckFuture(roomID, EMPTY_ROOM_ID_ERROR)) .flatMap(_ => openConnection()) @@ -205,8 +210,9 @@ case class RoomsLocalDAO(override val configurationPath: String = "rooms/databas .andThen { case _ => conn.close() }) } - override def exitRoom(roomID: String)(implicit user: User): Future[Unit] = { - logger.debug(s"exitRoom() roomID:$roomID, user:$user") + override def exitRoom(roomID: String) + (implicit user: User): Future[Unit] = { + log.debug(s"exitRoom() roomID:$roomID, user:$user") checkInitialization(notInitialized) .flatMap(_ => roomInfo(roomID)) .flatMap(_ => openConnection()) @@ -221,7 +227,7 @@ case class RoomsLocalDAO(override val configurationPath: String = "rooms/databas } override def listPublicRooms(): Future[Seq[Room]] = { - logger.debug("listPublicRooms()") + log.debug("listPublicRooms()") checkInitialization(notInitialized) .flatMap(_ => openConnection()) .flatMap(conn => conn.queryFuture(selectAllPublicRoomsSql) @@ -229,29 +235,31 @@ case class RoomsLocalDAO(override val configurationPath: String = "rooms/databas .map(resultOfJoinToRooms).map(_.map(_._1)) } - override def enterPublicRoom(playersNumber: Int)(implicit user: Participant, address: Address): Future[Unit] = { - logger.debug(s"enterPublicRoom() playersNumber:$playersNumber, user:$user, address:$address") + override def enterPublicRoom(playersNumber: Int) + (implicit user: Participant, address: Address): Future[Unit] = { + log.debug(s"enterPublicRoom() playersNumber:$playersNumber, user:$user, address:$address") checkInitialization(notInitialized) .flatMap(_ => publicRoomIdFromPlayersNumber(playersNumber)) .flatMap(enterRoom(_)(user, address)) } override def publicRoomInfo(playersNumber: Int): Future[(Room, Seq[Address])] = { - logger.debug(s"publicRoomInfo() playersNumber:$playersNumber") + log.debug(s"publicRoomInfo() playersNumber:$playersNumber") checkInitialization(notInitialized) .flatMap(_ => publicRoomIdFromPlayersNumber(playersNumber)) .flatMap(roomInfo) } - override def exitPublicRoom(playersNumber: Int)(implicit user: User): Future[Unit] = { - logger.debug(s"exitPublicRoom() playersNumber:$playersNumber, user:$user") + override def exitPublicRoom(playersNumber: Int) + (implicit user: User): Future[Unit] = { + log.debug(s"exitPublicRoom() playersNumber:$playersNumber, user:$user") checkInitialization(notInitialized) .flatMap(_ => publicRoomIdFromPlayersNumber(playersNumber)) .flatMap(exitRoom) } override def deleteRoom(roomID: String): Future[Unit] = { - logger.debug(s"deleteRoom() roomID:$roomID") + log.debug(s"deleteRoom() roomID:$roomID") checkInitialization(notInitialized) .flatMap(_ => roomInfo(roomID)).map(_._1) .flatMap(room => openConnection() @@ -269,7 +277,7 @@ case class RoomsLocalDAO(override val configurationPath: String = "rooms/databas } override def deleteAndRecreatePublicRoom(playersNumber: Int): Future[Unit] = { - logger.debug(s"deleteAndRecreatePublicRoom() playersNumber:$playersNumber") + log.debug(s"deleteAndRecreatePublicRoom() playersNumber:$playersNumber") checkInitialization(notInitialized) .flatMap(_ => publicRoomIdFromPlayersNumber(playersNumber)) .flatMap(deleteRoom) @@ -298,7 +306,6 @@ case class RoomsLocalDAO(override val configurationPath: String = "rooms/databas * Companion Object */ object RoomsLocalDAO { - private val logger: Logger = Logger[RoomsLocalDAO] val publicPrefix: String = "public" @@ -361,6 +368,7 @@ object RoomsLocalDAO { private def getNotAlreadyPresentRoomID(connection: SQLConnection, generator: => String) (implicit executionContext: ExecutionContext): Future[String] = { + //noinspection ScalaStyle def _getNotAlreadyPresentRoomID(toCheckID: String, connection: SQLConnection): Future[String] = checkRoomPresence(toCheckID, connection, "") .flatMap(_ => _getNotAlreadyPresentRoomID(generator, connection)) @@ -425,15 +433,6 @@ object RoomsLocalDAO { ) yield output).toSeq } - /** - * Implicit conversion to jsonArray - * - * @return the converted data - */ - protected implicit def stringsToJsonArray(arguments: Iterable[String]): JsonArray = { - arguments.foldLeft(new JsonArray)(_.add(_)) - } - /** * Method that generates a random room identifier */ @@ -442,10 +441,10 @@ object RoomsLocalDAO { /** * @return a succeeded Future if string is ok, a failed Future otherwise */ - private def stringCheckFuture(toCheck: String, errorMessage: String): Future[Unit] = Future { - import Utils.emptyString - require(!emptyString(toCheck), errorMessage) - }(ExecutionContext.Implicits.global) + private def stringCheckFuture(toCheck: String, errorMessage: String): Future[Unit] = + Future { + require(!emptyString(toCheck), errorMessage) + }(ExecutionContext.Implicits.global) /** * @return a succeeded Future if playersNumber is correct, a failed Future otherwise @@ -457,9 +456,8 @@ object RoomsLocalDAO { /** * @return a succeeded future if the room with given ID is present, a failed future otherwise */ - private def checkRoomPresence(roomID: String, - connection: SQLConnection, - errorMessage: String)(implicit executionContext: ExecutionContext): Future[Unit] = { + private def checkRoomPresence(roomID: String, connection: SQLConnection, errorMessage: String) + (implicit executionContext: ExecutionContext): Future[Unit] = { connection.queryWithParamsFuture(selectARoomIDSql, Seq(roomID)) .flatMap(_.getResults.size match { case 0 => Future.failed(new NoSuchElementException(errorMessage)) @@ -472,8 +470,8 @@ object RoomsLocalDAO { * * @return the future that completes when the room is created */ - private def createPublicRoom(connection: SQLConnection, - playersNumber: Int)(implicit executionContext: ExecutionContext): Future[Unit] = { + private def createPublicRoom(connection: SQLConnection, playersNumber: Int) + (implicit executionContext: ExecutionContext): Future[Unit] = { getNotAlreadyPresentRoomID(connection, s"$publicPrefix${generateRandomRoomID()}") .flatMap(publicRoomID => connection.updateWithParamsFuture(insertNewRoomSql, Seq(publicRoomID, s"$publicPrefix$playersNumber", playersNumber.toString))) @@ -483,9 +481,8 @@ object RoomsLocalDAO { /** * @return a succeeded future if the room has available space for other users */ - private def checkRoomSpaceAvailable(roomID: String, - connection: SQLConnection, - errorMessage: String)(implicit executionContext: ExecutionContext): Future[Unit] = { + private def checkRoomSpaceAvailable(roomID: String, connection: SQLConnection, errorMessage: String) + (implicit executionContext: ExecutionContext): Future[Unit] = { connection.queryWithParamsFuture(selectRoomByIDSql, Seq(roomID)) .map(resultOfJoinToRooms(_).map(_._1)) .flatMap(_.head match { From a35be66c1713dcc998e12a73d6308e97208caa92 Mon Sep 17 00:00:00 2001 From: Enrico Siboni Date: Tue, 24 Jul 2018 19:51:36 +0200 Subject: [PATCH 022/193] - Added doc - Reformatted code and added error message in VertxServer --- .../scala/it/cwmp/utils/VertxServer.scala | 49 ++++++++++++++----- .../AuthenticationServiceVerticle.scala | 8 +-- 2 files changed, 40 insertions(+), 17 deletions(-) diff --git a/core/src/main/scala/it/cwmp/utils/VertxServer.scala b/core/src/main/scala/it/cwmp/utils/VertxServer.scala index 36e0a137..77ccc355 100644 --- a/core/src/main/scala/it/cwmp/utils/VertxServer.scala +++ b/core/src/main/scala/it/cwmp/utils/VertxServer.scala @@ -1,16 +1,17 @@ package it.cwmp.utils +import io.netty.handler.codec.http.HttpHeaderNames import io.vertx.lang.scala.ScalaVerticle import io.vertx.scala.core.http.{HttpServer, HttpServerRequest, HttpServerResponse} import io.vertx.scala.ext.web.{Router, RoutingContext} import it.cwmp.exceptions.HTTPException import it.cwmp.model.User +import it.cwmp.utils.VertxServer.NO_AUTH_HEADER_IN_REQUEST_ERROR import scala.concurrent.Future import scala.util.{Failure, Success} /** - * * This is a Utility trait that simplifies the creation and management of a vertx server. * * @author Eugenio Pierfederici @@ -35,10 +36,23 @@ trait VertxServer extends ScalaVerticle { } } + /** + * Initializes the server + * + * @return the future that completes when the server is initialized + */ protected def initServer: Future[_] = Future.successful(()) + /** + * @return the server port + */ protected def serverPort: Int + /** + * Initializes the server router for requests + * + * @param router the router to initialize + */ protected def initRouter(router: Router): Unit /** @@ -74,9 +88,9 @@ trait VertxServer extends ScalaVerticle { * @param routingContext the routing context on which to extract * @return the extracted room name */ - protected def getRequestParameter(paramName: String)(implicit routingContext: RoutingContext): Option[String] = { + protected def getRequestParameter(paramName: String) + (implicit routingContext: RoutingContext): Option[String] = request.getParam(paramName) - } /** * Utility method to obtain the request object @@ -89,22 +103,21 @@ trait VertxServer extends ScalaVerticle { /** * An implicit class to provide the [[HttpServerRequest]] with some more useful utilities. */ - - import io.netty.handler.codec.http.HttpHeaderNames - - implicit class richHttpRequest(request: HttpServerRequest) { + implicit class RichHttpRequest(request: HttpServerRequest) { /** * This is a utility method that checks if the request is authenticated. * For the check it uses the validation strategy given. - * @param strategy the validation strategy to use. + * + * @param strategy the validation strategy to use. * @param routingContext the routing context in which to execute the check. * @return A future containing the authenticated user, if present, otherwise it fails with a [[HTTPException]] */ - def checkAuthentication(implicit strategy: Validation[String, User], routingContext: RoutingContext): Future[User] = getAuthentication match { + def checkAuthentication(implicit strategy: Validation[String, User], + routingContext: RoutingContext): Future[User] = getAuthentication match { case None => - log.warn("No authorization header in request") - Future.failed(HTTPException(400)) + log.warn(NO_AUTH_HEADER_IN_REQUEST_ERROR) + Future.failed(HTTPException(400, NO_AUTH_HEADER_IN_REQUEST_ERROR)) case Some(authentication) => strategy.validate(authentication) } @@ -113,11 +126,13 @@ trait VertxServer extends ScalaVerticle { * For the check it uses the validation strategy given. * If it fails with any [[HTTPException]], then it responds to the request * with the status code and message specified in the exception. - * @param strategy the validation strategy to use. + * + * @param strategy the validation strategy to use. * @param routingContext the routing context in which to execute the check. * @return A future containing the authenticated user, if present */ - def checkAuthenticationOrReject(implicit strategy: Validation[String, User], routingContext: RoutingContext): Future[User] = + def checkAuthenticationOrReject(implicit strategy: Validation[String, User], + routingContext: RoutingContext): Future[User] = checkAuthentication(strategy, routingContext).recoverWith { case HTTPException(statusCode, errorMessage) => sendResponse(statusCode, errorMessage) @@ -126,9 +141,17 @@ trait VertxServer extends ScalaVerticle { /** * Reads the authorization token in the request. + * * @return An optional containing the header, if present. Otherwise None */ def getAuthentication: Option[String] = request.getHeader(HttpHeaderNames.AUTHORIZATION.toString) } +} + +/** + * Comppanion object + */ +object VertxServer { + private val NO_AUTH_HEADER_IN_REQUEST_ERROR = "No authorization header in request!" } \ No newline at end of file diff --git a/services/authentication/src/main/scala/it/cwmp/services/authentication/AuthenticationServiceVerticle.scala b/services/authentication/src/main/scala/it/cwmp/services/authentication/AuthenticationServiceVerticle.scala index bde9a54f..757eeb4b 100644 --- a/services/authentication/src/main/scala/it/cwmp/services/authentication/AuthenticationServiceVerticle.scala +++ b/services/authentication/src/main/scala/it/cwmp/services/authentication/AuthenticationServiceVerticle.scala @@ -2,20 +2,20 @@ package it.cwmp.services.authentication import io.vertx.core.Handler import io.vertx.scala.ext.web.{Router, RoutingContext} +import it.cwmp.services.authentication.ServerParameters._ import it.cwmp.services.authentication.storage.StorageAsync import it.cwmp.utils.{HttpUtils, Logging, VertxServer} import scala.concurrent.Future import scala.util.{Failure, Success} +/** + * Class that implements the Authentication micro-service + */ case class AuthenticationServiceVerticle() extends VertxServer with Logging { - import it.cwmp.services.authentication.ServerParameters._ - override protected val serverPort: Int = DEFAULT_PORT - import it.cwmp.services.authentication.ServerParameters._ - private var storageFuture: Future[StorageAsync] = _ override protected def initRouter(router: Router): Unit = { From fd6c864f8a95e8e309a443fb9dac719619fbce9f Mon Sep 17 00:00:00 2001 From: Enrico Siboni Date: Tue, 24 Jul 2018 19:59:34 +0200 Subject: [PATCH 023/193] Added doc to core-testing classes --- .../scala/it/cwmp/testing/FutureMatchers.scala | 15 ++++++++++++++- .../scala/it/cwmp/testing/HttpMatchers.scala | 17 +++++++++++------ .../testing/VerticleBeforeAndAfterAll.scala | 6 +++++- .../testing/VerticleBeforeAndAfterEach.scala | 6 +++++- .../scala/it/cwmp/testing/VerticleTest.scala | 14 ++++++++------ 5 files changed, 43 insertions(+), 15 deletions(-) diff --git a/core-testing/src/main/scala/it/cwmp/testing/FutureMatchers.scala b/core-testing/src/main/scala/it/cwmp/testing/FutureMatchers.scala index c2f151e3..a02cb255 100644 --- a/core-testing/src/main/scala/it/cwmp/testing/FutureMatchers.scala +++ b/core-testing/src/main/scala/it/cwmp/testing/FutureMatchers.scala @@ -16,12 +16,22 @@ import scala.util.{Failure, Success} trait FutureMatchers { this: Matchers => + /** + * An exception thrown by FutureMatchers when failed + */ case object FutureTestingException extends Exception + /** + * A class that enables to rapidly test futures + * + * @param future the future to test + * @tparam T the type of future result + */ implicit class RichFutureTesting[T](future: Future[T]) extends Matchers { /** * Asserts that the future has any sort of failure. + * * @param executionContext the implicit execution context * @return the future containing the result of the verification */ @@ -33,11 +43,12 @@ trait FutureMatchers { /** * Asserts that the future has the failure requested + * * @param executionContext the implicit execution context * @tparam A the type of failure that should be obtained * @return the future containing the result of the verification */ - def shouldFailWith[A <: Exception: ClassTag](implicit executionContext: ExecutionContext): Future[Assertion] = future + def shouldFailWith[A <: Exception : ClassTag](implicit executionContext: ExecutionContext): Future[Assertion] = future .transform { case Failure(e) if classTag[A].runtimeClass.isInstance(e) => Success(succeed) case _ => Failure(FutureTestingException) @@ -45,10 +56,12 @@ trait FutureMatchers { /** * Asserts that the future succeed. + * * @param executionContext the implicit execution context * @return the future containing the result of the verification */ def shouldSucceed(implicit executionContext: ExecutionContext): Future[Assertion] = future .map(_ => succeed) } + } diff --git a/core-testing/src/main/scala/it/cwmp/testing/HttpMatchers.scala b/core-testing/src/main/scala/it/cwmp/testing/HttpMatchers.scala index 65b94e79..87e49aeb 100644 --- a/core-testing/src/main/scala/it/cwmp/testing/HttpMatchers.scala +++ b/core-testing/src/main/scala/it/cwmp/testing/HttpMatchers.scala @@ -25,23 +25,28 @@ trait HttpMatchers { /** * Asserts that the future succeed (the response is returned) and that the server responded with the * specified status code. - * @param statusCode the status code that the server should return + * + * @param statusCode the status code that the server should return * @param executionContext the implicit execution context * @return the future containing the result of the verification */ - def shouldAnswerWith(statusCode: Int)(implicit executionContext: ExecutionContext): Future[Assertion] = toCheck - .map(_.statusCode() shouldBe statusCode) + def shouldAnswerWith(statusCode: Int) + (implicit executionContext: ExecutionContext): Future[Assertion] = + toCheck.map(_.statusCode() shouldBe statusCode) /** * Asserts that the future succeed (the response is returned) and that the server responded with the * specified status code and that the body respects the rule specified in the strategy. - * @param statusCode the status code that the server should return - * @param strategy the strategy that should be used to validate the body + * + * @param statusCode the status code that the server should return + * @param strategy the strategy that should be used to validate the body * @param executionContext the implicit execution context * @return the future containing the result of the verification */ - def shouldAnswerWith(statusCode: Int, strategy: Option[String] => Boolean)(implicit executionContext: ExecutionContext): Future[Assertion] = toCheck + def shouldAnswerWith(statusCode: Int, strategy: Option[String] => Boolean) + (implicit executionContext: ExecutionContext): Future[Assertion] = toCheck .map(response => assert(response.statusCode() == statusCode && strategy(response.bodyAsString()))) } + } diff --git a/core-testing/src/main/scala/it/cwmp/testing/VerticleBeforeAndAfterAll.scala b/core-testing/src/main/scala/it/cwmp/testing/VerticleBeforeAndAfterAll.scala index e1744574..803c01b5 100644 --- a/core-testing/src/main/scala/it/cwmp/testing/VerticleBeforeAndAfterAll.scala +++ b/core-testing/src/main/scala/it/cwmp/testing/VerticleBeforeAndAfterAll.scala @@ -3,16 +3,20 @@ package it.cwmp.testing import io.vertx.lang.scala.ScalaVerticle import org.scalatest.BeforeAndAfterAll +/** + * A trait that makes possible to deploy a bunch of verticles before all tests and un-deploy after all + */ trait VerticleBeforeAndAfterAll extends VerticleTest with BeforeAndAfterAll { this: VertxTest => /** * It contains the list of verticles to deploy before all the tests. + * * @return a [[Traversable]] containing all the verticles to deploy */ protected def verticlesBeforeAll: Traversable[ScalaVerticle] - override protected def beforeAll(): Unit = { + override protected def beforeAll(): Unit = { super.beforeAll() deployAll(verticlesBeforeAll) } diff --git a/core-testing/src/main/scala/it/cwmp/testing/VerticleBeforeAndAfterEach.scala b/core-testing/src/main/scala/it/cwmp/testing/VerticleBeforeAndAfterEach.scala index c16eebde..5fa95c3d 100644 --- a/core-testing/src/main/scala/it/cwmp/testing/VerticleBeforeAndAfterEach.scala +++ b/core-testing/src/main/scala/it/cwmp/testing/VerticleBeforeAndAfterEach.scala @@ -3,16 +3,20 @@ package it.cwmp.testing import io.vertx.lang.scala.ScalaVerticle import org.scalatest.BeforeAndAfterEach +/** + * A trait that makes possible to deploy a bunch of verticles before each test and un-deploy after each + */ trait VerticleBeforeAndAfterEach extends VerticleTest with BeforeAndAfterEach { this: VertxTest => /** * It contains the list of verticles to deploy before each test. + * * @return a [[Traversable]] containing all the verticles to deploy */ protected def verticlesBeforeEach: Traversable[ScalaVerticle] - override protected def beforeEach(): Unit = { + override protected def beforeEach(): Unit = { super.beforeEach() deployAll(verticlesBeforeEach) } diff --git a/core-testing/src/main/scala/it/cwmp/testing/VerticleTest.scala b/core-testing/src/main/scala/it/cwmp/testing/VerticleTest.scala index 5d388e47..ce0321ab 100644 --- a/core-testing/src/main/scala/it/cwmp/testing/VerticleTest.scala +++ b/core-testing/src/main/scala/it/cwmp/testing/VerticleTest.scala @@ -8,7 +8,7 @@ import scala.util.{Failure, Success} /** * This class is automatically extended when using [[VerticleBeforeAndAfterEach]] or [[VerticleBeforeAndAfterAll]]. - * Here it is provided the structure for managing the deployment of the verticles and their undeploy at the end. + * Here it is provided the structure for managing the deployment of the verticles and their un-deploy at the end. * * @author Eugenio Pierfederici */ @@ -18,18 +18,19 @@ trait VerticleTest { /** * Once deployed, this set contains all the ids of the verticles just started. */ - private var deployementIds: Set[String] = _ + private var deploymentIds: Set[String] = _ /** * Deploys all the verticles passed as parameter. If any deploy fails or isn't deployed withing the * requested time, it throws a [[RuntimeException]] + * * @param verticles the list of verticle to deploy - * @param atMost the maximum amount of time we can wait for the verticle to start. By default: 10000 milliseconds + * @param atMost the maximum amount of time we can wait for the verticle to start. By default: 10000 milliseconds * @throws RuntimeException if any verticle can't be deployed */ protected def deployAll(verticles: Traversable[ScalaVerticle], atMost: Duration = 10000.millis): Unit = { - deployementIds = Set() - verticles.foreach(verticle => deployementIds = deployementIds + Await.result(vertx.deployVerticleFuture(verticle) + deploymentIds = Set() + verticles.foreach(verticle => deploymentIds = deploymentIds + Await.result(vertx.deployVerticleFuture(verticle) .andThen { case Success(d) => d case Failure(t) => throw new RuntimeException(t) @@ -39,11 +40,12 @@ trait VerticleTest { /** * Un-deploys all the verticles previously deployed. If any un-deploy fails or it isn't un-deployed withing the * requested time, it throws a [[RuntimeException]] + * * @param atMost the maximum amount of time we can wait for the verticle to stop. By default: 10000 milliseconds * @throws RuntimeException if any verticle can't be un-deployed */ protected def undeployAll(atMost: Duration = 10000.millis): Unit = - deployementIds.foreach(id => Await.result(vertx.undeployFuture(id) + deploymentIds.foreach(id => Await.result(vertx.undeployFuture(id) .andThen { case Success(d) => d case Failure(t) => throw new RuntimeException(t) From c02a4025d957bb6ca7c624c62b3772cb5f1cca7f Mon Sep 17 00:00:00 2001 From: Enrico Siboni Date: Tue, 24 Jul 2018 20:09:42 +0200 Subject: [PATCH 024/193] Added doc --- .../AuthenticationApiWrapperTest.scala | 3 +++ .../scala/it/cwmp/utils/HttpUtilsTest.scala | 3 +++ .../AuthenticationServiceMain.scala | 2 +- .../services/authentication/JwtUtils.scala | 1 + .../AuthenticationServiceVerticleTest.scala | 3 +++ .../authentication/JwtUtilsTest.scala | 3 +++ .../AuthenticationTesting.scala | 22 +++++++++++++++++-- 7 files changed, 34 insertions(+), 3 deletions(-) diff --git a/core/src/test/scala/it/cwmp/services/wrapper/AuthenticationApiWrapperTest.scala b/core/src/test/scala/it/cwmp/services/wrapper/AuthenticationApiWrapperTest.scala index 19a9ca42..252ef521 100644 --- a/core/src/test/scala/it/cwmp/services/wrapper/AuthenticationApiWrapperTest.scala +++ b/core/src/test/scala/it/cwmp/services/wrapper/AuthenticationApiWrapperTest.scala @@ -7,6 +7,9 @@ import it.cwmp.utils.Utils import scala.concurrent.Promise import scala.util.Failure +/** + * A test class for AuthenticationApiWrapper + */ class AuthenticationApiWrapperTest extends AuthenticationWebServiceTesting { private val auth = AuthenticationApiWrapper() diff --git a/core/src/test/scala/it/cwmp/utils/HttpUtilsTest.scala b/core/src/test/scala/it/cwmp/utils/HttpUtilsTest.scala index ce1b72c8..be13604c 100644 --- a/core/src/test/scala/it/cwmp/utils/HttpUtilsTest.scala +++ b/core/src/test/scala/it/cwmp/utils/HttpUtilsTest.scala @@ -2,6 +2,9 @@ package it.cwmp.utils import org.scalatest.FunSpec +/** + * A test class for HttpUtils + */ class HttpUtilsTest extends FunSpec { describe("Basic Authentication") { diff --git a/services/authentication/src/main/scala/it/cwmp/services/authentication/AuthenticationServiceMain.scala b/services/authentication/src/main/scala/it/cwmp/services/authentication/AuthenticationServiceMain.scala index b2816b42..140a2534 100644 --- a/services/authentication/src/main/scala/it/cwmp/services/authentication/AuthenticationServiceMain.scala +++ b/services/authentication/src/main/scala/it/cwmp/services/authentication/AuthenticationServiceMain.scala @@ -4,7 +4,7 @@ import io.vertx.scala.core.Vertx import it.cwmp.utils.Logging /** - * Hello class for server + * AuthenticationService entry-point */ object AuthenticationServiceMain extends App with Logging { diff --git a/services/authentication/src/main/scala/it/cwmp/services/authentication/JwtUtils.scala b/services/authentication/src/main/scala/it/cwmp/services/authentication/JwtUtils.scala index 9880a910..7b4099dc 100644 --- a/services/authentication/src/main/scala/it/cwmp/services/authentication/JwtUtils.scala +++ b/services/authentication/src/main/scala/it/cwmp/services/authentication/JwtUtils.scala @@ -5,6 +5,7 @@ import pdi.jwt.{Jwt, JwtAlgorithm, JwtClaim} import scala.util.{Failure, Success} +// TODO: add doc to all class methods object JwtUtils { private val secretKey = "secretKey" diff --git a/services/authentication/src/test/scala/it/cwmp/services/authentication/AuthenticationServiceVerticleTest.scala b/services/authentication/src/test/scala/it/cwmp/services/authentication/AuthenticationServiceVerticleTest.scala index 84430b01..43e62789 100644 --- a/services/authentication/src/test/scala/it/cwmp/services/authentication/AuthenticationServiceVerticleTest.scala +++ b/services/authentication/src/test/scala/it/cwmp/services/authentication/AuthenticationServiceVerticleTest.scala @@ -6,6 +6,9 @@ import it.cwmp.services.testing.authentication.AuthenticationWebServiceTesting import it.cwmp.testing.{FutureMatchers, HttpMatchers} import it.cwmp.utils.VertxClient +/** + * A test class for Authentication service + */ class AuthenticationServiceVerticleTest extends AuthenticationWebServiceTesting with HttpMatchers with FutureMatchers with VertxClient { diff --git a/services/authentication/src/test/scala/it/cwmp/services/authentication/JwtUtilsTest.scala b/services/authentication/src/test/scala/it/cwmp/services/authentication/JwtUtilsTest.scala index d5b37ea4..cce34be3 100644 --- a/services/authentication/src/test/scala/it/cwmp/services/authentication/JwtUtilsTest.scala +++ b/services/authentication/src/test/scala/it/cwmp/services/authentication/JwtUtilsTest.scala @@ -3,6 +3,9 @@ package it.cwmp.services.authentication import org.scalatest.FunSpec import pdi.jwt.JwtClaim +/** + * A test class for JwtUtils + */ class JwtUtilsTest extends FunSpec { describe("Generic") { diff --git a/services/authentication/src/test/scala/it/cwmp/services/testing/authentication/AuthenticationTesting.scala b/services/authentication/src/test/scala/it/cwmp/services/testing/authentication/AuthenticationTesting.scala index fdd2f329..8f85f81d 100644 --- a/services/authentication/src/test/scala/it/cwmp/services/testing/authentication/AuthenticationTesting.scala +++ b/services/authentication/src/test/scala/it/cwmp/services/testing/authentication/AuthenticationTesting.scala @@ -1,19 +1,30 @@ package it.cwmp.services.testing.authentication +import it.cwmp.services.testing.authentication.AuthenticationTesting.RANDOM_STRING_LENGTH import it.cwmp.testing.VertxTest import it.cwmp.utils.Utils import org.scalatest.Matchers +/** + * A base class for testing Authentication service + */ abstract class AuthenticationTesting extends VertxTest with Matchers { - protected def nextUsername: String = Utils.randomString(10) + /** + * @return a new random username + */ + protected def nextUsername: String = Utils.randomString(RANDOM_STRING_LENGTH) - protected def nextPassword: String = Utils.randomString(10) + /** + * @return a new random password + */ + protected def nextPassword: String = Utils.randomString(RANDOM_STRING_LENGTH) private val tokens = Iterator.continually(List( "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VybmFtZSI6InRpemlvIn0.f6eS98GeBmPau4O58NwQa_XRu3Opv6qWxYISWU78F68" )).flatten + // TODO: add doc protected def nextToken: String = tokens.next() protected val invalidToken: String = "INVALID" @@ -43,3 +54,10 @@ abstract class AuthenticationTesting extends VertxTest with Matchers { validationTests() } } + +/** + * Companion object + */ +object AuthenticationTesting { + private val RANDOM_STRING_LENGTH = 10 +} \ No newline at end of file From 8adbc8258f266b205ec5c4115503cd560d4e8101 Mon Sep 17 00:00:00 2001 From: Enrico Siboni Date: Tue, 24 Jul 2018 20:46:50 +0200 Subject: [PATCH 025/193] - Added doc - Replaced Random string generation in RoomsLocalDAO with Utils.randomString method --- .../authentication/AuthenticationWebServiceTesting.scala | 4 +++- .../main/scala/it/cwmp/services/rooms/RoomsLocalDAO.scala | 5 ++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/services/authentication/src/test/scala/it/cwmp/services/testing/authentication/AuthenticationWebServiceTesting.scala b/services/authentication/src/test/scala/it/cwmp/services/testing/authentication/AuthenticationWebServiceTesting.scala index 88aa6a54..42bd9c28 100644 --- a/services/authentication/src/test/scala/it/cwmp/services/testing/authentication/AuthenticationWebServiceTesting.scala +++ b/services/authentication/src/test/scala/it/cwmp/services/testing/authentication/AuthenticationWebServiceTesting.scala @@ -4,8 +4,10 @@ import io.vertx.lang.scala.ScalaVerticle import it.cwmp.services.authentication.AuthenticationServiceVerticle import it.cwmp.testing.VerticleBeforeAndAfterEach +/** + * Abstract base class for testing authentication we service + */ abstract class AuthenticationWebServiceTesting extends AuthenticationTesting with VerticleBeforeAndAfterEach { override protected val verticlesBeforeEach: List[ScalaVerticle] = List(AuthenticationServiceVerticle()) - } diff --git a/services/rooms/src/main/scala/it/cwmp/services/rooms/RoomsLocalDAO.scala b/services/rooms/src/main/scala/it/cwmp/services/rooms/RoomsLocalDAO.scala index 4e579a30..84c7f406 100644 --- a/services/rooms/src/main/scala/it/cwmp/services/rooms/RoomsLocalDAO.scala +++ b/services/rooms/src/main/scala/it/cwmp/services/rooms/RoomsLocalDAO.scala @@ -5,12 +5,11 @@ import it.cwmp.model.{Address, Participant, Room, User} import it.cwmp.services.rooms.RoomsLocalDAO._ import it.cwmp.utils.Utils.emptyString import it.cwmp.utils.VertxJDBC.stringsToJsonArray -import it.cwmp.utils.{Logging, VertxInstance, VertxJDBC} +import it.cwmp.utils.{Logging, Utils, VertxInstance, VertxJDBC} import scala.collection.mutable import scala.concurrent.{ExecutionContext, Future} import scala.language.implicitConversions -import scala.util.Random /** * A trait that describes the Rooms Data Access Object @@ -436,7 +435,7 @@ object RoomsLocalDAO { /** * Method that generates a random room identifier */ - private def generateRandomRoomID() = Random.nextInt(Int.MaxValue).toString + private def generateRandomRoomID() = Utils.randomString(Int.MaxValue) /** * @return a succeeded Future if string is ok, a failed Future otherwise From c49e256973d8e2e7afb4d1a9dfcbef3cc6091cad Mon Sep 17 00:00:00 2001 From: Enrico Siboni Date: Tue, 24 Jul 2018 20:59:58 +0200 Subject: [PATCH 026/193] - Added doc - Reformatted code, solved warnings --- .../RoomReceiverServiceVerticle.scala | 17 +++++++++++++---- .../RoomReceiverServiceVerticleTest.scala | 3 +++ .../roomreceiver/RoomReceiverTesting.scala | 15 +++++++++++++-- .../roomreceiver/RoomReceiverWebTesting.scala | 7 +++++-- 4 files changed, 34 insertions(+), 8 deletions(-) diff --git a/services/room-receiver/src/main/scala/it/cwmp/services/roomreceiver/RoomReceiverServiceVerticle.scala b/services/room-receiver/src/main/scala/it/cwmp/services/roomreceiver/RoomReceiverServiceVerticle.scala index e22b2a43..9066789c 100644 --- a/services/room-receiver/src/main/scala/it/cwmp/services/roomreceiver/RoomReceiverServiceVerticle.scala +++ b/services/room-receiver/src/main/scala/it/cwmp/services/roomreceiver/RoomReceiverServiceVerticle.scala @@ -5,8 +5,16 @@ import io.vertx.core.buffer.Buffer import io.vertx.lang.scala.json.JsonObject import io.vertx.scala.ext.web.{Router, RoutingContext} import it.cwmp.model.Participant +import it.cwmp.model.Participant.Converters._ +import it.cwmp.services.roomreceiver.ServerParameters._ import it.cwmp.utils.{Logging, VertxServer} +/** + * A class implementing a one-time service provided by clients to receive room infromation + * + * @param token the token on which to listen for an authorized response + * @param receptionStrategy the strategy to use when the data has been received + */ case class RoomReceiverServiceVerticle(token: String, receptionStrategy: List[Participant] => Unit) extends VertxServer with Logging { override protected val serverPort: Int = 0 @@ -14,12 +22,14 @@ case class RoomReceiverServiceVerticle(token: String, receptionStrategy: List[Pa def port: Int = server.actualPort() override protected def initRouter(router: Router): Unit = { - import it.cwmp.services.roomreceiver.ServerParameters._ - router post API_RECEIVE_PARTICIPANTS_URL(token) handler updateRoomParticipantsHandler + router post API_RECEIVE_PARTICIPANTS_URL(token) handler createParticipantReceiverHandler log.info(s"Starting the RoomReceiver service with the token: $token ...") } - private def updateRoomParticipantsHandler: Handler[RoutingContext] = implicit routingContext => { + /** + * Handles the reception of list of participants to the room + */ + private def createParticipantReceiverHandler: Handler[RoutingContext] = implicit routingContext => { log.info("Receiving participant list...") request.bodyHandler(body => extractIncomingParticipantListFromBody(body) match { @@ -38,7 +48,6 @@ case class RoomReceiverServiceVerticle(token: String, receptionStrategy: List[Pa try { var result = List[Participant]() val jsonArray = body.toJsonArray - import Participant.Converters._ jsonArray.forEach { case jsonObject: JsonObject => result = result :+ jsonObject.toParticipant } diff --git a/services/room-receiver/src/test/scala/it/cwmp/services/roomreceiver/RoomReceiverServiceVerticleTest.scala b/services/room-receiver/src/test/scala/it/cwmp/services/roomreceiver/RoomReceiverServiceVerticleTest.scala index e4ae17a6..47273d5f 100644 --- a/services/room-receiver/src/test/scala/it/cwmp/services/roomreceiver/RoomReceiverServiceVerticleTest.scala +++ b/services/room-receiver/src/test/scala/it/cwmp/services/roomreceiver/RoomReceiverServiceVerticleTest.scala @@ -11,6 +11,9 @@ import it.cwmp.utils.VertxClient import scala.util.{Failure, Success} +/** + * A test class for Room receiver service + */ class RoomReceiverServiceVerticleTest extends RoomReceiverWebTesting with HttpMatchers with FutureMatchers with VertxClient { diff --git a/services/room-receiver/src/test/scala/it/cwmp/services/testing/roomreceiver/RoomReceiverTesting.scala b/services/room-receiver/src/test/scala/it/cwmp/services/testing/roomreceiver/RoomReceiverTesting.scala index 630e91a6..f039dc59 100644 --- a/services/room-receiver/src/test/scala/it/cwmp/services/testing/roomreceiver/RoomReceiverTesting.scala +++ b/services/room-receiver/src/test/scala/it/cwmp/services/testing/roomreceiver/RoomReceiverTesting.scala @@ -1,19 +1,23 @@ package it.cwmp.services.testing.roomreceiver import it.cwmp.model.Participant +import it.cwmp.services.testing.roomreceiver.RoomReceiverTesting.TOKEN_LENGTH import it.cwmp.testing.VertxTest import it.cwmp.utils.Utils import org.scalatest.{BeforeAndAfterEach, Matchers} import scala.concurrent.Promise +/** + * An abstract base class for testing Room receiver service + */ abstract class RoomReceiverTesting extends VertxTest with Matchers with BeforeAndAfterEach { protected var port: Int - protected val rightToken: String = Utils.randomString(20) + protected val rightToken: String = Utils.randomString(TOKEN_LENGTH) - protected val wrongToken: String = Utils.randomString(20) + protected val wrongToken: String = Utils.randomString(TOKEN_LENGTH) protected val participants: List[Participant] = List( Participant("Nome", "Indirizzo"), @@ -28,3 +32,10 @@ abstract class RoomReceiverTesting extends VertxTest with Matchers with BeforeAn } } + +/** + * Companion object + */ +object RoomReceiverTesting { + private val TOKEN_LENGTH = 20 +} \ No newline at end of file diff --git a/services/room-receiver/src/test/scala/it/cwmp/services/testing/roomreceiver/RoomReceiverWebTesting.scala b/services/room-receiver/src/test/scala/it/cwmp/services/testing/roomreceiver/RoomReceiverWebTesting.scala index ad169a45..b0d83510 100644 --- a/services/room-receiver/src/test/scala/it/cwmp/services/testing/roomreceiver/RoomReceiverWebTesting.scala +++ b/services/room-receiver/src/test/scala/it/cwmp/services/testing/roomreceiver/RoomReceiverWebTesting.scala @@ -3,12 +3,15 @@ package it.cwmp.services.testing.roomreceiver import it.cwmp.services.roomreceiver.RoomReceiverServiceVerticle import it.cwmp.testing.VerticleBeforeAndAfterEach +/** + * An abstract base class for testing the room receiver web service + */ abstract class RoomReceiverWebTesting extends RoomReceiverTesting with VerticleBeforeAndAfterEach { override var port: Int = _ - override protected val verticlesBeforeEach: List[RoomReceiverServiceVerticle] = List( - RoomReceiverServiceVerticle(rightToken, s => participantsPromise.success(s))) + override protected val verticlesBeforeEach: List[RoomReceiverServiceVerticle] = + List(RoomReceiverServiceVerticle(rightToken, s => participantsPromise.success(s))) override def beforeEach(): Unit = { super.beforeEach() From ca013a1d317b8e1aac21cbfd8cb81e5123302a10 Mon Sep 17 00:00:00 2001 From: Enrico Siboni Date: Tue, 24 Jul 2018 21:15:17 +0200 Subject: [PATCH 027/193] Fixed bug introduced replacing random ID generation --- .../src/main/scala/it/cwmp/services/rooms/RoomsLocalDAO.scala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/services/rooms/src/main/scala/it/cwmp/services/rooms/RoomsLocalDAO.scala b/services/rooms/src/main/scala/it/cwmp/services/rooms/RoomsLocalDAO.scala index 84c7f406..b3308395 100644 --- a/services/rooms/src/main/scala/it/cwmp/services/rooms/RoomsLocalDAO.scala +++ b/services/rooms/src/main/scala/it/cwmp/services/rooms/RoomsLocalDAO.scala @@ -316,7 +316,7 @@ object RoomsLocalDAO { else Future.successful(Unit) } - + private val ROOM_ID_LENGTH = 20 private val userToRoomLinkField = "user_room" private val createRoomTableSql = s""" @@ -435,7 +435,7 @@ object RoomsLocalDAO { /** * Method that generates a random room identifier */ - private def generateRandomRoomID() = Utils.randomString(Int.MaxValue) + private def generateRandomRoomID() = Utils.randomString(ROOM_ID_LENGTH) /** * @return a succeeded Future if string is ok, a failed Future otherwise From 82614e9fb534ad110042794cb24f5a4f0b92ea67 Mon Sep 17 00:00:00 2001 From: Davide Borficchia Date: Wed, 25 Jul 2018 10:07:51 +0200 Subject: [PATCH 028/193] aggiunta documentazione --- .../main/scala/it/cwmp/client/view/game/ObjectDrawer.scala | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/client/src/main/scala/it/cwmp/client/view/game/ObjectDrawer.scala b/client/src/main/scala/it/cwmp/client/view/game/ObjectDrawer.scala index c587cdfe..89b24959 100644 --- a/client/src/main/scala/it/cwmp/client/view/game/ObjectDrawer.scala +++ b/client/src/main/scala/it/cwmp/client/view/game/ObjectDrawer.scala @@ -42,6 +42,12 @@ trait ObjectDrawer { svgShape } + /** + * Metodo per disegnare l'energia di una cella + * @param cell cella della quale disegnare l'energia + * @param graphicsContext oggetto che disegna la cella + * @return il testo da aggiungere alla scena + */ def drawCellEnergy(cell: CellView)(implicit graphicsContext: GraphicsContext): Text = { val t = new Text(cell.center.x - cell.size / 2, cell.center.y - cell.size / 2, cell.energy.toInt.toString) import javafx.scene.text.Font From 14f00ddb21608440f938f4e439bddd4ef17d7a2b Mon Sep 17 00:00:00 2001 From: Davide Borficchia Date: Wed, 25 Jul 2018 10:30:12 +0200 Subject: [PATCH 029/193] ora l'energia della cella viene disegnata al centro --- .../scala/it/cwmp/client/view/game/ObjectDrawer.scala | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/client/src/main/scala/it/cwmp/client/view/game/ObjectDrawer.scala b/client/src/main/scala/it/cwmp/client/view/game/ObjectDrawer.scala index 89b24959..1866a334 100644 --- a/client/src/main/scala/it/cwmp/client/view/game/ObjectDrawer.scala +++ b/client/src/main/scala/it/cwmp/client/view/game/ObjectDrawer.scala @@ -45,14 +45,17 @@ trait ObjectDrawer { /** * Metodo per disegnare l'energia di una cella * @param cell cella della quale disegnare l'energia - * @param graphicsContext oggetto che disegna la cella * @return il testo da aggiungere alla scena */ - def drawCellEnergy(cell: CellView)(implicit graphicsContext: GraphicsContext): Text = { - val t = new Text(cell.center.x - cell.size / 2, cell.center.y - cell.size / 2, cell.energy.toInt.toString) + def drawCellEnergy(cell: CellView): Text = { + val t = new Text(cell.center.x, cell.center.y, cell.energy.toInt.toString) import javafx.scene.text.Font t.setFont(Font.font("Verdana", 20)) t.setFill(Color.BLACK) + val width = t.getLayoutBounds.getWidth + val height = t.getLayoutBounds.getHeight + t.setX(cell.center.x - (width /2)) + t.setY(cell.center.y + (height /2)) t } From 31a0231c72a61b7bbf78f6e3f4f23f6a745091e5 Mon Sep 17 00:00:00 2001 From: Davide Borficchia Date: Wed, 25 Jul 2018 10:44:17 +0200 Subject: [PATCH 030/193] lavorando alla visualizzazione dell'istante --- .../it/cwmp/client/view/game/GameFX.scala | 1 + .../cwmp/client/view/game/ObjectDrawer.scala | 26 ++++++++++++------- 2 files changed, 18 insertions(+), 9 deletions(-) diff --git a/client/src/main/scala/it/cwmp/client/view/game/GameFX.scala b/client/src/main/scala/it/cwmp/client/view/game/GameFX.scala index 4c1c75b9..88e8107e 100644 --- a/client/src/main/scala/it/cwmp/client/view/game/GameFX.scala +++ b/client/src/main/scala/it/cwmp/client/view/game/GameFX.scala @@ -53,6 +53,7 @@ case class GameFX() extends ObjectDrawer { world.attacks.foreach(tentacle => root.getChildren.add(drawArch(tentacle, world.instant))) world.characters.foreach(cell => root.getChildren.add(drawCell(cell))) world.characters.foreach(cell => root.getChildren.add(drawCellEnergy(cell))) + //root.getChildren.add(drawInstant(world.instant)) }) } } diff --git a/client/src/main/scala/it/cwmp/client/view/game/ObjectDrawer.scala b/client/src/main/scala/it/cwmp/client/view/game/ObjectDrawer.scala index 1866a334..2034b099 100644 --- a/client/src/main/scala/it/cwmp/client/view/game/ObjectDrawer.scala +++ b/client/src/main/scala/it/cwmp/client/view/game/ObjectDrawer.scala @@ -9,6 +9,7 @@ import javafx.scene.canvas.GraphicsContext import javafx.scene.layout._ import javafx.scene.shape.{Line, SVGPath} import javafx.scene.text.Text +import javafx.scene.text.Font import scala.language.implicitConversions @@ -49,22 +50,20 @@ trait ObjectDrawer { */ def drawCellEnergy(cell: CellView): Text = { val t = new Text(cell.center.x, cell.center.y, cell.energy.toInt.toString) - import javafx.scene.text.Font t.setFont(Font.font("Verdana", 20)) t.setFill(Color.BLACK) - val width = t.getLayoutBounds.getWidth - val height = t.getLayoutBounds.getHeight - t.setX(cell.center.x - (width /2)) - t.setY(cell.center.y + (height /2)) + t.setX(cell.center.x - (t.getLayoutBounds.getWidth /2)) + t.setY(cell.center.y + (t.getLayoutBounds.getHeight /2)) t } /** - * Metodo utilizato per disegnare l'arco che unisce due celle - * - * @param graphicsContext è l'oggetto che disenga l'arco + * Metodo utilizato per disegnare il tentacolo che unisce due celle + * @param tentacle il tentacolo da disegnare + * @param actualInstant l'istante di gioco + * @return la linea da visualizzare nella GUI */ - def drawArch(tentacle: Tentacle, actualInstant: Instant)(implicit graphicsContext: GraphicsContext): Line = { + def drawArch(tentacle: Tentacle, actualInstant: Instant): Line = { val line = new Line() line.setStroke(TentacleView.coloringStrategy(tentacle)) @@ -78,6 +77,15 @@ trait ObjectDrawer { line } +// def drawInstant(instant: Instant) (implicit graphicsContext: GraphicsContext) : Text = { +// val t = new Text(, cell.center.y, instant.toString) +// t.setFont(Font.font("Verdana", 20)) +// t.setFill(Color.BLACK) +// t.setX(cell.center.x - (t.getLayoutBounds.getWidth /2)) +// t.setY(cell.center.y + (t.getLayoutBounds.getHeight /2)) +// t +// } + /** * Funzione per convertire i colori java.awt nel formato di colori utilizzato da javaFX * From 76c3144a1a38fab29d6a3f25782c82732c822878 Mon Sep 17 00:00:00 2001 From: Davide Borficchia Date: Wed, 25 Jul 2018 11:14:53 +0200 Subject: [PATCH 031/193] iniziata gestione dell'eccezione di non inizializzazione --- .../authentication/StorageLoaclDAO.scala | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/services/authentication/src/main/scala/it/cwmp/services/authentication/StorageLoaclDAO.scala b/services/authentication/src/main/scala/it/cwmp/services/authentication/StorageLoaclDAO.scala index fef10f0e..dd1b5059 100644 --- a/services/authentication/src/main/scala/it/cwmp/services/authentication/StorageLoaclDAO.scala +++ b/services/authentication/src/main/scala/it/cwmp/services/authentication/StorageLoaclDAO.scala @@ -60,10 +60,8 @@ case class StorageLoaclDAO(override val configurationPath: String = "authenticat (for ( connection <- openConnection(); - result <- connection.executeFuture( - createStorageTableSql) + _ <- connection.executeFuture(createStorageTableSql) ) yield { - result notInitialized = false }).closeConnections } @@ -73,11 +71,11 @@ case class StorageLoaclDAO(override val configurationPath: String = "authenticat (for ( // Controllo l'input username <- Option(usernameP) if username.nonEmpty; - password <- Option(passwordP) if password.nonEmpty; - future <- checkInitialization(notInitialized) + password <- Option(passwordP) if password.nonEmpty ) yield { (for ( // Eseguo operazioni sul db in maniera sequenziale + _ <- checkInitialization(notInitialized); connection <- openConnection(); _ <- connection.updateWithParamsFuture( insertNewUserSql, new JsonArray().add(username).add(password).add("SALT")) @@ -96,8 +94,7 @@ case class StorageLoaclDAO(override val configurationPath: String = "authenticat (for ( // Eseguo operazioni sul db in maniera sequenziale connection <- openConnection(); - result <- connection.updateWithParamsFuture( - signoutUserSql, new JsonArray().add(username)) if result.getUpdated > 0 + result <- connection.updateWithParamsFuture(signoutUserSql, new JsonArray().add(username)) if result.getUpdated > 0 ) yield ()).closeConnections }).getOrElse(Future.failed(new IllegalArgumentException())) } @@ -143,10 +140,9 @@ object StorageLoaclDAO { /** * Utility method per controlloare se il DAO è stato inizializzato */ - private def checkInitialization(notInitialized: Boolean): Option[Future[Unit]] = { - //if (notInitialized) Future.failed(new IllegalStateException("Not initialized, you should first call initialize()")) - if (notInitialized) None //TODO implementare eccezione della riga sopra - else Some(Future.successful(Unit)) + private def checkInitialization(notInitialized: Boolean): Future[Unit] = { + if (notInitialized) Future.failed(new IllegalStateException("Not initialized, you should first call initialize()")) + else Future.successful(Unit) } private val createStorageTableSql = From 0ffccb1a102e2ae03c4a6ca2adeb51759eb9690e Mon Sep 17 00:00:00 2001 From: Davide Borficchia Date: Wed, 25 Jul 2018 11:15:52 +0200 Subject: [PATCH 032/193] eliminato commenti --- .../src/main/scala/it/cwmp/client/view/game/GameFX.scala | 1 - .../scala/it/cwmp/client/view/game/ObjectDrawer.scala | 9 --------- 2 files changed, 10 deletions(-) diff --git a/client/src/main/scala/it/cwmp/client/view/game/GameFX.scala b/client/src/main/scala/it/cwmp/client/view/game/GameFX.scala index 88e8107e..4c1c75b9 100644 --- a/client/src/main/scala/it/cwmp/client/view/game/GameFX.scala +++ b/client/src/main/scala/it/cwmp/client/view/game/GameFX.scala @@ -53,7 +53,6 @@ case class GameFX() extends ObjectDrawer { world.attacks.foreach(tentacle => root.getChildren.add(drawArch(tentacle, world.instant))) world.characters.foreach(cell => root.getChildren.add(drawCell(cell))) world.characters.foreach(cell => root.getChildren.add(drawCellEnergy(cell))) - //root.getChildren.add(drawInstant(world.instant)) }) } } diff --git a/client/src/main/scala/it/cwmp/client/view/game/ObjectDrawer.scala b/client/src/main/scala/it/cwmp/client/view/game/ObjectDrawer.scala index 2034b099..1afacd0e 100644 --- a/client/src/main/scala/it/cwmp/client/view/game/ObjectDrawer.scala +++ b/client/src/main/scala/it/cwmp/client/view/game/ObjectDrawer.scala @@ -77,15 +77,6 @@ trait ObjectDrawer { line } -// def drawInstant(instant: Instant) (implicit graphicsContext: GraphicsContext) : Text = { -// val t = new Text(, cell.center.y, instant.toString) -// t.setFont(Font.font("Verdana", 20)) -// t.setFill(Color.BLACK) -// t.setX(cell.center.x - (t.getLayoutBounds.getWidth /2)) -// t.setY(cell.center.y + (t.getLayoutBounds.getHeight /2)) -// t -// } - /** * Funzione per convertire i colori java.awt nel formato di colori utilizzato da javaFX * From f8496c0b0da54d5ad7e905b82117d15e0f1ff3d5 Mon Sep 17 00:00:00 2001 From: Enrico Siboni Date: Wed, 25 Jul 2018 11:21:49 +0200 Subject: [PATCH 033/193] Removed unused import --- .../src/main/scala/it/cwmp/services/rooms/RoomsServiceMain.scala | 1 - 1 file changed, 1 deletion(-) diff --git a/services/rooms/src/main/scala/it/cwmp/services/rooms/RoomsServiceMain.scala b/services/rooms/src/main/scala/it/cwmp/services/rooms/RoomsServiceMain.scala index 5134d529..ca1f0431 100644 --- a/services/rooms/src/main/scala/it/cwmp/services/rooms/RoomsServiceMain.scala +++ b/services/rooms/src/main/scala/it/cwmp/services/rooms/RoomsServiceMain.scala @@ -1,6 +1,5 @@ package it.cwmp.services.rooms -import com.typesafe.scalalogging.Logger import io.vertx.lang.scala.VertxExecutionContext import io.vertx.scala.core.Vertx import it.cwmp.services.wrapper.{AuthenticationApiWrapper, RoomReceiverApiWrapper} From 8ce574b7f81eef04565953122d039faf9ccb577b Mon Sep 17 00:00:00 2001 From: Davide Borficchia Date: Wed, 25 Jul 2018 11:23:57 +0200 Subject: [PATCH 034/193] aggiunto check inizialized DAO --- .../cwmp/services/authentication/StorageLoaclDAO.scala | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/services/authentication/src/main/scala/it/cwmp/services/authentication/StorageLoaclDAO.scala b/services/authentication/src/main/scala/it/cwmp/services/authentication/StorageLoaclDAO.scala index dd1b5059..23ba96d1 100644 --- a/services/authentication/src/main/scala/it/cwmp/services/authentication/StorageLoaclDAO.scala +++ b/services/authentication/src/main/scala/it/cwmp/services/authentication/StorageLoaclDAO.scala @@ -57,7 +57,6 @@ case class StorageLoaclDAO(override val configurationPath: String = "authenticat def initialize(): Future[Unit] = { logger.info("Initializing RoomLocalDAO...") - (for ( connection <- openConnection(); _ <- connection.executeFuture(createStorageTableSql) @@ -93,6 +92,7 @@ case class StorageLoaclDAO(override val configurationPath: String = "authenticat ) yield { (for ( // Eseguo operazioni sul db in maniera sequenziale + _ <- checkInitialization(notInitialized); connection <- openConnection(); result <- connection.updateWithParamsFuture(signoutUserSql, new JsonArray().add(username)) if result.getUpdated > 0 ) yield ()).closeConnections @@ -108,9 +108,9 @@ case class StorageLoaclDAO(override val configurationPath: String = "authenticat ) yield { (for ( // Eseguo operazioni sul db in maniera sequenziale + _ <- checkInitialization(notInitialized); connection <- openConnection(); - result <- connection.queryWithParamsFuture( - loginUserSql, new JsonArray().add(username).add(password)) if result.getResults.nonEmpty + result <- connection.queryWithParamsFuture(loginUserSql, new JsonArray().add(username).add(password)) if result.getResults.nonEmpty ) yield ()).closeConnections }).getOrElse(Future.failed(new IllegalArgumentException())) } @@ -123,9 +123,9 @@ case class StorageLoaclDAO(override val configurationPath: String = "authenticat ) yield { (for ( // Eseguo operazioni sul db in maniera sequenziale + _ <- checkInitialization(notInitialized); connection <- openConnection(); - result <- connection.queryWithParamsFuture( - existFutureUserSql, new JsonArray().add(username)) if result.getResults.nonEmpty + result <- connection.queryWithParamsFuture(existFutureUserSql, new JsonArray().add(username)) if result.getResults.nonEmpty ) yield ()).closeConnections }).getOrElse(Future.failed(new IllegalArgumentException())) } From 02a19e3d72f009498704573db08898b245416756 Mon Sep 17 00:00:00 2001 From: Enrico Siboni Date: Wed, 25 Jul 2018 11:41:24 +0200 Subject: [PATCH 035/193] Solved a problem after merge with GameViewActor constructor --- client/src/main/scala/it/cwmp/client/GameMain.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/main/scala/it/cwmp/client/GameMain.scala b/client/src/main/scala/it/cwmp/client/GameMain.scala index 8fc5e82d..0a14ff43 100644 --- a/client/src/main/scala/it/cwmp/client/GameMain.scala +++ b/client/src/main/scala/it/cwmp/client/GameMain.scala @@ -15,7 +15,7 @@ object GameMain extends App { val system = ActorSystem(APP_NAME, config) - val gameActor = system.actorOf(Props(classOf[GameViewActor]), GameViewActor.getClass.getName) + val gameActor = system.actorOf(Props(classOf[GameViewActor], null), GameViewActor.getClass.getName) import GameViewActor._ From 990d3bdb56e330a992c8912e18068b2d35ae216a Mon Sep 17 00:00:00 2001 From: Enrico Siboni Date: Wed, 25 Jul 2018 12:16:42 +0200 Subject: [PATCH 036/193] Made javaFx colors the default and replaced present conversion to awtColors --- .../cwmp/client/view/game/ObjectDrawer.scala | 31 ++++++++++--------- .../client/view/game/model/CellView.scala | 7 +++-- .../client/view/game/model/TentacleView.scala | 2 +- 3 files changed, 21 insertions(+), 19 deletions(-) diff --git a/client/src/main/scala/it/cwmp/client/view/game/ObjectDrawer.scala b/client/src/main/scala/it/cwmp/client/view/game/ObjectDrawer.scala index d44595d8..76c12e00 100644 --- a/client/src/main/scala/it/cwmp/client/view/game/ObjectDrawer.scala +++ b/client/src/main/scala/it/cwmp/client/view/game/ObjectDrawer.scala @@ -1,15 +1,14 @@ package it.cwmp.client.view.game -import java.awt.Color import java.time.Instant import it.cwmp.client.model.game.impl.Tentacle import it.cwmp.client.view.game.model._ import javafx.scene.canvas.GraphicsContext import javafx.scene.layout._ +import javafx.scene.paint.Color import javafx.scene.shape.{Line, SVGPath} -import javafx.scene.text.Text -import javafx.scene.text.Font +import javafx.scene.text.{Font, Text} import scala.language.implicitConversions @@ -45,21 +44,23 @@ trait ObjectDrawer { /** * Metodo per disegnare l'energia di una cella + * * @param cell cella della quale disegnare l'energia * @return il testo da aggiungere alla scena */ def drawCellEnergy(cell: CellView): Text = { - val t = new Text(cell.center.x, cell.center.y, cell.energy.toInt.toString) - t.setFont(Font.font("Verdana", 20)) - t.setFill(Color.BLACK) - t.setX(cell.center.x - (t.getLayoutBounds.getWidth /2)) - t.setY(cell.center.y + (t.getLayoutBounds.getHeight /2)) - t + val energyText = new Text(cell.center.x, cell.center.y, cell.energy.toInt.toString) + energyText.setFont(Font.font("Verdana", 20)) + energyText.setFill(Color.BLACK) + energyText.setX(cell.center.x - (energyText.getLayoutBounds.getWidth / 2)) + energyText.setY(cell.center.y + (energyText.getLayoutBounds.getHeight / 2)) + energyText } /** * Metodo utilizato per disegnare il tentacolo che unisce due celle - * @param tentacle il tentacolo da disegnare + * + * @param tentacle il tentacolo da disegnare * @param actualInstant l'istante di gioco * @return la linea da visualizzare nella GUI */ @@ -78,12 +79,12 @@ trait ObjectDrawer { } /** - * Funzione per convertire i colori java.awt nel formato di colori utilizzato da javaFX + * Funzione per convertire i colori javaFX nel formato di colori utilizzato da java.awt * - * @param awtColor Colore che si vuole convertire - * @return + * @param fxColor Colore che si vuole convertire + * @return il colore awt */ - private implicit def awtColorToFxColor(awtColor: Color): javafx.scene.paint.Color = { - new javafx.scene.paint.Color(awtColor.getRed / 255.0, awtColor.getGreen / 255.0, awtColor.getBlue / 255.0, awtColor.getAlpha / 255.0) + private implicit def fxColorToAwtColor(fxColor: javafx.scene.paint.Color): java.awt.Color = { + new java.awt.Color((fxColor.getRed * 255).toFloat, (fxColor.getGreen * 255).toFloat, (fxColor.getBlue * 255).toFloat, (fxColor.getOpacity * 255).toFloat) } } diff --git a/client/src/main/scala/it/cwmp/client/view/game/model/CellView.scala b/client/src/main/scala/it/cwmp/client/view/game/model/CellView.scala index cb9aee25..5a278e9d 100644 --- a/client/src/main/scala/it/cwmp/client/view/game/model/CellView.scala +++ b/client/src/main/scala/it/cwmp/client/view/game/model/CellView.scala @@ -1,11 +1,10 @@ package it.cwmp.client.view.game.model -import java.awt.Color - import com.github.tkqubo.colorHash.ColorHash import it.cwmp.client.model.game.SizingStrategy import it.cwmp.client.model.game.impl.{Cell, Point} import it.cwmp.client.view.game.ColoringStrategy +import javafx.scene.paint.Color import scala.language.implicitConversions @@ -25,6 +24,8 @@ case class CellView(center: Point, radius: Double, color: Color, energy: Double) */ object CellView { + private val CELL_VIEW_COLOR_OPACITY = 1 + /** * @return the ViewCell corresponding to the given Cell */ @@ -37,7 +38,7 @@ object CellView { */ val coloringStrategy: ColoringStrategy[Cell, Color] = (cell: Cell) => { val color = new ColorHash().rgb(cell.owner.username) - new Color(color.red, color.green, color.blue) + new Color(color.red, color.green, color.blue, CELL_VIEW_COLOR_OPACITY) } /** diff --git a/client/src/main/scala/it/cwmp/client/view/game/model/TentacleView.scala b/client/src/main/scala/it/cwmp/client/view/game/model/TentacleView.scala index 6190c265..30b38ebc 100644 --- a/client/src/main/scala/it/cwmp/client/view/game/model/TentacleView.scala +++ b/client/src/main/scala/it/cwmp/client/view/game/model/TentacleView.scala @@ -1,6 +1,6 @@ package it.cwmp.client.view.game.model -import java.awt.Color +import javafx.scene.paint.Color import java.time.{Duration, Instant} import it.cwmp.client.model.game.SizingStrategy From 835c7fb61e25d5c1c74dfe3c0cf5eaf827f95414 Mon Sep 17 00:00:00 2001 From: Enrico Siboni Date: Wed, 25 Jul 2018 12:28:45 +0200 Subject: [PATCH 037/193] - Moved constant of TentacleView in its proper class - Solved some problems of conversion with colors in ObjectDrawer --- .../cwmp/client/view/game/GameViewConstants.scala | 4 ++-- .../it/cwmp/client/view/game/ObjectDrawer.scala | 2 +- .../it/cwmp/client/view/game/model/CellView.scala | 3 ++- .../client/view/game/model/TentacleView.scala | 15 +++++++++++---- 4 files changed, 16 insertions(+), 8 deletions(-) diff --git a/client/src/main/scala/it/cwmp/client/view/game/GameViewConstants.scala b/client/src/main/scala/it/cwmp/client/view/game/GameViewConstants.scala index 31964261..3451b61a 100644 --- a/client/src/main/scala/it/cwmp/client/view/game/GameViewConstants.scala +++ b/client/src/main/scala/it/cwmp/client/view/game/GameViewConstants.scala @@ -8,7 +8,7 @@ package it.cwmp.client.view.game object GameViewConstants { /** - * Provides default value for tentacle thickness + * The constant value indicating the rgb range max value */ - val DEFAULT_TENTACLE_THICKNESS = 3d + val RGB_RANGE = 255.0 } diff --git a/client/src/main/scala/it/cwmp/client/view/game/ObjectDrawer.scala b/client/src/main/scala/it/cwmp/client/view/game/ObjectDrawer.scala index 76c12e00..daae8254 100644 --- a/client/src/main/scala/it/cwmp/client/view/game/ObjectDrawer.scala +++ b/client/src/main/scala/it/cwmp/client/view/game/ObjectDrawer.scala @@ -85,6 +85,6 @@ trait ObjectDrawer { * @return il colore awt */ private implicit def fxColorToAwtColor(fxColor: javafx.scene.paint.Color): java.awt.Color = { - new java.awt.Color((fxColor.getRed * 255).toFloat, (fxColor.getGreen * 255).toFloat, (fxColor.getBlue * 255).toFloat, (fxColor.getOpacity * 255).toFloat) + new java.awt.Color(fxColor.getRed.toFloat, fxColor.getGreen.toFloat, fxColor.getBlue.toFloat, fxColor.getOpacity.toFloat) } } diff --git a/client/src/main/scala/it/cwmp/client/view/game/model/CellView.scala b/client/src/main/scala/it/cwmp/client/view/game/model/CellView.scala index 5a278e9d..365f6be1 100644 --- a/client/src/main/scala/it/cwmp/client/view/game/model/CellView.scala +++ b/client/src/main/scala/it/cwmp/client/view/game/model/CellView.scala @@ -4,6 +4,7 @@ import com.github.tkqubo.colorHash.ColorHash import it.cwmp.client.model.game.SizingStrategy import it.cwmp.client.model.game.impl.{Cell, Point} import it.cwmp.client.view.game.ColoringStrategy +import it.cwmp.client.view.game.GameViewConstants.RGB_RANGE import javafx.scene.paint.Color import scala.language.implicitConversions @@ -38,7 +39,7 @@ object CellView { */ val coloringStrategy: ColoringStrategy[Cell, Color] = (cell: Cell) => { val color = new ColorHash().rgb(cell.owner.username) - new Color(color.red, color.green, color.blue, CELL_VIEW_COLOR_OPACITY) + new Color(color.red / RGB_RANGE, color.green / RGB_RANGE, color.blue / RGB_RANGE, CELL_VIEW_COLOR_OPACITY) } /** diff --git a/client/src/main/scala/it/cwmp/client/view/game/model/TentacleView.scala b/client/src/main/scala/it/cwmp/client/view/game/model/TentacleView.scala index 30b38ebc..db268541 100644 --- a/client/src/main/scala/it/cwmp/client/view/game/model/TentacleView.scala +++ b/client/src/main/scala/it/cwmp/client/view/game/model/TentacleView.scala @@ -1,11 +1,11 @@ package it.cwmp.client.view.game.model -import javafx.scene.paint.Color import java.time.{Duration, Instant} import it.cwmp.client.model.game.SizingStrategy import it.cwmp.client.model.game.impl.{GeometricUtils, Point, Tentacle} -import it.cwmp.client.view.game.{ColoringStrategy, GameViewConstants} +import it.cwmp.client.view.game.ColoringStrategy +import javafx.scene.paint.Color /** @@ -15,6 +15,11 @@ import it.cwmp.client.view.game.{ColoringStrategy, GameViewConstants} */ object TentacleView { + /** + * Provides default value for tentacle thickness + */ + val DEFAULT_TENTACLE_THICKNESS = 3d + /** * Default coloring strategy for tentacles * @@ -29,7 +34,7 @@ object TentacleView { * Returns always same thickness */ val thicknessStrategy: SizingStrategy[Tentacle, Double] = // TODO: make thickness vary with attackers cell energy - (_: Tentacle) => GameViewConstants.DEFAULT_TENTACLE_THICKNESS + (_: Tentacle) => DEFAULT_TENTACLE_THICKNESS /** * A method returning the Point reached actually by the tentacle @@ -45,6 +50,8 @@ object TentacleView { val deltaXYFromAttackerPosition = GeometricUtils.deltaXYFromFirstPoint(attackerPosition, tentacle.to.position, tentacleActualLength) Point(attackerPosition.x + deltaXYFromAttackerPosition._1.toInt, attackerPosition.y + deltaXYFromAttackerPosition._2.toInt) - } else tentacle.to.position + } else { + tentacle.to.position + } } } From 793590644082e5a3f855fcb7a4b9446ce7ae6a49 Mon Sep 17 00:00:00 2001 From: Enrico Siboni Date: Wed, 25 Jul 2018 12:33:44 +0200 Subject: [PATCH 038/193] Moved CellView energy font inside CellView class constant --- .../main/scala/it/cwmp/client/view/game/ObjectDrawer.scala | 6 +++--- .../scala/it/cwmp/client/view/game/model/CellView.scala | 3 +++ 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/client/src/main/scala/it/cwmp/client/view/game/ObjectDrawer.scala b/client/src/main/scala/it/cwmp/client/view/game/ObjectDrawer.scala index daae8254..029fd9f1 100644 --- a/client/src/main/scala/it/cwmp/client/view/game/ObjectDrawer.scala +++ b/client/src/main/scala/it/cwmp/client/view/game/ObjectDrawer.scala @@ -8,7 +8,7 @@ import javafx.scene.canvas.GraphicsContext import javafx.scene.layout._ import javafx.scene.paint.Color import javafx.scene.shape.{Line, SVGPath} -import javafx.scene.text.{Font, Text} +import javafx.scene.text.Text import scala.language.implicitConversions @@ -50,8 +50,8 @@ trait ObjectDrawer { */ def drawCellEnergy(cell: CellView): Text = { val energyText = new Text(cell.center.x, cell.center.y, cell.energy.toInt.toString) - energyText.setFont(Font.font("Verdana", 20)) - energyText.setFill(Color.BLACK) + energyText.setFont(CellView.ENERGY_FONT) + energyText.setFill(Color.BLACK) // TODO: move to a coloring strategy inside CellView energyText.setX(cell.center.x - (energyText.getLayoutBounds.getWidth / 2)) energyText.setY(cell.center.y + (energyText.getLayoutBounds.getHeight / 2)) energyText diff --git a/client/src/main/scala/it/cwmp/client/view/game/model/CellView.scala b/client/src/main/scala/it/cwmp/client/view/game/model/CellView.scala index 365f6be1..ae95677e 100644 --- a/client/src/main/scala/it/cwmp/client/view/game/model/CellView.scala +++ b/client/src/main/scala/it/cwmp/client/view/game/model/CellView.scala @@ -6,6 +6,7 @@ import it.cwmp.client.model.game.impl.{Cell, Point} import it.cwmp.client.view.game.ColoringStrategy import it.cwmp.client.view.game.GameViewConstants.RGB_RANGE import javafx.scene.paint.Color +import javafx.scene.text.Font import scala.language.implicitConversions @@ -25,6 +26,8 @@ case class CellView(center: Point, radius: Double, color: Color, energy: Double) */ object CellView { + val ENERGY_FONT = Font.font("Verdana", 20) + private val CELL_VIEW_COLOR_OPACITY = 1 /** From 991ca45f2d54e8a61752ba32d04b295f8cee10ef Mon Sep 17 00:00:00 2001 From: Enrico Siboni Date: Wed, 25 Jul 2018 14:04:36 +0200 Subject: [PATCH 039/193] - Added doc - Reformatted code --- .../services/rooms/RoomsServiceMain.scala | 1 - .../services/rooms/RoomsServiceUtils.scala | 14 +++++------ .../services/rooms/RoomsServiceVerticle.scala | 23 +++++++++---------- 3 files changed, 18 insertions(+), 20 deletions(-) diff --git a/services/rooms/src/main/scala/it/cwmp/services/rooms/RoomsServiceMain.scala b/services/rooms/src/main/scala/it/cwmp/services/rooms/RoomsServiceMain.scala index ca1f0431..cfd1a0f7 100644 --- a/services/rooms/src/main/scala/it/cwmp/services/rooms/RoomsServiceMain.scala +++ b/services/rooms/src/main/scala/it/cwmp/services/rooms/RoomsServiceMain.scala @@ -21,5 +21,4 @@ object RoomsServiceMain extends App with Logging { case Success(_) => log.info("RoomsService up and running!") case Failure(ex) => log.info("Error deploying RoomsService", ex) }(VertxExecutionContext(vertx.getOrCreateContext())) - } diff --git a/services/rooms/src/main/scala/it/cwmp/services/rooms/RoomsServiceUtils.scala b/services/rooms/src/main/scala/it/cwmp/services/rooms/RoomsServiceUtils.scala index 97c49789..f2957e65 100644 --- a/services/rooms/src/main/scala/it/cwmp/services/rooms/RoomsServiceUtils.scala +++ b/services/rooms/src/main/scala/it/cwmp/services/rooms/RoomsServiceUtils.scala @@ -4,12 +4,16 @@ import io.vertx.core.buffer.Buffer import io.vertx.core.json.JsonObject import io.vertx.scala.core.Vertx import io.vertx.scala.ext.web.RoutingContext +import it.cwmp.model.Address.Converters._ import it.cwmp.model.{Address, Room} import it.cwmp.services.wrapper.RoomReceiverApiWrapper import it.cwmp.utils.{Logging, VertxServer} import scala.concurrent.{ExecutionContext, Future} +/** + * A trait containing RoomsService utilities + */ trait RoomsServiceUtils { this: VertxServer with Logging => @@ -35,7 +39,6 @@ trait RoomsServiceUtils { val userAddressJson = jsonArray.getJsonObject(0) val userNotificationAddressJson = jsonArray.getJsonObject(1) if ((userAddressJson containsKey Address.FIELD_ADDRESS) && (userNotificationAddressJson containsKey Address.FIELD_ADDRESS)) { - import Address.Converters._ Some((userAddressJson.toAddress, userNotificationAddressJson.toAddress)) } else None } catch { @@ -74,10 +77,8 @@ trait RoomsServiceUtils { * @param onRetrievedRoomAction the action to do if the room is full * @return a future that completes when all players received addresses */ - private[this] def handleRoomFilling(roomInformationFuture: Future[(Room, Seq[Address])], - onRetrievedRoomAction: => Future[Unit]) - (implicit communicationStrategy: RoomReceiverApiWrapper, - executionContext: ExecutionContext): Future[Unit] = { + private[this] def handleRoomFilling(roomInformationFuture: Future[(Room, Seq[Address])], onRetrievedRoomAction: => Future[Unit]) + (implicit communicationStrategy: RoomReceiverApiWrapper, executionContext: ExecutionContext): Future[Unit] = { roomInformationFuture.map(tuple => tuple._1).filter(roomIsFull) .flatMap(_ => { onRetrievedRoomAction @@ -96,8 +97,7 @@ trait RoomsServiceUtils { * @param roomInformation the room where players are waiting in */ private[rooms] def sendParticipantAddresses(roomInformation: (Room, Seq[Address])) - (implicit communicationStrategy: RoomReceiverApiWrapper, - executionContext: ExecutionContext): Future[Unit] = { + (implicit communicationStrategy: RoomReceiverApiWrapper, executionContext: ExecutionContext): Future[Unit] = { log.info(s"Preparing to send participant list to room ${roomInformation._1.name} (with id:${roomInformation._1.identifier}) participants ...") val notificationAddresses = for (notificationAddress <- roomInformation._2) yield notificationAddress val players = for (player <- roomInformation._1.participants) yield player diff --git a/services/rooms/src/main/scala/it/cwmp/services/rooms/RoomsServiceVerticle.scala b/services/rooms/src/main/scala/it/cwmp/services/rooms/RoomsServiceVerticle.scala index 00b893ea..59532305 100644 --- a/services/rooms/src/main/scala/it/cwmp/services/rooms/RoomsServiceVerticle.scala +++ b/services/rooms/src/main/scala/it/cwmp/services/rooms/RoomsServiceVerticle.scala @@ -4,6 +4,7 @@ import io.vertx.core.Handler import io.vertx.core.buffer.Buffer import io.vertx.lang.scala.json.Json import io.vertx.scala.ext.web.{Router, RoutingContext} +import it.cwmp.model.Room.Converters._ import it.cwmp.model.{Address, Participant, Room, User} import it.cwmp.services.rooms.ServerParameters._ import it.cwmp.services.wrapper.RoomReceiverApiWrapper @@ -12,11 +13,6 @@ import it.cwmp.utils.{Logging, Validation, VertxServer} import scala.concurrent.Future import scala.util.{Failure, Success} -object RoomsServiceVerticle { - def apply(implicit validationStrategy: Validation[String, User], clientCommunicationStrategy: RoomReceiverApiWrapper): RoomsServiceVerticle = - new RoomsServiceVerticle()(validationStrategy, clientCommunicationStrategy) -} - /** * Class that implements the Rooms micro-service * @@ -116,9 +112,7 @@ class RoomsServiceVerticle(implicit val validationStrategy: Validation[String, U getRequestParameter(Room.FIELD_IDENTIFIER) match { case Some(roomId) => daoFuture.map(_.roomInfo(roomId).map(_._1).onComplete { - case Success(room) => - import Room.Converters._ - sendResponse(200, room.toJson.encode()) + case Success(room) => sendResponse(200, room.toJson.encode()) case Failure(ex: NoSuchElementException) => sendResponse(404, ex.getMessage) case Failure(ex) => sendResponse(400, ex.getMessage) }) @@ -153,7 +147,6 @@ class RoomsServiceVerticle(implicit val validationStrategy: Validation[String, U request.checkAuthenticationOrReject.map(_ => { daoFuture.map(_.listPublicRooms().onComplete { case Success(rooms) => - import Room.Converters._ val jsonArray = rooms.foldLeft(Json emptyArr())(_ add _.toJson) sendResponse(200, jsonArray encode()) case Failure(ex) => sendResponse(400, ex.getMessage) @@ -205,9 +198,7 @@ class RoomsServiceVerticle(implicit val validationStrategy: Validation[String, U }) match { case Some(playersNumber) => daoFuture.map(_.publicRoomInfo(playersNumber).map(_._1).onComplete { - case Success(room) => - import Room.Converters._ - sendResponse(200, room.toJson.encode()) + case Success(room) => sendResponse(200, room.toJson.encode()) case Failure(ex: NoSuchElementException) => sendResponse(404, ex.getMessage) case Failure(ex) => sendResponse(400, ex.getMessage) }) @@ -240,4 +231,12 @@ class RoomsServiceVerticle(implicit val validationStrategy: Validation[String, U } }) } +} + +/** + * Cmpanion object + */ +object RoomsServiceVerticle { + def apply(implicit validationStrategy: Validation[String, User], clientCommunicationStrategy: RoomReceiverApiWrapper): RoomsServiceVerticle = + new RoomsServiceVerticle()(validationStrategy, clientCommunicationStrategy) } \ No newline at end of file From af7c6bb76fe97f3d5ac5ec3036e55af6a7304dd3 Mon Sep 17 00:00:00 2001 From: Enrico Siboni Date: Wed, 25 Jul 2018 14:09:43 +0200 Subject: [PATCH 040/193] Services main classes now are mixed in with VertxInstance --- .../authentication/AuthenticationServiceMain.scala | 7 +++---- .../it/cwmp/services/rooms/RoomsServiceMain.scala | 10 +++------- 2 files changed, 6 insertions(+), 11 deletions(-) diff --git a/services/authentication/src/main/scala/it/cwmp/services/authentication/AuthenticationServiceMain.scala b/services/authentication/src/main/scala/it/cwmp/services/authentication/AuthenticationServiceMain.scala index 140a2534..9a4254e2 100644 --- a/services/authentication/src/main/scala/it/cwmp/services/authentication/AuthenticationServiceMain.scala +++ b/services/authentication/src/main/scala/it/cwmp/services/authentication/AuthenticationServiceMain.scala @@ -1,14 +1,13 @@ package it.cwmp.services.authentication -import io.vertx.scala.core.Vertx -import it.cwmp.utils.Logging +import it.cwmp.utils.{Logging, VertxInstance} /** * AuthenticationService entry-point */ -object AuthenticationServiceMain extends App with Logging { +object AuthenticationServiceMain extends App with VertxInstance with Logging { - Vertx.vertx().deployVerticle(new AuthenticationServiceVerticle) + vertx.deployVerticle(new AuthenticationServiceVerticle) log.info("Deploying AuthenticationServiceVerticle... ") } diff --git a/services/rooms/src/main/scala/it/cwmp/services/rooms/RoomsServiceMain.scala b/services/rooms/src/main/scala/it/cwmp/services/rooms/RoomsServiceMain.scala index cfd1a0f7..fbc27e80 100644 --- a/services/rooms/src/main/scala/it/cwmp/services/rooms/RoomsServiceMain.scala +++ b/services/rooms/src/main/scala/it/cwmp/services/rooms/RoomsServiceMain.scala @@ -1,9 +1,7 @@ package it.cwmp.services.rooms -import io.vertx.lang.scala.VertxExecutionContext -import io.vertx.scala.core.Vertx import it.cwmp.services.wrapper.{AuthenticationApiWrapper, RoomReceiverApiWrapper} -import it.cwmp.utils.Logging +import it.cwmp.utils.{Logging, VertxInstance} import scala.util.{Failure, Success} @@ -12,13 +10,11 @@ import scala.util.{Failure, Success} * * @author Enrico Siboni */ -object RoomsServiceMain extends App with Logging { - private val vertx: Vertx = Vertx.vertx() - +object RoomsServiceMain extends App with VertxInstance with Logging { log.info("Deploying RoomService...") vertx.deployVerticleFuture(RoomsServiceVerticle(AuthenticationApiWrapper(), RoomReceiverApiWrapper())) .onComplete { case Success(_) => log.info("RoomsService up and running!") case Failure(ex) => log.info("Error deploying RoomsService", ex) - }(VertxExecutionContext(vertx.getOrCreateContext())) + } } From 4a8e92917bda048c9f039d70e6cbe71e025f6955 Mon Sep 17 00:00:00 2001 From: Davide Borficchia Date: Wed, 25 Jul 2018 14:17:47 +0200 Subject: [PATCH 041/193] aggiunti test per il check dell'inizializzazione del DAO --- .../{storage => }/StorageLocalDAOTest.scala | 30 +++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) rename services/authentication/src/test/scala/it/cwmp/services/authentication/{storage => }/StorageLocalDAOTest.scala (79%) diff --git a/services/authentication/src/test/scala/it/cwmp/services/authentication/storage/StorageLocalDAOTest.scala b/services/authentication/src/test/scala/it/cwmp/services/authentication/StorageLocalDAOTest.scala similarity index 79% rename from services/authentication/src/test/scala/it/cwmp/services/authentication/storage/StorageLocalDAOTest.scala rename to services/authentication/src/test/scala/it/cwmp/services/authentication/StorageLocalDAOTest.scala index e9d00891..e06eeeb7 100644 --- a/services/authentication/src/test/scala/it/cwmp/services/authentication/storage/StorageLocalDAOTest.scala +++ b/services/authentication/src/test/scala/it/cwmp/services/authentication/StorageLocalDAOTest.scala @@ -1,6 +1,5 @@ -package it.cwmp.services.authentication.storage +package it.cwmp.services.authentication -import it.cwmp.services.authentication.{StorageDAO, StorageLoaclDAO} import it.cwmp.testing.{FutureMatchers, VertxTest} import it.cwmp.utils.Utils import org.scalatest.{BeforeAndAfterEach, Matchers} @@ -10,11 +9,13 @@ import scala.concurrent.Future class StorageLocalDAOTest extends VertxTest with Matchers with FutureMatchers with BeforeAndAfterEach { var storageFuture: Future[StorageDAO] = _ + var storageNotInizializedFuture: Future[StorageDAO] = _ override def beforeEach(): Unit = { super.beforeEach() val storage = StorageLoaclDAO() storageFuture = storage.initialize().map(_ => storage) + storageNotInizializedFuture = Future(storage) } describe("Storage manager") { @@ -117,5 +118,30 @@ class StorageLocalDAOTest extends VertxTest with Matchers with FutureMatchers wi } } } + describe("The Helper shouldn't work") { + describe("if not initialized") { + it("sign up") { + val password = Utils.randomString(10) + val username = Utils.randomString(10) + storageNotInizializedFuture + .flatMap(storage => storage.signupFuture(username, password)) + .shouldFailWith[IllegalStateException] + } + it("sign out") { + val password = Utils.randomString(10) + val username = Utils.randomString(10) + storageNotInizializedFuture + .flatMap(storage => storage.signoutFuture(username)) + .shouldFailWith[IllegalStateException] + } + it("login") { + val password = Utils.randomString(10) + val username = Utils.randomString(10) + storageNotInizializedFuture + .flatMap(storage => storage.loginFuture(username, password)) + .shouldFailWith[IllegalStateException] + } + } + } } From b8cc279917f3b0f80580df6ef49ff63375daaa1c Mon Sep 17 00:00:00 2001 From: Enrico Siboni Date: Wed, 25 Jul 2018 14:18:00 +0200 Subject: [PATCH 042/193] Reformatted and refactored some code in rooms testing classes --- .../it/cwmp/services/rooms/RoomsLocalDAOTest.scala | 2 +- .../cwmp/services/rooms/RoomsServiceVerticleTest.scala | 10 ++++++---- .../scala/it/cwmp/testing/rooms/RoomsTesting.scala | 4 ++++ .../it/cwmp/testing/rooms/RoomsWebServiceTesting.scala | 8 +++++--- 4 files changed, 16 insertions(+), 8 deletions(-) diff --git a/services/rooms/src/test/scala/it/cwmp/services/rooms/RoomsLocalDAOTest.scala b/services/rooms/src/test/scala/it/cwmp/services/rooms/RoomsLocalDAOTest.scala index fa3b4998..32bdbad2 100644 --- a/services/rooms/src/test/scala/it/cwmp/services/rooms/RoomsLocalDAOTest.scala +++ b/services/rooms/src/test/scala/it/cwmp/services/rooms/RoomsLocalDAOTest.scala @@ -262,7 +262,7 @@ class RoomsLocalDAOTest extends RoomsTesting with BeforeAndAfterEach with Future test(0).shouldFailWith[IllegalArgumentException] } it("if there's no room with such players number") { - test(20).shouldFailWith[NoSuchElementException] + test(TOO_BIG_PLAYERS_NUMBER).shouldFailWith[NoSuchElementException] } } diff --git a/services/rooms/src/test/scala/it/cwmp/services/rooms/RoomsServiceVerticleTest.scala b/services/rooms/src/test/scala/it/cwmp/services/rooms/RoomsServiceVerticleTest.scala index 6159a03d..b4dfd22a 100644 --- a/services/rooms/src/test/scala/it/cwmp/services/rooms/RoomsServiceVerticleTest.scala +++ b/services/rooms/src/test/scala/it/cwmp/services/rooms/RoomsServiceVerticleTest.scala @@ -4,6 +4,7 @@ import io.vertx.core.buffer.Buffer import io.vertx.core.http.HttpMethod._ import io.vertx.scala.ext.web.client.{HttpResponse, WebClientOptions} import it.cwmp.model.Room +import it.cwmp.model.Room.Converters._ import it.cwmp.services.rooms.ServerParameters._ import it.cwmp.testing.HttpMatchers import it.cwmp.testing.rooms.RoomsWebServiceTesting @@ -84,7 +85,6 @@ class RoomsServiceVerticleTest extends RoomsWebServiceTesting with RoomApiWrappe createAPrivateRoomAndGetID(roomName, playersNumber) .flatMap(roomID => privateRoomInfoRequest(roomID) .map(response => { - import Room.Converters._ roomJson = Room(roomID, roomName, playersNumber, Seq()).toJson.encode() response })) @@ -189,7 +189,8 @@ class RoomsServiceVerticleTest extends RoomsWebServiceTesting with RoomApiWrappe override protected def publicRoomExitingTests(playersNumber: Int): Unit = { it("should succeed if players number is correct and user is inside") { - (enterPublicRoomRequest(playersNumber, participantList.head, notificationAddress) flatMap (_ => exitPublicRoomRequest(playersNumber))) shouldAnswerWith 200 + enterPublicRoomRequest(playersNumber, participantList.head, notificationAddress) + .flatMap(_ => exitPublicRoomRequest(playersNumber)) shouldAnswerWith 200 } it("user should not be inside after it") { enterPublicRoomRequest(playersNumber, participantList.head, notificationAddress) @@ -233,7 +234,8 @@ class RoomsServiceVerticleTest extends RoomsWebServiceTesting with RoomApiWrappe client.request(apiCall._1, apiCall._2).addAuthentication("token").sendFuture() shouldAnswerWith 401 } it(s"if token isn't valid, doing ${apiCall._1.toString} on ${apiCall._2}") { - client.request(apiCall._1, apiCall._2).addAuthentication("eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VybmFtZSI6InRpemlvIn0.f6eS98GeBmPau4O58NwQa_XRu3Opv6qWxYISWU78F68") + client.request(apiCall._1, apiCall._2) + .addAuthentication("eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VybmFtZSI6InRpemlvIn0.f6eS98GeBmPau4O58NwQa_XRu3Opv6qWxYISWU78F68") .sendFuture() shouldAnswerWith 401 } } @@ -260,7 +262,7 @@ class RoomsServiceVerticleTest extends RoomsWebServiceTesting with RoomApiWrappe apiCall(0).mapTo[HttpResponse[Buffer]] shouldAnswerWith 400 } it("if room with such players number doesn't exist") { - apiCall(20).mapTo[HttpResponse[Buffer]] shouldAnswerWith 404 + apiCall(TOO_BIG_PLAYERS_NUMBER).mapTo[HttpResponse[Buffer]] shouldAnswerWith 404 } } diff --git a/services/rooms/src/test/scala/it/cwmp/testing/rooms/RoomsTesting.scala b/services/rooms/src/test/scala/it/cwmp/testing/rooms/RoomsTesting.scala index 28d1ccfc..ff103a58 100644 --- a/services/rooms/src/test/scala/it/cwmp/testing/rooms/RoomsTesting.scala +++ b/services/rooms/src/test/scala/it/cwmp/testing/rooms/RoomsTesting.scala @@ -7,6 +7,8 @@ import scala.concurrent.Future /** * A base class that provides common tests structure for Rooms + * + * @author Enrico Siboni */ abstract class RoomsTesting extends VertxTest with Matchers { @@ -14,6 +16,8 @@ abstract class RoomsTesting extends VertxTest with Matchers { private val privateRoomPlayersNumber = 2 private val publicRoomPlayersNumber = 2 + protected val TOO_BIG_PLAYERS_NUMBER = 20 + describe("Private Room") { describe("Creation") { privateRoomCreationTests(roomName, privateRoomPlayersNumber) diff --git a/services/rooms/src/test/scala/it/cwmp/testing/rooms/RoomsWebServiceTesting.scala b/services/rooms/src/test/scala/it/cwmp/testing/rooms/RoomsWebServiceTesting.scala index 77535b7d..3f222a88 100644 --- a/services/rooms/src/test/scala/it/cwmp/testing/rooms/RoomsWebServiceTesting.scala +++ b/services/rooms/src/test/scala/it/cwmp/testing/rooms/RoomsWebServiceTesting.scala @@ -21,10 +21,12 @@ import scala.concurrent.Future */ abstract class RoomsWebServiceTesting extends RoomsTesting with VerticleBeforeAndAfterEach { + private val participantAddress = "http://127.0.1.1:8668/api/client/pFU9qOCU3kmYqwk1qqkl/room/participants" + protected val participants: Map[String, Participant] = Map( - "CORRECT_TOKEN_1" -> Participant("Enrico1", "http://127.0.1.1:8668/api/client/pFU9qOCU3kmYqwk1qqkl/room/participants"), - "CORRECT_TOKEN_2" -> Participant("Enrico2", "http://127.0.1.1:8668/api/client/pFU9qOCU3kmYqwk1qqkl/room/participants"), - "CORRECT_TOKEN_3" -> Participant("Enrico3", "http://127.0.1.1:8668/api/client/pFU9qOCU3kmYqwk1qqkl/room/participants")) + "CORRECT_TOKEN_1" -> Participant("Enrico1", participantAddress), + "CORRECT_TOKEN_2" -> Participant("Enrico2", participantAddress), + "CORRECT_TOKEN_3" -> Participant("Enrico3", participantAddress)) protected implicit val defaultParticipant: Participant = participants.values.head protected val participantList: List[Participant] = participants.values.toList protected implicit val defaultToken: String = participants.keys.head From 2627d5a67130a94aa651c8fae058633509fb7d60 Mon Sep 17 00:00:00 2001 From: Enrico Siboni Date: Wed, 25 Jul 2018 14:20:28 +0200 Subject: [PATCH 043/193] Moved CellWorldDistributedState int impl package of game model --- .../src/main/scala/it/cwmp/client/model/PlayerActor.scala | 2 +- .../model/{ => game/impl}/CellWorldDistributedState.scala | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) rename client/src/main/scala/it/cwmp/client/model/{ => game/impl}/CellWorldDistributedState.scala (92%) diff --git a/client/src/main/scala/it/cwmp/client/model/PlayerActor.scala b/client/src/main/scala/it/cwmp/client/model/PlayerActor.scala index d545be6b..a353898c 100644 --- a/client/src/main/scala/it/cwmp/client/model/PlayerActor.scala +++ b/client/src/main/scala/it/cwmp/client/model/PlayerActor.scala @@ -6,7 +6,7 @@ import akka.cluster.ClusterEvent._ import akka.cluster.ddata.DistributedData import it.cwmp.client.GameMain import it.cwmp.client.model.PlayerActor._ -import it.cwmp.client.model.game.impl.CellWorld +import it.cwmp.client.model.game.impl.{CellWorld, CellWorldDistributedState} import it.cwmp.client.view.game.GameViewActor import it.cwmp.client.view.game.GameViewActor._ import it.cwmp.model.Address diff --git a/client/src/main/scala/it/cwmp/client/model/CellWorldDistributedState.scala b/client/src/main/scala/it/cwmp/client/model/game/impl/CellWorldDistributedState.scala similarity index 92% rename from client/src/main/scala/it/cwmp/client/model/CellWorldDistributedState.scala rename to client/src/main/scala/it/cwmp/client/model/game/impl/CellWorldDistributedState.scala index 8c7517f5..56593cf5 100644 --- a/client/src/main/scala/it/cwmp/client/model/CellWorldDistributedState.scala +++ b/client/src/main/scala/it/cwmp/client/model/game/impl/CellWorldDistributedState.scala @@ -1,12 +1,12 @@ -package it.cwmp.client.model +package it.cwmp.client.model.game.impl import akka.actor.Actor.Receive import akka.actor.ActorRef import akka.cluster.Cluster -import akka.cluster.ddata.{LWWRegister, Replicator} import akka.cluster.ddata.Replicator.{Update, WriteLocal} +import akka.cluster.ddata.{LWWRegister, Replicator} +import it.cwmp.client.model.DistributedState import it.cwmp.client.model.DistributedState.UpdateState -import it.cwmp.client.model.game.impl.CellWorld /** * Distributed representation of the world and of his behaviours. From 7f4b6334d9fc1ccadf3cb937968fdfe14ff95362 Mon Sep 17 00:00:00 2001 From: Enrico Siboni Date: Wed, 25 Jul 2018 14:22:53 +0200 Subject: [PATCH 044/193] Moved GeometricUtils out of game.impl package, because they are general for game model --- .../cwmp/client/model/game/{impl => }/GeometricUtils.scala | 4 +++- .../main/scala/it/cwmp/client/view/game/GameViewActor.scala | 1 + .../scala/it/cwmp/client/view/game/model/TentacleView.scala | 4 ++-- .../client/model/game/{impl => }/GeometricUtilsTest.scala | 5 +++-- 4 files changed, 9 insertions(+), 5 deletions(-) rename client/src/main/scala/it/cwmp/client/model/game/{impl => }/GeometricUtils.scala (98%) rename client/src/test/scala/it/cwmp/client/model/game/{impl => }/GeometricUtilsTest.scala (98%) diff --git a/client/src/main/scala/it/cwmp/client/model/game/impl/GeometricUtils.scala b/client/src/main/scala/it/cwmp/client/model/game/GeometricUtils.scala similarity index 98% rename from client/src/main/scala/it/cwmp/client/model/game/impl/GeometricUtils.scala rename to client/src/main/scala/it/cwmp/client/model/game/GeometricUtils.scala index 9aa6aa0b..05e65808 100644 --- a/client/src/main/scala/it/cwmp/client/model/game/impl/GeometricUtils.scala +++ b/client/src/main/scala/it/cwmp/client/model/game/GeometricUtils.scala @@ -1,4 +1,6 @@ -package it.cwmp.client.model.game.impl +package it.cwmp.client.model.game + +import it.cwmp.client.model.game.impl.Point /** * A little collection of useful geometric utils diff --git a/client/src/main/scala/it/cwmp/client/view/game/GameViewActor.scala b/client/src/main/scala/it/cwmp/client/view/game/GameViewActor.scala index 44f907fd..ebfddd04 100644 --- a/client/src/main/scala/it/cwmp/client/view/game/GameViewActor.scala +++ b/client/src/main/scala/it/cwmp/client/view/game/GameViewActor.scala @@ -3,6 +3,7 @@ package it.cwmp.client.view.game import akka.actor.{Actor, ActorRef, Cancellable} import it.cwmp.client.controller.game.GameEngine import it.cwmp.client.model.DistributedState +import it.cwmp.client.model.game.GeometricUtils import it.cwmp.client.model.game.impl._ import it.cwmp.client.view.game.GameViewActor._ import it.cwmp.client.view.game.model.{CellView, TentacleView} diff --git a/client/src/main/scala/it/cwmp/client/view/game/model/TentacleView.scala b/client/src/main/scala/it/cwmp/client/view/game/model/TentacleView.scala index db268541..08f0955c 100644 --- a/client/src/main/scala/it/cwmp/client/view/game/model/TentacleView.scala +++ b/client/src/main/scala/it/cwmp/client/view/game/model/TentacleView.scala @@ -2,8 +2,8 @@ package it.cwmp.client.view.game.model import java.time.{Duration, Instant} -import it.cwmp.client.model.game.SizingStrategy -import it.cwmp.client.model.game.impl.{GeometricUtils, Point, Tentacle} +import it.cwmp.client.model.game.{GeometricUtils, SizingStrategy} +import it.cwmp.client.model.game.impl.{Point, Tentacle} import it.cwmp.client.view.game.ColoringStrategy import javafx.scene.paint.Color diff --git a/client/src/test/scala/it/cwmp/client/model/game/impl/GeometricUtilsTest.scala b/client/src/test/scala/it/cwmp/client/model/game/GeometricUtilsTest.scala similarity index 98% rename from client/src/test/scala/it/cwmp/client/model/game/impl/GeometricUtilsTest.scala rename to client/src/test/scala/it/cwmp/client/model/game/GeometricUtilsTest.scala index b13d556d..2a1c2d7e 100644 --- a/client/src/test/scala/it/cwmp/client/model/game/impl/GeometricUtilsTest.scala +++ b/client/src/test/scala/it/cwmp/client/model/game/GeometricUtilsTest.scala @@ -1,6 +1,7 @@ -package it.cwmp.client.model.game.impl +package it.cwmp.client.model.game -import it.cwmp.client.model.game.impl.GeometricUtils.RichDouble +import it.cwmp.client.model.game.GeometricUtils.RichDouble +import it.cwmp.client.model.game.impl.Point import org.scalatest.prop.PropertyChecks import org.scalatest.{Matchers, PropSpec} From e3a9a99ac18dd43d5932725908dd903c7c447b88 Mon Sep 17 00:00:00 2001 From: Davide Borficchia Date: Wed, 25 Jul 2018 14:34:50 +0200 Subject: [PATCH 045/193] rifattorizzato test e aggiunta doc --- .../authentication/StorageLocalDAOTest.scala | 25 +++++++------------ 1 file changed, 9 insertions(+), 16 deletions(-) diff --git a/services/authentication/src/test/scala/it/cwmp/services/authentication/StorageLocalDAOTest.scala b/services/authentication/src/test/scala/it/cwmp/services/authentication/StorageLocalDAOTest.scala index e06eeeb7..92c000c0 100644 --- a/services/authentication/src/test/scala/it/cwmp/services/authentication/StorageLocalDAOTest.scala +++ b/services/authentication/src/test/scala/it/cwmp/services/authentication/StorageLocalDAOTest.scala @@ -3,19 +3,27 @@ package it.cwmp.services.authentication import it.cwmp.testing.{FutureMatchers, VertxTest} import it.cwmp.utils.Utils import org.scalatest.{BeforeAndAfterEach, Matchers} - import scala.concurrent.Future +/** + * Test per la classe StorageLocalDAO + * + * @author Davide Borficchia + */ class StorageLocalDAOTest extends VertxTest with Matchers with FutureMatchers with BeforeAndAfterEach { var storageFuture: Future[StorageDAO] = _ var storageNotInizializedFuture: Future[StorageDAO] = _ + var username: String = _ + var password: String = _ override def beforeEach(): Unit = { super.beforeEach() val storage = StorageLoaclDAO() storageFuture = storage.initialize().map(_ => storage) storageNotInizializedFuture = Future(storage) + username = Utils.randomString(10) + password = Utils.randomString(10) } describe("Storage manager") { @@ -62,7 +70,6 @@ class StorageLocalDAOTest extends VertxTest with Matchers with FutureMatchers wi .shouldFail } it("when username doesn't exists") { - val username = Utils.randomString(10) storageFuture .flatMap(storage => storage.signoutFuture(username)) .shouldFail @@ -70,8 +77,6 @@ class StorageLocalDAOTest extends VertxTest with Matchers with FutureMatchers wi } describe("should succeed") { it("when all right") { - val username = Utils.randomString(10) - val password = Utils.randomString(10) storageFuture .flatMap(storage => storage.signupFuture(username, password).map(_ => storage)) .flatMap(storage => storage.signoutFuture(username)) @@ -83,20 +88,16 @@ class StorageLocalDAOTest extends VertxTest with Matchers with FutureMatchers wi describe("login") { describe("should fail with error") { it("when username empty") { - val password = Utils.randomString(10) storageFuture .flatMap(storage => storage.loginFuture("", password)) .shouldFail } it("when username doesn't exists") { - val username = Utils.randomString(10) storageFuture .flatMap(storage => storage.loginFuture(username, "")) .shouldFail } it("when password is wrong") { - val username = Utils.randomString(10) - val password = Utils.randomString(10) val passwordWrong = Utils.randomString(10) storageFuture .flatMap(storage => storage.signupFuture(username, password).map(_ => storage)) @@ -107,8 +108,6 @@ class StorageLocalDAOTest extends VertxTest with Matchers with FutureMatchers wi } describe("should succeed") { it("when all right") { - val username = Utils.randomString(10) - val password = Utils.randomString(10) storageFuture .flatMap(storage => storage.signupFuture(username, password).map(_ => storage)) .flatMap(storage => storage.loginFuture(username, password).map(_ => storage)) @@ -122,22 +121,16 @@ class StorageLocalDAOTest extends VertxTest with Matchers with FutureMatchers wi describe("if not initialized") { it("sign up") { - val password = Utils.randomString(10) - val username = Utils.randomString(10) storageNotInizializedFuture .flatMap(storage => storage.signupFuture(username, password)) .shouldFailWith[IllegalStateException] } it("sign out") { - val password = Utils.randomString(10) - val username = Utils.randomString(10) storageNotInizializedFuture .flatMap(storage => storage.signoutFuture(username)) .shouldFailWith[IllegalStateException] } it("login") { - val password = Utils.randomString(10) - val username = Utils.randomString(10) storageNotInizializedFuture .flatMap(storage => storage.loginFuture(username, password)) .shouldFailWith[IllegalStateException] From a5c4d668ef3a119459dee35e6b35af6c23f67a26 Mon Sep 17 00:00:00 2001 From: Enrico Siboni Date: Wed, 25 Jul 2018 14:51:26 +0200 Subject: [PATCH 046/193] Removed old TODO --- .../main/scala/it/cwmp/client/model/game/impl/CellWorld.scala | 2 -- 1 file changed, 2 deletions(-) diff --git a/client/src/main/scala/it/cwmp/client/model/game/impl/CellWorld.scala b/client/src/main/scala/it/cwmp/client/model/game/impl/CellWorld.scala index e76ed3ba..69d3e0b0 100644 --- a/client/src/main/scala/it/cwmp/client/model/game/impl/CellWorld.scala +++ b/client/src/main/scala/it/cwmp/client/model/game/impl/CellWorld.scala @@ -74,6 +74,4 @@ object CellWorld { */ val durationToEnergyConversionStrategy: SizingStrategy[Duration, Double] = (attackDuration: Duration) => attackDuration.toMillis / ATTACK_DURATION_TO_ENERGY_REDUCTION_RATE - - // TODO: Add converter to DDATA } From d46c4886aa8c5aa3668f24e20f926ebc9928e56a Mon Sep 17 00:00:00 2001 From: Enrico Siboni Date: Wed, 25 Jul 2018 15:10:36 +0200 Subject: [PATCH 047/193] - Renamed StorageDAO to AuthenticationDAO - Adjusted misspelling in LoclDAO to LocalDAO --- ...ageLoaclDAO.scala => AuthenticationLoacalDAO.scala} | 10 +++++----- .../authentication/AuthenticationServiceVerticle.scala | 4 ++-- .../services/authentication/StorageLocalDAOTest.scala | 6 +++--- 3 files changed, 10 insertions(+), 10 deletions(-) rename services/authentication/src/main/scala/it/cwmp/services/authentication/{StorageLoaclDAO.scala => AuthenticationLoacalDAO.scala} (94%) diff --git a/services/authentication/src/main/scala/it/cwmp/services/authentication/StorageLoaclDAO.scala b/services/authentication/src/main/scala/it/cwmp/services/authentication/AuthenticationLoacalDAO.scala similarity index 94% rename from services/authentication/src/main/scala/it/cwmp/services/authentication/StorageLoaclDAO.scala rename to services/authentication/src/main/scala/it/cwmp/services/authentication/AuthenticationLoacalDAO.scala index 23ba96d1..f439f7ed 100644 --- a/services/authentication/src/main/scala/it/cwmp/services/authentication/StorageLoaclDAO.scala +++ b/services/authentication/src/main/scala/it/cwmp/services/authentication/AuthenticationLoacalDAO.scala @@ -2,7 +2,7 @@ package it.cwmp.services.authentication import com.typesafe.scalalogging.Logger import io.vertx.core.json.JsonArray -import it.cwmp.services.authentication.StorageLoaclDAO._ +import it.cwmp.services.authentication.AuthenticationLoacalDAO._ import it.cwmp.utils.{VertxInstance, VertxJDBC} import scala.concurrent._ @@ -11,7 +11,7 @@ import scala.concurrent._ * * @author Davide Borficchia */ -trait StorageDAO { +trait AuthenticationDAO { /** * Registra un nuovo utente all'interno dello storage * @@ -52,7 +52,7 @@ trait StorageDAO { * * @author Davide Borficchia */ -case class StorageLoaclDAO(override val configurationPath: String = "authentication/database.json") extends StorageDAO with VertxInstance with VertxJDBC { +case class AuthenticationLoacalDAO(override val configurationPath: String = "authentication/database.json") extends AuthenticationDAO with VertxInstance with VertxJDBC { private var notInitialized = true def initialize(): Future[Unit] = { @@ -131,8 +131,8 @@ case class StorageLoaclDAO(override val configurationPath: String = "authenticat } } -object StorageLoaclDAO { - private val logger: Logger = Logger[StorageLoaclDAO] +object AuthenticationLoacalDAO { + private val logger: Logger = Logger[AuthenticationLoacalDAO] private val FIELD_AUTH_USERNAME = "auth_username" private val FIELD_AUTH_PASSWORD = "auth_password" private val FIELD_AUTH_SALT = "auth_salt" diff --git a/services/authentication/src/main/scala/it/cwmp/services/authentication/AuthenticationServiceVerticle.scala b/services/authentication/src/main/scala/it/cwmp/services/authentication/AuthenticationServiceVerticle.scala index e2e5a71b..8d367041 100644 --- a/services/authentication/src/main/scala/it/cwmp/services/authentication/AuthenticationServiceVerticle.scala +++ b/services/authentication/src/main/scala/it/cwmp/services/authentication/AuthenticationServiceVerticle.scala @@ -15,7 +15,7 @@ case class AuthenticationServiceVerticle() extends VertxServer with Logging { override protected val serverPort: Int = DEFAULT_PORT - private var storageFuture: Future[StorageDAO] = _ + private var storageFuture: Future[AuthenticationDAO] = _ override protected def initRouter(router: Router): Unit = { router post API_SIGNUP handler handlerSignup @@ -25,7 +25,7 @@ case class AuthenticationServiceVerticle() extends VertxServer with Logging { } override protected def initServer: Future[_] = { - val storage = StorageLoaclDAO() + val storage = AuthenticationLoacalDAO() storageFuture = storage.initialize().map(_ => storage) storageFuture } diff --git a/services/authentication/src/test/scala/it/cwmp/services/authentication/StorageLocalDAOTest.scala b/services/authentication/src/test/scala/it/cwmp/services/authentication/StorageLocalDAOTest.scala index 92c000c0..82c0de2d 100644 --- a/services/authentication/src/test/scala/it/cwmp/services/authentication/StorageLocalDAOTest.scala +++ b/services/authentication/src/test/scala/it/cwmp/services/authentication/StorageLocalDAOTest.scala @@ -12,14 +12,14 @@ import scala.concurrent.Future */ class StorageLocalDAOTest extends VertxTest with Matchers with FutureMatchers with BeforeAndAfterEach { - var storageFuture: Future[StorageDAO] = _ - var storageNotInizializedFuture: Future[StorageDAO] = _ + var storageFuture: Future[AuthenticationDAO] = _ + var storageNotInizializedFuture: Future[AuthenticationDAO] = _ var username: String = _ var password: String = _ override def beforeEach(): Unit = { super.beforeEach() - val storage = StorageLoaclDAO() + val storage = AuthenticationLoacalDAO() storageFuture = storage.initialize().map(_ => storage) storageNotInizializedFuture = Future(storage) username = Utils.randomString(10) From df5a845acfbabcbd6602eacdb81e7f255fb0e8c9 Mon Sep 17 00:00:00 2001 From: Enrico Siboni Date: Wed, 25 Jul 2018 15:14:48 +0200 Subject: [PATCH 048/193] - Adjusted misspelling - Added our logging - Renamed methods so now there are no warnings --- ...DAO.scala => AuthenticationLocalDAO.scala} | 40 ++++++++++--------- .../AuthenticationServiceVerticle.scala | 6 +-- .../authentication/StorageLocalDAOTest.scala | 34 ++++++++-------- 3 files changed, 42 insertions(+), 38 deletions(-) rename services/authentication/src/main/scala/it/cwmp/services/authentication/{AuthenticationLoacalDAO.scala => AuthenticationLocalDAO.scala} (81%) diff --git a/services/authentication/src/main/scala/it/cwmp/services/authentication/AuthenticationLoacalDAO.scala b/services/authentication/src/main/scala/it/cwmp/services/authentication/AuthenticationLocalDAO.scala similarity index 81% rename from services/authentication/src/main/scala/it/cwmp/services/authentication/AuthenticationLoacalDAO.scala rename to services/authentication/src/main/scala/it/cwmp/services/authentication/AuthenticationLocalDAO.scala index f439f7ed..061d5810 100644 --- a/services/authentication/src/main/scala/it/cwmp/services/authentication/AuthenticationLoacalDAO.scala +++ b/services/authentication/src/main/scala/it/cwmp/services/authentication/AuthenticationLocalDAO.scala @@ -1,9 +1,9 @@ package it.cwmp.services.authentication -import com.typesafe.scalalogging.Logger import io.vertx.core.json.JsonArray -import it.cwmp.services.authentication.AuthenticationLoacalDAO._ -import it.cwmp.utils.{VertxInstance, VertxJDBC} +import it.cwmp.services.authentication.AuthenticationLocalDAO._ +import it.cwmp.utils.{Logging, VertxInstance, VertxJDBC} + import scala.concurrent._ /** @@ -19,7 +19,7 @@ trait AuthenticationDAO { * @param password password del nuovo utente * @return ritorna un Future vuoto */ - def signupFuture(username: String, password: String): Future[Unit] + def signUpFuture(username: String, password: String): Future[Unit] /** * Fa sloggare un utente che ha precedentemente fatto login @@ -27,7 +27,7 @@ trait AuthenticationDAO { * @param username username dell'utente che si vuole fare sloggare * @return ritorna un Future vuoto */ - def signoutFuture(username: String): Future[Unit] + def signOutFuture(username: String): Future[Unit] /** * Permette di far loggare un utente precedentemente registrato nel sistema @@ -52,11 +52,12 @@ trait AuthenticationDAO { * * @author Davide Borficchia */ -case class AuthenticationLoacalDAO(override val configurationPath: String = "authentication/database.json") extends AuthenticationDAO with VertxInstance with VertxJDBC { +case class AuthenticationLocalDAO(override val configurationPath: String = "authentication/database.json") + extends AuthenticationDAO with VertxInstance with VertxJDBC with Logging { private var notInitialized = true def initialize(): Future[Unit] = { - logger.info("Initializing RoomLocalDAO...") + log.info("Initializing RoomLocalDAO...") (for ( connection <- openConnection(); _ <- connection.executeFuture(createStorageTableSql) @@ -65,8 +66,8 @@ case class AuthenticationLoacalDAO(override val configurationPath: String = "aut }).closeConnections } - override def signupFuture(usernameP: String, passwordP: String): Future[Unit] = { - logger.debug(s"signup() username:$usernameP, password:$passwordP") + override def signUpFuture(usernameP: String, passwordP: String): Future[Unit] = { + log.debug(s"signup() username:$usernameP, password:$passwordP") (for ( // Controllo l'input username <- Option(usernameP) if username.nonEmpty; @@ -79,13 +80,13 @@ case class AuthenticationLoacalDAO(override val configurationPath: String = "aut _ <- connection.updateWithParamsFuture( insertNewUserSql, new JsonArray().add(username).add(password).add("SALT")) ) yield { - logger.debug("inizialized") + log.debug("inizialized") }).closeConnections }).getOrElse(Future.failed(new IllegalArgumentException())) } - override def signoutFuture(usernameP: String): Future[Unit] = { - logger.debug(s"signoutFuture() username:$usernameP") + override def signOutFuture(usernameP: String): Future[Unit] = { + log.debug(s"signoutFuture() username:$usernameP") (for ( // Controllo l'input username <- Option(usernameP) if username.nonEmpty @@ -94,13 +95,13 @@ case class AuthenticationLoacalDAO(override val configurationPath: String = "aut // Eseguo operazioni sul db in maniera sequenziale _ <- checkInitialization(notInitialized); connection <- openConnection(); - result <- connection.updateWithParamsFuture(signoutUserSql, new JsonArray().add(username)) if result.getUpdated > 0 + result <- connection.updateWithParamsFuture(signOutUserSql, new JsonArray().add(username)) if result.getUpdated > 0 ) yield ()).closeConnections }).getOrElse(Future.failed(new IllegalArgumentException())) } override def loginFuture(usernameP: String, passwordP: String): Future[Unit] = { - logger.debug(s"loginFuture() username:$usernameP, password:$passwordP") + log.debug(s"loginFuture() username:$usernameP, password:$passwordP") (for ( // Controllo l'input username <- Option(usernameP) if username.nonEmpty; @@ -116,7 +117,7 @@ case class AuthenticationLoacalDAO(override val configurationPath: String = "aut } override def existsFuture(usernameP: String): Future[Unit] = { - logger.debug(s"existsFuture() username:$usernameP") + log.debug(s"existsFuture() username:$usernameP") (for ( // Controllo l'input username <- Option(usernameP) if username.nonEmpty @@ -131,8 +132,11 @@ case class AuthenticationLoacalDAO(override val configurationPath: String = "aut } } -object AuthenticationLoacalDAO { - private val logger: Logger = Logger[AuthenticationLoacalDAO] +/** + * Companion Object + */ +object AuthenticationLocalDAO { + private val FIELD_AUTH_USERNAME = "auth_username" private val FIELD_AUTH_PASSWORD = "auth_password" private val FIELD_AUTH_SALT = "auth_salt" @@ -155,7 +159,7 @@ object AuthenticationLoacalDAO { """ private val insertNewUserSql = "INSERT INTO authorization VALUES (?, ?, ?)" - private val signoutUserSql = "DELETE FROM authorization WHERE auth_username = ?" + private val signOutUserSql = "DELETE FROM authorization WHERE auth_username = ?" private val loginUserSql = s""" SELECT * diff --git a/services/authentication/src/main/scala/it/cwmp/services/authentication/AuthenticationServiceVerticle.scala b/services/authentication/src/main/scala/it/cwmp/services/authentication/AuthenticationServiceVerticle.scala index 8d367041..a601b08b 100644 --- a/services/authentication/src/main/scala/it/cwmp/services/authentication/AuthenticationServiceVerticle.scala +++ b/services/authentication/src/main/scala/it/cwmp/services/authentication/AuthenticationServiceVerticle.scala @@ -25,7 +25,7 @@ case class AuthenticationServiceVerticle() extends VertxServer with Logging { } override protected def initServer: Future[_] = { - val storage = AuthenticationLoacalDAO() + val storage = AuthenticationLocalDAO() storageFuture = storage.initialize().map(_ => storage) storageFuture } @@ -36,7 +36,7 @@ case class AuthenticationServiceVerticle() extends VertxServer with Logging { authorizationHeader <- request.getAuthentication; (username, password) <- HttpUtils.readBasicAuthentication(authorizationHeader) ) yield { - storageFuture flatMap (_.signupFuture(username, password)) onComplete { + storageFuture flatMap (_.signUpFuture(username, password)) onComplete { case Success(_) => log.info(s"User $username signed up.") JwtUtils @@ -55,7 +55,7 @@ case class AuthenticationServiceVerticle() extends VertxServer with Logging { username <- JwtUtils.decodeUsernameToken(token) ) yield { // If every check pass, username contains the username contained in the token and we can check it exists - storageFuture.map(_.signoutFuture(username).onComplete { + storageFuture.map(_.signOutFuture(username).onComplete { case Success(_) => log.info(s"User $username signed out.") sendResponse(202) diff --git a/services/authentication/src/test/scala/it/cwmp/services/authentication/StorageLocalDAOTest.scala b/services/authentication/src/test/scala/it/cwmp/services/authentication/StorageLocalDAOTest.scala index 82c0de2d..6e645edf 100644 --- a/services/authentication/src/test/scala/it/cwmp/services/authentication/StorageLocalDAOTest.scala +++ b/services/authentication/src/test/scala/it/cwmp/services/authentication/StorageLocalDAOTest.scala @@ -19,7 +19,7 @@ class StorageLocalDAOTest extends VertxTest with Matchers with FutureMatchers wi override def beforeEach(): Unit = { super.beforeEach() - val storage = AuthenticationLoacalDAO() + val storage = AuthenticationLocalDAO() storageFuture = storage.initialize().map(_ => storage) storageNotInizializedFuture = Future(storage) username = Utils.randomString(10) @@ -32,21 +32,21 @@ class StorageLocalDAOTest extends VertxTest with Matchers with FutureMatchers wi it("when username empty") { val password = Utils.randomString(10) storageFuture - .flatMap(storage => storage.signupFuture("", password)) + .flatMap(storage => storage.signUpFuture("", password)) .shouldFail } it("when password empty") { val username = Utils.randomString(10) storageFuture - .flatMap(storage => storage.signupFuture(username, "")) + .flatMap(storage => storage.signUpFuture(username, "")) .shouldFail } it("when username already present") { val username = Utils.randomString(10) val password = Utils.randomString(10) storageFuture - .flatMap(storage => storage.signupFuture(username, password).map(_ => storage)) - .flatMap(storage => storage.signupFuture(username, password)) + .flatMap(storage => storage.signUpFuture(username, password).map(_ => storage)) + .flatMap(storage => storage.signUpFuture(username, password)) .shouldFail } } @@ -55,8 +55,8 @@ class StorageLocalDAOTest extends VertxTest with Matchers with FutureMatchers wi val username = Utils.randomString(10) val password = Utils.randomString(10) storageFuture - .flatMap(storage => storage.signupFuture(username, password).map(_ => storage)) - .flatMap(storage => storage.signoutFuture(username)) + .flatMap(storage => storage.signUpFuture(username, password).map(_ => storage)) + .flatMap(storage => storage.signOutFuture(username)) .shouldSucceed } } @@ -66,20 +66,20 @@ class StorageLocalDAOTest extends VertxTest with Matchers with FutureMatchers wi describe("should fail with error") { it("when username empty") { storageFuture - .flatMap(storage => storage.signoutFuture("")) + .flatMap(storage => storage.signOutFuture("")) .shouldFail } it("when username doesn't exists") { storageFuture - .flatMap(storage => storage.signoutFuture(username)) + .flatMap(storage => storage.signOutFuture(username)) .shouldFail } } describe("should succeed") { it("when all right") { storageFuture - .flatMap(storage => storage.signupFuture(username, password).map(_ => storage)) - .flatMap(storage => storage.signoutFuture(username)) + .flatMap(storage => storage.signUpFuture(username, password).map(_ => storage)) + .flatMap(storage => storage.signOutFuture(username)) .shouldSucceed } } @@ -100,18 +100,18 @@ class StorageLocalDAOTest extends VertxTest with Matchers with FutureMatchers wi it("when password is wrong") { val passwordWrong = Utils.randomString(10) storageFuture - .flatMap(storage => storage.signupFuture(username, password).map(_ => storage)) + .flatMap(storage => storage.signUpFuture(username, password).map(_ => storage)) .flatMap(storage => storage.loginFuture(username, passwordWrong).map(_ => storage)) - .flatMap(storage => storage.signoutFuture(username)) + .flatMap(storage => storage.signOutFuture(username)) .shouldFail } } describe("should succeed") { it("when all right") { storageFuture - .flatMap(storage => storage.signupFuture(username, password).map(_ => storage)) + .flatMap(storage => storage.signUpFuture(username, password).map(_ => storage)) .flatMap(storage => storage.loginFuture(username, password).map(_ => storage)) - .flatMap(storage => storage.signoutFuture(username)) + .flatMap(storage => storage.signOutFuture(username)) .shouldSucceed } } @@ -122,12 +122,12 @@ class StorageLocalDAOTest extends VertxTest with Matchers with FutureMatchers wi it("sign up") { storageNotInizializedFuture - .flatMap(storage => storage.signupFuture(username, password)) + .flatMap(storage => storage.signUpFuture(username, password)) .shouldFailWith[IllegalStateException] } it("sign out") { storageNotInizializedFuture - .flatMap(storage => storage.signoutFuture(username)) + .flatMap(storage => storage.signOutFuture(username)) .shouldFailWith[IllegalStateException] } it("login") { From 698c0f0fa7a98491575faeabb9793493fabb44f9 Mon Sep 17 00:00:00 2001 From: Enrico Siboni Date: Wed, 25 Jul 2018 15:17:35 +0200 Subject: [PATCH 049/193] Used implicit conversion to JsonArray embedded in VertxJDBC --- .../authentication/AuthenticationLocalDAO.scala | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/services/authentication/src/main/scala/it/cwmp/services/authentication/AuthenticationLocalDAO.scala b/services/authentication/src/main/scala/it/cwmp/services/authentication/AuthenticationLocalDAO.scala index 061d5810..08e4d344 100644 --- a/services/authentication/src/main/scala/it/cwmp/services/authentication/AuthenticationLocalDAO.scala +++ b/services/authentication/src/main/scala/it/cwmp/services/authentication/AuthenticationLocalDAO.scala @@ -1,7 +1,7 @@ package it.cwmp.services.authentication -import io.vertx.core.json.JsonArray import it.cwmp.services.authentication.AuthenticationLocalDAO._ +import it.cwmp.utils.VertxJDBC.stringsToJsonArray import it.cwmp.utils.{Logging, VertxInstance, VertxJDBC} import scala.concurrent._ @@ -78,7 +78,7 @@ case class AuthenticationLocalDAO(override val configurationPath: String = "auth _ <- checkInitialization(notInitialized); connection <- openConnection(); _ <- connection.updateWithParamsFuture( - insertNewUserSql, new JsonArray().add(username).add(password).add("SALT")) + insertNewUserSql, Seq(username, password, "SALT")) ) yield { log.debug("inizialized") }).closeConnections @@ -95,7 +95,7 @@ case class AuthenticationLocalDAO(override val configurationPath: String = "auth // Eseguo operazioni sul db in maniera sequenziale _ <- checkInitialization(notInitialized); connection <- openConnection(); - result <- connection.updateWithParamsFuture(signOutUserSql, new JsonArray().add(username)) if result.getUpdated > 0 + result <- connection.updateWithParamsFuture(signOutUserSql, Seq(username)) if result.getUpdated > 0 ) yield ()).closeConnections }).getOrElse(Future.failed(new IllegalArgumentException())) } @@ -111,7 +111,7 @@ case class AuthenticationLocalDAO(override val configurationPath: String = "auth // Eseguo operazioni sul db in maniera sequenziale _ <- checkInitialization(notInitialized); connection <- openConnection(); - result <- connection.queryWithParamsFuture(loginUserSql, new JsonArray().add(username).add(password)) if result.getResults.nonEmpty + result <- connection.queryWithParamsFuture(loginUserSql, Seq(username, password)) if result.getResults.nonEmpty ) yield ()).closeConnections }).getOrElse(Future.failed(new IllegalArgumentException())) } @@ -126,7 +126,7 @@ case class AuthenticationLocalDAO(override val configurationPath: String = "auth // Eseguo operazioni sul db in maniera sequenziale _ <- checkInitialization(notInitialized); connection <- openConnection(); - result <- connection.queryWithParamsFuture(existFutureUserSql, new JsonArray().add(username)) if result.getResults.nonEmpty + result <- connection.queryWithParamsFuture(existFutureUserSql, Seq(username)) if result.getResults.nonEmpty ) yield ()).closeConnections }).getOrElse(Future.failed(new IllegalArgumentException())) } From d82eaae48c8c951aab5483ecb0f2d7eebd9dadf8 Mon Sep 17 00:00:00 2001 From: Enrico Siboni Date: Wed, 25 Jul 2018 15:21:57 +0200 Subject: [PATCH 050/193] - Renamed Test for AuthenticationLocalDAO accordingly - Parametrized username and password lengths - Removed redundant initializations --- .../AuthenticationLocalDAO.scala | 1 + ...scala => AuthenticationLocalDAOTest.scala} | 30 +++++++++---------- 2 files changed, 15 insertions(+), 16 deletions(-) rename services/authentication/src/test/scala/it/cwmp/services/authentication/{StorageLocalDAOTest.scala => AuthenticationLocalDAOTest.scala} (83%) diff --git a/services/authentication/src/main/scala/it/cwmp/services/authentication/AuthenticationLocalDAO.scala b/services/authentication/src/main/scala/it/cwmp/services/authentication/AuthenticationLocalDAO.scala index 08e4d344..6127085d 100644 --- a/services/authentication/src/main/scala/it/cwmp/services/authentication/AuthenticationLocalDAO.scala +++ b/services/authentication/src/main/scala/it/cwmp/services/authentication/AuthenticationLocalDAO.scala @@ -54,6 +54,7 @@ trait AuthenticationDAO { */ case class AuthenticationLocalDAO(override val configurationPath: String = "authentication/database.json") extends AuthenticationDAO with VertxInstance with VertxJDBC with Logging { + private var notInitialized = true def initialize(): Future[Unit] = { diff --git a/services/authentication/src/test/scala/it/cwmp/services/authentication/StorageLocalDAOTest.scala b/services/authentication/src/test/scala/it/cwmp/services/authentication/AuthenticationLocalDAOTest.scala similarity index 83% rename from services/authentication/src/test/scala/it/cwmp/services/authentication/StorageLocalDAOTest.scala rename to services/authentication/src/test/scala/it/cwmp/services/authentication/AuthenticationLocalDAOTest.scala index 6e645edf..d2f22fe8 100644 --- a/services/authentication/src/test/scala/it/cwmp/services/authentication/StorageLocalDAOTest.scala +++ b/services/authentication/src/test/scala/it/cwmp/services/authentication/AuthenticationLocalDAOTest.scala @@ -3,47 +3,47 @@ package it.cwmp.services.authentication import it.cwmp.testing.{FutureMatchers, VertxTest} import it.cwmp.utils.Utils import org.scalatest.{BeforeAndAfterEach, Matchers} + import scala.concurrent.Future /** - * Test per la classe StorageLocalDAO + * Test per la classe AuthenticationLocalDAO * * @author Davide Borficchia */ -class StorageLocalDAOTest extends VertxTest with Matchers with FutureMatchers with BeforeAndAfterEach { +class AuthenticationLocalDAOTest extends VertxTest with Matchers with FutureMatchers with BeforeAndAfterEach { var storageFuture: Future[AuthenticationDAO] = _ - var storageNotInizializedFuture: Future[AuthenticationDAO] = _ + var storageNotInitializedFuture: Future[AuthenticationDAO] = _ var username: String = _ var password: String = _ + private val USERNAME_LENGTH = 10 + private val PASSWORD_LENGTH = 15 + override def beforeEach(): Unit = { super.beforeEach() val storage = AuthenticationLocalDAO() storageFuture = storage.initialize().map(_ => storage) - storageNotInizializedFuture = Future(storage) - username = Utils.randomString(10) - password = Utils.randomString(10) + storageNotInitializedFuture = Future(storage) + username = Utils.randomString(USERNAME_LENGTH) + password = Utils.randomString(PASSWORD_LENGTH) } describe("Storage manager") { describe("sign up") { describe("should fail with error") { it("when username empty") { - val password = Utils.randomString(10) storageFuture .flatMap(storage => storage.signUpFuture("", password)) .shouldFail } it("when password empty") { - val username = Utils.randomString(10) storageFuture .flatMap(storage => storage.signUpFuture(username, "")) .shouldFail } it("when username already present") { - val username = Utils.randomString(10) - val password = Utils.randomString(10) storageFuture .flatMap(storage => storage.signUpFuture(username, password).map(_ => storage)) .flatMap(storage => storage.signUpFuture(username, password)) @@ -52,8 +52,6 @@ class StorageLocalDAOTest extends VertxTest with Matchers with FutureMatchers wi } describe("should succeed") { it("when all right") { - val username = Utils.randomString(10) - val password = Utils.randomString(10) storageFuture .flatMap(storage => storage.signUpFuture(username, password).map(_ => storage)) .flatMap(storage => storage.signOutFuture(username)) @@ -98,7 +96,7 @@ class StorageLocalDAOTest extends VertxTest with Matchers with FutureMatchers wi .shouldFail } it("when password is wrong") { - val passwordWrong = Utils.randomString(10) + val passwordWrong = Utils.randomString(PASSWORD_LENGTH) storageFuture .flatMap(storage => storage.signUpFuture(username, password).map(_ => storage)) .flatMap(storage => storage.loginFuture(username, passwordWrong).map(_ => storage)) @@ -121,17 +119,17 @@ class StorageLocalDAOTest extends VertxTest with Matchers with FutureMatchers wi describe("if not initialized") { it("sign up") { - storageNotInizializedFuture + storageNotInitializedFuture .flatMap(storage => storage.signUpFuture(username, password)) .shouldFailWith[IllegalStateException] } it("sign out") { - storageNotInizializedFuture + storageNotInitializedFuture .flatMap(storage => storage.signOutFuture(username)) .shouldFailWith[IllegalStateException] } it("login") { - storageNotInizializedFuture + storageNotInitializedFuture .flatMap(storage => storage.loginFuture(username, password)) .shouldFailWith[IllegalStateException] } From 5393da3647ecb31f0ad7b2c4c5d7674ca1ecfe06 Mon Sep 17 00:00:00 2001 From: Enrico Siboni Date: Wed, 25 Jul 2018 15:26:54 +0200 Subject: [PATCH 051/193] Renamed methods avoiding warnings --- .../authentication/AuthenticationServiceVerticle.scala | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/services/authentication/src/main/scala/it/cwmp/services/authentication/AuthenticationServiceVerticle.scala b/services/authentication/src/main/scala/it/cwmp/services/authentication/AuthenticationServiceVerticle.scala index a601b08b..d439349d 100644 --- a/services/authentication/src/main/scala/it/cwmp/services/authentication/AuthenticationServiceVerticle.scala +++ b/services/authentication/src/main/scala/it/cwmp/services/authentication/AuthenticationServiceVerticle.scala @@ -18,8 +18,8 @@ case class AuthenticationServiceVerticle() extends VertxServer with Logging { private var storageFuture: Future[AuthenticationDAO] = _ override protected def initRouter(router: Router): Unit = { - router post API_SIGNUP handler handlerSignup - router post API_SIGNOUT handler handlerSignout + router post API_SIGNUP handler handlerSignUp + router post API_SIGNOUT handler handlerSignOut router get API_LOGIN handler handlerLogin router get API_VALIDATE handler handlerValidation } @@ -30,7 +30,7 @@ case class AuthenticationServiceVerticle() extends VertxServer with Logging { storageFuture } - private def handlerSignup: Handler[RoutingContext] = implicit routingContext => { + private def handlerSignUp: Handler[RoutingContext] = implicit routingContext => { log.debug("Received sign up request.") (for ( authorizationHeader <- request.getAuthentication; @@ -47,7 +47,7 @@ case class AuthenticationServiceVerticle() extends VertxServer with Logging { }) orElse Some(sendResponse(400)) } - private def handlerSignout: Handler[RoutingContext] = implicit routingContext => { + private def handlerSignOut: Handler[RoutingContext] = implicit routingContext => { log.debug("Received sign out request.") (for ( authorizationHeader <- request.getAuthentication; From 3e5166d13c89c3713078a1166249eeb009865d8e Mon Sep 17 00:00:00 2001 From: Enrico Siboni Date: Wed, 25 Jul 2018 15:36:47 +0200 Subject: [PATCH 052/193] Moved constants in RoomsTesting to companion object --- .../scala/it/cwmp/testing/rooms/RoomsTesting.scala | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/services/rooms/src/test/scala/it/cwmp/testing/rooms/RoomsTesting.scala b/services/rooms/src/test/scala/it/cwmp/testing/rooms/RoomsTesting.scala index ff103a58..47846a62 100644 --- a/services/rooms/src/test/scala/it/cwmp/testing/rooms/RoomsTesting.scala +++ b/services/rooms/src/test/scala/it/cwmp/testing/rooms/RoomsTesting.scala @@ -1,6 +1,7 @@ package it.cwmp.testing.rooms import it.cwmp.testing.VertxTest +import it.cwmp.testing.rooms.RoomsTesting.{privateRoomPlayersNumber, publicRoomPlayersNumber, roomName} import org.scalatest.Matchers import scala.concurrent.Future @@ -12,10 +13,6 @@ import scala.concurrent.Future */ abstract class RoomsTesting extends VertxTest with Matchers { - private val roomName = "Stanza" - private val privateRoomPlayersNumber = 2 - private val publicRoomPlayersNumber = 2 - protected val TOO_BIG_PLAYERS_NUMBER = 20 describe("Private Room") { @@ -80,3 +77,12 @@ abstract class RoomsTesting extends VertxTest with Matchers { */ protected def onWrongPlayersNumber(test: Int => Future[_]) } + +/** + * Companion object + */ +object RoomsTesting { + private val roomName = "Stanza" + private val privateRoomPlayersNumber = 2 + private val publicRoomPlayersNumber = 2 +} \ No newline at end of file From afe1a7694d9ec978cafb7e0e6feafd6bfaf5f1b2 Mon Sep 17 00:00:00 2001 From: Enrico Siboni Date: Wed, 25 Jul 2018 15:57:42 +0200 Subject: [PATCH 053/193] Added a plugin to view tasks dependencies (which tasks are launched starting from one) --- build.gradle | 3 +++ 1 file changed, 3 insertions(+) diff --git a/build.gradle b/build.gradle index af0c26f5..bf596003 100644 --- a/build.gradle +++ b/build.gradle @@ -10,6 +10,7 @@ def scalaStyleOutputPath = "${buildDir.path}$scalaStyleOutput" allprojects { apply plugin: 'idea' apply plugin: 'eclipse' + apply plugin: "com.dorongold.task-tree" repositories { // Repositories where to find libraries @@ -112,6 +113,8 @@ buildscript { } } dependencies { + classpath "gradle.plugin.com.dorongold.plugins:task-tree:1.3" + classpath "gradle.plugin.org.scoverage:gradle-scoverage:2.3.0" classpath "gradle.plugin.com.github.maiflai:gradle-scalatest:0.22" From de9633329a177666f9900efe9759aa75fa631491 Mon Sep 17 00:00:00 2001 From: Enrico Siboni Date: Wed, 25 Jul 2018 15:58:37 +0200 Subject: [PATCH 054/193] "build" task already calls "shadowJar" for projects, so it's waste of time calling it again --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index bf596003..cf49c015 100644 --- a/build.gradle +++ b/build.gradle @@ -124,4 +124,4 @@ buildscript { } } -defaultTasks 'clean', 'build', 'javadoc', 'scaladoc', 'reportScoverage', 'shadowJar' +defaultTasks 'clean', 'build', 'javadoc', 'scaladoc', 'reportScoverage' From ce45c33fdfbc6f96627287bb5b912768cf7ad4a9 Mon Sep 17 00:00:00 2001 From: Enrico Siboni Date: Wed, 25 Jul 2018 16:48:53 +0200 Subject: [PATCH 055/193] Created a FontSize constant in GameViewConstants --- .../scala/it/cwmp/client/view/game/GameViewConstants.scala | 5 +++++ .../main/scala/it/cwmp/client/view/game/model/CellView.scala | 4 ++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/client/src/main/scala/it/cwmp/client/view/game/GameViewConstants.scala b/client/src/main/scala/it/cwmp/client/view/game/GameViewConstants.scala index 3451b61a..f5af62bf 100644 --- a/client/src/main/scala/it/cwmp/client/view/game/GameViewConstants.scala +++ b/client/src/main/scala/it/cwmp/client/view/game/GameViewConstants.scala @@ -11,4 +11,9 @@ object GameViewConstants { * The constant value indicating the rgb range max value */ val RGB_RANGE = 255.0 + + /** + * The game font size + */ + val GAME_FONT_SIZE = 20 } diff --git a/client/src/main/scala/it/cwmp/client/view/game/model/CellView.scala b/client/src/main/scala/it/cwmp/client/view/game/model/CellView.scala index ae95677e..c95f6cd4 100644 --- a/client/src/main/scala/it/cwmp/client/view/game/model/CellView.scala +++ b/client/src/main/scala/it/cwmp/client/view/game/model/CellView.scala @@ -3,8 +3,8 @@ package it.cwmp.client.view.game.model import com.github.tkqubo.colorHash.ColorHash import it.cwmp.client.model.game.SizingStrategy import it.cwmp.client.model.game.impl.{Cell, Point} -import it.cwmp.client.view.game.ColoringStrategy import it.cwmp.client.view.game.GameViewConstants.RGB_RANGE +import it.cwmp.client.view.game.{ColoringStrategy, GameViewConstants} import javafx.scene.paint.Color import javafx.scene.text.Font @@ -26,7 +26,7 @@ case class CellView(center: Point, radius: Double, color: Color, energy: Double) */ object CellView { - val ENERGY_FONT = Font.font("Verdana", 20) + val ENERGY_FONT: Font = Font.font("Verdana", GameViewConstants.GAME_FONT_SIZE) private val CELL_VIEW_COLOR_OPACITY = 1 From 9b95e706bd6198c0f6e85ccf62fdb56c76f3a578 Mon Sep 17 00:00:00 2001 From: Enrico Siboni Date: Wed, 25 Jul 2018 17:32:45 +0200 Subject: [PATCH 056/193] - Added default Game font size and color to GameViewConstants - Added a coloring strategy for energy text in CellView --- .../scala/it/cwmp/client/view/game/GameFX.scala | 2 +- .../cwmp/client/view/game/GameViewConstants.scala | 11 +++++++++-- .../it/cwmp/client/view/game/ObjectDrawer.scala | 2 +- .../it/cwmp/client/view/game/model/CellView.scala | 15 ++++++++++++++- 4 files changed, 25 insertions(+), 5 deletions(-) diff --git a/client/src/main/scala/it/cwmp/client/view/game/GameFX.scala b/client/src/main/scala/it/cwmp/client/view/game/GameFX.scala index 4c1c75b9..6a1444d6 100644 --- a/client/src/main/scala/it/cwmp/client/view/game/GameFX.scala +++ b/client/src/main/scala/it/cwmp/client/view/game/GameFX.scala @@ -1,6 +1,7 @@ package it.cwmp.client.view.game import it.cwmp.client.model.game.impl.CellWorld +import it.cwmp.client.view.game.model.CellView._ import javafx.application.Platform import javafx.embed.swing.JFXPanel import javafx.scene.canvas.{Canvas, GraphicsContext} @@ -48,7 +49,6 @@ case class GameFX() extends ObjectDrawer { Platform.runLater(() => { implicit val graphicsContext: GraphicsContext = canvas.getGraphicsContext2D root.getChildren.clear() - import it.cwmp.client.view.game.model.CellView._ world.attacks.foreach(tentacle => root.getChildren.add(drawArch(tentacle, world.instant))) world.characters.foreach(cell => root.getChildren.add(drawCell(cell))) diff --git a/client/src/main/scala/it/cwmp/client/view/game/GameViewConstants.scala b/client/src/main/scala/it/cwmp/client/view/game/GameViewConstants.scala index f5af62bf..fc9967cd 100644 --- a/client/src/main/scala/it/cwmp/client/view/game/GameViewConstants.scala +++ b/client/src/main/scala/it/cwmp/client/view/game/GameViewConstants.scala @@ -1,5 +1,7 @@ package it.cwmp.client.view.game +import javafx.scene.paint.Color + /** * An object where to put constants about the game visual * @@ -13,7 +15,12 @@ object GameViewConstants { val RGB_RANGE = 255.0 /** - * The game font size + * The game default font size + */ + val GAME_DEFAULT_FONT_SIZE = 20 + + /** + * The game default font color */ - val GAME_FONT_SIZE = 20 + val GAME_DEFAULT_FONT_COLOR: Color = Color.BLACK } diff --git a/client/src/main/scala/it/cwmp/client/view/game/ObjectDrawer.scala b/client/src/main/scala/it/cwmp/client/view/game/ObjectDrawer.scala index 029fd9f1..5e399dc6 100644 --- a/client/src/main/scala/it/cwmp/client/view/game/ObjectDrawer.scala +++ b/client/src/main/scala/it/cwmp/client/view/game/ObjectDrawer.scala @@ -50,7 +50,7 @@ trait ObjectDrawer { */ def drawCellEnergy(cell: CellView): Text = { val energyText = new Text(cell.center.x, cell.center.y, cell.energy.toInt.toString) - energyText.setFont(CellView.ENERGY_FONT) + energyText.setFont(CellView.ENERGY_DEFAULT_FONT) energyText.setFill(Color.BLACK) // TODO: move to a coloring strategy inside CellView energyText.setX(cell.center.x - (energyText.getLayoutBounds.getWidth / 2)) energyText.setY(cell.center.y + (energyText.getLayoutBounds.getHeight / 2)) diff --git a/client/src/main/scala/it/cwmp/client/view/game/model/CellView.scala b/client/src/main/scala/it/cwmp/client/view/game/model/CellView.scala index c95f6cd4..e35c3643 100644 --- a/client/src/main/scala/it/cwmp/client/view/game/model/CellView.scala +++ b/client/src/main/scala/it/cwmp/client/view/game/model/CellView.scala @@ -1,6 +1,7 @@ package it.cwmp.client.view.game.model import com.github.tkqubo.colorHash.ColorHash +import it.cwmp.client.controller.game.GameConstants import it.cwmp.client.model.game.SizingStrategy import it.cwmp.client.model.game.impl.{Cell, Point} import it.cwmp.client.view.game.GameViewConstants.RGB_RANGE @@ -26,9 +27,13 @@ case class CellView(center: Point, radius: Double, color: Color, energy: Double) */ object CellView { - val ENERGY_FONT: Font = Font.font("Verdana", GameViewConstants.GAME_FONT_SIZE) + /** + * The default font for energy text on cellViews + */ + val ENERGY_DEFAULT_FONT: Font = Font.font("Verdana", GameViewConstants.GAME_DEFAULT_FONT_SIZE) private val CELL_VIEW_COLOR_OPACITY = 1 + private val CELL_DYING_FONT_COLOR = Color.DARKRED /** * @return the ViewCell corresponding to the given Cell @@ -45,6 +50,14 @@ object CellView { new Color(color.red / RGB_RANGE, color.green / RGB_RANGE, color.blue / RGB_RANGE, CELL_VIEW_COLOR_OPACITY) } + /** + * Default energy text coloring strategy + */ + val energyTextColoringStrategy: ColoringStrategy[Cell, Color] = { + case cell: Cell if cell.energy < GameConstants.CELL_ENERGY_WHEN_BORN => CELL_DYING_FONT_COLOR + case _ => GameViewConstants.GAME_DEFAULT_FONT_COLOR + } + /** * The default sizing strategy; returns the radius that the cellView should have * From 1ad5a54508dbf262f6e9717796b331c74958664e Mon Sep 17 00:00:00 2001 From: Enrico Siboni Date: Wed, 25 Jul 2018 17:34:42 +0200 Subject: [PATCH 057/193] Added CellView capability to transport energy text color --- .../main/scala/it/cwmp/client/view/game/ObjectDrawer.scala | 2 +- .../main/scala/it/cwmp/client/view/game/model/CellView.scala | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/client/src/main/scala/it/cwmp/client/view/game/ObjectDrawer.scala b/client/src/main/scala/it/cwmp/client/view/game/ObjectDrawer.scala index 5e399dc6..54b7a7bf 100644 --- a/client/src/main/scala/it/cwmp/client/view/game/ObjectDrawer.scala +++ b/client/src/main/scala/it/cwmp/client/view/game/ObjectDrawer.scala @@ -51,7 +51,7 @@ trait ObjectDrawer { def drawCellEnergy(cell: CellView): Text = { val energyText = new Text(cell.center.x, cell.center.y, cell.energy.toInt.toString) energyText.setFont(CellView.ENERGY_DEFAULT_FONT) - energyText.setFill(Color.BLACK) // TODO: move to a coloring strategy inside CellView + energyText.setFill(cell.energyTextColor) energyText.setX(cell.center.x - (energyText.getLayoutBounds.getWidth / 2)) energyText.setY(cell.center.y + (energyText.getLayoutBounds.getHeight / 2)) energyText diff --git a/client/src/main/scala/it/cwmp/client/view/game/model/CellView.scala b/client/src/main/scala/it/cwmp/client/view/game/model/CellView.scala index e35c3643..70a12090 100644 --- a/client/src/main/scala/it/cwmp/client/view/game/model/CellView.scala +++ b/client/src/main/scala/it/cwmp/client/view/game/model/CellView.scala @@ -20,7 +20,7 @@ import scala.language.implicitConversions * @param radius dimensione della cella * @param energy energia della cella */ -case class CellView(center: Point, radius: Double, color: Color, energy: Double) +case class CellView(center: Point, radius: Double, color: Color, energy: Double, energyTextColor: Color) /** * Companion object @@ -38,7 +38,8 @@ object CellView { /** * @return the ViewCell corresponding to the given Cell */ - implicit def cellToViewCell(cell: Cell): CellView = CellView(cell.position, sizingStrategy(cell), coloringStrategy(cell), cell.energy) + implicit def cellToViewCell(cell: Cell): CellView = + CellView(cell.position, sizingStrategy(cell), coloringStrategy(cell), cell.energy, energyTextColoringStrategy(cell)) /** * Default cell coloring strategy From 192bb0a87b42a7aaa6e216d2c922aea13b089b6f Mon Sep 17 00:00:00 2001 From: Enrico Siboni Date: Wed, 25 Jul 2018 17:44:14 +0200 Subject: [PATCH 058/193] Now radius value is used as it was thought --- .../it/cwmp/client/view/game/ObjectDrawer.scala | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/client/src/main/scala/it/cwmp/client/view/game/ObjectDrawer.scala b/client/src/main/scala/it/cwmp/client/view/game/ObjectDrawer.scala index 54b7a7bf..e4c6e407 100644 --- a/client/src/main/scala/it/cwmp/client/view/game/ObjectDrawer.scala +++ b/client/src/main/scala/it/cwmp/client/view/game/ObjectDrawer.scala @@ -24,21 +24,19 @@ trait ObjectDrawer { * @param cell oggetto che rappresenta la cella che verrà disegnata * @param graphicsContext è l'oggetto che disenga la cella */ - def drawCell(cell: CellView)(implicit graphicsContext: GraphicsContext): Region = { + def drawCell(cell: CellView) + (implicit graphicsContext: GraphicsContext): Region = { val svg = new SVGPath //TODO cella hardcodata svg.setContent("M52.232,44.235c-1.039-0.285-2.039-0.297-2.969-0.112c-0.632,0.126-1.286-0.008-1.788-0.411 l-1.411-1.132c-0.766-0.614-0.992-1.665-0.585-2.559c0.377-0.829,0.69-1.693,0.932-2.587c0.402-1.487,2.008-2.394,3.444-1.838 c1.535,0.593,3.311,0.557,4.908-0.266c2.772-1.429,3.996-4.918,2.728-7.767c-1.364-3.066-4.967-4.413-8.002-3.009 c-0.266,0.123-0.563,0.312-0.868,0.535c-1.36,0.995-3.169,0.637-4.034-0.809c-0.546-0.913-1.215-1.741-1.882-2.571 c-0.883-1.098-1.037-2.618-0.387-3.878l1.479-2.871c0.55-1.068,1.57-1.871,2.765-1.988c0.603-0.059,1.226-0.22,1.865-0.512 c1.888-0.864,3.284-2.642,3.537-4.703c0.486-3.963-2.896-7.283-6.876-6.689c-2.527,0.377-4.589,2.411-4.996,4.933 c-0.197,1.221-0.025,2.386,0.423,3.404c0.459,1.045,0.499,2.226-0.024,3.241l-1.158,2.249c-0.805,1.563-2.612,2.394-4.29,1.87 c-0.981-0.306-2.718-0.523-3.92-0.644c-0.787-0.079-1.438-0.646-1.621-1.416L28.36,9.904c-0.141-0.594,0.036-1.207,0.435-1.669 c0.945-1.093,1.431-2.589,1.119-4.212c-0.371-1.933-1.91-3.514-3.838-3.913C22.849-0.557,20.009,1.89,20.009,5 c0,2.146,1.356,3.962,3.256,4.668c0.611,0.227,1.095,0.705,1.246,1.339l0.913,3.852c0.219,0.925-0.304,1.849-1.198,2.172 c-1.281,0.462-2.491,1.072-3.608,1.813c-0.802,0.531-1.895,0.519-2.642-0.086c-0.815-0.661-0.991-1.728-0.603-2.64 c0.628-1.474,0.829-3.173,0.429-4.95c-0.683-3.039-3.181-5.446-6.243-6.021c-5.63-1.057-10.471,3.79-9.402,9.422 c0.603,3.175,3.181,5.722,6.36,6.297c1.408,0.254,2.765,0.139,3.991-0.264c0.847-0.279,1.776,0.029,2.335,0.724l0.4,0.498 c0.574,0.714,0.636,1.706,0.167,2.493c-1.177,1.973-1.964,4.202-2.258,6.587c-0.122,0.992-0.904,1.771-1.9,1.86l-1.899,0.17 c-0.65,0.058-1.266-0.211-1.732-0.667c-0.721-0.705-1.688-1.181-2.83-1.258c-1.783-0.12-3.526,0.87-4.309,2.477 c-1.295,2.657,0.195,5.671,2.899,6.372c1.949,0.505,3.916-0.356,4.926-1.979c0.363-0.584,1.017-0.926,1.702-0.987l1.631-0.146 c0.987-0.088,1.888,0.529,2.192,1.472c0.669,2.076,1.728,3.977,3.089,5.618c0.487,0.587,0.459,1.443-0.051,2.009 c-0.425,0.472-1.085,0.609-1.69,0.416c-0.687-0.219-1.434-0.307-2.209-0.233c-2.498,0.237-4.582,2.233-4.913,4.721 c-0.497,3.738,2.765,6.871,6.537,6.15c1.964-0.376,3.596-1.867,4.172-3.783c0.28-0.93,0.303-1.829,0.139-2.661 c-0.092-0.468,0.051-0.95,0.37-1.305l0.785-0.871c0.472-0.524,1.243-0.673,1.862-0.336c0.489,0.266,0.993,0.508,1.51,0.726 c1.104,0.464,1.704,1.618,1.598,2.81c-0.051,0.575-0.019,1.174,0.11,1.787c0.528,2.504,2.683,4.44,5.228,4.703 c3.6,0.372,6.638-2.443,6.638-5.967c0-0.384-0.037-0.76-0.107-1.124c-0.23-1.199,0.257-2.415,1.325-3.006 c0.984-0.545,1.909-1.185,2.761-1.909c0.525-0.446,1.222-0.7,1.891-0.531c1.365,0.345,1.95,1.682,1.526,2.836 c-0.376,1.023-0.502,2.167-0.301,3.36c0.463,2.746,2.736,4.939,5.495,5.313c4.215,0.571,7.784-2.901,7.378-7.088 C56.721,47.208,54.792,44.938,52.232,44.235z") val svgShape = new Region svgShape.setShape(svg) - // TODO: the cell size is not drawn according to size value!!!! svgShape.setBorder(new Border(new BorderStroke(Color.BLACK, BorderStrokeStyle.SOLID, CornerRadii.EMPTY, BorderWidths.DEFAULT))) - svgShape.setMinSize(cell.radius, cell.radius) - svgShape.setPrefSize(cell.radius, cell.radius) // TODO: la cellula ora fornisce il suo raggio, rivedere il dimensionamento (fare raggio * 2?) - svgShape.setMaxSize(cell.radius, cell.radius) - svgShape.setStyle("-fx-background-color: " + "#" + Integer.toHexString(cell.color.getRGB).substring(2)) - svgShape.setLayoutX(cell.center.x - cell.radius / 2) - svgShape.setLayoutY(cell.center.y - cell.radius / 2) + svgShape.setPrefSize(cell.radius * 2, cell.radius * 2) + svgShape.setStyle("-fx-background-color: #" + Integer.toHexString(cell.color.getRGB).substring(2)) + svgShape.setLayoutX(cell.center.x - cell.radius) + svgShape.setLayoutY(cell.center.y - cell.radius) svgShape } @@ -66,7 +64,7 @@ trait ObjectDrawer { */ def drawArch(tentacle: Tentacle, actualInstant: Instant): Line = { val line = new Line() - line.setStroke(TentacleView.coloringStrategy(tentacle)) + line.setStroke(TentacleView.coloringStrategy(tentacle)) // TODO: make a tentacle view line.setStrokeWidth(TentacleView.thicknessStrategy(tentacle)) val attackerPosition = tentacle.from.position From ccce89abb3e39e15ef5f18e79e8ee7883015db6a Mon Sep 17 00:00:00 2001 From: Enrico Siboni Date: Wed, 25 Jul 2018 18:45:58 +0200 Subject: [PATCH 059/193] Implemented cellViewSizing between a minimum and maximum sizes --- .../client/model/game/GeometricUtils.scala | 2 +- .../cwmp/client/view/game/ObjectDrawer.scala | 2 +- .../client/view/game/model/CellView.scala | 32 +++++++++++++++++-- 3 files changed, 31 insertions(+), 5 deletions(-) diff --git a/client/src/main/scala/it/cwmp/client/model/game/GeometricUtils.scala b/client/src/main/scala/it/cwmp/client/model/game/GeometricUtils.scala index 05e65808..e5058735 100644 --- a/client/src/main/scala/it/cwmp/client/model/game/GeometricUtils.scala +++ b/client/src/main/scala/it/cwmp/client/model/game/GeometricUtils.scala @@ -63,7 +63,7 @@ object GeometricUtils { def deltaXYFromFirstPoint(point1: Point, point2: Point, distance: Double): (Double, Double) = { - require(distance > 0, "Distance should be greater that 0") + require(distance > 0, "Distance should be greater than 0") val deltaY = if (point1.y == point2.y) 0 // point on same horizontal line has no delta Y diff --git a/client/src/main/scala/it/cwmp/client/view/game/ObjectDrawer.scala b/client/src/main/scala/it/cwmp/client/view/game/ObjectDrawer.scala index e4c6e407..ea2151cc 100644 --- a/client/src/main/scala/it/cwmp/client/view/game/ObjectDrawer.scala +++ b/client/src/main/scala/it/cwmp/client/view/game/ObjectDrawer.scala @@ -34,7 +34,7 @@ trait ObjectDrawer { svgShape.setBorder(new Border(new BorderStroke(Color.BLACK, BorderStrokeStyle.SOLID, CornerRadii.EMPTY, BorderWidths.DEFAULT))) svgShape.setPrefSize(cell.radius * 2, cell.radius * 2) - svgShape.setStyle("-fx-background-color: #" + Integer.toHexString(cell.color.getRGB).substring(2)) + svgShape.setStyle("-fx-background-color: #" + Integer.toHexString(cell.color.getRGB).substring(2)) // TODO: make a method for this conversion svgShape.setLayoutX(cell.center.x - cell.radius) svgShape.setLayoutY(cell.center.y - cell.radius) svgShape diff --git a/client/src/main/scala/it/cwmp/client/view/game/model/CellView.scala b/client/src/main/scala/it/cwmp/client/view/game/model/CellView.scala index 70a12090..2a120e36 100644 --- a/client/src/main/scala/it/cwmp/client/view/game/model/CellView.scala +++ b/client/src/main/scala/it/cwmp/client/view/game/model/CellView.scala @@ -2,8 +2,8 @@ package it.cwmp.client.view.game.model import com.github.tkqubo.colorHash.ColorHash import it.cwmp.client.controller.game.GameConstants -import it.cwmp.client.model.game.SizingStrategy import it.cwmp.client.model.game.impl.{Cell, Point} +import it.cwmp.client.model.game.{GeometricUtils, SizingStrategy} import it.cwmp.client.view.game.GameViewConstants.RGB_RANGE import it.cwmp.client.view.game.{ColoringStrategy, GameViewConstants} import javafx.scene.paint.Color @@ -35,6 +35,9 @@ object CellView { private val CELL_VIEW_COLOR_OPACITY = 1 private val CELL_DYING_FONT_COLOR = Color.DARKRED + private val CELL_MINIMUM_RADIUS_FOR_ENERGY = (25d, 20d) + private val CELL_MAX_RADIUS_FOR_ENERGY = (45d, 100d) + /** * @return the ViewCell corresponding to the given Cell */ @@ -61,8 +64,31 @@ object CellView { /** * The default sizing strategy; returns the radius that the cellView should have + */ + val sizingStrategy: SizingStrategy[Cell, Double] = { + case cell: Cell if cell.energy <= CELL_MINIMUM_RADIUS_FOR_ENERGY._2 => CELL_MINIMUM_RADIUS_FOR_ENERGY._1 + case cell: Cell if cell.energy >= CELL_MAX_RADIUS_FOR_ENERGY._2 => CELL_MAX_RADIUS_FOR_ENERGY._1 + case cell: Cell => radiusBetweenMinimumAndMaximum(cell, CELL_MINIMUM_RADIUS_FOR_ENERGY, CELL_MAX_RADIUS_FOR_ENERGY) + } + + /** + * A method to calculate the radius of the cell between maximum and minimum provided * - * Maps energy to radius + * @param cell the cell to draw + * @param minimumRadiusAndEnergy the lower bound values + * @param maximumRadiusAndEnergy the upper bound values + * @return the sized cell radius */ - val sizingStrategy: SizingStrategy[Cell, Double] = _.energy + private def radiusBetweenMinimumAndMaximum(cell: Cell, + minimumRadiusAndEnergy: (Double, Double), + maximumRadiusAndEnergy: (Double, Double)): Double = { + val energyDeltaFromMinimum = cell.energy - minimumRadiusAndEnergy._2 + val minimumPoint = Point(minimumRadiusAndEnergy._1.toInt, minimumRadiusAndEnergy._2.toInt) + val maximumPoint = Point(maximumRadiusAndEnergy._1.toInt, maximumRadiusAndEnergy._2.toInt) + + // I use geometric utils to calculate a pair (a point) between minimum and maximum pairs, related to energy delta + // I'm interested in first component of the delta because it represents the radius + val radiusDelta = GeometricUtils.deltaXYFromFirstPoint(minimumPoint, maximumPoint, energyDeltaFromMinimum)._1 + minimumRadiusAndEnergy._1 + radiusDelta + } } From fa87d4d60ff02cb3ca203d3e36a1fd035b12fef9 Mon Sep 17 00:00:00 2001 From: Enrico Siboni Date: Wed, 25 Jul 2018 19:09:30 +0200 Subject: [PATCH 060/193] - Solved warnings in Cell (due to wildcard imports) - Added the default energy when born to Cell - Modified tests doc --- .../main/scala/it/cwmp/client/model/game/impl/Cell.scala | 8 ++++---- .../scala/it/cwmp/client/model/game/impl/CellTest.scala | 2 ++ .../it/cwmp/client/model/game/impl/CellWorldTest.scala | 4 +++- .../it/cwmp/client/model/game/impl/TentacleTest.scala | 2 ++ 4 files changed, 11 insertions(+), 5 deletions(-) diff --git a/client/src/main/scala/it/cwmp/client/model/game/impl/Cell.scala b/client/src/main/scala/it/cwmp/client/model/game/impl/Cell.scala index 86b46f99..e08b2cfb 100644 --- a/client/src/main/scala/it/cwmp/client/model/game/impl/Cell.scala +++ b/client/src/main/scala/it/cwmp/client/model/game/impl/Cell.scala @@ -1,10 +1,10 @@ package it.cwmp.client.model.game.impl import java.time.Duration -import java.util.Objects._ +import java.util.Objects.requireNonNull -import it.cwmp.client.controller.game.GameConstants._ -import it.cwmp.client.model.game._ +import it.cwmp.client.controller.game.GameConstants.{CELL_ENERGY_WHEN_BORN, MILLIS_TO_ENERGY_CONVERSION_RATE} +import it.cwmp.client.model.game.{Character, EvolutionStrategy, GeometricUtils} import it.cwmp.model.User /** @@ -17,7 +17,7 @@ import it.cwmp.model.User */ case class Cell(owner: User, position: Point, - energy: Double) extends Character[User, Point, Double] { + energy: Double = CELL_ENERGY_WHEN_BORN) extends Character[User, Point, Double] { requireNonNull(owner, "User owner must not be null") requireNonNull(position, "Position must not be null") diff --git a/client/src/test/scala/it/cwmp/client/model/game/impl/CellTest.scala b/client/src/test/scala/it/cwmp/client/model/game/impl/CellTest.scala index 2a87ab3e..e3ed437a 100644 --- a/client/src/test/scala/it/cwmp/client/model/game/impl/CellTest.scala +++ b/client/src/test/scala/it/cwmp/client/model/game/impl/CellTest.scala @@ -7,6 +7,8 @@ import org.scalatest.FunSpec /** * A test for cell class + * + * @author Enrico Siboni */ class CellTest extends FunSpec { diff --git a/client/src/test/scala/it/cwmp/client/model/game/impl/CellWorldTest.scala b/client/src/test/scala/it/cwmp/client/model/game/impl/CellWorldTest.scala index 12dbd1dc..3ebbc598 100644 --- a/client/src/test/scala/it/cwmp/client/model/game/impl/CellWorldTest.scala +++ b/client/src/test/scala/it/cwmp/client/model/game/impl/CellWorldTest.scala @@ -7,6 +7,8 @@ import org.scalatest.FunSpec /** * A test class for CellWorld + * + * @author Enrico Siboni */ class CellWorldTest extends FunSpec { @@ -47,7 +49,7 @@ class CellWorldTest extends FunSpec { assert(newWorld.attacks contains tentacle) } - it("can remove tntacle from world") { + it("can remove tentacle from world") { val newWorld = myCellWorld -- tentacles.head assert(!(newWorld.attacks contains tentacles.head)) diff --git a/client/src/test/scala/it/cwmp/client/model/game/impl/TentacleTest.scala b/client/src/test/scala/it/cwmp/client/model/game/impl/TentacleTest.scala index dbf0a47b..4fb3f9eb 100644 --- a/client/src/test/scala/it/cwmp/client/model/game/impl/TentacleTest.scala +++ b/client/src/test/scala/it/cwmp/client/model/game/impl/TentacleTest.scala @@ -8,6 +8,8 @@ import org.scalatest.{BeforeAndAfterEach, FunSpec} /** * A test class for Tentacle + * + * @author Enrico Siboni */ class TentacleTest extends FunSpec with BeforeAndAfterEach { From 2567443bb2da230f26ac3235f9179002b605ec94 Mon Sep 17 00:00:00 2001 From: Enrico Siboni Date: Wed, 25 Jul 2018 19:20:32 +0200 Subject: [PATCH 061/193] Solved warnings in CellWorld and Tentacle (due to wildcard imports) --- .../main/scala/it/cwmp/client/model/game/impl/CellWorld.scala | 4 ++-- .../main/scala/it/cwmp/client/model/game/impl/Tentacle.scala | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/client/src/main/scala/it/cwmp/client/model/game/impl/CellWorld.scala b/client/src/main/scala/it/cwmp/client/model/game/impl/CellWorld.scala index 69d3e0b0..7d237c7c 100644 --- a/client/src/main/scala/it/cwmp/client/model/game/impl/CellWorld.scala +++ b/client/src/main/scala/it/cwmp/client/model/game/impl/CellWorld.scala @@ -1,9 +1,9 @@ package it.cwmp.client.model.game.impl import java.time.{Duration, Instant} -import java.util.Objects._ +import java.util.Objects.requireNonNull -import it.cwmp.client.controller.game.GameConstants._ +import it.cwmp.client.controller.game.GameConstants.{ATTACK_DURATION_TO_ENERGY_REDUCTION_RATE, LENGTH_TO_ENERGY_REDUCTION_RATE} import it.cwmp.client.model.game.{SizingStrategy, World} /** diff --git a/client/src/main/scala/it/cwmp/client/model/game/impl/Tentacle.scala b/client/src/main/scala/it/cwmp/client/model/game/impl/Tentacle.scala index 61267d00..df2dc392 100644 --- a/client/src/main/scala/it/cwmp/client/model/game/impl/Tentacle.scala +++ b/client/src/main/scala/it/cwmp/client/model/game/impl/Tentacle.scala @@ -1,9 +1,9 @@ package it.cwmp.client.model.game.impl import java.time.{Duration, Instant} -import java.util.Objects._ +import java.util.Objects.requireNonNull -import it.cwmp.client.controller.game.GameConstants._ +import it.cwmp.client.controller.game.GameConstants.MILLIS_TO_MOVEMENT_CONVERSION_RATE import it.cwmp.client.model.game.{Attack, SizingStrategy} /** From 5764cdeef474ea650c6626dcba0c2a96484341b8 Mon Sep 17 00:00:00 2001 From: Enrico Siboni Date: Wed, 25 Jul 2018 19:25:50 +0200 Subject: [PATCH 062/193] - Added doc to ParticipantListReceiver - Created companion object for constants --- .../cwmp/client/model/DistributedState.scala | 3 ++- .../model/ParticipantListReceiver.scala | 19 ++++++++++++++++++- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/client/src/main/scala/it/cwmp/client/model/DistributedState.scala b/client/src/main/scala/it/cwmp/client/model/DistributedState.scala index 12f31bfb..f4688b14 100644 --- a/client/src/main/scala/it/cwmp/client/model/DistributedState.scala +++ b/client/src/main/scala/it/cwmp/client/model/DistributedState.scala @@ -15,7 +15,8 @@ import it.cwmp.utils.Logging * @author Eugenio Pierfederici * @author contributor Enrico Siboni */ -abstract class DistributedState[T](updateSubscriber: ActorRef, onWorldUpdate: T => Unit)(implicit replicatorActor: ActorRef, cluster: Cluster) extends Logging { +abstract class DistributedState[T](updateSubscriber: ActorRef, onWorldUpdate: T => Unit) + (implicit replicatorActor: ActorRef, cluster: Cluster) extends Logging { protected val DistributedKey: LWWRegisterKey[T] = LWWRegisterKey[T](DISTRIBUTED_KEY_NAME) diff --git a/client/src/main/scala/it/cwmp/client/model/ParticipantListReceiver.scala b/client/src/main/scala/it/cwmp/client/model/ParticipantListReceiver.scala index da67f013..9512d2d1 100644 --- a/client/src/main/scala/it/cwmp/client/model/ParticipantListReceiver.scala +++ b/client/src/main/scala/it/cwmp/client/model/ParticipantListReceiver.scala @@ -2,6 +2,7 @@ package it.cwmp.client.model import java.net.InetAddress +import it.cwmp.client.model.ParticipantListReceiver.ADDRESS_TOKEN_LENGTH import it.cwmp.model.{Address, Participant} import it.cwmp.services.roomreceiver.RoomReceiverServiceVerticle import it.cwmp.services.roomreceiver.ServerParameters._ @@ -9,13 +10,29 @@ import it.cwmp.utils.{Utils, VertxInstance} import scala.concurrent.Future +/** + * A trait implementing a one time server to receive a participant list to the game room + */ trait ParticipantListReceiver extends VertxInstance { + /** + * Listens for a list of participants + * + * @param onListReceived the action to execute on list received + * @return the Future containing the address on which to contact this listener + */ def listenForParticipantListFuture(onListReceived: List[Participant] => Unit): Future[Address] = { - val token = Utils.randomString(20) + val token = Utils.randomString(ADDRESS_TOKEN_LENGTH) val verticle = RoomReceiverServiceVerticle(token, participants => onListReceived(participants)) vertx.deployVerticleFuture(verticle) .map(_ => Address(s"http://${InetAddress.getLocalHost.getHostAddress}:${verticle.port}" + API_RECEIVE_PARTICIPANTS_URL(token))) } } + +/** + * Companion object + */ +object ParticipantListReceiver { + private val ADDRESS_TOKEN_LENGTH = 20 +} \ No newline at end of file From b0a6fd8b0ccf4370d03bfb25f2702ac40d3b600f Mon Sep 17 00:00:00 2001 From: Enrico Siboni Date: Wed, 25 Jul 2018 19:34:23 +0200 Subject: [PATCH 063/193] Reworded doc for CellView --- .../it/cwmp/client/view/game/model/CellView.scala | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/client/src/main/scala/it/cwmp/client/view/game/model/CellView.scala b/client/src/main/scala/it/cwmp/client/view/game/model/CellView.scala index 2a120e36..bdc60bbb 100644 --- a/client/src/main/scala/it/cwmp/client/view/game/model/CellView.scala +++ b/client/src/main/scala/it/cwmp/client/view/game/model/CellView.scala @@ -12,18 +12,22 @@ import javafx.scene.text.Font import scala.language.implicitConversions /** - * Classe che rappresenta una cella + * A class representing the View counterpart of a Cell * + * @param center the center point where the CellView will be placed + * @param radius the radius of the cell + * @param color the color of the cellView + * @param energy the cell energy + * @param energyTextColor the color of the energyText * @author Davide Borficchia * @author Eugenio Pierfederici - * @param center punto nel quale verrà disegnata la cella - * @param radius dimensione della cella - * @param energy energia della cella */ case class CellView(center: Point, radius: Double, color: Color, energy: Double, energyTextColor: Color) /** * Companion object + * + * @author Enrico Siboni */ object CellView { From 7f23264a7ee845404571ccdb73595d90c32f3eb3 Mon Sep 17 00:00:00 2001 From: Enrico Siboni Date: Wed, 25 Jul 2018 19:36:51 +0200 Subject: [PATCH 064/193] Added a TentacleView class --- .../cwmp/client/view/game/model/TentacleView.scala | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/client/src/main/scala/it/cwmp/client/view/game/model/TentacleView.scala b/client/src/main/scala/it/cwmp/client/view/game/model/TentacleView.scala index 08f0955c..390f71a6 100644 --- a/client/src/main/scala/it/cwmp/client/view/game/model/TentacleView.scala +++ b/client/src/main/scala/it/cwmp/client/view/game/model/TentacleView.scala @@ -2,14 +2,23 @@ package it.cwmp.client.view.game.model import java.time.{Duration, Instant} -import it.cwmp.client.model.game.{GeometricUtils, SizingStrategy} import it.cwmp.client.model.game.impl.{Point, Tentacle} +import it.cwmp.client.model.game.{GeometricUtils, SizingStrategy} import it.cwmp.client.view.game.ColoringStrategy import javafx.scene.paint.Color +/** + * A class representing the View counterpart of Tentacle + * + * @param startPoint the starting point for this tentacle + * @param arrivePoint the arrive point for thi tentacle + * @param color the color of this tetacle + * @author Enrico Siboni + */ +case class TentacleView(startPoint: Point, arrivePoint: Point, color: Color) /** - * Tentacle View utilities + * Companion Object * * @author Enrico Siboni */ From 86f55705cb50c24d1cb5023320c13d2c3ba1e4b2 Mon Sep 17 00:00:00 2001 From: Enrico Siboni Date: Wed, 25 Jul 2018 19:39:42 +0200 Subject: [PATCH 065/193] - Added implicit conversion from Tentacle to TentacleView - Added thickness field --- .../it/cwmp/client/view/game/model/TentacleView.scala | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/client/src/main/scala/it/cwmp/client/view/game/model/TentacleView.scala b/client/src/main/scala/it/cwmp/client/view/game/model/TentacleView.scala index 390f71a6..5b7b4603 100644 --- a/client/src/main/scala/it/cwmp/client/view/game/model/TentacleView.scala +++ b/client/src/main/scala/it/cwmp/client/view/game/model/TentacleView.scala @@ -7,6 +7,8 @@ import it.cwmp.client.model.game.{GeometricUtils, SizingStrategy} import it.cwmp.client.view.game.ColoringStrategy import javafx.scene.paint.Color +import scala.language.implicitConversions + /** * A class representing the View counterpart of Tentacle * @@ -15,7 +17,7 @@ import javafx.scene.paint.Color * @param color the color of this tetacle * @author Enrico Siboni */ -case class TentacleView(startPoint: Point, arrivePoint: Point, color: Color) +case class TentacleView(startPoint: Point, arrivePoint: Point, color: Color, thickness: Double) /** * Companion Object @@ -27,7 +29,10 @@ object TentacleView { /** * Provides default value for tentacle thickness */ - val DEFAULT_TENTACLE_THICKNESS = 3d + val TENTACLE_DEFAULT_THICKNESS = 3d + + implicit def tentacleToTentacleView(tentacle: Tentacle): TentacleView = + TentacleView(tentacle.from.position, tentacle.to.position, coloringStrategy(tentacle), thicknessStrategy(tentacle)) /** * Default coloring strategy for tentacles @@ -43,7 +48,7 @@ object TentacleView { * Returns always same thickness */ val thicknessStrategy: SizingStrategy[Tentacle, Double] = // TODO: make thickness vary with attackers cell energy - (_: Tentacle) => DEFAULT_TENTACLE_THICKNESS + (_: Tentacle) => TENTACLE_DEFAULT_THICKNESS /** * A method returning the Point reached actually by the tentacle From 9a90f16f72d255294f1b4b2751481f6bf9ab8487 Mon Sep 17 00:00:00 2001 From: Enrico Siboni Date: Wed, 25 Jul 2018 19:44:23 +0200 Subject: [PATCH 066/193] Added private modifiers where missing --- .../src/main/scala/it/cwmp/client/view/game/GameFX.scala | 8 ++++---- .../it/cwmp/client/view/game/model/TentacleView.scala | 2 +- .../authentication/AuthenticationLocalDAOTest.scala | 8 ++++---- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/client/src/main/scala/it/cwmp/client/view/game/GameFX.scala b/client/src/main/scala/it/cwmp/client/view/game/GameFX.scala index 6a1444d6..3a7facf4 100644 --- a/client/src/main/scala/it/cwmp/client/view/game/GameFX.scala +++ b/client/src/main/scala/it/cwmp/client/view/game/GameFX.scala @@ -15,12 +15,12 @@ import javafx.stage.Stage */ case class GameFX() extends ObjectDrawer { - var stage: Stage = _ - var root: Group = _ - var canvas: Canvas = _ + private var stage: Stage = _ + private var root: Group = _ + private var canvas: Canvas = _ def start(title: String, size: Int): Unit = { - new JFXPanel() + new JFXPanel() // initializes JavaFX Platform.runLater(() => { stage = new Stage root = new Group diff --git a/client/src/main/scala/it/cwmp/client/view/game/model/TentacleView.scala b/client/src/main/scala/it/cwmp/client/view/game/model/TentacleView.scala index 5b7b4603..bb98aaf3 100644 --- a/client/src/main/scala/it/cwmp/client/view/game/model/TentacleView.scala +++ b/client/src/main/scala/it/cwmp/client/view/game/model/TentacleView.scala @@ -47,7 +47,7 @@ object TentacleView { * * Returns always same thickness */ - val thicknessStrategy: SizingStrategy[Tentacle, Double] = // TODO: make thickness vary with attackers cell energy + val thicknessStrategy: SizingStrategy[Tentacle, Double] = (_: Tentacle) => TENTACLE_DEFAULT_THICKNESS /** diff --git a/services/authentication/src/test/scala/it/cwmp/services/authentication/AuthenticationLocalDAOTest.scala b/services/authentication/src/test/scala/it/cwmp/services/authentication/AuthenticationLocalDAOTest.scala index d2f22fe8..839b3814 100644 --- a/services/authentication/src/test/scala/it/cwmp/services/authentication/AuthenticationLocalDAOTest.scala +++ b/services/authentication/src/test/scala/it/cwmp/services/authentication/AuthenticationLocalDAOTest.scala @@ -13,10 +13,10 @@ import scala.concurrent.Future */ class AuthenticationLocalDAOTest extends VertxTest with Matchers with FutureMatchers with BeforeAndAfterEach { - var storageFuture: Future[AuthenticationDAO] = _ - var storageNotInitializedFuture: Future[AuthenticationDAO] = _ - var username: String = _ - var password: String = _ + private var storageFuture: Future[AuthenticationDAO] = _ + private var storageNotInitializedFuture: Future[AuthenticationDAO] = _ + private var username: String = _ + private var password: String = _ private val USERNAME_LENGTH = 10 private val PASSWORD_LENGTH = 15 From 213aa59531c2b42c04a16d88cb90e6cbe9a74b47 Mon Sep 17 00:00:00 2001 From: Enrico Siboni Date: Wed, 25 Jul 2018 19:48:10 +0200 Subject: [PATCH 067/193] Added GameFX doc --- .../it/cwmp/client/view/game/GameFX.scala | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/client/src/main/scala/it/cwmp/client/view/game/GameFX.scala b/client/src/main/scala/it/cwmp/client/view/game/GameFX.scala index 3a7facf4..29a51248 100644 --- a/client/src/main/scala/it/cwmp/client/view/game/GameFX.scala +++ b/client/src/main/scala/it/cwmp/client/view/game/GameFX.scala @@ -9,7 +9,7 @@ import javafx.scene.{Group, Scene} import javafx.stage.Stage /** - * Questa classe permette di visualizzare una GUI statica che rappresenta uno stato del gioco + * This class shows the Game GUI * * @author Davide Borficchia */ @@ -19,6 +19,12 @@ case class GameFX() extends ObjectDrawer { private var root: Group = _ private var canvas: Canvas = _ + /** + * Initializes the GUI + * + * @param title the GUI title + * @param size the Window size + */ def start(title: String, size: Int): Unit = { new JFXPanel() // initializes JavaFX Platform.runLater(() => { @@ -30,7 +36,7 @@ case class GameFX() extends ObjectDrawer { root.getChildren.add(canvas) stage.setScene(new Scene(root)) - //stabilisco cosa fare alla chiusura della finestra + // what to do on window closed stage.setOnCloseRequest(_ => { Platform.exit() System.exit(0) @@ -39,12 +45,20 @@ case class GameFX() extends ObjectDrawer { }) } + /** + * Closes the GUI + */ def close(): Unit = { Platform.runLater(() => { stage.close() }) } + /** + * Updates the GUI with the newly provided world + * + * @param world the new world to draw + */ def updateWorld(world: CellWorld): Unit = { Platform.runLater(() => { implicit val graphicsContext: GraphicsContext = canvas.getGraphicsContext2D From 5edf9b9ac155676210ca463d9eeea17cacd6e1db Mon Sep 17 00:00:00 2001 From: Enrico Siboni Date: Wed, 25 Jul 2018 19:52:38 +0200 Subject: [PATCH 068/193] Added a method to convert colors to HexDecimal strings --- .../scala/it/cwmp/client/view/game/ObjectDrawer.scala | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/client/src/main/scala/it/cwmp/client/view/game/ObjectDrawer.scala b/client/src/main/scala/it/cwmp/client/view/game/ObjectDrawer.scala index ea2151cc..830a781d 100644 --- a/client/src/main/scala/it/cwmp/client/view/game/ObjectDrawer.scala +++ b/client/src/main/scala/it/cwmp/client/view/game/ObjectDrawer.scala @@ -13,6 +13,7 @@ import javafx.scene.text.Text import scala.language.implicitConversions /** + * A trait that makes possible to draw View items * * @author Eugenio Pierfederici * @author Davide Borficchia @@ -34,7 +35,7 @@ trait ObjectDrawer { svgShape.setBorder(new Border(new BorderStroke(Color.BLACK, BorderStrokeStyle.SOLID, CornerRadii.EMPTY, BorderWidths.DEFAULT))) svgShape.setPrefSize(cell.radius * 2, cell.radius * 2) - svgShape.setStyle("-fx-background-color: #" + Integer.toHexString(cell.color.getRGB).substring(2)) // TODO: make a method for this conversion + svgShape.setStyle("-fx-background-color: #" + getHexDecimalColor(cell.color)) svgShape.setLayoutX(cell.center.x - cell.radius) svgShape.setLayoutY(cell.center.y - cell.radius) svgShape @@ -85,4 +86,12 @@ trait ObjectDrawer { private implicit def fxColorToAwtColor(fxColor: javafx.scene.paint.Color): java.awt.Color = { new java.awt.Color(fxColor.getRed.toFloat, fxColor.getGreen.toFloat, fxColor.getBlue.toFloat, fxColor.getOpacity.toFloat) } + + /** + * Returns the Hex string representation of the color + * + * @param color the color of which to calculate the Hex representation + * @return the Hex string representation + */ + private def getHexDecimalColor(color: Color): String = Integer.toHexString(color.getRGB).substring(2) } From 4f5e155d385db2fb4704557b2493b0f16bbfffaf Mon Sep 17 00:00:00 2001 From: Enrico Siboni Date: Wed, 25 Jul 2018 20:05:48 +0200 Subject: [PATCH 069/193] - Modified TentacleView to piggyback the reached point of the tentacle - Made ObjectDrawer doc English - Modified drawArch to accept in input a TentacleView --- .../it/cwmp/client/view/game/GameFX.scala | 3 +- .../cwmp/client/view/game/ObjectDrawer.scala | 37 +++++++++---------- .../client/view/game/model/TentacleView.scala | 12 +++--- 3 files changed, 25 insertions(+), 27 deletions(-) diff --git a/client/src/main/scala/it/cwmp/client/view/game/GameFX.scala b/client/src/main/scala/it/cwmp/client/view/game/GameFX.scala index 29a51248..a50d5986 100644 --- a/client/src/main/scala/it/cwmp/client/view/game/GameFX.scala +++ b/client/src/main/scala/it/cwmp/client/view/game/GameFX.scala @@ -2,6 +2,7 @@ package it.cwmp.client.view.game import it.cwmp.client.model.game.impl.CellWorld import it.cwmp.client.view.game.model.CellView._ +import it.cwmp.client.view.game.model.TentacleView import javafx.application.Platform import javafx.embed.swing.JFXPanel import javafx.scene.canvas.{Canvas, GraphicsContext} @@ -64,7 +65,7 @@ case class GameFX() extends ObjectDrawer { implicit val graphicsContext: GraphicsContext = canvas.getGraphicsContext2D root.getChildren.clear() - world.attacks.foreach(tentacle => root.getChildren.add(drawArch(tentacle, world.instant))) + world.attacks.foreach(tentacle => root.getChildren.add(drawArch(TentacleView.tentacleToView(tentacle, world.instant)))) world.characters.foreach(cell => root.getChildren.add(drawCell(cell))) world.characters.foreach(cell => root.getChildren.add(drawCellEnergy(cell))) }) diff --git a/client/src/main/scala/it/cwmp/client/view/game/ObjectDrawer.scala b/client/src/main/scala/it/cwmp/client/view/game/ObjectDrawer.scala index 830a781d..1067bc94 100644 --- a/client/src/main/scala/it/cwmp/client/view/game/ObjectDrawer.scala +++ b/client/src/main/scala/it/cwmp/client/view/game/ObjectDrawer.scala @@ -1,8 +1,5 @@ package it.cwmp.client.view.game -import java.time.Instant - -import it.cwmp.client.model.game.impl.Tentacle import it.cwmp.client.view.game.model._ import javafx.scene.canvas.GraphicsContext import javafx.scene.layout._ @@ -19,11 +16,13 @@ import scala.language.implicitConversions * @author Davide Borficchia */ trait ObjectDrawer { + /** - * Meodo utilizzato per disegnare una cella nella GUI + * A method to draw a CellView * - * @param cell oggetto che rappresenta la cella che verrà disegnata - * @param graphicsContext è l'oggetto che disenga la cella + * @param cell the cell to draw + * @param graphicsContext the context in which to draw + * @return the drawn region */ def drawCell(cell: CellView) (implicit graphicsContext: GraphicsContext): Region = { @@ -32,8 +31,7 @@ trait ObjectDrawer { svg.setContent("M52.232,44.235c-1.039-0.285-2.039-0.297-2.969-0.112c-0.632,0.126-1.286-0.008-1.788-0.411 l-1.411-1.132c-0.766-0.614-0.992-1.665-0.585-2.559c0.377-0.829,0.69-1.693,0.932-2.587c0.402-1.487,2.008-2.394,3.444-1.838 c1.535,0.593,3.311,0.557,4.908-0.266c2.772-1.429,3.996-4.918,2.728-7.767c-1.364-3.066-4.967-4.413-8.002-3.009 c-0.266,0.123-0.563,0.312-0.868,0.535c-1.36,0.995-3.169,0.637-4.034-0.809c-0.546-0.913-1.215-1.741-1.882-2.571 c-0.883-1.098-1.037-2.618-0.387-3.878l1.479-2.871c0.55-1.068,1.57-1.871,2.765-1.988c0.603-0.059,1.226-0.22,1.865-0.512 c1.888-0.864,3.284-2.642,3.537-4.703c0.486-3.963-2.896-7.283-6.876-6.689c-2.527,0.377-4.589,2.411-4.996,4.933 c-0.197,1.221-0.025,2.386,0.423,3.404c0.459,1.045,0.499,2.226-0.024,3.241l-1.158,2.249c-0.805,1.563-2.612,2.394-4.29,1.87 c-0.981-0.306-2.718-0.523-3.92-0.644c-0.787-0.079-1.438-0.646-1.621-1.416L28.36,9.904c-0.141-0.594,0.036-1.207,0.435-1.669 c0.945-1.093,1.431-2.589,1.119-4.212c-0.371-1.933-1.91-3.514-3.838-3.913C22.849-0.557,20.009,1.89,20.009,5 c0,2.146,1.356,3.962,3.256,4.668c0.611,0.227,1.095,0.705,1.246,1.339l0.913,3.852c0.219,0.925-0.304,1.849-1.198,2.172 c-1.281,0.462-2.491,1.072-3.608,1.813c-0.802,0.531-1.895,0.519-2.642-0.086c-0.815-0.661-0.991-1.728-0.603-2.64 c0.628-1.474,0.829-3.173,0.429-4.95c-0.683-3.039-3.181-5.446-6.243-6.021c-5.63-1.057-10.471,3.79-9.402,9.422 c0.603,3.175,3.181,5.722,6.36,6.297c1.408,0.254,2.765,0.139,3.991-0.264c0.847-0.279,1.776,0.029,2.335,0.724l0.4,0.498 c0.574,0.714,0.636,1.706,0.167,2.493c-1.177,1.973-1.964,4.202-2.258,6.587c-0.122,0.992-0.904,1.771-1.9,1.86l-1.899,0.17 c-0.65,0.058-1.266-0.211-1.732-0.667c-0.721-0.705-1.688-1.181-2.83-1.258c-1.783-0.12-3.526,0.87-4.309,2.477 c-1.295,2.657,0.195,5.671,2.899,6.372c1.949,0.505,3.916-0.356,4.926-1.979c0.363-0.584,1.017-0.926,1.702-0.987l1.631-0.146 c0.987-0.088,1.888,0.529,2.192,1.472c0.669,2.076,1.728,3.977,3.089,5.618c0.487,0.587,0.459,1.443-0.051,2.009 c-0.425,0.472-1.085,0.609-1.69,0.416c-0.687-0.219-1.434-0.307-2.209-0.233c-2.498,0.237-4.582,2.233-4.913,4.721 c-0.497,3.738,2.765,6.871,6.537,6.15c1.964-0.376,3.596-1.867,4.172-3.783c0.28-0.93,0.303-1.829,0.139-2.661 c-0.092-0.468,0.051-0.95,0.37-1.305l0.785-0.871c0.472-0.524,1.243-0.673,1.862-0.336c0.489,0.266,0.993,0.508,1.51,0.726 c1.104,0.464,1.704,1.618,1.598,2.81c-0.051,0.575-0.019,1.174,0.11,1.787c0.528,2.504,2.683,4.44,5.228,4.703 c3.6,0.372,6.638-2.443,6.638-5.967c0-0.384-0.037-0.76-0.107-1.124c-0.23-1.199,0.257-2.415,1.325-3.006 c0.984-0.545,1.909-1.185,2.761-1.909c0.525-0.446,1.222-0.7,1.891-0.531c1.365,0.345,1.95,1.682,1.526,2.836 c-0.376,1.023-0.502,2.167-0.301,3.36c0.463,2.746,2.736,4.939,5.495,5.313c4.215,0.571,7.784-2.901,7.378-7.088 C56.721,47.208,54.792,44.938,52.232,44.235z") val svgShape = new Region svgShape.setShape(svg) - svgShape.setBorder(new Border(new BorderStroke(Color.BLACK, - BorderStrokeStyle.SOLID, CornerRadii.EMPTY, BorderWidths.DEFAULT))) + svgShape.setBorder(new Border(new BorderStroke(Color.BLACK, BorderStrokeStyle.SOLID, CornerRadii.EMPTY, BorderWidths.DEFAULT))) svgShape.setPrefSize(cell.radius * 2, cell.radius * 2) svgShape.setStyle("-fx-background-color: #" + getHexDecimalColor(cell.color)) svgShape.setLayoutX(cell.center.x - cell.radius) @@ -42,10 +40,10 @@ trait ObjectDrawer { } /** - * Metodo per disegnare l'energia di una cella + * A method to draw the cell energy * - * @param cell cella della quale disegnare l'energia - * @return il testo da aggiungere alla scena + * @param cell the cell of which energy is to be drawn + * @return the text to add to scene */ def drawCellEnergy(cell: CellView): Text = { val energyText = new Text(cell.center.x, cell.center.y, cell.energy.toInt.toString) @@ -57,19 +55,18 @@ trait ObjectDrawer { } /** - * Metodo utilizato per disegnare il tentacolo che unisce due celle + * A method to draw a tentacle on GUI * - * @param tentacle il tentacolo da disegnare - * @param actualInstant l'istante di gioco - * @return la linea da visualizzare nella GUI + * @param tentacle the tentacle View to draw + * @return the line to add in GUI */ - def drawArch(tentacle: Tentacle, actualInstant: Instant): Line = { + def drawArch(tentacle: TentacleView): Line = { val line = new Line() - line.setStroke(TentacleView.coloringStrategy(tentacle)) // TODO: make a tentacle view - line.setStrokeWidth(TentacleView.thicknessStrategy(tentacle)) + line.setStroke(tentacle.color) + line.setStrokeWidth(tentacle.thickness) - val attackerPosition = tentacle.from.position - val tentacleReachedPoint = TentacleView.reachedPoint(tentacle, actualInstant) + val attackerPosition = tentacle.startPoint + val tentacleReachedPoint = tentacle.reachedPoint line.setStartX(attackerPosition.x) line.setStartY(attackerPosition.y) line.setEndX(tentacleReachedPoint.x) diff --git a/client/src/main/scala/it/cwmp/client/view/game/model/TentacleView.scala b/client/src/main/scala/it/cwmp/client/view/game/model/TentacleView.scala index bb98aaf3..e7f79bc1 100644 --- a/client/src/main/scala/it/cwmp/client/view/game/model/TentacleView.scala +++ b/client/src/main/scala/it/cwmp/client/view/game/model/TentacleView.scala @@ -12,12 +12,12 @@ import scala.language.implicitConversions /** * A class representing the View counterpart of Tentacle * - * @param startPoint the starting point for this tentacle - * @param arrivePoint the arrive point for thi tentacle - * @param color the color of this tetacle + * @param startPoint the starting point for this tentacle View + * @param reachedPoint the arrive point for this tentacle View + * @param color the color of this tetacle * @author Enrico Siboni */ -case class TentacleView(startPoint: Point, arrivePoint: Point, color: Color, thickness: Double) +case class TentacleView(startPoint: Point, reachedPoint: Point, color: Color, thickness: Double) /** * Companion Object @@ -31,8 +31,8 @@ object TentacleView { */ val TENTACLE_DEFAULT_THICKNESS = 3d - implicit def tentacleToTentacleView(tentacle: Tentacle): TentacleView = - TentacleView(tentacle.from.position, tentacle.to.position, coloringStrategy(tentacle), thicknessStrategy(tentacle)) + def tentacleToView(tentacle: Tentacle, actualInstant: Instant): TentacleView = + TentacleView(tentacle.from.position, reachedPoint(tentacle, actualInstant), coloringStrategy(tentacle), thicknessStrategy(tentacle)) /** * Default coloring strategy for tentacles From 46f7fe49ac6ae3391b65e80802361f7be6150d4a Mon Sep 17 00:00:00 2001 From: Enrico Siboni Date: Wed, 25 Jul 2018 20:06:32 +0200 Subject: [PATCH 070/193] Renamed drawArch to drawTentacle --- client/src/main/scala/it/cwmp/client/view/game/GameFX.scala | 2 +- .../src/main/scala/it/cwmp/client/view/game/ObjectDrawer.scala | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/client/src/main/scala/it/cwmp/client/view/game/GameFX.scala b/client/src/main/scala/it/cwmp/client/view/game/GameFX.scala index a50d5986..378020cf 100644 --- a/client/src/main/scala/it/cwmp/client/view/game/GameFX.scala +++ b/client/src/main/scala/it/cwmp/client/view/game/GameFX.scala @@ -65,7 +65,7 @@ case class GameFX() extends ObjectDrawer { implicit val graphicsContext: GraphicsContext = canvas.getGraphicsContext2D root.getChildren.clear() - world.attacks.foreach(tentacle => root.getChildren.add(drawArch(TentacleView.tentacleToView(tentacle, world.instant)))) + world.attacks.foreach(tentacle => root.getChildren.add(drawTentacle(TentacleView.tentacleToView(tentacle, world.instant)))) world.characters.foreach(cell => root.getChildren.add(drawCell(cell))) world.characters.foreach(cell => root.getChildren.add(drawCellEnergy(cell))) }) diff --git a/client/src/main/scala/it/cwmp/client/view/game/ObjectDrawer.scala b/client/src/main/scala/it/cwmp/client/view/game/ObjectDrawer.scala index 1067bc94..109f6ea0 100644 --- a/client/src/main/scala/it/cwmp/client/view/game/ObjectDrawer.scala +++ b/client/src/main/scala/it/cwmp/client/view/game/ObjectDrawer.scala @@ -60,7 +60,7 @@ trait ObjectDrawer { * @param tentacle the tentacle View to draw * @return the line to add in GUI */ - def drawArch(tentacle: TentacleView): Line = { + def drawTentacle(tentacle: TentacleView): Line = { val line = new Line() line.setStroke(tentacle.color) line.setStrokeWidth(tentacle.thickness) From 96e1982721b4dd0c138e9f54fb4fc0aa946dab73 Mon Sep 17 00:00:00 2001 From: Enrico Siboni Date: Wed, 25 Jul 2018 20:08:29 +0200 Subject: [PATCH 071/193] Another comment from italian to english in ObjectDrawer --- .../main/scala/it/cwmp/client/view/game/ObjectDrawer.scala | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/client/src/main/scala/it/cwmp/client/view/game/ObjectDrawer.scala b/client/src/main/scala/it/cwmp/client/view/game/ObjectDrawer.scala index 109f6ea0..da86a3b0 100644 --- a/client/src/main/scala/it/cwmp/client/view/game/ObjectDrawer.scala +++ b/client/src/main/scala/it/cwmp/client/view/game/ObjectDrawer.scala @@ -75,10 +75,10 @@ trait ObjectDrawer { } /** - * Funzione per convertire i colori javaFX nel formato di colori utilizzato da java.awt + * Converter from JavaFX Colors to JavaAWT colors * - * @param fxColor Colore che si vuole convertire - * @return il colore awt + * @param fxColor the JavaFX color to convert + * @return the JAvaAWT correspondent */ private implicit def fxColorToAwtColor(fxColor: javafx.scene.paint.Color): java.awt.Color = { new java.awt.Color(fxColor.getRed.toFloat, fxColor.getGreen.toFloat, fxColor.getBlue.toFloat, fxColor.getOpacity.toFloat) From 81b36d2d57f59ce0e9475ac02714fc411d96475e Mon Sep 17 00:00:00 2001 From: Enrico Siboni Date: Wed, 25 Jul 2018 20:09:29 +0200 Subject: [PATCH 072/193] Renamed implicit method cellToViewCell to cellToView --- .../main/scala/it/cwmp/client/view/game/model/CellView.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/main/scala/it/cwmp/client/view/game/model/CellView.scala b/client/src/main/scala/it/cwmp/client/view/game/model/CellView.scala index bdc60bbb..9d483675 100644 --- a/client/src/main/scala/it/cwmp/client/view/game/model/CellView.scala +++ b/client/src/main/scala/it/cwmp/client/view/game/model/CellView.scala @@ -45,7 +45,7 @@ object CellView { /** * @return the ViewCell corresponding to the given Cell */ - implicit def cellToViewCell(cell: Cell): CellView = + implicit def cellToView(cell: Cell): CellView = CellView(cell.position, sizingStrategy(cell), coloringStrategy(cell), cell.energy, energyTextColoringStrategy(cell)) /** From b31d4e34477d617dea3ba1582db3993ebc7bd970 Mon Sep 17 00:00:00 2001 From: Enrico Siboni Date: Wed, 25 Jul 2018 20:27:46 +0200 Subject: [PATCH 073/193] Refactored GameViewActor: - splitting his behaviours - removing useless isHidden variable - adding constants for view settings --- .../cwmp/client/view/game/GameViewActor.scala | 47 +++++++++++++------ 1 file changed, 33 insertions(+), 14 deletions(-) diff --git a/client/src/main/scala/it/cwmp/client/view/game/GameViewActor.scala b/client/src/main/scala/it/cwmp/client/view/game/GameViewActor.scala index ebfddd04..a07b3a00 100644 --- a/client/src/main/scala/it/cwmp/client/view/game/GameViewActor.scala +++ b/client/src/main/scala/it/cwmp/client/view/game/GameViewActor.scala @@ -21,29 +21,38 @@ class GameViewActor(parentActor: ActorRef) extends Actor with Logging { private val gameFX: GameFX = GameFX() private val FRAME_RATE: FiniteDuration = 50.millis - private var isHidden = true private var updatingSchedule: Cancellable = _ private var tempWorld: CellWorld = _ - override def receive: Receive = { + override def receive: Receive = showGUIBehaviour + + /** + * The behaviour of opening the view + */ + private def showGUIBehaviour: Receive = { case ShowGUI => - if (isHidden) { - isHidden = false - gameFX.start("GIOCO", 512) - } + gameFX.start(VIEW_TITLE, VIEW_SIZE) + context.become(hideGUIBehaviour orElse worldModificationsBehaviour) + } + + /** + * The behaviour of closing the view + */ + private def hideGUIBehaviour: Receive = { case HideGUI => - if (!isHidden) { - isHidden = true - gameFX.close() - } + gameFX.close() + context.become(showGUIBehaviour) + } + + /** + * The behaviour of receiving and sending world modifications + */ + private def worldModificationsBehaviour: Receive = { case NewWorld(world) => if (updatingSchedule != null) updatingSchedule.cancel() tempWorld = world updatingSchedule = context.system.scheduler - .schedule(0.millis, - FRAME_RATE, - self, - UpdateLocalWorld)(context.dispatcher) + .schedule(0.millis, FRAME_RATE, self, UpdateLocalWorld)(context.dispatcher) case UpdateLocalWorld => // log.info(s"World to paint: Characters=${tempWorld.characters} Attacks=${tempWorld.attacks} Instant=${tempWorld.instant}") @@ -82,6 +91,16 @@ class GameViewActor(parentActor: ActorRef) extends Actor with Logging { object GameViewActor { def apply(parentActor: ActorRef): GameViewActor = new GameViewActor(parentActor) + /** + * The title of game view + */ + val VIEW_TITLE = "GIOCO" + + /** + * The size of the squared view + */ + val VIEW_SIZE = 512 // TODO: sarebbe buono forse fare una dimensione diversa in base alla dimensione dello schermo + /** * Shows the GUI */ From 38302691cd65d55c9a53d0a0a1954488e3c3325e Mon Sep 17 00:00:00 2001 From: Enrico Siboni Date: Wed, 25 Jul 2018 20:30:06 +0200 Subject: [PATCH 074/193] Modified ViewTitle to more appropriate CellWars --- .../src/main/scala/it/cwmp/client/view/game/GameViewActor.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/main/scala/it/cwmp/client/view/game/GameViewActor.scala b/client/src/main/scala/it/cwmp/client/view/game/GameViewActor.scala index a07b3a00..441d1e44 100644 --- a/client/src/main/scala/it/cwmp/client/view/game/GameViewActor.scala +++ b/client/src/main/scala/it/cwmp/client/view/game/GameViewActor.scala @@ -94,7 +94,7 @@ object GameViewActor { /** * The title of game view */ - val VIEW_TITLE = "GIOCO" + val VIEW_TITLE = "CellWars" /** * The size of the squared view From 66552ca7fc713e9e3c48f8637b100af9495e0c07 Mon Sep 17 00:00:00 2001 From: Davide Borficchia Date: Wed, 25 Jul 2018 20:54:19 +0200 Subject: [PATCH 075/193] eliminato parametro inutilizzato --- .../src/main/scala/it/cwmp/client/view/game/ObjectDrawer.scala | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/client/src/main/scala/it/cwmp/client/view/game/ObjectDrawer.scala b/client/src/main/scala/it/cwmp/client/view/game/ObjectDrawer.scala index 029fd9f1..87ac235a 100644 --- a/client/src/main/scala/it/cwmp/client/view/game/ObjectDrawer.scala +++ b/client/src/main/scala/it/cwmp/client/view/game/ObjectDrawer.scala @@ -22,9 +22,8 @@ trait ObjectDrawer { * Meodo utilizzato per disegnare una cella nella GUI * * @param cell oggetto che rappresenta la cella che verrà disegnata - * @param graphicsContext è l'oggetto che disenga la cella */ - def drawCell(cell: CellView)(implicit graphicsContext: GraphicsContext): Region = { + def drawCell(cell: CellView): Region = { val svg = new SVGPath //TODO cella hardcodata svg.setContent("M52.232,44.235c-1.039-0.285-2.039-0.297-2.969-0.112c-0.632,0.126-1.286-0.008-1.788-0.411 l-1.411-1.132c-0.766-0.614-0.992-1.665-0.585-2.559c0.377-0.829,0.69-1.693,0.932-2.587c0.402-1.487,2.008-2.394,3.444-1.838 c1.535,0.593,3.311,0.557,4.908-0.266c2.772-1.429,3.996-4.918,2.728-7.767c-1.364-3.066-4.967-4.413-8.002-3.009 c-0.266,0.123-0.563,0.312-0.868,0.535c-1.36,0.995-3.169,0.637-4.034-0.809c-0.546-0.913-1.215-1.741-1.882-2.571 c-0.883-1.098-1.037-2.618-0.387-3.878l1.479-2.871c0.55-1.068,1.57-1.871,2.765-1.988c0.603-0.059,1.226-0.22,1.865-0.512 c1.888-0.864,3.284-2.642,3.537-4.703c0.486-3.963-2.896-7.283-6.876-6.689c-2.527,0.377-4.589,2.411-4.996,4.933 c-0.197,1.221-0.025,2.386,0.423,3.404c0.459,1.045,0.499,2.226-0.024,3.241l-1.158,2.249c-0.805,1.563-2.612,2.394-4.29,1.87 c-0.981-0.306-2.718-0.523-3.92-0.644c-0.787-0.079-1.438-0.646-1.621-1.416L28.36,9.904c-0.141-0.594,0.036-1.207,0.435-1.669 c0.945-1.093,1.431-2.589,1.119-4.212c-0.371-1.933-1.91-3.514-3.838-3.913C22.849-0.557,20.009,1.89,20.009,5 c0,2.146,1.356,3.962,3.256,4.668c0.611,0.227,1.095,0.705,1.246,1.339l0.913,3.852c0.219,0.925-0.304,1.849-1.198,2.172 c-1.281,0.462-2.491,1.072-3.608,1.813c-0.802,0.531-1.895,0.519-2.642-0.086c-0.815-0.661-0.991-1.728-0.603-2.64 c0.628-1.474,0.829-3.173,0.429-4.95c-0.683-3.039-3.181-5.446-6.243-6.021c-5.63-1.057-10.471,3.79-9.402,9.422 c0.603,3.175,3.181,5.722,6.36,6.297c1.408,0.254,2.765,0.139,3.991-0.264c0.847-0.279,1.776,0.029,2.335,0.724l0.4,0.498 c0.574,0.714,0.636,1.706,0.167,2.493c-1.177,1.973-1.964,4.202-2.258,6.587c-0.122,0.992-0.904,1.771-1.9,1.86l-1.899,0.17 c-0.65,0.058-1.266-0.211-1.732-0.667c-0.721-0.705-1.688-1.181-2.83-1.258c-1.783-0.12-3.526,0.87-4.309,2.477 c-1.295,2.657,0.195,5.671,2.899,6.372c1.949,0.505,3.916-0.356,4.926-1.979c0.363-0.584,1.017-0.926,1.702-0.987l1.631-0.146 c0.987-0.088,1.888,0.529,2.192,1.472c0.669,2.076,1.728,3.977,3.089,5.618c0.487,0.587,0.459,1.443-0.051,2.009 c-0.425,0.472-1.085,0.609-1.69,0.416c-0.687-0.219-1.434-0.307-2.209-0.233c-2.498,0.237-4.582,2.233-4.913,4.721 c-0.497,3.738,2.765,6.871,6.537,6.15c1.964-0.376,3.596-1.867,4.172-3.783c0.28-0.93,0.303-1.829,0.139-2.661 c-0.092-0.468,0.051-0.95,0.37-1.305l0.785-0.871c0.472-0.524,1.243-0.673,1.862-0.336c0.489,0.266,0.993,0.508,1.51,0.726 c1.104,0.464,1.704,1.618,1.598,2.81c-0.051,0.575-0.019,1.174,0.11,1.787c0.528,2.504,2.683,4.44,5.228,4.703 c3.6,0.372,6.638-2.443,6.638-5.967c0-0.384-0.037-0.76-0.107-1.124c-0.23-1.199,0.257-2.415,1.325-3.006 c0.984-0.545,1.909-1.185,2.761-1.909c0.525-0.446,1.222-0.7,1.891-0.531c1.365,0.345,1.95,1.682,1.526,2.836 c-0.376,1.023-0.502,2.167-0.301,3.36c0.463,2.746,2.736,4.939,5.495,5.313c4.215,0.571,7.784-2.901,7.378-7.088 C56.721,47.208,54.792,44.938,52.232,44.235z") From e99d91c22d519912a1d04139180a21a35168ac32 Mon Sep 17 00:00:00 2001 From: Enrico Siboni Date: Wed, 25 Jul 2018 21:41:11 +0200 Subject: [PATCH 076/193] Added check if Color calculated by ColorHash is a color used in GUI In that case another hash is calculated on half of the username string --- .../it/cwmp/client/view/game/model/CellView.scala | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/client/src/main/scala/it/cwmp/client/view/game/model/CellView.scala b/client/src/main/scala/it/cwmp/client/view/game/model/CellView.scala index 2a120e36..4a49ed9f 100644 --- a/client/src/main/scala/it/cwmp/client/view/game/model/CellView.scala +++ b/client/src/main/scala/it/cwmp/client/view/game/model/CellView.scala @@ -1,6 +1,6 @@ package it.cwmp.client.view.game.model -import com.github.tkqubo.colorHash.ColorHash +import com.github.tkqubo.colorHash.{ColorHash, Rgb} import it.cwmp.client.controller.game.GameConstants import it.cwmp.client.model.game.impl.{Cell, Point} import it.cwmp.client.model.game.{GeometricUtils, SizingStrategy} @@ -50,8 +50,16 @@ object CellView { * Color based on the username hash value */ val coloringStrategy: ColoringStrategy[Cell, Color] = (cell: Cell) => { - val color = new ColorHash().rgb(cell.owner.username) - new Color(color.red / RGB_RANGE, color.green / RGB_RANGE, color.blue / RGB_RANGE, CELL_VIEW_COLOR_OPACITY) + implicit def colorFromRGB(userColor: Rgb): Color = + new Color(userColor.red / RGB_RANGE, userColor.green / RGB_RANGE, userColor.blue / RGB_RANGE, CELL_VIEW_COLOR_OPACITY) + + val colorHash = new ColorHash() + val username = cell.owner.username + val userColor: Color = colorHash.rgb(username) + // if userName hash gives a color used in GUI take another color + if (Seq(GameViewConstants.GAME_DEFAULT_FONT_COLOR, CellView.CELL_DYING_FONT_COLOR).contains(userColor)) { + colorHash.rgb(username.substring(username.length / 2)) + } else userColor } /** From a4642c217cd90cd8812edf94d36251eb3d445ccb Mon Sep 17 00:00:00 2001 From: Davide Borficchia Date: Wed, 25 Jul 2018 22:12:08 +0200 Subject: [PATCH 077/193] prima implementazione della visualizzazione del tempo nella GUI --- .../it/cwmp/client/view/game/GameFX.scala | 1 + .../cwmp/client/view/game/ObjectDrawer.scala | 25 ++++++++++++++++--- 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/client/src/main/scala/it/cwmp/client/view/game/GameFX.scala b/client/src/main/scala/it/cwmp/client/view/game/GameFX.scala index 4c1c75b9..6f2ccdcf 100644 --- a/client/src/main/scala/it/cwmp/client/view/game/GameFX.scala +++ b/client/src/main/scala/it/cwmp/client/view/game/GameFX.scala @@ -53,6 +53,7 @@ case class GameFX() extends ObjectDrawer { world.attacks.foreach(tentacle => root.getChildren.add(drawArch(tentacle, world.instant))) world.characters.foreach(cell => root.getChildren.add(drawCell(cell))) world.characters.foreach(cell => root.getChildren.add(drawCellEnergy(cell))) + world.characters.foreach(cell => root.getChildren.add(drawInstant(world.instant))) }) } } diff --git a/client/src/main/scala/it/cwmp/client/view/game/ObjectDrawer.scala b/client/src/main/scala/it/cwmp/client/view/game/ObjectDrawer.scala index 87ac235a..e45d1a68 100644 --- a/client/src/main/scala/it/cwmp/client/view/game/ObjectDrawer.scala +++ b/client/src/main/scala/it/cwmp/client/view/game/ObjectDrawer.scala @@ -1,15 +1,13 @@ package it.cwmp.client.view.game -import java.time.Instant +import java.time.{Duration, Instant} import it.cwmp.client.model.game.impl.Tentacle import it.cwmp.client.view.game.model._ -import javafx.scene.canvas.GraphicsContext import javafx.scene.layout._ import javafx.scene.paint.Color import javafx.scene.shape.{Line, SVGPath} import javafx.scene.text.Text - import scala.language.implicitConversions /** @@ -18,10 +16,14 @@ import scala.language.implicitConversions * @author Davide Borficchia */ trait ObjectDrawer { + + var firstDraw = true + var oldInstant: Instant = _ + /** * Meodo utilizzato per disegnare una cella nella GUI * - * @param cell oggetto che rappresenta la cella che verrà disegnata + * @param cell oggetto che rappresenta la cella che verrà disegnata */ def drawCell(cell: CellView): Region = { val svg = new SVGPath @@ -77,6 +79,21 @@ trait ObjectDrawer { line } + def drawInstant(worldInstant: Instant): Text = { + var instantToDraw: Duration = Duration.ofSeconds(0) + var actualInstant: Instant = worldInstant + if(!firstDraw){ + instantToDraw = Duration.between(oldInstant, actualInstant) + }else { + firstDraw = false + oldInstant = actualInstant + } + val instantText = new Text(70, 20, instantToDraw.getSeconds.toString) + instantText.setFont(CellView.ENERGY_FONT) + instantText.setFill(Color.BLACK) + instantText + } + /** * Funzione per convertire i colori javaFX nel formato di colori utilizzato da java.awt * From c1ac87f264e87f1a329c90a672054674521c5492 Mon Sep 17 00:00:00 2001 From: Davide Borficchia Date: Wed, 25 Jul 2018 22:13:13 +0200 Subject: [PATCH 078/193] corretto distrazione --- client/src/main/scala/it/cwmp/client/view/game/GameFX.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/main/scala/it/cwmp/client/view/game/GameFX.scala b/client/src/main/scala/it/cwmp/client/view/game/GameFX.scala index 6f2ccdcf..2193fd7a 100644 --- a/client/src/main/scala/it/cwmp/client/view/game/GameFX.scala +++ b/client/src/main/scala/it/cwmp/client/view/game/GameFX.scala @@ -53,7 +53,7 @@ case class GameFX() extends ObjectDrawer { world.attacks.foreach(tentacle => root.getChildren.add(drawArch(tentacle, world.instant))) world.characters.foreach(cell => root.getChildren.add(drawCell(cell))) world.characters.foreach(cell => root.getChildren.add(drawCellEnergy(cell))) - world.characters.foreach(cell => root.getChildren.add(drawInstant(world.instant))) + root.getChildren.add(drawInstant(world.instant)) }) } } From ffb6971ec0f8447752b0840601832e485b4ecda9 Mon Sep 17 00:00:00 2001 From: Davide Borficchia Date: Wed, 25 Jul 2018 22:48:54 +0200 Subject: [PATCH 079/193] visualizzato tempo nella GUI --- .../cwmp/client/view/game/ObjectDrawer.scala | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/client/src/main/scala/it/cwmp/client/view/game/ObjectDrawer.scala b/client/src/main/scala/it/cwmp/client/view/game/ObjectDrawer.scala index e45d1a68..70262efb 100644 --- a/client/src/main/scala/it/cwmp/client/view/game/ObjectDrawer.scala +++ b/client/src/main/scala/it/cwmp/client/view/game/ObjectDrawer.scala @@ -4,10 +4,12 @@ import java.time.{Duration, Instant} import it.cwmp.client.model.game.impl.Tentacle import it.cwmp.client.view.game.model._ +import javafx.scene.canvas.GraphicsContext import javafx.scene.layout._ import javafx.scene.paint.Color import javafx.scene.shape.{Line, SVGPath} import javafx.scene.text.Text + import scala.language.implicitConversions /** @@ -79,18 +81,25 @@ trait ObjectDrawer { line } - def drawInstant(worldInstant: Instant): Text = { + /** + * Metodo per disegnare il tempo trascorso dall'inizio della partita + * @param worldInstant tempo attuale + * @return il text da disegnare + */ + def drawInstant(worldInstant: Instant)(implicit graphicsContext: GraphicsContext) : Text = { var instantToDraw: Duration = Duration.ofSeconds(0) var actualInstant: Instant = worldInstant - if(!firstDraw){ - instantToDraw = Duration.between(oldInstant, actualInstant) - }else { + if (!firstDraw) { + instantToDraw = Duration.between(oldInstant, actualInstant) + } else { firstDraw = false oldInstant = actualInstant } - val instantText = new Text(70, 20, instantToDraw.getSeconds.toString) + val instantText = new Text(70, 20, (instantToDraw.getSeconds / 60) + ":" + (instantToDraw.getSeconds % 60)) instantText.setFont(CellView.ENERGY_FONT) instantText.setFill(Color.BLACK) + instantText.setX((graphicsContext.getCanvas.getWidth / 2) - (instantText.getLayoutBounds.getWidth / 2)) + instantText.setY(instantText.getLayoutBounds.getHeight) instantText } From a06625d09353d9efa66ba3979c306f491153e159 Mon Sep 17 00:00:00 2001 From: Enrico Siboni Date: Wed, 25 Jul 2018 23:26:52 +0200 Subject: [PATCH 080/193] - Modified ObjectDrawer to a more specific CellWorldObjectDrawer - Translated comment to english --- ...bjectDrawer.scala => CellWorldObjectDrawer.scala} | 12 +++++++----- .../main/scala/it/cwmp/client/view/game/GameFX.scala | 2 +- 2 files changed, 8 insertions(+), 6 deletions(-) rename client/src/main/scala/it/cwmp/client/view/game/{ObjectDrawer.scala => CellWorldObjectDrawer.scala} (95%) diff --git a/client/src/main/scala/it/cwmp/client/view/game/ObjectDrawer.scala b/client/src/main/scala/it/cwmp/client/view/game/CellWorldObjectDrawer.scala similarity index 95% rename from client/src/main/scala/it/cwmp/client/view/game/ObjectDrawer.scala rename to client/src/main/scala/it/cwmp/client/view/game/CellWorldObjectDrawer.scala index e51f99a9..2c1b52a6 100644 --- a/client/src/main/scala/it/cwmp/client/view/game/ObjectDrawer.scala +++ b/client/src/main/scala/it/cwmp/client/view/game/CellWorldObjectDrawer.scala @@ -17,7 +17,7 @@ import scala.language.implicitConversions * @author Eugenio Pierfederici * @author Davide Borficchia */ -trait ObjectDrawer { +trait CellWorldObjectDrawer { var firstDraw = true var oldInstant: Instant = _ @@ -78,12 +78,14 @@ trait ObjectDrawer { } /** - * Metodo per disegnare il tempo trascorso dall'inizio della partita + * A method to draw elapsed time on GUI * - * @param worldInstant tempo attuale - * @return il text da disegnare + * @param worldInstant the actualWorldInstant + * @param graphicsContext the graphic context on which to draw + * @return the text to draw */ - def drawInstant(worldInstant: Instant)(implicit graphicsContext: GraphicsContext): Text = { + def drawInstant(worldInstant: Instant) + (implicit graphicsContext: GraphicsContext): Text = { var instantToDraw: Duration = Duration.ofSeconds(0) var actualInstant: Instant = worldInstant if (!firstDraw) { diff --git a/client/src/main/scala/it/cwmp/client/view/game/GameFX.scala b/client/src/main/scala/it/cwmp/client/view/game/GameFX.scala index 042d7fd7..103f8f05 100644 --- a/client/src/main/scala/it/cwmp/client/view/game/GameFX.scala +++ b/client/src/main/scala/it/cwmp/client/view/game/GameFX.scala @@ -14,7 +14,7 @@ import javafx.stage.Stage * * @author Davide Borficchia */ -case class GameFX() extends ObjectDrawer { +case class GameFX() extends CellWorldObjectDrawer { private var stage: Stage = _ private var root: Group = _ From 13e4e24011db99247c60b67ca2b5f917796fb3b0 Mon Sep 17 00:00:00 2001 From: Enrico Siboni Date: Wed, 25 Jul 2018 23:36:56 +0200 Subject: [PATCH 081/193] Refactored drawInstant method to use an option instead of a boolean flag --- .../view/game/CellWorldObjectDrawer.scala | 28 +++++++++---------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/client/src/main/scala/it/cwmp/client/view/game/CellWorldObjectDrawer.scala b/client/src/main/scala/it/cwmp/client/view/game/CellWorldObjectDrawer.scala index 2c1b52a6..b5ec2921 100644 --- a/client/src/main/scala/it/cwmp/client/view/game/CellWorldObjectDrawer.scala +++ b/client/src/main/scala/it/cwmp/client/view/game/CellWorldObjectDrawer.scala @@ -19,8 +19,7 @@ import scala.language.implicitConversions */ trait CellWorldObjectDrawer { - var firstDraw = true - var oldInstant: Instant = _ + private var firstWorldInstantOption: Option[Instant] = None /** * A method to draw a CellView @@ -49,7 +48,7 @@ trait CellWorldObjectDrawer { * @return the text to add to scene */ def drawCellEnergy(cell: CellView): Text = { - val energyText = new Text(cell.center.x, cell.center.y, cell.energy.toInt.toString) + val energyText = new Text(cell.energy.toInt.toString) energyText.setFont(CellView.ENERGY_DEFAULT_FONT) energyText.setFill(cell.energyTextColor) energyText.setX(cell.center.x - (energyText.getLayoutBounds.getWidth / 2)) @@ -80,21 +79,20 @@ trait CellWorldObjectDrawer { /** * A method to draw elapsed time on GUI * - * @param worldInstant the actualWorldInstant - * @param graphicsContext the graphic context on which to draw + * @param actualWorldInstant the actual World Instant + * @param graphicsContext the graphic context on which to draw * @return the text to draw */ - def drawInstant(worldInstant: Instant) + def drawInstant(actualWorldInstant: Instant) (implicit graphicsContext: GraphicsContext): Text = { - var instantToDraw: Duration = Duration.ofSeconds(0) - var actualInstant: Instant = worldInstant - if (!firstDraw) { - instantToDraw = Duration.between(oldInstant, actualInstant) - } else { - firstDraw = false - oldInstant = actualInstant - } - val instantText = new Text(70, 20, (instantToDraw.getSeconds / 60) + ":" + (instantToDraw.getSeconds % 60)) + val elapsedTimeFromBeginning: Duration = + firstWorldInstantOption match { + case Some(firstWorldInstant) => Duration.between(firstWorldInstant, actualWorldInstant) + case None => + firstWorldInstantOption = Some(actualWorldInstant) + Duration.ofSeconds(0) + } + val instantText = new Text((elapsedTimeFromBeginning.getSeconds / 60) + ":" + (elapsedTimeFromBeginning.getSeconds % 60)) instantText.setFont(CellView.ENERGY_DEFAULT_FONT) // TODO: add font for instant instantText.setFill(Color.BLACK) // TODO: add constant for game instant color instantText.setX((graphicsContext.getCanvas.getWidth / 2) - (instantText.getLayoutBounds.getWidth / 2)) From 220687e42ad74397b23eddfa10e0ccc569cf560b Mon Sep 17 00:00:00 2001 From: Enrico Siboni Date: Wed, 25 Jul 2018 23:41:12 +0200 Subject: [PATCH 082/193] Added GameViewConstants for time text font and color --- .../cwmp/client/view/game/CellWorldObjectDrawer.scala | 4 ++-- .../it/cwmp/client/view/game/GameViewConstants.scala | 11 +++++++++++ 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/client/src/main/scala/it/cwmp/client/view/game/CellWorldObjectDrawer.scala b/client/src/main/scala/it/cwmp/client/view/game/CellWorldObjectDrawer.scala index b5ec2921..247d4901 100644 --- a/client/src/main/scala/it/cwmp/client/view/game/CellWorldObjectDrawer.scala +++ b/client/src/main/scala/it/cwmp/client/view/game/CellWorldObjectDrawer.scala @@ -93,8 +93,8 @@ trait CellWorldObjectDrawer { Duration.ofSeconds(0) } val instantText = new Text((elapsedTimeFromBeginning.getSeconds / 60) + ":" + (elapsedTimeFromBeginning.getSeconds % 60)) - instantText.setFont(CellView.ENERGY_DEFAULT_FONT) // TODO: add font for instant - instantText.setFill(Color.BLACK) // TODO: add constant for game instant color + instantText.setFont(GameViewConstants.GAME_TIME_TEXT_FONT) + instantText.setFill(GameViewConstants.GAME_TIME_TEXT_COLOR) instantText.setX((graphicsContext.getCanvas.getWidth / 2) - (instantText.getLayoutBounds.getWidth / 2)) instantText.setY(instantText.getLayoutBounds.getHeight) instantText diff --git a/client/src/main/scala/it/cwmp/client/view/game/GameViewConstants.scala b/client/src/main/scala/it/cwmp/client/view/game/GameViewConstants.scala index fc9967cd..014de5ed 100644 --- a/client/src/main/scala/it/cwmp/client/view/game/GameViewConstants.scala +++ b/client/src/main/scala/it/cwmp/client/view/game/GameViewConstants.scala @@ -1,6 +1,7 @@ package it.cwmp.client.view.game import javafx.scene.paint.Color +import javafx.scene.text.Font /** * An object where to put constants about the game visual @@ -23,4 +24,14 @@ object GameViewConstants { * The game default font color */ val GAME_DEFAULT_FONT_COLOR: Color = Color.BLACK + + /** + * The game time default font + */ + val GAME_TIME_TEXT_FONT: Font = Font.font("Verdana", GAME_DEFAULT_FONT_SIZE) + + /** + * The game time default font color + */ + val GAME_TIME_TEXT_COLOR: Color = GAME_DEFAULT_FONT_COLOR } From 34ffc7601b4b943af52895f1b8b7f0c5cb5a153b Mon Sep 17 00:00:00 2001 From: Enrico Siboni Date: Wed, 25 Jul 2018 23:42:54 +0200 Subject: [PATCH 083/193] Reformatted code --- .../client/view/game/CellWorldObjectDrawer.scala | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/client/src/main/scala/it/cwmp/client/view/game/CellWorldObjectDrawer.scala b/client/src/main/scala/it/cwmp/client/view/game/CellWorldObjectDrawer.scala index 247d4901..3c408452 100644 --- a/client/src/main/scala/it/cwmp/client/view/game/CellWorldObjectDrawer.scala +++ b/client/src/main/scala/it/cwmp/client/view/game/CellWorldObjectDrawer.scala @@ -85,13 +85,12 @@ trait CellWorldObjectDrawer { */ def drawInstant(actualWorldInstant: Instant) (implicit graphicsContext: GraphicsContext): Text = { - val elapsedTimeFromBeginning: Duration = - firstWorldInstantOption match { - case Some(firstWorldInstant) => Duration.between(firstWorldInstant, actualWorldInstant) - case None => - firstWorldInstantOption = Some(actualWorldInstant) - Duration.ofSeconds(0) - } + val elapsedTimeFromBeginning: Duration = firstWorldInstantOption match { + case Some(firstWorldInstant) => Duration.between(firstWorldInstant, actualWorldInstant) + case None => + firstWorldInstantOption = Some(actualWorldInstant) + Duration.ofSeconds(0) + } val instantText = new Text((elapsedTimeFromBeginning.getSeconds / 60) + ":" + (elapsedTimeFromBeginning.getSeconds % 60)) instantText.setFont(GameViewConstants.GAME_TIME_TEXT_FONT) instantText.setFill(GameViewConstants.GAME_TIME_TEXT_COLOR) From 8c7493a6906e32ce5ad17b0f75c47643890011e5 Mon Sep 17 00:00:00 2001 From: Davide Borficchia Date: Thu, 26 Jul 2018 09:18:18 +0200 Subject: [PATCH 084/193] aggiunta trasparenza per il tempo visualizzato nella GUI --- .../it/cwmp/client/view/game/CellWorldObjectDrawer.scala | 3 ++- .../scala/it/cwmp/client/view/game/GameViewConstants.scala | 5 +++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/client/src/main/scala/it/cwmp/client/view/game/CellWorldObjectDrawer.scala b/client/src/main/scala/it/cwmp/client/view/game/CellWorldObjectDrawer.scala index 3c408452..c96935c1 100644 --- a/client/src/main/scala/it/cwmp/client/view/game/CellWorldObjectDrawer.scala +++ b/client/src/main/scala/it/cwmp/client/view/game/CellWorldObjectDrawer.scala @@ -93,7 +93,8 @@ trait CellWorldObjectDrawer { } val instantText = new Text((elapsedTimeFromBeginning.getSeconds / 60) + ":" + (elapsedTimeFromBeginning.getSeconds % 60)) instantText.setFont(GameViewConstants.GAME_TIME_TEXT_FONT) - instantText.setFill(GameViewConstants.GAME_TIME_TEXT_COLOR) + instantText.setFill(Color.rgb(GameViewConstants.GAME_TIME_TEXT_COLOR.getRed.toInt, GameViewConstants.GAME_TIME_TEXT_COLOR.getGreen.toInt, + GameViewConstants.GAME_TIME_TEXT_COLOR.getBlue.toInt, GameViewConstants.TRANSPARENCY_INSTANT)) instantText.setX((graphicsContext.getCanvas.getWidth / 2) - (instantText.getLayoutBounds.getWidth / 2)) instantText.setY(instantText.getLayoutBounds.getHeight) instantText diff --git a/client/src/main/scala/it/cwmp/client/view/game/GameViewConstants.scala b/client/src/main/scala/it/cwmp/client/view/game/GameViewConstants.scala index 014de5ed..959af13a 100644 --- a/client/src/main/scala/it/cwmp/client/view/game/GameViewConstants.scala +++ b/client/src/main/scala/it/cwmp/client/view/game/GameViewConstants.scala @@ -9,6 +9,11 @@ import javafx.scene.text.Font * @author Enrico Siboni */ object GameViewConstants { + /** + * The constant value indicating the transparency of instant text in the GUI + */ + val TRANSPARENCY_INSTANT: Double = 0.5 + /** * The constant value indicating the rgb range max value From 16f031b5796c26e7fb3c98dd38acd85cb7c1789b Mon Sep 17 00:00:00 2001 From: Davide Borficchia Date: Thu, 26 Jul 2018 09:24:39 +0200 Subject: [PATCH 085/193] rifattorizzato codice --- .../scala/it/cwmp/client/view/game/CellWorldObjectDrawer.scala | 3 +-- .../scala/it/cwmp/client/view/game/GameViewConstants.scala | 3 ++- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/client/src/main/scala/it/cwmp/client/view/game/CellWorldObjectDrawer.scala b/client/src/main/scala/it/cwmp/client/view/game/CellWorldObjectDrawer.scala index c96935c1..3c408452 100644 --- a/client/src/main/scala/it/cwmp/client/view/game/CellWorldObjectDrawer.scala +++ b/client/src/main/scala/it/cwmp/client/view/game/CellWorldObjectDrawer.scala @@ -93,8 +93,7 @@ trait CellWorldObjectDrawer { } val instantText = new Text((elapsedTimeFromBeginning.getSeconds / 60) + ":" + (elapsedTimeFromBeginning.getSeconds % 60)) instantText.setFont(GameViewConstants.GAME_TIME_TEXT_FONT) - instantText.setFill(Color.rgb(GameViewConstants.GAME_TIME_TEXT_COLOR.getRed.toInt, GameViewConstants.GAME_TIME_TEXT_COLOR.getGreen.toInt, - GameViewConstants.GAME_TIME_TEXT_COLOR.getBlue.toInt, GameViewConstants.TRANSPARENCY_INSTANT)) + instantText.setFill(GameViewConstants.GAME_TIME_TEXT_COLOR) instantText.setX((graphicsContext.getCanvas.getWidth / 2) - (instantText.getLayoutBounds.getWidth / 2)) instantText.setY(instantText.getLayoutBounds.getHeight) instantText diff --git a/client/src/main/scala/it/cwmp/client/view/game/GameViewConstants.scala b/client/src/main/scala/it/cwmp/client/view/game/GameViewConstants.scala index 959af13a..94dcf898 100644 --- a/client/src/main/scala/it/cwmp/client/view/game/GameViewConstants.scala +++ b/client/src/main/scala/it/cwmp/client/view/game/GameViewConstants.scala @@ -38,5 +38,6 @@ object GameViewConstants { /** * The game time default font color */ - val GAME_TIME_TEXT_COLOR: Color = GAME_DEFAULT_FONT_COLOR + val GAME_TIME_TEXT_COLOR: Color = Color.rgb(GAME_DEFAULT_FONT_COLOR.getRed.toInt, GameViewConstants.GAME_DEFAULT_FONT_COLOR.getGreen.toInt, + GameViewConstants.GAME_DEFAULT_FONT_COLOR.getBlue.toInt, GameViewConstants.TRANSPARENCY_INSTANT) } From 2f76cce7727fefc92aff0be31ae0625887e984cf Mon Sep 17 00:00:00 2001 From: Davide Borficchia Date: Thu, 26 Jul 2018 09:28:53 +0200 Subject: [PATCH 086/193] aggiunta formattazione del tempo trascorso di gioco --- .../scala/it/cwmp/client/view/game/CellWorldObjectDrawer.scala | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/client/src/main/scala/it/cwmp/client/view/game/CellWorldObjectDrawer.scala b/client/src/main/scala/it/cwmp/client/view/game/CellWorldObjectDrawer.scala index 3c408452..db384e08 100644 --- a/client/src/main/scala/it/cwmp/client/view/game/CellWorldObjectDrawer.scala +++ b/client/src/main/scala/it/cwmp/client/view/game/CellWorldObjectDrawer.scala @@ -91,7 +91,8 @@ trait CellWorldObjectDrawer { firstWorldInstantOption = Some(actualWorldInstant) Duration.ofSeconds(0) } - val instantText = new Text((elapsedTimeFromBeginning.getSeconds / 60) + ":" + (elapsedTimeFromBeginning.getSeconds % 60)) + //val stringa = + val instantText = new Text(f"${(elapsedTimeFromBeginning.getSeconds / 60)}%02d : ${(elapsedTimeFromBeginning.getSeconds % 60)}%02d") instantText.setFont(GameViewConstants.GAME_TIME_TEXT_FONT) instantText.setFill(GameViewConstants.GAME_TIME_TEXT_COLOR) instantText.setX((graphicsContext.getCanvas.getWidth / 2) - (instantText.getLayoutBounds.getWidth / 2)) From 09e7236f97b4520c6fea9da317af731803cae9f5 Mon Sep 17 00:00:00 2001 From: Enrico Siboni Date: Thu, 26 Jul 2018 09:57:43 +0200 Subject: [PATCH 087/193] Refactored CellView to contain it's border parameter and it's default shape in a constant --- .../view/game/CellWorldObjectDrawer.scala | 5 ++--- .../cwmp/client/view/game/model/CellView.scala | 17 +++++++++++++++-- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/client/src/main/scala/it/cwmp/client/view/game/CellWorldObjectDrawer.scala b/client/src/main/scala/it/cwmp/client/view/game/CellWorldObjectDrawer.scala index db384e08..e71a23e4 100644 --- a/client/src/main/scala/it/cwmp/client/view/game/CellWorldObjectDrawer.scala +++ b/client/src/main/scala/it/cwmp/client/view/game/CellWorldObjectDrawer.scala @@ -29,11 +29,10 @@ trait CellWorldObjectDrawer { */ def drawCell(cell: CellView): Region = { val svg = new SVGPath - //TODO cella hardcodata - svg.setContent("M52.232,44.235c-1.039-0.285-2.039-0.297-2.969-0.112c-0.632,0.126-1.286-0.008-1.788-0.411 l-1.411-1.132c-0.766-0.614-0.992-1.665-0.585-2.559c0.377-0.829,0.69-1.693,0.932-2.587c0.402-1.487,2.008-2.394,3.444-1.838 c1.535,0.593,3.311,0.557,4.908-0.266c2.772-1.429,3.996-4.918,2.728-7.767c-1.364-3.066-4.967-4.413-8.002-3.009 c-0.266,0.123-0.563,0.312-0.868,0.535c-1.36,0.995-3.169,0.637-4.034-0.809c-0.546-0.913-1.215-1.741-1.882-2.571 c-0.883-1.098-1.037-2.618-0.387-3.878l1.479-2.871c0.55-1.068,1.57-1.871,2.765-1.988c0.603-0.059,1.226-0.22,1.865-0.512 c1.888-0.864,3.284-2.642,3.537-4.703c0.486-3.963-2.896-7.283-6.876-6.689c-2.527,0.377-4.589,2.411-4.996,4.933 c-0.197,1.221-0.025,2.386,0.423,3.404c0.459,1.045,0.499,2.226-0.024,3.241l-1.158,2.249c-0.805,1.563-2.612,2.394-4.29,1.87 c-0.981-0.306-2.718-0.523-3.92-0.644c-0.787-0.079-1.438-0.646-1.621-1.416L28.36,9.904c-0.141-0.594,0.036-1.207,0.435-1.669 c0.945-1.093,1.431-2.589,1.119-4.212c-0.371-1.933-1.91-3.514-3.838-3.913C22.849-0.557,20.009,1.89,20.009,5 c0,2.146,1.356,3.962,3.256,4.668c0.611,0.227,1.095,0.705,1.246,1.339l0.913,3.852c0.219,0.925-0.304,1.849-1.198,2.172 c-1.281,0.462-2.491,1.072-3.608,1.813c-0.802,0.531-1.895,0.519-2.642-0.086c-0.815-0.661-0.991-1.728-0.603-2.64 c0.628-1.474,0.829-3.173,0.429-4.95c-0.683-3.039-3.181-5.446-6.243-6.021c-5.63-1.057-10.471,3.79-9.402,9.422 c0.603,3.175,3.181,5.722,6.36,6.297c1.408,0.254,2.765,0.139,3.991-0.264c0.847-0.279,1.776,0.029,2.335,0.724l0.4,0.498 c0.574,0.714,0.636,1.706,0.167,2.493c-1.177,1.973-1.964,4.202-2.258,6.587c-0.122,0.992-0.904,1.771-1.9,1.86l-1.899,0.17 c-0.65,0.058-1.266-0.211-1.732-0.667c-0.721-0.705-1.688-1.181-2.83-1.258c-1.783-0.12-3.526,0.87-4.309,2.477 c-1.295,2.657,0.195,5.671,2.899,6.372c1.949,0.505,3.916-0.356,4.926-1.979c0.363-0.584,1.017-0.926,1.702-0.987l1.631-0.146 c0.987-0.088,1.888,0.529,2.192,1.472c0.669,2.076,1.728,3.977,3.089,5.618c0.487,0.587,0.459,1.443-0.051,2.009 c-0.425,0.472-1.085,0.609-1.69,0.416c-0.687-0.219-1.434-0.307-2.209-0.233c-2.498,0.237-4.582,2.233-4.913,4.721 c-0.497,3.738,2.765,6.871,6.537,6.15c1.964-0.376,3.596-1.867,4.172-3.783c0.28-0.93,0.303-1.829,0.139-2.661 c-0.092-0.468,0.051-0.95,0.37-1.305l0.785-0.871c0.472-0.524,1.243-0.673,1.862-0.336c0.489,0.266,0.993,0.508,1.51,0.726 c1.104,0.464,1.704,1.618,1.598,2.81c-0.051,0.575-0.019,1.174,0.11,1.787c0.528,2.504,2.683,4.44,5.228,4.703 c3.6,0.372,6.638-2.443,6.638-5.967c0-0.384-0.037-0.76-0.107-1.124c-0.23-1.199,0.257-2.415,1.325-3.006 c0.984-0.545,1.909-1.185,2.761-1.909c0.525-0.446,1.222-0.7,1.891-0.531c1.365,0.345,1.95,1.682,1.526,2.836 c-0.376,1.023-0.502,2.167-0.301,3.36c0.463,2.746,2.736,4.939,5.495,5.313c4.215,0.571,7.784-2.901,7.378-7.088 C56.721,47.208,54.792,44.938,52.232,44.235z") + svg.setContent(CellView.CELL_VIEW_DEFAULT_SHAPE) val svgShape = new Region svgShape.setShape(svg) - svgShape.setBorder(new Border(new BorderStroke(Color.BLACK, BorderStrokeStyle.SOLID, CornerRadii.EMPTY, BorderWidths.DEFAULT))) + svgShape.setBorder(cell.border) svgShape.setPrefSize(cell.radius * 2, cell.radius * 2) svgShape.setStyle("-fx-background-color: #" + getHexDecimalColor(cell.color)) svgShape.setLayoutX(cell.center.x - cell.radius) diff --git a/client/src/main/scala/it/cwmp/client/view/game/model/CellView.scala b/client/src/main/scala/it/cwmp/client/view/game/model/CellView.scala index 80fa4c0e..3d7ff726 100644 --- a/client/src/main/scala/it/cwmp/client/view/game/model/CellView.scala +++ b/client/src/main/scala/it/cwmp/client/view/game/model/CellView.scala @@ -6,6 +6,7 @@ import it.cwmp.client.model.game.impl.{Cell, Point} import it.cwmp.client.model.game.{GeometricUtils, SizingStrategy} import it.cwmp.client.view.game.GameViewConstants.RGB_RANGE import it.cwmp.client.view.game.{ColoringStrategy, GameViewConstants} +import javafx.scene.layout._ import javafx.scene.paint.Color import javafx.scene.text.Font @@ -19,10 +20,12 @@ import scala.language.implicitConversions * @param color the color of the cellView * @param energy the cell energy * @param energyTextColor the color of the energyText + * @param border the cell border * @author Davide Borficchia * @author Eugenio Pierfederici */ -case class CellView(center: Point, radius: Double, color: Color, energy: Double, energyTextColor: Color) +case class CellView(center: Point, radius: Double, color: Color, + energy: Double, energyTextColor: Color, border: Border) /** * Companion object @@ -36,9 +39,18 @@ object CellView { */ val ENERGY_DEFAULT_FONT: Font = Font.font("Verdana", GameViewConstants.GAME_DEFAULT_FONT_SIZE) + /** + * The cell default shape in SVG string format + */ + val CELL_VIEW_DEFAULT_SHAPE: String = "M52.232,44.235c-1.039-0.285-2.039-0.297-2.969-0.112c-0.632,0.126-1.286-0.008-1.788-0.411 l-1.411-1.132c-0.766-0.614-0.992-1.665-0.585-2.559c0.377-0.829,0.69-1.693,0.932-2.587c0.402-1.487,2.008-2.394,3.444-1.838 c1.535,0.593,3.311,0.557,4.908-0.266c2.772-1.429,3.996-4.918,2.728-7.767c-1.364-3.066-4.967-4.413-8.002-3.009 c-0.266,0.123-0.563,0.312-0.868,0.535c-1.36,0.995-3.169,0.637-4.034-0.809c-0.546-0.913-1.215-1.741-1.882-2.571 c-0.883-1.098-1.037-2.618-0.387-3.878l1.479-2.871c0.55-1.068,1.57-1.871,2.765-1.988c0.603-0.059,1.226-0.22,1.865-0.512 c1.888-0.864,3.284-2.642,3.537-4.703c0.486-3.963-2.896-7.283-6.876-6.689c-2.527,0.377-4.589,2.411-4.996,4.933 c-0.197,1.221-0.025,2.386,0.423,3.404c0.459,1.045,0.499,2.226-0.024,3.241l-1.158,2.249c-0.805,1.563-2.612,2.394-4.29,1.87 c-0.981-0.306-2.718-0.523-3.92-0.644c-0.787-0.079-1.438-0.646-1.621-1.416L28.36,9.904c-0.141-0.594,0.036-1.207,0.435-1.669 c0.945-1.093,1.431-2.589,1.119-4.212c-0.371-1.933-1.91-3.514-3.838-3.913C22.849-0.557,20.009,1.89,20.009,5 c0,2.146,1.356,3.962,3.256,4.668c0.611,0.227,1.095,0.705,1.246,1.339l0.913,3.852c0.219,0.925-0.304,1.849-1.198,2.172 c-1.281,0.462-2.491,1.072-3.608,1.813c-0.802,0.531-1.895,0.519-2.642-0.086c-0.815-0.661-0.991-1.728-0.603-2.64 c0.628-1.474,0.829-3.173,0.429-4.95c-0.683-3.039-3.181-5.446-6.243-6.021c-5.63-1.057-10.471,3.79-9.402,9.422 c0.603,3.175,3.181,5.722,6.36,6.297c1.408,0.254,2.765,0.139,3.991-0.264c0.847-0.279,1.776,0.029,2.335,0.724l0.4,0.498 c0.574,0.714,0.636,1.706,0.167,2.493c-1.177,1.973-1.964,4.202-2.258,6.587c-0.122,0.992-0.904,1.771-1.9,1.86l-1.899,0.17 c-0.65,0.058-1.266-0.211-1.732-0.667c-0.721-0.705-1.688-1.181-2.83-1.258c-1.783-0.12-3.526,0.87-4.309,2.477 c-1.295,2.657,0.195,5.671,2.899,6.372c1.949,0.505,3.916-0.356,4.926-1.979c0.363-0.584,1.017-0.926,1.702-0.987l1.631-0.146 c0.987-0.088,1.888,0.529,2.192,1.472c0.669,2.076,1.728,3.977,3.089,5.618c0.487,0.587,0.459,1.443-0.051,2.009 c-0.425,0.472-1.085,0.609-1.69,0.416c-0.687-0.219-1.434-0.307-2.209-0.233c-2.498,0.237-4.582,2.233-4.913,4.721 c-0.497,3.738,2.765,6.871,6.537,6.15c1.964-0.376,3.596-1.867,4.172-3.783c0.28-0.93,0.303-1.829,0.139-2.661 c-0.092-0.468,0.051-0.95,0.37-1.305l0.785-0.871c0.472-0.524,1.243-0.673,1.862-0.336c0.489,0.266,0.993,0.508,1.51,0.726 c1.104,0.464,1.704,1.618,1.598,2.81c-0.051,0.575-0.019,1.174,0.11,1.787c0.528,2.504,2.683,4.44,5.228,4.703 c3.6,0.372,6.638-2.443,6.638-5.967c0-0.384-0.037-0.76-0.107-1.124c-0.23-1.199,0.257-2.415,1.325-3.006 c0.984-0.545,1.909-1.185,2.761-1.909c0.525-0.446,1.222-0.7,1.891-0.531c1.365,0.345,1.95,1.682,1.526,2.836 c-0.376,1.023-0.502,2.167-0.301,3.36c0.463,2.746,2.736,4.939,5.495,5.313c4.215,0.571,7.784-2.901,7.378-7.088 C56.721,47.208,54.792,44.938,52.232,44.235z" + private val CELL_VIEW_COLOR_OPACITY = 1 private val CELL_DYING_FONT_COLOR = Color.DARKRED + private val CELL_BORDER_COLOR = Color.BLACK + private val CELL_BORDER = + new Border(new BorderStroke(CELL_BORDER_COLOR, BorderStrokeStyle.SOLID, CornerRadii.EMPTY, BorderWidths.DEFAULT)) + private val CELL_MINIMUM_RADIUS_FOR_ENERGY = (25d, 20d) private val CELL_MAX_RADIUS_FOR_ENERGY = (45d, 100d) @@ -46,7 +58,8 @@ object CellView { * @return the ViewCell corresponding to the given Cell */ implicit def cellToView(cell: Cell): CellView = - CellView(cell.position, sizingStrategy(cell), coloringStrategy(cell), cell.energy, energyTextColoringStrategy(cell)) + CellView(cell.position, sizingStrategy(cell), coloringStrategy(cell), + cell.energy, energyTextColoringStrategy(cell), CELL_BORDER) /** * Default cell coloring strategy From 838867fd9502b3350a166c9e6bf16888797433e0 Mon Sep 17 00:00:00 2001 From: Enrico Siboni Date: Thu, 26 Jul 2018 09:59:22 +0200 Subject: [PATCH 088/193] Renamed constant in GameViewConstants --- .../client/view/game/CellWorldObjectDrawer.scala | 1 - .../it/cwmp/client/view/game/GameViewConstants.scala | 12 ++++++------ 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/client/src/main/scala/it/cwmp/client/view/game/CellWorldObjectDrawer.scala b/client/src/main/scala/it/cwmp/client/view/game/CellWorldObjectDrawer.scala index e71a23e4..c4787c38 100644 --- a/client/src/main/scala/it/cwmp/client/view/game/CellWorldObjectDrawer.scala +++ b/client/src/main/scala/it/cwmp/client/view/game/CellWorldObjectDrawer.scala @@ -90,7 +90,6 @@ trait CellWorldObjectDrawer { firstWorldInstantOption = Some(actualWorldInstant) Duration.ofSeconds(0) } - //val stringa = val instantText = new Text(f"${(elapsedTimeFromBeginning.getSeconds / 60)}%02d : ${(elapsedTimeFromBeginning.getSeconds % 60)}%02d") instantText.setFont(GameViewConstants.GAME_TIME_TEXT_FONT) instantText.setFill(GameViewConstants.GAME_TIME_TEXT_COLOR) diff --git a/client/src/main/scala/it/cwmp/client/view/game/GameViewConstants.scala b/client/src/main/scala/it/cwmp/client/view/game/GameViewConstants.scala index 94dcf898..23b9b838 100644 --- a/client/src/main/scala/it/cwmp/client/view/game/GameViewConstants.scala +++ b/client/src/main/scala/it/cwmp/client/view/game/GameViewConstants.scala @@ -9,11 +9,6 @@ import javafx.scene.text.Font * @author Enrico Siboni */ object GameViewConstants { - /** - * The constant value indicating the transparency of instant text in the GUI - */ - val TRANSPARENCY_INSTANT: Double = 0.5 - /** * The constant value indicating the rgb range max value @@ -35,9 +30,14 @@ object GameViewConstants { */ val GAME_TIME_TEXT_FONT: Font = Font.font("Verdana", GAME_DEFAULT_FONT_SIZE) + /** + * The constant value indicating the transparency of instant text in the GUI + */ + val GAME_TIME_TEXT_TRANSPARENCY: Double = 0.5 + /** * The game time default font color */ val GAME_TIME_TEXT_COLOR: Color = Color.rgb(GAME_DEFAULT_FONT_COLOR.getRed.toInt, GameViewConstants.GAME_DEFAULT_FONT_COLOR.getGreen.toInt, - GameViewConstants.GAME_DEFAULT_FONT_COLOR.getBlue.toInt, GameViewConstants.TRANSPARENCY_INSTANT) + GameViewConstants.GAME_DEFAULT_FONT_COLOR.getBlue.toInt, GameViewConstants.GAME_TIME_TEXT_TRANSPARENCY) } From 119eabfdd8fd5c1272ec73a24e62b523de35dc47 Mon Sep 17 00:00:00 2001 From: Enrico Siboni Date: Thu, 26 Jul 2018 10:03:08 +0200 Subject: [PATCH 089/193] Removed redundant conversion to rgb color in GameViewConstants --- .../scala/it/cwmp/client/view/game/GameViewConstants.scala | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/client/src/main/scala/it/cwmp/client/view/game/GameViewConstants.scala b/client/src/main/scala/it/cwmp/client/view/game/GameViewConstants.scala index 23b9b838..d9ecceb0 100644 --- a/client/src/main/scala/it/cwmp/client/view/game/GameViewConstants.scala +++ b/client/src/main/scala/it/cwmp/client/view/game/GameViewConstants.scala @@ -38,6 +38,7 @@ object GameViewConstants { /** * The game time default font color */ - val GAME_TIME_TEXT_COLOR: Color = Color.rgb(GAME_DEFAULT_FONT_COLOR.getRed.toInt, GameViewConstants.GAME_DEFAULT_FONT_COLOR.getGreen.toInt, - GameViewConstants.GAME_DEFAULT_FONT_COLOR.getBlue.toInt, GameViewConstants.GAME_TIME_TEXT_TRANSPARENCY) + val GAME_TIME_TEXT_COLOR: Color = + Color.color(GAME_DEFAULT_FONT_COLOR.getRed, GameViewConstants.GAME_DEFAULT_FONT_COLOR.getGreen, + GameViewConstants.GAME_DEFAULT_FONT_COLOR.getBlue, GameViewConstants.GAME_TIME_TEXT_TRANSPARENCY) } From db5a84980ec8b816ec6a0061e2596161edf20140 Mon Sep 17 00:00:00 2001 From: Enrico Siboni Date: Thu, 26 Jul 2018 10:15:14 +0200 Subject: [PATCH 090/193] - Added Doc - Added a constant in GameViewConstants that hold Time format string --- .../it/cwmp/client/view/game/CellWorldObjectDrawer.scala | 4 +++- .../it/cwmp/client/view/game/GameViewConstants.scala | 8 ++++++++ .../scala/it/cwmp/client/view/game/model/CellView.scala | 2 ++ .../it/cwmp/client/view/game/model/TentacleView.scala | 7 +++++++ 4 files changed, 20 insertions(+), 1 deletion(-) diff --git a/client/src/main/scala/it/cwmp/client/view/game/CellWorldObjectDrawer.scala b/client/src/main/scala/it/cwmp/client/view/game/CellWorldObjectDrawer.scala index c4787c38..9637be81 100644 --- a/client/src/main/scala/it/cwmp/client/view/game/CellWorldObjectDrawer.scala +++ b/client/src/main/scala/it/cwmp/client/view/game/CellWorldObjectDrawer.scala @@ -90,7 +90,9 @@ trait CellWorldObjectDrawer { firstWorldInstantOption = Some(actualWorldInstant) Duration.ofSeconds(0) } - val instantText = new Text(f"${(elapsedTimeFromBeginning.getSeconds / 60)}%02d : ${(elapsedTimeFromBeginning.getSeconds % 60)}%02d") + val minutes = elapsedTimeFromBeginning.getSeconds / 60 + val seconds = elapsedTimeFromBeginning.getSeconds % 60 + val instantText = new Text(GameViewConstants.GAME_TIME_TEXT_FORMAT.format(minutes, seconds)) instantText.setFont(GameViewConstants.GAME_TIME_TEXT_FONT) instantText.setFill(GameViewConstants.GAME_TIME_TEXT_COLOR) instantText.setX((graphicsContext.getCanvas.getWidth / 2) - (instantText.getLayoutBounds.getWidth / 2)) diff --git a/client/src/main/scala/it/cwmp/client/view/game/GameViewConstants.scala b/client/src/main/scala/it/cwmp/client/view/game/GameViewConstants.scala index d9ecceb0..fc6b2cd1 100644 --- a/client/src/main/scala/it/cwmp/client/view/game/GameViewConstants.scala +++ b/client/src/main/scala/it/cwmp/client/view/game/GameViewConstants.scala @@ -25,6 +25,9 @@ object GameViewConstants { */ val GAME_DEFAULT_FONT_COLOR: Color = Color.BLACK + + // GAME TIME TEXT CONSTANTS + /** * The game time default font */ @@ -41,4 +44,9 @@ object GameViewConstants { val GAME_TIME_TEXT_COLOR: Color = Color.color(GAME_DEFAULT_FONT_COLOR.getRed, GameViewConstants.GAME_DEFAULT_FONT_COLOR.getGreen, GameViewConstants.GAME_DEFAULT_FONT_COLOR.getBlue, GameViewConstants.GAME_TIME_TEXT_TRANSPARENCY) + + /** + * The game time default format + */ + val GAME_TIME_TEXT_FORMAT: String = "%02dm : %02ds" } diff --git a/client/src/main/scala/it/cwmp/client/view/game/model/CellView.scala b/client/src/main/scala/it/cwmp/client/view/game/model/CellView.scala index 3d7ff726..04c16f70 100644 --- a/client/src/main/scala/it/cwmp/client/view/game/model/CellView.scala +++ b/client/src/main/scala/it/cwmp/client/view/game/model/CellView.scala @@ -55,6 +55,8 @@ object CellView { private val CELL_MAX_RADIUS_FOR_ENERGY = (45d, 100d) /** + * Implicit Conversion from Cell to CellView + * * @return the ViewCell corresponding to the given Cell */ implicit def cellToView(cell: Cell): CellView = diff --git a/client/src/main/scala/it/cwmp/client/view/game/model/TentacleView.scala b/client/src/main/scala/it/cwmp/client/view/game/model/TentacleView.scala index e7f79bc1..2e3d7cd7 100644 --- a/client/src/main/scala/it/cwmp/client/view/game/model/TentacleView.scala +++ b/client/src/main/scala/it/cwmp/client/view/game/model/TentacleView.scala @@ -31,6 +31,13 @@ object TentacleView { */ val TENTACLE_DEFAULT_THICKNESS = 3d + /** + * Conversion from Tentacle to TentacleView + * + * @param tentacle the tentacle to convert + * @param actualInstant the instant of the world + * @return the TentacleView corresponding to the give Tentacle + */ def tentacleToView(tentacle: Tentacle, actualInstant: Instant): TentacleView = TentacleView(tentacle.from.position, reachedPoint(tentacle, actualInstant), coloringStrategy(tentacle), thicknessStrategy(tentacle)) From e1bf8d45871163ecabc0eb9ec9c31f8a205d71da Mon Sep 17 00:00:00 2001 From: Enrico Siboni Date: Thu, 26 Jul 2018 10:17:35 +0200 Subject: [PATCH 091/193] Added GameTimeText color in check of used colors when selecting user color --- .../scala/it/cwmp/client/view/game/model/CellView.scala | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/client/src/main/scala/it/cwmp/client/view/game/model/CellView.scala b/client/src/main/scala/it/cwmp/client/view/game/model/CellView.scala index 04c16f70..7d3a78e0 100644 --- a/client/src/main/scala/it/cwmp/client/view/game/model/CellView.scala +++ b/client/src/main/scala/it/cwmp/client/view/game/model/CellView.scala @@ -4,7 +4,7 @@ import com.github.tkqubo.colorHash.{ColorHash, Rgb} import it.cwmp.client.controller.game.GameConstants import it.cwmp.client.model.game.impl.{Cell, Point} import it.cwmp.client.model.game.{GeometricUtils, SizingStrategy} -import it.cwmp.client.view.game.GameViewConstants.RGB_RANGE +import it.cwmp.client.view.game.GameViewConstants.{GAME_DEFAULT_FONT_COLOR, GAME_TIME_TEXT_COLOR, RGB_RANGE} import it.cwmp.client.view.game.{ColoringStrategy, GameViewConstants} import javafx.scene.layout._ import javafx.scene.paint.Color @@ -76,7 +76,7 @@ object CellView { val username = cell.owner.username val userColor: Color = colorHash.rgb(username) // if userName hash gives a color used in GUI take another color - if (Seq(GameViewConstants.GAME_DEFAULT_FONT_COLOR, CellView.CELL_DYING_FONT_COLOR).contains(userColor)) { + if (Seq(GAME_DEFAULT_FONT_COLOR, CELL_DYING_FONT_COLOR, GAME_TIME_TEXT_COLOR).contains(userColor)) { colorHash.rgb(username.substring(username.length / 2)) } else userColor } @@ -86,7 +86,7 @@ object CellView { */ val energyTextColoringStrategy: ColoringStrategy[Cell, Color] = { case cell: Cell if cell.energy < GameConstants.CELL_ENERGY_WHEN_BORN => CELL_DYING_FONT_COLOR - case _ => GameViewConstants.GAME_DEFAULT_FONT_COLOR + case _ => GAME_DEFAULT_FONT_COLOR } /** From d4d9c7fe9538293031b70b3623a36b80698f01c2 Mon Sep 17 00:00:00 2001 From: Enrico Siboni Date: Thu, 26 Jul 2018 11:43:47 +0200 Subject: [PATCH 092/193] Added an object in GameFX that will manage user made events on GUI --- .../it/cwmp/client/view/game/GameFX.scala | 57 ++++++++++++++++++- 1 file changed, 56 insertions(+), 1 deletion(-) diff --git a/client/src/main/scala/it/cwmp/client/view/game/GameFX.scala b/client/src/main/scala/it/cwmp/client/view/game/GameFX.scala index 103f8f05..4da32628 100644 --- a/client/src/main/scala/it/cwmp/client/view/game/GameFX.scala +++ b/client/src/main/scala/it/cwmp/client/view/game/GameFX.scala @@ -1,18 +1,22 @@ package it.cwmp.client.view.game -import it.cwmp.client.model.game.impl.CellWorld +import it.cwmp.client.model.game.impl.{CellWorld, Point} import it.cwmp.client.view.game.model.CellView._ import it.cwmp.client.view.game.model.TentacleView import javafx.application.Platform import javafx.embed.swing.JFXPanel import javafx.scene.canvas.{Canvas, GraphicsContext} +import javafx.scene.input.MouseEvent import javafx.scene.{Group, Scene} import javafx.stage.Stage +import scala.language.implicitConversions + /** * This class shows the Game GUI * * @author Davide Borficchia + * @author contributor Enrico Siboni */ case class GameFX() extends CellWorldObjectDrawer { @@ -33,6 +37,8 @@ case class GameFX() extends CellWorldObjectDrawer { root = new Group canvas = new Canvas(size, size) + UserEventHandler.initializeEventHandlers(root) + stage.setTitle(title) root.getChildren.add(canvas) stage.setScene(new Scene(root)) @@ -71,4 +77,53 @@ case class GameFX() extends CellWorldObjectDrawer { root.getChildren.add(drawInstant(world.instant)) }) } + + /** + * An object that wraps logic behind user events un GUI + * + * @author Enrico Siboni + */ + private object UserEventHandler { + + private var mouseIsDragging = false + + private var startDragPoint: Point = _ + + /** + * A method to initialize event handlers for GUI user actions + * + * @param viewGroup the viewGroup on which to listen for events + */ + def initializeEventHandlers(viewGroup: Group): Unit = { + + viewGroup.addEventHandler(MouseEvent.DRAG_DETECTED, (event: MouseEvent) => { + mouseIsDragging = true + startDragPoint = event + }) + viewGroup.addEventHandler(MouseEvent.MOUSE_RELEASED, (event: MouseEvent) => + if (mouseIsDragging) { + val stopDragPoint: Point = event + // TODO: send a message to GameViewActor + }) + + viewGroup.addEventHandler(MouseEvent.MOUSE_CLICKED, (event: MouseEvent) => + if (mouseIsDragging) { + mouseIsDragging = false + } else { + val clickedPoint: Point = event + // TODO: send a message to GameViewActor + } + ) + } + + /** + * An implicit conversion from mouse event to the point where event was generated + * + * @param event the event to convert + * @return the Point where event was generated + */ + implicit def eventToPoint(event: MouseEvent): Point = + Point(event.getX.toInt, event.getY.toInt) + } + } From 0208de668edd1b7aeb11556db2274477f3bd02c1 Mon Sep 17 00:00:00 2001 From: Enrico Siboni Date: Thu, 26 Jul 2018 11:50:10 +0200 Subject: [PATCH 093/193] Replaced flag management with Option type in UserEventHandler --- .../it/cwmp/client/view/game/GameFX.scala | 21 ++++++++++--------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/client/src/main/scala/it/cwmp/client/view/game/GameFX.scala b/client/src/main/scala/it/cwmp/client/view/game/GameFX.scala index 4da32628..45d5e3b1 100644 --- a/client/src/main/scala/it/cwmp/client/view/game/GameFX.scala +++ b/client/src/main/scala/it/cwmp/client/view/game/GameFX.scala @@ -85,9 +85,7 @@ case class GameFX() extends CellWorldObjectDrawer { */ private object UserEventHandler { - private var mouseIsDragging = false - - private var startDragPoint: Point = _ + private var startDragPoint: Option[Point] = None /** * A method to initialize event handlers for GUI user actions @@ -96,19 +94,22 @@ case class GameFX() extends CellWorldObjectDrawer { */ def initializeEventHandlers(viewGroup: Group): Unit = { - viewGroup.addEventHandler(MouseEvent.DRAG_DETECTED, (event: MouseEvent) => { - mouseIsDragging = true - startDragPoint = event - }) + // start of user dragging + viewGroup.addEventHandler(MouseEvent.DRAG_DETECTED, + (event: MouseEvent) => startDragPoint = Some(event)) + + // stop of user dragging viewGroup.addEventHandler(MouseEvent.MOUSE_RELEASED, (event: MouseEvent) => - if (mouseIsDragging) { + if (startDragPoint.isDefined) { val stopDragPoint: Point = event // TODO: send a message to GameViewActor }) + // user click event viewGroup.addEventHandler(MouseEvent.MOUSE_CLICKED, (event: MouseEvent) => - if (mouseIsDragging) { - mouseIsDragging = false + // if the user was dragging this event is launched after MOUSE_RELEASED + if (startDragPoint.isDefined) { + startDragPoint = None // reset user dragging state } else { val clickedPoint: Point = event // TODO: send a message to GameViewActor From d2072dd5f7dd6a2ba3aba18c1d77a5210ebbe834 Mon Sep 17 00:00:00 2001 From: Enrico Siboni Date: Thu, 26 Jul 2018 12:00:51 +0200 Subject: [PATCH 094/193] Added methods to communicate to GameViewActor --- .../it/cwmp/client/view/game/GameFX.scala | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/client/src/main/scala/it/cwmp/client/view/game/GameFX.scala b/client/src/main/scala/it/cwmp/client/view/game/GameFX.scala index 45d5e3b1..ae7144af 100644 --- a/client/src/main/scala/it/cwmp/client/view/game/GameFX.scala +++ b/client/src/main/scala/it/cwmp/client/view/game/GameFX.scala @@ -1,5 +1,6 @@ package it.cwmp.client.view.game +import akka.actor.ActorRef import it.cwmp.client.model.game.impl.{CellWorld, Point} import it.cwmp.client.view.game.model.CellView._ import it.cwmp.client.view.game.model.TentacleView @@ -117,6 +118,25 @@ case class GameFX() extends CellWorldObjectDrawer { ) } + /** + * A method to send the AddAttack message to provided actor + * + * @param start the start point of the attack + * @param stop the stop point of the attack + * @param actor the actor responsible of this management + */ + private def sendAddAttackEvent(start: Point, stop: Point)(implicit actor: ActorRef): Unit = + actor ! GameViewActor.AddAttack(start, stop) + + /** + * A method to send the RemoveAttack messsage to provided actor + * + * @param onAttackPoint the point on the Attack View to remove + * @param actor the actor responsible of this management + */ + private def sendRemoveAttackEvent(onAttackPoint: Point)(implicit actor: ActorRef): Unit = + actor ! GameViewActor.RemoveAttack(onAttackPoint) + /** * An implicit conversion from mouse event to the point where event was generated * From 42a093872597e7f0746827ffffc139e8d8d22ef7 Mon Sep 17 00:00:00 2001 From: Enrico Siboni Date: Thu, 26 Jul 2018 12:28:08 +0200 Subject: [PATCH 095/193] - Modified GameFx to hold a reference to GameViewActor - Bound actions of user to messages sending --- .../scala/it/cwmp/client/view/game/GameFX.scala | 14 ++++++++------ .../it/cwmp/client/view/game/GameViewActor.scala | 2 +- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/client/src/main/scala/it/cwmp/client/view/game/GameFX.scala b/client/src/main/scala/it/cwmp/client/view/game/GameFX.scala index ae7144af..4d7060c9 100644 --- a/client/src/main/scala/it/cwmp/client/view/game/GameFX.scala +++ b/client/src/main/scala/it/cwmp/client/view/game/GameFX.scala @@ -16,10 +16,11 @@ import scala.language.implicitConversions /** * This class shows the Game GUI * + * @param viewManagerActor the actor that manages view events * @author Davide Borficchia * @author contributor Enrico Siboni */ -case class GameFX() extends CellWorldObjectDrawer { +case class GameFX(viewManagerActor: ActorRef) extends CellWorldObjectDrawer { private var stage: Stage = _ private var root: Group = _ @@ -38,7 +39,7 @@ case class GameFX() extends CellWorldObjectDrawer { root = new Group canvas = new Canvas(size, size) - UserEventHandler.initializeEventHandlers(root) + UserEventHandler.initializeEventHandlers(root, viewManagerActor) stage.setTitle(title) root.getChildren.add(canvas) @@ -87,13 +88,15 @@ case class GameFX() extends CellWorldObjectDrawer { private object UserEventHandler { private var startDragPoint: Option[Point] = None + private implicit var viewActor: ActorRef = _ /** * A method to initialize event handlers for GUI user actions * * @param viewGroup the viewGroup on which to listen for events */ - def initializeEventHandlers(viewGroup: Group): Unit = { + def initializeEventHandlers(viewGroup: Group, viewManagerActor: ActorRef): Unit = { + viewActor = viewManagerActor // start of user dragging viewGroup.addEventHandler(MouseEvent.DRAG_DETECTED, @@ -103,7 +106,7 @@ case class GameFX() extends CellWorldObjectDrawer { viewGroup.addEventHandler(MouseEvent.MOUSE_RELEASED, (event: MouseEvent) => if (startDragPoint.isDefined) { val stopDragPoint: Point = event - // TODO: send a message to GameViewActor + sendAddAttackEvent(startDragPoint.get, stopDragPoint) }) // user click event @@ -112,8 +115,7 @@ case class GameFX() extends CellWorldObjectDrawer { if (startDragPoint.isDefined) { startDragPoint = None // reset user dragging state } else { - val clickedPoint: Point = event - // TODO: send a message to GameViewActor + sendRemoveAttackEvent(event) } ) } diff --git a/client/src/main/scala/it/cwmp/client/view/game/GameViewActor.scala b/client/src/main/scala/it/cwmp/client/view/game/GameViewActor.scala index 441d1e44..2c7b4071 100644 --- a/client/src/main/scala/it/cwmp/client/view/game/GameViewActor.scala +++ b/client/src/main/scala/it/cwmp/client/view/game/GameViewActor.scala @@ -18,7 +18,7 @@ import scala.concurrent.duration._ */ class GameViewActor(parentActor: ActorRef) extends Actor with Logging { - private val gameFX: GameFX = GameFX() + private val gameFX: GameFX = GameFX(self) private val FRAME_RATE: FiniteDuration = 50.millis private var updatingSchedule: Cancellable = _ From 2f491d3e9bc0220b3107914b52af6ab682d9a445 Mon Sep 17 00:00:00 2001 From: Enrico Siboni Date: Thu, 26 Jul 2018 12:33:25 +0200 Subject: [PATCH 096/193] Removed useless variable --- .../main/scala/it/cwmp/client/view/game/GameFX.scala | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/client/src/main/scala/it/cwmp/client/view/game/GameFX.scala b/client/src/main/scala/it/cwmp/client/view/game/GameFX.scala index 4d7060c9..0131eea7 100644 --- a/client/src/main/scala/it/cwmp/client/view/game/GameFX.scala +++ b/client/src/main/scala/it/cwmp/client/view/game/GameFX.scala @@ -88,7 +88,6 @@ case class GameFX(viewManagerActor: ActorRef) extends CellWorldObjectDrawer { private object UserEventHandler { private var startDragPoint: Option[Point] = None - private implicit var viewActor: ActorRef = _ /** * A method to initialize event handlers for GUI user actions @@ -96,7 +95,6 @@ case class GameFX(viewManagerActor: ActorRef) extends CellWorldObjectDrawer { * @param viewGroup the viewGroup on which to listen for events */ def initializeEventHandlers(viewGroup: Group, viewManagerActor: ActorRef): Unit = { - viewActor = viewManagerActor // start of user dragging viewGroup.addEventHandler(MouseEvent.DRAG_DETECTED, @@ -106,7 +104,7 @@ case class GameFX(viewManagerActor: ActorRef) extends CellWorldObjectDrawer { viewGroup.addEventHandler(MouseEvent.MOUSE_RELEASED, (event: MouseEvent) => if (startDragPoint.isDefined) { val stopDragPoint: Point = event - sendAddAttackEvent(startDragPoint.get, stopDragPoint) + sendAddAttackEvent(startDragPoint.get, stopDragPoint, viewManagerActor) }) // user click event @@ -115,7 +113,7 @@ case class GameFX(viewManagerActor: ActorRef) extends CellWorldObjectDrawer { if (startDragPoint.isDefined) { startDragPoint = None // reset user dragging state } else { - sendRemoveAttackEvent(event) + sendRemoveAttackEvent(event, viewManagerActor) } ) } @@ -127,7 +125,7 @@ case class GameFX(viewManagerActor: ActorRef) extends CellWorldObjectDrawer { * @param stop the stop point of the attack * @param actor the actor responsible of this management */ - private def sendAddAttackEvent(start: Point, stop: Point)(implicit actor: ActorRef): Unit = + private def sendAddAttackEvent(start: Point, stop: Point, actor: ActorRef): Unit = actor ! GameViewActor.AddAttack(start, stop) /** @@ -136,7 +134,7 @@ case class GameFX(viewManagerActor: ActorRef) extends CellWorldObjectDrawer { * @param onAttackPoint the point on the Attack View to remove * @param actor the actor responsible of this management */ - private def sendRemoveAttackEvent(onAttackPoint: Point)(implicit actor: ActorRef): Unit = + private def sendRemoveAttackEvent(onAttackPoint: Point, actor: ActorRef): Unit = actor ! GameViewActor.RemoveAttack(onAttackPoint) /** From e35e4d1a46581d3b59c0587380e68ea757cb4ff8 Mon Sep 17 00:00:00 2001 From: Enrico Siboni Date: Thu, 26 Jul 2018 14:42:11 +0200 Subject: [PATCH 097/193] Added Check if attack is being made from one cell to same cell --- .../main/scala/it/cwmp/client/view/game/GameViewActor.scala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/src/main/scala/it/cwmp/client/view/game/GameViewActor.scala b/client/src/main/scala/it/cwmp/client/view/game/GameViewActor.scala index 2c7b4071..cceaa2cf 100644 --- a/client/src/main/scala/it/cwmp/client/view/game/GameViewActor.scala +++ b/client/src/main/scala/it/cwmp/client/view/game/GameViewActor.scala @@ -67,10 +67,10 @@ class GameViewActor(parentActor: ActorRef) extends Actor with Logging { val fromCell = findCellNearTo(from, worldCharacters) val toCell = findCellNearTo(to, worldCharacters) (fromCell, toCell) match { - case (Some(attacker), Some(attacked)) => + case (Some(attacker), Some(attacked)) if attacker != attacked => log.debug(s"Adding attack from $attacker to $attacked ...") parentActor ! DistributedState.UpdateState(tempWorld ++ Tentacle(attacker, attacked, tempWorld.instant)) - case tmp@_ => log.debug(s"No cells detected $tmp") + case tmp@_ => log.debug(s"No cells detected or auto-attack $tmp") } case RemoveAttack(pointOnAttackView) => From 373839ef490c50f8554c7b03711226cfeb5a78aa Mon Sep 17 00:00:00 2001 From: Enrico Siboni Date: Thu, 26 Jul 2018 14:49:10 +0200 Subject: [PATCH 098/193] Further separated GameViewActor behaviours --- .../it/cwmp/client/view/game/GameViewActor.scala | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/client/src/main/scala/it/cwmp/client/view/game/GameViewActor.scala b/client/src/main/scala/it/cwmp/client/view/game/GameViewActor.scala index cceaa2cf..d3cf38ea 100644 --- a/client/src/main/scala/it/cwmp/client/view/game/GameViewActor.scala +++ b/client/src/main/scala/it/cwmp/client/view/game/GameViewActor.scala @@ -32,7 +32,8 @@ class GameViewActor(parentActor: ActorRef) extends Actor with Logging { private def showGUIBehaviour: Receive = { case ShowGUI => gameFX.start(VIEW_TITLE, VIEW_SIZE) - context.become(hideGUIBehaviour orElse worldModificationsBehaviour) + context.become(hideGUIBehaviour orElse + newWorldBehaviour orElse guiWorldModificationsBehaviour) } /** @@ -45,9 +46,9 @@ class GameViewActor(parentActor: ActorRef) extends Actor with Logging { } /** - * The behaviour of receiving and sending world modifications + * The behaviour of receiving world modifications from external source */ - private def worldModificationsBehaviour: Receive = { + private def newWorldBehaviour: Receive = { case NewWorld(world) => if (updatingSchedule != null) updatingSchedule.cancel() tempWorld = world @@ -60,7 +61,12 @@ class GameViewActor(parentActor: ActorRef) extends Actor with Logging { // is that to heavy computation here ??? tempWorld = GameEngine(tempWorld, java.time.Duration.ofMillis(FRAME_RATE.toMillis)) + } + /** + * The behaviour of listening for user events on GUI + */ + private def guiWorldModificationsBehaviour: Receive = { case AddAttack(from, to) => log.info(s"AddAttack from:$from to:$to") val worldCharacters = tempWorld.characters From 3610e4a2b7cb47646b419f06b82c5acdec1fc29b Mon Sep 17 00:00:00 2001 From: Enrico Siboni Date: Thu, 26 Jul 2018 15:07:11 +0200 Subject: [PATCH 099/193] - Re-enabled flag management in GameFx UserEventHandler - Now it listens to Mouse_Pressed event to solve cases where user is to fast and DRAG_DETECTED event comes late --- .../scala/it/cwmp/client/view/game/GameFX.scala | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/client/src/main/scala/it/cwmp/client/view/game/GameFX.scala b/client/src/main/scala/it/cwmp/client/view/game/GameFX.scala index 0131eea7..ab7b95a4 100644 --- a/client/src/main/scala/it/cwmp/client/view/game/GameFX.scala +++ b/client/src/main/scala/it/cwmp/client/view/game/GameFX.scala @@ -87,7 +87,8 @@ case class GameFX(viewManagerActor: ActorRef) extends CellWorldObjectDrawer { */ private object UserEventHandler { - private var startDragPoint: Option[Point] = None + private var mouseIsDragging = false + private var startDragPoint: Point = _ /** * A method to initialize event handlers for GUI user actions @@ -96,22 +97,24 @@ case class GameFX(viewManagerActor: ActorRef) extends CellWorldObjectDrawer { */ def initializeEventHandlers(viewGroup: Group, viewManagerActor: ActorRef): Unit = { + // user pressed mouse + viewGroup.addEventHandler(MouseEvent.MOUSE_PRESSED, (event: MouseEvent) => startDragPoint = event) + // start of user dragging - viewGroup.addEventHandler(MouseEvent.DRAG_DETECTED, - (event: MouseEvent) => startDragPoint = Some(event)) + viewGroup.addEventHandler(MouseEvent.DRAG_DETECTED, (_: MouseEvent) => mouseIsDragging = true) // stop of user dragging viewGroup.addEventHandler(MouseEvent.MOUSE_RELEASED, (event: MouseEvent) => - if (startDragPoint.isDefined) { + if (mouseIsDragging) { val stopDragPoint: Point = event - sendAddAttackEvent(startDragPoint.get, stopDragPoint, viewManagerActor) + sendAddAttackEvent(startDragPoint, stopDragPoint, viewManagerActor) }) // user click event viewGroup.addEventHandler(MouseEvent.MOUSE_CLICKED, (event: MouseEvent) => // if the user was dragging this event is launched after MOUSE_RELEASED - if (startDragPoint.isDefined) { - startDragPoint = None // reset user dragging state + if (mouseIsDragging) { + mouseIsDragging = false // reset user dragging state } else { sendRemoveAttackEvent(event, viewManagerActor) } From 3f5d6bef616bb0759c54eeb27bc1135a2dd4f479 Mon Sep 17 00:00:00 2001 From: Enrico Siboni Date: Thu, 26 Jul 2018 16:33:02 +0200 Subject: [PATCH 100/193] Solved a BUG that made not possible to use RoomService: - Modified AuthenticationApiWrapper to take in input an authentication header to validate (this way Rooms have not to know how authentication header has been built) - Added an implicit method to addAuthenticationHeader to a request in VertxClient - Renamed methods and variables with proper names in VertxServer - Modified AuthenticationApiWrapperTest to test a real situation - Cleaned code --- .../wrapper/AuthenticationApiWrapper.scala | 6 ++--- .../scala/it/cwmp/utils/VertxClient.scala | 23 +++++++++++++++++-- .../scala/it/cwmp/utils/VertxServer.scala | 8 +++---- .../AuthenticationApiWrapperTest.scala | 18 +++++++-------- .../wrapper/RoomsApiWrapperTest.scala | 3 ++- .../AuthenticationLocalDAO.scala | 4 +--- .../AuthenticationServiceVerticle.scala | 8 +++---- .../AuthenticationServiceVerticleTest.scala | 4 ++-- .../AuthenticationTesting.scala | 8 +++---- 9 files changed, 50 insertions(+), 32 deletions(-) diff --git a/core/src/main/scala/it/cwmp/services/wrapper/AuthenticationApiWrapper.scala b/core/src/main/scala/it/cwmp/services/wrapper/AuthenticationApiWrapper.scala index 0643991a..b4def384 100644 --- a/core/src/main/scala/it/cwmp/services/wrapper/AuthenticationApiWrapper.scala +++ b/core/src/main/scala/it/cwmp/services/wrapper/AuthenticationApiWrapper.scala @@ -57,14 +57,14 @@ object AuthenticationApiWrapper { .expectStatus(200) .map(_.bodyAsString().getOrElse("")) - override def validate(token: String): Future[User] = + override def validate(authenticationHeader: String): Future[User] ={ client.get(API_VALIDATE) - .addAuthentication(token) + .addAuthenticationHeader(authenticationHeader) .sendFuture() .expectStatus(200) .mapBody { case Some(body) => Future.successful(User(body)) - case _ => Future.failed(HTTPException(400, "Empty body")) + case _ => Future.failed(HTTPException(400, "Empty body"))} } } diff --git a/core/src/main/scala/it/cwmp/utils/VertxClient.scala b/core/src/main/scala/it/cwmp/utils/VertxClient.scala index 2d180f57..a94f34e2 100644 --- a/core/src/main/scala/it/cwmp/utils/VertxClient.scala +++ b/core/src/main/scala/it/cwmp/utils/VertxClient.scala @@ -65,7 +65,7 @@ trait VertxClient { */ def addAuthentication(username: String, password: String): HttpRequest[T] = HttpUtils.buildBasicAuthentication(username, password) - .map(request.putHeader(HttpHeaderNames.AUTHORIZATION.toString, _)) + .map(putRequestAuthorizationHeader(request, _)) .getOrElse(request) /** @@ -76,8 +76,27 @@ trait VertxClient { */ def addAuthentication(implicit token: String): HttpRequest[T] = HttpUtils.buildJwtAuthentication(token) - .map(request.putHeader(HttpHeaderNames.AUTHORIZATION.toString, _)) + .map(putRequestAuthorizationHeader(request, _)) .getOrElse(request) + + /** + * Simplified way to add an authorization header as is in request + * + * @param authenticationHeader the authorization header to add as is + * @return the same [[HttpRequest]] enriched, with the authorization header + */ + def addAuthenticationHeader(implicit authenticationHeader: String): HttpRequest[T] = + putRequestAuthorizationHeader(request, authenticationHeader) + + /** + * Utility mthod to put the authorization header in request + * + * @param request the request + * @param authorizationHeader the authorization header to put + * @return the request with provided header + */ + private def putRequestAuthorizationHeader(request: HttpRequest[T], authorizationHeader: String): HttpRequest[T] = + request.putHeader(HttpHeaderNames.AUTHORIZATION.toString, authorizationHeader) } /** diff --git a/core/src/main/scala/it/cwmp/utils/VertxServer.scala b/core/src/main/scala/it/cwmp/utils/VertxServer.scala index 77ccc355..9cbc0d2d 100644 --- a/core/src/main/scala/it/cwmp/utils/VertxServer.scala +++ b/core/src/main/scala/it/cwmp/utils/VertxServer.scala @@ -114,11 +114,11 @@ trait VertxServer extends ScalaVerticle { * @return A future containing the authenticated user, if present, otherwise it fails with a [[HTTPException]] */ def checkAuthentication(implicit strategy: Validation[String, User], - routingContext: RoutingContext): Future[User] = getAuthentication match { + routingContext: RoutingContext): Future[User] = getAuthenticationHeader match { case None => log.warn(NO_AUTH_HEADER_IN_REQUEST_ERROR) Future.failed(HTTPException(400, NO_AUTH_HEADER_IN_REQUEST_ERROR)) - case Some(authentication) => strategy.validate(authentication) + case Some(authenticationHeader) => strategy.validate(authenticationHeader) } /** @@ -140,11 +140,11 @@ trait VertxServer extends ScalaVerticle { } /** - * Reads the authorization token in the request. + * Reads the authorization header (with token) in the request. * * @return An optional containing the header, if present. Otherwise None */ - def getAuthentication: Option[String] = request.getHeader(HttpHeaderNames.AUTHORIZATION.toString) + def getAuthenticationHeader: Option[String] = request.getHeader(HttpHeaderNames.AUTHORIZATION.toString) } } diff --git a/core/src/test/scala/it/cwmp/services/wrapper/AuthenticationApiWrapperTest.scala b/core/src/test/scala/it/cwmp/services/wrapper/AuthenticationApiWrapperTest.scala index 252ef521..b99248e9 100644 --- a/core/src/test/scala/it/cwmp/services/wrapper/AuthenticationApiWrapperTest.scala +++ b/core/src/test/scala/it/cwmp/services/wrapper/AuthenticationApiWrapperTest.scala @@ -2,7 +2,7 @@ package it.cwmp.services.wrapper import it.cwmp.exceptions.HTTPException import it.cwmp.services.testing.authentication.AuthenticationWebServiceTesting -import it.cwmp.utils.Utils +import it.cwmp.utils.{HttpUtils, Utils} import scala.concurrent.Promise import scala.util.Failure @@ -14,8 +14,8 @@ class AuthenticationApiWrapperTest extends AuthenticationWebServiceTesting { private val auth = AuthenticationApiWrapper() - override protected def singupTests(): Unit = { - it("when right should succed") { + override protected def singUpTests(): Unit = { + it("when right should succeed") { val username = nextUsername val password = nextPassword @@ -38,12 +38,12 @@ class AuthenticationApiWrapperTest extends AuthenticationWebServiceTesting { } } - override protected def signoutTests(): Unit = { + override protected def signOutTests(): Unit = { // TODO implementation } override protected def loginTests(): Unit = { - it("when right should succed") { + it("when right should succeed") { val username = nextUsername val password = nextPassword @@ -68,7 +68,7 @@ class AuthenticationApiWrapperTest extends AuthenticationWebServiceTesting { it("when password is wrong should fail") { val username = nextUsername val password = nextPassword - val passwordWrong = Utils.randomString(10) + val passwordWrong = nextPassword val promiseResult: Promise[Unit] = Promise() auth.signUp(username, password) @@ -82,12 +82,12 @@ class AuthenticationApiWrapperTest extends AuthenticationWebServiceTesting { } override protected def validationTests(): Unit = { - it("when right should succed") { + it("when right should succeed") { val username = nextUsername val password = nextPassword auth.signUp(username, password) - .flatMap(token => auth.validate(token)) + .flatMap(token => auth.validate(HttpUtils.buildJwtAuthentication(token).get)) .map(user => assert(user.username == username)) } @@ -107,7 +107,7 @@ class AuthenticationApiWrapperTest extends AuthenticationWebServiceTesting { val myToken = nextToken val promiseResult: Promise[Unit] = Promise() - auth.validate(myToken) + auth.validate(HttpUtils.buildJwtAuthentication(myToken).get) .onComplete({ case Failure(HTTPException(statusCode, _)) if statusCode == 401 => promiseResult.success(Unit) case _ => promiseResult.failure(new Exception) diff --git a/core/src/test/scala/it/cwmp/services/wrapper/RoomsApiWrapperTest.scala b/core/src/test/scala/it/cwmp/services/wrapper/RoomsApiWrapperTest.scala index 7853522c..d7e487f3 100644 --- a/core/src/test/scala/it/cwmp/services/wrapper/RoomsApiWrapperTest.scala +++ b/core/src/test/scala/it/cwmp/services/wrapper/RoomsApiWrapperTest.scala @@ -17,6 +17,7 @@ class RoomsApiWrapperTest extends RoomsWebServiceTesting with FutureMatchers { private val apiWrapper = RoomsApiWrapper() + //noinspection ScalaStyle import apiWrapper._ override protected def privateRoomCreationTests(roomName: String, playersNumber: Int): Unit = { @@ -162,7 +163,7 @@ class RoomsApiWrapperTest extends RoomsWebServiceTesting with FutureMatchers { apiCall(0).shouldFailWith[HTTPException] } it("if room with such players number doesn't exist") { - apiCall(20).shouldFailWith[HTTPException] + apiCall(TOO_BIG_PLAYERS_NUMBER).shouldFailWith[HTTPException] } } diff --git a/services/authentication/src/main/scala/it/cwmp/services/authentication/AuthenticationLocalDAO.scala b/services/authentication/src/main/scala/it/cwmp/services/authentication/AuthenticationLocalDAO.scala index 6127085d..958acd7b 100644 --- a/services/authentication/src/main/scala/it/cwmp/services/authentication/AuthenticationLocalDAO.scala +++ b/services/authentication/src/main/scala/it/cwmp/services/authentication/AuthenticationLocalDAO.scala @@ -80,9 +80,7 @@ case class AuthenticationLocalDAO(override val configurationPath: String = "auth connection <- openConnection(); _ <- connection.updateWithParamsFuture( insertNewUserSql, Seq(username, password, "SALT")) - ) yield { - log.debug("inizialized") - }).closeConnections + ) yield ()).closeConnections }).getOrElse(Future.failed(new IllegalArgumentException())) } diff --git a/services/authentication/src/main/scala/it/cwmp/services/authentication/AuthenticationServiceVerticle.scala b/services/authentication/src/main/scala/it/cwmp/services/authentication/AuthenticationServiceVerticle.scala index d439349d..55b50769 100644 --- a/services/authentication/src/main/scala/it/cwmp/services/authentication/AuthenticationServiceVerticle.scala +++ b/services/authentication/src/main/scala/it/cwmp/services/authentication/AuthenticationServiceVerticle.scala @@ -33,7 +33,7 @@ case class AuthenticationServiceVerticle() extends VertxServer with Logging { private def handlerSignUp: Handler[RoutingContext] = implicit routingContext => { log.debug("Received sign up request.") (for ( - authorizationHeader <- request.getAuthentication; + authorizationHeader <- request.getAuthenticationHeader; (username, password) <- HttpUtils.readBasicAuthentication(authorizationHeader) ) yield { storageFuture flatMap (_.signUpFuture(username, password)) onComplete { @@ -50,7 +50,7 @@ case class AuthenticationServiceVerticle() extends VertxServer with Logging { private def handlerSignOut: Handler[RoutingContext] = implicit routingContext => { log.debug("Received sign out request.") (for ( - authorizationHeader <- request.getAuthentication; + authorizationHeader <- request.getAuthenticationHeader; token <- HttpUtils.readJwtAuthentication(authorizationHeader); username <- JwtUtils.decodeUsernameToken(token) ) yield { @@ -67,7 +67,7 @@ case class AuthenticationServiceVerticle() extends VertxServer with Logging { private def handlerLogin: Handler[RoutingContext] = implicit routingContext => { log.debug("Received login request.") (for ( - authorizationHeader <- request.getAuthentication; + authorizationHeader <- request.getAuthenticationHeader; (username, password) <- HttpUtils.readBasicAuthentication(authorizationHeader) ) yield { storageFuture flatMap (_.loginFuture(username, password)) onComplete { @@ -84,7 +84,7 @@ case class AuthenticationServiceVerticle() extends VertxServer with Logging { private def handlerValidation: Handler[RoutingContext] = implicit routingContext => { log.debug("Received token validation request.") (for ( - authorizationHeader <- request.getAuthentication; + authorizationHeader <- request.getAuthenticationHeader; token <- HttpUtils.readJwtAuthentication(authorizationHeader); username <- JwtUtils.decodeUsernameToken(token) ) yield { diff --git a/services/authentication/src/test/scala/it/cwmp/services/authentication/AuthenticationServiceVerticleTest.scala b/services/authentication/src/test/scala/it/cwmp/services/authentication/AuthenticationServiceVerticleTest.scala index 43e62789..98fadf33 100644 --- a/services/authentication/src/test/scala/it/cwmp/services/authentication/AuthenticationServiceVerticleTest.scala +++ b/services/authentication/src/test/scala/it/cwmp/services/authentication/AuthenticationServiceVerticleTest.scala @@ -17,7 +17,7 @@ class AuthenticationServiceVerticleTest extends AuthenticationWebServiceTesting .setDefaultPort(DEFAULT_PORT) .setKeepAlive(false) - override protected def singupTests(): Unit = { + override protected def singUpTests(): Unit = { it("when right should succed") { val username = nextUsername val password = nextPassword @@ -57,7 +57,7 @@ class AuthenticationServiceVerticleTest extends AuthenticationWebServiceTesting } } - override protected def signoutTests(): Unit = { + override protected def signOutTests(): Unit = { // TODO implement } diff --git a/services/authentication/src/test/scala/it/cwmp/services/testing/authentication/AuthenticationTesting.scala b/services/authentication/src/test/scala/it/cwmp/services/testing/authentication/AuthenticationTesting.scala index 8f85f81d..6dd4dd1b 100644 --- a/services/authentication/src/test/scala/it/cwmp/services/testing/authentication/AuthenticationTesting.scala +++ b/services/authentication/src/test/scala/it/cwmp/services/testing/authentication/AuthenticationTesting.scala @@ -30,16 +30,16 @@ abstract class AuthenticationTesting extends VertxTest with Matchers { protected val invalidToken: String = "INVALID" - protected def singupTests() + protected def singUpTests() describe("Sign up") { - singupTests() + singUpTests() } - protected def signoutTests() + protected def signOutTests() describe("Sign out") { - signoutTests() + signOutTests() } protected def loginTests() From 62a4bd17e50636c975d27941e06fe4982420486b Mon Sep 17 00:00:00 2001 From: Enrico Siboni Date: Thu, 26 Jul 2018 16:34:43 +0200 Subject: [PATCH 101/193] Removed unused import --- .../it/cwmp/services/wrapper/AuthenticationApiWrapperTest.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/test/scala/it/cwmp/services/wrapper/AuthenticationApiWrapperTest.scala b/core/src/test/scala/it/cwmp/services/wrapper/AuthenticationApiWrapperTest.scala index b99248e9..bbd21955 100644 --- a/core/src/test/scala/it/cwmp/services/wrapper/AuthenticationApiWrapperTest.scala +++ b/core/src/test/scala/it/cwmp/services/wrapper/AuthenticationApiWrapperTest.scala @@ -2,7 +2,7 @@ package it.cwmp.services.wrapper import it.cwmp.exceptions.HTTPException import it.cwmp.services.testing.authentication.AuthenticationWebServiceTesting -import it.cwmp.utils.{HttpUtils, Utils} +import it.cwmp.utils.HttpUtils import scala.concurrent.Promise import scala.util.Failure From 5fe2e402a9f0e6aafdaf0e3fbc1d588081db67a6 Mon Sep 17 00:00:00 2001 From: Enrico Siboni Date: Thu, 26 Jul 2018 16:47:24 +0200 Subject: [PATCH 102/193] Added a better error message in VertxClient --- .../it/cwmp/services/wrapper/AuthenticationApiWrapper.scala | 4 ++-- core/src/main/scala/it/cwmp/utils/VertxClient.scala | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/core/src/main/scala/it/cwmp/services/wrapper/AuthenticationApiWrapper.scala b/core/src/main/scala/it/cwmp/services/wrapper/AuthenticationApiWrapper.scala index b4def384..d67d246a 100644 --- a/core/src/main/scala/it/cwmp/services/wrapper/AuthenticationApiWrapper.scala +++ b/core/src/main/scala/it/cwmp/services/wrapper/AuthenticationApiWrapper.scala @@ -57,14 +57,14 @@ object AuthenticationApiWrapper { .expectStatus(200) .map(_.bodyAsString().getOrElse("")) - override def validate(authenticationHeader: String): Future[User] ={ + override def validate(authenticationHeader: String): Future[User] = client.get(API_VALIDATE) .addAuthenticationHeader(authenticationHeader) .sendFuture() .expectStatus(200) .mapBody { case Some(body) => Future.successful(User(body)) - case _ => Future.failed(HTTPException(400, "Empty body"))} + case _ => Future.failed(HTTPException(400, "Empty body")) } } diff --git a/core/src/main/scala/it/cwmp/utils/VertxClient.scala b/core/src/main/scala/it/cwmp/utils/VertxClient.scala index a94f34e2..6ad2b68d 100644 --- a/core/src/main/scala/it/cwmp/utils/VertxClient.scala +++ b/core/src/main/scala/it/cwmp/utils/VertxClient.scala @@ -113,7 +113,7 @@ trait VertxClient { def expectStatus(statusCode: Int*): Future[HttpResponse[T]] = { response.transform { case s@Success(res) if statusCode.contains(res.statusCode()) => s - case Success(res) => Failure(HTTPException(res.statusCode(), "Invalid response code")) + case Success(res) => Failure(HTTPException(res.statusCode(), s"Error code: ${res.statusCode()}")) case f@Failure(_) => f } } From 0f380011c004ce5d95c53a86d7f66230a2a856ac Mon Sep 17 00:00:00 2001 From: Enrico Siboni Date: Thu, 26 Jul 2018 16:55:13 +0200 Subject: [PATCH 103/193] Modified AuthenticationApiWrapper to have a method nextHeader that returns an authentication header --- .../wrapper/AuthenticationApiWrapperTest.scala | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/core/src/test/scala/it/cwmp/services/wrapper/AuthenticationApiWrapperTest.scala b/core/src/test/scala/it/cwmp/services/wrapper/AuthenticationApiWrapperTest.scala index bbd21955..a365f867 100644 --- a/core/src/test/scala/it/cwmp/services/wrapper/AuthenticationApiWrapperTest.scala +++ b/core/src/test/scala/it/cwmp/services/wrapper/AuthenticationApiWrapperTest.scala @@ -14,6 +14,11 @@ class AuthenticationApiWrapperTest extends AuthenticationWebServiceTesting { private val auth = AuthenticationApiWrapper() + /** + * @return a new authentication header with a token + */ + protected def nextHeader: String = HttpUtils.buildJwtAuthentication(super.nextToken).get + override protected def singUpTests(): Unit = { it("when right should succeed") { val username = nextUsername @@ -103,11 +108,11 @@ class AuthenticationApiWrapperTest extends AuthenticationWebServiceTesting { promiseResult.future.map(_ => succeed) } - it("when unauthorized token should fail") { - val myToken = nextToken + it("when unauthorized header should fail") { + val myAuthHeader = nextHeader val promiseResult: Promise[Unit] = Promise() - auth.validate(HttpUtils.buildJwtAuthentication(myToken).get) + auth.validate(myAuthHeader) .onComplete({ case Failure(HTTPException(statusCode, _)) if statusCode == 401 => promiseResult.success(Unit) case _ => promiseResult.failure(new Exception) From b096bb117c836e99633aff7a3f9ad73d4bc08e6a Mon Sep 17 00:00:00 2001 From: Enrico Siboni Date: Thu, 26 Jul 2018 17:57:20 +0200 Subject: [PATCH 104/193] - Removed useless parameter in DistributeState and its subclass - Added an unsubscribe method in DistributedState - Player actor wasn't subscribed to distributed state, now it is --- .../cwmp/client/model/DistributedState.scala | 21 ++++++++++++------- .../it/cwmp/client/model/PlayerActor.scala | 8 +++++-- .../game/impl/CellWorldDistributedState.scala | 4 ++-- 3 files changed, 22 insertions(+), 11 deletions(-) diff --git a/client/src/main/scala/it/cwmp/client/model/DistributedState.scala b/client/src/main/scala/it/cwmp/client/model/DistributedState.scala index f4688b14..6a8af17d 100644 --- a/client/src/main/scala/it/cwmp/client/model/DistributedState.scala +++ b/client/src/main/scala/it/cwmp/client/model/DistributedState.scala @@ -11,11 +11,11 @@ import it.cwmp.utils.Logging /** * Distributed representation of data and attached behaviours. * - * @param onWorldUpdate the update strategy when the world is changed + * @param onDistributedStateUpdate the update strategy when the world is changed * @author Eugenio Pierfederici * @author contributor Enrico Siboni */ -abstract class DistributedState[T](updateSubscriber: ActorRef, onWorldUpdate: T => Unit) +abstract class DistributedState[T](onDistributedStateUpdate: T => Unit) (implicit replicatorActor: ActorRef, cluster: Cluster) extends Logging { protected val DistributedKey: LWWRegisterKey[T] = LWWRegisterKey[T](DISTRIBUTED_KEY_NAME) @@ -23,11 +23,18 @@ abstract class DistributedState[T](updateSubscriber: ActorRef, onWorldUpdate: T /** * Subscribes the provided actor to receive changes in this distributed state * - * @param actorRef the actor to subscribe + * @param subscriber the actor to subscribe */ - def subscribe(actorRef: ActorRef): Unit = { - replicatorActor ! Subscribe(DistributedKey, actorRef) - } + def subscribe(subscriber: ActorRef): Unit = + replicatorActor ! Subscribe(DistributedKey, subscriber) + + /** + * Un-subscribes the provided actor from updates of this distributed state + * + * @param subscriber the exiting subscriber + */ + def unsubscribe(subscriber: ActorRef): Unit = + replicatorActor ! Unsubscribe(DistributedKey, subscriber) /** * This behaviour provides an easy way to make the interested actor, @@ -42,7 +49,7 @@ abstract class DistributedState[T](updateSubscriber: ActorRef, onWorldUpdate: T // Called when notified of the distributed data change case c@Changed(DistributedKey) => log.debug("Being notified that distributed state has changed") - onWorldUpdate(c.get(DistributedKey).getValue) + onDistributedStateUpdate(c.get(DistributedKey).getValue) } /** diff --git a/client/src/main/scala/it/cwmp/client/model/PlayerActor.scala b/client/src/main/scala/it/cwmp/client/model/PlayerActor.scala index a353898c..f7c507ea 100644 --- a/client/src/main/scala/it/cwmp/client/model/PlayerActor.scala +++ b/client/src/main/scala/it/cwmp/client/model/PlayerActor.scala @@ -33,7 +33,7 @@ class PlayerActor(system: ActorSystem) extends Actor with Logging { // Distributed world private val distributedState: DistributedState[CellWorld] = - CellWorldDistributedState(self, onWorldUpdatedAction)(replicator, cluster) + CellWorldDistributedState(onWorldUpdatedAction)(replicator, cluster) override def preStart(): Unit = { log.info(s"Initializing the game-view actor...") @@ -41,9 +41,13 @@ class PlayerActor(system: ActorSystem) extends Actor with Logging { log.info(s"Subscribing to cluster changes...") cluster.subscribe(self, initialStateMode = InitialStateAsEvents, classOf[MemberEvent], classOf[UnreachableMember]) + distributedState.subscribe(self) } - override def postStop(): Unit = cluster.unsubscribe(self) + override def postStop(): Unit = { + cluster.unsubscribe(self) + distributedState.unsubscribe(self) + } override def receive: Receive = clusterBehaviour orElse lobbyBehaviour diff --git a/client/src/main/scala/it/cwmp/client/model/game/impl/CellWorldDistributedState.scala b/client/src/main/scala/it/cwmp/client/model/game/impl/CellWorldDistributedState.scala index 56593cf5..aa850182 100644 --- a/client/src/main/scala/it/cwmp/client/model/game/impl/CellWorldDistributedState.scala +++ b/client/src/main/scala/it/cwmp/client/model/game/impl/CellWorldDistributedState.scala @@ -14,8 +14,8 @@ import it.cwmp.client.model.DistributedState.UpdateState * @author Eugenio Pierfederici * @author contributor Enrico Siboni */ -case class CellWorldDistributedState(updateSubscriber: ActorRef, onWorldUpdate: CellWorld => Unit)(implicit replicatorActor: ActorRef, cluster: Cluster) - extends DistributedState[CellWorld](updateSubscriber, onWorldUpdate) { +case class CellWorldDistributedState(onWorldUpdate: CellWorld => Unit) + (implicit replicatorActor: ActorRef, cluster: Cluster) extends DistributedState[CellWorld](onWorldUpdate) { override def consistencyPolicy: Replicator.WriteConsistency = WriteLocal From 4dca5e3ea0f80a7b22717ea212f638beb6388c1f Mon Sep 17 00:00:00 2001 From: Enrico Siboni Date: Thu, 26 Jul 2018 18:23:51 +0200 Subject: [PATCH 105/193] Solved a bug in TentacleView --- .../it/cwmp/client/view/game/model/TentacleView.scala | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/client/src/main/scala/it/cwmp/client/view/game/model/TentacleView.scala b/client/src/main/scala/it/cwmp/client/view/game/model/TentacleView.scala index 2e3d7cd7..f657bbaf 100644 --- a/client/src/main/scala/it/cwmp/client/view/game/model/TentacleView.scala +++ b/client/src/main/scala/it/cwmp/client/view/game/model/TentacleView.scala @@ -65,8 +65,11 @@ object TentacleView { * @return the point that the tentacle has reached going towards enemy cell */ def reachedPoint(tentacle: Tentacle, actualInstant: Instant): Point = { - if (tentacle.hasReachedDestinationFor(actualInstant) == Duration.ZERO) { - val tentacleActualLength = tentacle.length(actualInstant) + val tentacleActualLength = tentacle.length(actualInstant) + + if (tentacleActualLength == 0) { + tentacle.from.position + } else if (tentacle.hasReachedDestinationFor(actualInstant) == Duration.ZERO) { val attackerPosition = tentacle.from.position val deltaXYFromAttackerPosition = GeometricUtils.deltaXYFromFirstPoint(attackerPosition, tentacle.to.position, tentacleActualLength) Point(attackerPosition.x + deltaXYFromAttackerPosition._1.toInt, From 2440b1c5375c39bc56db0f131dea42f380ee939e Mon Sep 17 00:00:00 2001 From: Enrico Siboni Date: Thu, 26 Jul 2018 18:32:38 +0200 Subject: [PATCH 106/193] Now there's better synchronization between games because of the WriteConsistency changed to WriteMajority --- .../client/model/game/impl/CellWorldDistributedState.scala | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/client/src/main/scala/it/cwmp/client/model/game/impl/CellWorldDistributedState.scala b/client/src/main/scala/it/cwmp/client/model/game/impl/CellWorldDistributedState.scala index aa850182..cb143125 100644 --- a/client/src/main/scala/it/cwmp/client/model/game/impl/CellWorldDistributedState.scala +++ b/client/src/main/scala/it/cwmp/client/model/game/impl/CellWorldDistributedState.scala @@ -3,11 +3,13 @@ package it.cwmp.client.model.game.impl import akka.actor.Actor.Receive import akka.actor.ActorRef import akka.cluster.Cluster -import akka.cluster.ddata.Replicator.{Update, WriteLocal} +import akka.cluster.ddata.Replicator.{Update, WriteMajority} import akka.cluster.ddata.{LWWRegister, Replicator} import it.cwmp.client.model.DistributedState import it.cwmp.client.model.DistributedState.UpdateState +import scala.concurrent.duration._ + /** * Distributed representation of the world and of his behaviours. * @@ -17,7 +19,7 @@ import it.cwmp.client.model.DistributedState.UpdateState case class CellWorldDistributedState(onWorldUpdate: CellWorld => Unit) (implicit replicatorActor: ActorRef, cluster: Cluster) extends DistributedState[CellWorld](onWorldUpdate) { - override def consistencyPolicy: Replicator.WriteConsistency = WriteLocal + override def consistencyPolicy: Replicator.WriteConsistency = WriteMajority(1.seconds) override protected def activeBehaviour: Receive = { case UpdateState(state: CellWorld) => From ed7a68317688c2addcbaab12009a944939751c9e Mon Sep 17 00:00:00 2001 From: Enrico Siboni Date: Thu, 26 Jul 2018 18:38:24 +0200 Subject: [PATCH 107/193] Augmented time between game frames, so it's now more lightweight to compute --- .../main/scala/it/cwmp/client/view/game/GameViewActor.scala | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/client/src/main/scala/it/cwmp/client/view/game/GameViewActor.scala b/client/src/main/scala/it/cwmp/client/view/game/GameViewActor.scala index d3cf38ea..768ef2bd 100644 --- a/client/src/main/scala/it/cwmp/client/view/game/GameViewActor.scala +++ b/client/src/main/scala/it/cwmp/client/view/game/GameViewActor.scala @@ -19,7 +19,7 @@ import scala.concurrent.duration._ class GameViewActor(parentActor: ActorRef) extends Actor with Logging { private val gameFX: GameFX = GameFX(self) - private val FRAME_RATE: FiniteDuration = 50.millis + private val TIME_BETWEEN_FRAMES: FiniteDuration = 500.millis private var updatingSchedule: Cancellable = _ private var tempWorld: CellWorld = _ @@ -53,14 +53,14 @@ class GameViewActor(parentActor: ActorRef) extends Actor with Logging { if (updatingSchedule != null) updatingSchedule.cancel() tempWorld = world updatingSchedule = context.system.scheduler - .schedule(0.millis, FRAME_RATE, self, UpdateLocalWorld)(context.dispatcher) + .schedule(0.millis, TIME_BETWEEN_FRAMES, self, UpdateLocalWorld)(context.dispatcher) case UpdateLocalWorld => // log.info(s"World to paint: Characters=${tempWorld.characters} Attacks=${tempWorld.attacks} Instant=${tempWorld.instant}") gameFX.updateWorld(tempWorld) // is that to heavy computation here ??? - tempWorld = GameEngine(tempWorld, java.time.Duration.ofMillis(FRAME_RATE.toMillis)) + tempWorld = GameEngine(tempWorld, java.time.Duration.ofMillis(TIME_BETWEEN_FRAMES.toMillis)) } /** From 9488f04a0b385861a04aaebaf036565e54a8286a Mon Sep 17 00:00:00 2001 From: Enrico Siboni Date: Thu, 26 Jul 2018 19:44:05 +0200 Subject: [PATCH 108/193] Travis CI Speedup - written the line of commands to execute (now tests are run one time, not two) the "-x test" after "build" means that build task should not execute its "test" task because it will be executed later by "reportScoverage" task --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 159bf074..299277c8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,7 +3,7 @@ env: global: - secure: "dRKFshApyl4AUJFX35C3GfeYoV7jFjZirDj9YbNMSegvEMf6eIiapdBP/GfnCYKmOCO9cuZU3p2hUHGNNZYRdDcuP12SlrCVfxDnLkqPgwuZKGm0T0yAsACVJZRD/uNfy5HMiCPMDyT+h9pqMlBj+LsCov46AlaQdmwS9luIjPWNA+Ter17javVpLLzsRH+8Vsh1UtiEk4seIHkhOlxQLaAEvoTr2kRrI048C3aVYY8hDIMNrK/OPiVwF+83ZeXbZL0Q9E+QnmXimAB/lS7VleW4DD1g4JI9NL3HHAJbe3yDHdwRb/fYLX/ZpT0MA0qgYSlxwT2hrpFYQa/HgRUN2jREpSLWxnfKd1QQYXuxTGQaI9WUd+j+8ppvvJZHqdqc8QGMRHrodtdYcDJhYk5Z1nOlkVux+Axt/x4o63RJtZ7dX8JTsHyFW415FhnK56iGfRTLe7aipYuepZcxeydWrEis8+hy7eVuPwxH0qiCHugHRlzyTJZLR9z6peXg0IeDpCULm4Wy7LX/xHSagk4CFbqHghzdMtcaCSn9q7ooFv5RWqHYEq+szAAl/usYN5MuN2g1ZD7T4BooWJdUbntELiLh4yBpAkFaW0VTN1A5N+UK/QdCzFG0Sl6VXYGxU3/93fgbhf7Q1v+Q/H7wc5GrGQy+4R425WCYXilOksFJkWk=" script: - - './gradlew' + - './gradlew clean build -x test javadoc scaladoc reportScoverage' after_success: - 'bash scripts/commit_and_upload.sh -r iuginP/pps-17-cw-mp -b master -s latest-docs/scala -d scala' - 'bash scripts/commit_and_upload.sh -r iuginP/pps-17-cw-mp -b master -s latest-docs/java -d java' From 8e68c37299ceb5fc12f45a4325b27def24ef1164 Mon Sep 17 00:00:00 2001 From: Enrico Siboni Date: Thu, 26 Jul 2018 19:55:56 +0200 Subject: [PATCH 109/193] Silenced logging in tests for all services --- .../authentication/src/test/resources/logback-test.xml | 10 ++++++++++ .../room-receiver/src/test/resources/logback-test.xml | 10 ++++++++++ 2 files changed, 20 insertions(+) create mode 100644 services/authentication/src/test/resources/logback-test.xml create mode 100644 services/room-receiver/src/test/resources/logback-test.xml diff --git a/services/authentication/src/test/resources/logback-test.xml b/services/authentication/src/test/resources/logback-test.xml new file mode 100644 index 00000000..b211d12b --- /dev/null +++ b/services/authentication/src/test/resources/logback-test.xml @@ -0,0 +1,10 @@ + + + + %msg%n + + + + + + \ No newline at end of file diff --git a/services/room-receiver/src/test/resources/logback-test.xml b/services/room-receiver/src/test/resources/logback-test.xml new file mode 100644 index 00000000..b211d12b --- /dev/null +++ b/services/room-receiver/src/test/resources/logback-test.xml @@ -0,0 +1,10 @@ + + + + %msg%n + + + + + + \ No newline at end of file From f07d95fdd3437bee561b87021693ed379352581b Mon Sep 17 00:00:00 2001 From: Davide Borficchia Date: Fri, 27 Jul 2018 11:13:49 +0200 Subject: [PATCH 110/193] create classe per la visualizzazione del dialog di attesa --- .../it/cwmp/client/view/FXLoadingDialog.scala | 45 +++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 client/src/main/scala/it/cwmp/client/view/FXLoadingDialog.scala diff --git a/client/src/main/scala/it/cwmp/client/view/FXLoadingDialog.scala b/client/src/main/scala/it/cwmp/client/view/FXLoadingDialog.scala new file mode 100644 index 00000000..e1ae69e2 --- /dev/null +++ b/client/src/main/scala/it/cwmp/client/view/FXLoadingDialog.scala @@ -0,0 +1,45 @@ +package it.cwmp.client.view + +import javafx.application.Platform +import javafx.scene.control.{Dialog, ProgressBar} +import javafx.scene.layout.BorderPane + +/** + * Classe per gestire il dialog di attessa + * + * @author Davide Borficchia + */ +trait FXLoadingDialog { + + this: FXController => + + private var dialog = new Dialog[Boolean]() + + /** + * Mostra un dialog customizzato + * @param title titolo del dialog + * @param message messaggio del dialog + */ + def showLoadingDialog(title: String, message: String): Unit = { + Platform.runLater(() => { + dialog.setTitle(title) + dialog.setHeaderText(message) + val pane = new BorderPane() + val infiniteProgress = new ProgressBar() + pane.setCenter(infiniteProgress) + dialog.getDialogPane.setContent(pane) + dialog.setOnCloseRequest(dialog.getOnCloseRequest) + dialog.show() + }) + } + + /** + * Metodo che chiude il dialog + */ + def hideLoadingDialog(): Unit = { + Platform.runLater(() => { + dialog.setResult(true) + dialog.hide() + }) + } +} From 996e2346d4bde9b69bee68f49b2379cc6ce0c4e2 Mon Sep 17 00:00:00 2001 From: Davide Borficchia Date: Fri, 27 Jul 2018 11:16:19 +0200 Subject: [PATCH 111/193] aggiunto metodo per customizzare il comportamente alla ricezione di un alert --- .../main/scala/it/cwmp/client/view/AlertActor.scala | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/client/src/main/scala/it/cwmp/client/view/AlertActor.scala b/client/src/main/scala/it/cwmp/client/view/AlertActor.scala index 0045e8f8..4fc54366 100644 --- a/client/src/main/scala/it/cwmp/client/view/AlertActor.scala +++ b/client/src/main/scala/it/cwmp/client/view/AlertActor.scala @@ -37,7 +37,16 @@ trait AlertActor { */ import AlertMessages._ protected def alertBehaviour: Receive = { - case Info(title, message, onClose) => fxController showInfo(title, message, onClose) - case Error(title, message, onClose) => fxController showError(title, message, onClose) + case Info(title, message, onClose) => + fxController showInfo(title, message, onClose) + onAlertReceived() + case Error(title, message, onClose) => + fxController showError(title, message, onClose) + onAlertReceived() } + + /** + * metodo per aggiungere un comportamento quando si riceve un alert + */ + protected def onAlertReceived(): Unit = {} } From c635251fb535ad38ecdd31ae4e7e1bcd0a57f70e Mon Sep 17 00:00:00 2001 From: Davide Borficchia Date: Fri, 27 Jul 2018 11:18:49 +0200 Subject: [PATCH 112/193] rifattorizzato nomi componenti e iniziata la visualizzazione dei dialog nelle room --- .../resources/layouts/roomManagerLayout.fxml | 16 ++--- .../it/cwmp/client/view/FXController.scala | 2 + .../client/view/room/RoomFXController.scala | 58 ++++++++++++++----- 3 files changed, 53 insertions(+), 23 deletions(-) diff --git a/client/src/main/resources/layouts/roomManagerLayout.fxml b/client/src/main/resources/layouts/roomManagerLayout.fxml index 57914ed1..e097a34d 100644 --- a/client/src/main/resources/layouts/roomManagerLayout.fxml +++ b/client/src/main/resources/layouts/roomManagerLayout.fxml @@ -21,24 +21,24 @@ + fx:id="tfPrivateCreateRoomName" layoutX="115.0" layoutY="28.0"/> - -