package actors import actors.UserActor.GetName import akka.actor._ import akka.event.LoggingReceive import akka.pattern.ask import akka.util.Timeout import com.typesafe.scalalogging.LazyLogging import play.api.libs.json._ import scala.concurrent.ExecutionContext.Implicits.global import scala.concurrent.duration.DurationInt import scala.util.{Failure, Success} class UserActor(out: ActorRef, userParentActor: ActorRef, lobbiesActor: ActorRef) extends Actor with LazyLogging { implicit val timeout: Timeout = 3.seconds var userStatus: UserStatus = InLobby() implicit val lobbyResponseWrites: Writes[List[LobbyInfoResponse]] = new Writes[List[LobbyInfoResponse]] { implicit val lobbyWrites: OWrites[LobbyInfoResponse] = Json.writes[LobbyInfoResponse] override def writes(o: List[LobbyInfoResponse]): JsValue = { JsArray(o.map(lobby => Json.toJson(lobby))) } } implicit val mapJson: Writes[DeciderMap] = new Writes[DeciderMap] { def writes(deciderMap: DeciderMap): JsValue = { Json.obj( "map" -> deciderMap.map, "isBanned" -> deciderMap.isBanned ) } } var name = "" override def preStart(): Unit = { super.preStart() configureDefaultStocks() } def configureDefaultStocks(): Unit = { logger.info(s"Creating user actor") } override def receive: Receive = LoggingReceive { case MapsUpdate(deciderMaps) => val maps = deciderMaps.map(map => Json.toJson(map)) out ! Json.obj("type" -> "maps", "deciderMaps" -> maps) case GetName => sender ! name case json: JsValue => // When the user types in a stock in the upper right corner, this is triggered val comType = (json \ "type").asOpt[String] comType match { case Some("userName") => name = (json \ "name").as[String] logger.debug(s"Set user name: $name for actor ${this.self}") case Some("getAllUsers") => val usersActorFuture = (userParentActor ? UserParentActor.GetAllUsers).mapTo[Iterable[ActorRef]] usersActorFuture.map(actorRefs => { logger.debug(s"There are ${actorRefs.size} users on site") actorRefs.map(userActorRef => userActorRef ? GetName).map(res => { res.onComplete { case Success(name) => logger.debug(s"There is $name on site") } }) }) case Some("createDecider") => lobbiesActor ! CreateLobby(name) case Some("leaveDecider") => lobbiesActor ! LeaveLobby(name) case Some("updateDecider") => lobbiesActor ! BanMap("map1") case Some("getLobbies") => logger.debug("Get all lobby request") (lobbiesActor ? GetAllLobbies).mapTo[List[LobbyInfoResponse]] onComplete { case Success(lobbies) => { logger.info(s"Received lobbies: $lobbies") out ! Json.obj("type" -> "lobbies", "lobbies" -> lobbies) } case Failure(ex) => logger.error("Received error", ex) } } } } class UserParentActor(actorSystem: ActorSystem) extends Actor with ActorLogging { import UserParentActor._ override def receive: Receive = LoggingReceive { case Create(id, out, lobbiesActor) => val child: ActorRef = actorSystem.actorOf(Props(classOf[UserActor], out, self, lobbiesActor), s"userActor-$id") sender() ! child case GetAllUsers => sender() ! context.children } } class UserStatus case class InLobby() extends UserStatus case class NotReady() extends UserStatus case class Ready() extends UserStatus object UserParentActor { case class Create(id: String, out: ActorRef, lobbiesActor: ActorRef) case object GetAllUsers } object UserActor { trait Factory { // Corresponds to the @Assisted parameters defined in the constructor def apply(out: ActorRef): Actor } case object GetName case object CreateLobby }