Decider v 0.9
This commit is contained in:
+107
-22
@@ -1,74 +1,159 @@
|
||||
package actors
|
||||
|
||||
import actors.UserActor.{GetName, HostLeaveLobby, RefreshLobbyInfo, SetUserAsHost}
|
||||
import akka.actor.{Actor, ActorLogging, ActorRef}
|
||||
import akka.event.LoggingReceive
|
||||
import com.typesafe.scalalogging.LazyLogging
|
||||
import akka.pattern.ask
|
||||
import akka.util.Timeout
|
||||
import com.typesafe.config.{Config, ConfigFactory}
|
||||
|
||||
import scala.collection.JavaConverters.iterableAsScalaIterableConverter
|
||||
import scala.collection.immutable.{HashSet, Queue}
|
||||
import scala.concurrent.Await
|
||||
import scala.concurrent.duration._
|
||||
|
||||
case class DeciderMap(map: String, isBanned: Boolean = false)
|
||||
case class LobbyUser(name: String, actorRef: ActorRef)
|
||||
case class DeciderMap(map: String, var isBanned: Boolean = false)
|
||||
|
||||
/**
|
||||
* There is one StockActor per stock symbol. The StockActor maintains a list of users watching the stock and the stock
|
||||
* values. Each StockActor updates a rolling dataset of randomly generated stock values.
|
||||
*/
|
||||
class LobbieActor(lobbyName: String, hostUser: ActorRef) extends Actor with LazyLogging {
|
||||
class LobbieActor(hostUser: LobbyUser) extends Actor with LazyLogging {
|
||||
|
||||
private val name: String = lobbyName
|
||||
val config = ConfigFactory.load()
|
||||
logger.info(s"Create lobby... host: ${hostUser.actorRef.path.name}")
|
||||
|
||||
// user actors
|
||||
|
||||
private val host: LobbyUser = hostUser
|
||||
private var secondPlayer: Option[LobbyUser] = None
|
||||
|
||||
private var firstPlayerReady: Boolean = false
|
||||
private var secondPlayerReady: Boolean = false
|
||||
|
||||
private var playerTurn = 1
|
||||
|
||||
// all lobby users actors (observer and players)
|
||||
protected[this] var users: HashSet[ActorRef] = HashSet.empty[ActorRef]
|
||||
|
||||
private var status = NotStarted
|
||||
users = users + host.actorRef
|
||||
|
||||
private var maps: List[DeciderMap] = List(DeciderMap("map1"), DeciderMap("map2"), DeciderMap("map3"))
|
||||
private var status: LobbyStatus = NotStarted()
|
||||
|
||||
private var secondPlayer: Option[ActorRef] = None
|
||||
private val mapsLobby: Set[DeciderMap] = {
|
||||
val configMaps = config.getStringList("maps").asScala
|
||||
configMaps.map(e => {
|
||||
DeciderMap(e)
|
||||
}).toSet
|
||||
}
|
||||
|
||||
logger.info(s"Create lobby with name $lobbyName")
|
||||
hostUser.actorRef.tell(
|
||||
SetUserAsHost(LobbyInfo(hostUser.name, "", firstPlayerReady, secondPlayerReady, self.path.name, status.toString(), mapsLobby)), this.self)
|
||||
|
||||
implicit val timeout: Timeout = 1.second
|
||||
|
||||
|
||||
def receive = LoggingReceive {
|
||||
case BanMap(mapName: String) =>
|
||||
// notify watchers
|
||||
logger.info(s"Ban map $mapName by ${sender.path.name}")
|
||||
users.foreach(_ ! MapsUpdate( maps))
|
||||
case JoinLobbyAsPlayer(_) =>
|
||||
secondPlayer = Some(sender)
|
||||
if(status == Draft()){
|
||||
if((playerTurn == 1 && sender == host.actorRef) ||
|
||||
(playerTurn == 2 && secondPlayer.exists(_.actorRef == sender))){
|
||||
mapsLobby.find(p => p.map == mapName).foreach(_.isBanned = true)
|
||||
if (playerTurn== 1) playerTurn = 2 else playerTurn = 1
|
||||
if(mapsLobby.count(_.isBanned == false) == 1){
|
||||
status = Finish()
|
||||
}
|
||||
users.foreach(_ ! RefreshLobbyInfo(getLobbyInfoResponse))
|
||||
} else{
|
||||
logger.warn(s"Player ${sender.path.name} ban map, but turn is $playerTurn")
|
||||
}
|
||||
} else {
|
||||
logger.warn(s"Player ${sender.path.name} ban map, but it is '$status' status")
|
||||
}
|
||||
case SetReady =>
|
||||
// notify watchers
|
||||
var readyPlayer = sender()
|
||||
if(readyPlayer == hostUser.actorRef){
|
||||
firstPlayerReady = true
|
||||
} else if (secondPlayer.exists(sp => sp.actorRef == readyPlayer)) {
|
||||
secondPlayerReady = true
|
||||
}
|
||||
|
||||
if(firstPlayerReady && secondPlayerReady){
|
||||
status = Draft()
|
||||
}
|
||||
|
||||
users.foreach(_ ! RefreshLobbyInfo(getLobbyInfoResponse))
|
||||
|
||||
case SetNotReady =>
|
||||
// notify watchers
|
||||
var notReadyPlayer = sender()
|
||||
if(notReadyPlayer == hostUser.actorRef){
|
||||
firstPlayerReady = false
|
||||
} else if (secondPlayer.exists(sp => sp.actorRef == notReadyPlayer)) {
|
||||
secondPlayerReady = false
|
||||
}
|
||||
users.foreach(_ ! RefreshLobbyInfo(getLobbyInfoResponse))
|
||||
|
||||
case JoinLobbyAsPlayer(sp) =>
|
||||
logger.info(s"User ${sender.path.name} join lobby ${self.path.name} as player")
|
||||
secondPlayer = Some(sp)
|
||||
users = users + sp.actorRef
|
||||
sp.actorRef.tell(
|
||||
SetUserAsHost(LobbyInfo(hostUser.name, sp.name, firstPlayerReady, secondPlayerReady, self.path.name, status.toString(), mapsLobby)), this.self)
|
||||
users.foreach(_ ! RefreshLobbyInfo(getLobbyInfoResponse))
|
||||
case WatchLobby(_) =>
|
||||
// add the watcher to the list
|
||||
users = users + sender
|
||||
case LeaveLobby =>
|
||||
users = users - sender
|
||||
if(secondPlayer.contains(sender)) secondPlayer = None
|
||||
if(secondPlayer.exists(sp => sp.actorRef == sender)) secondPlayer = None
|
||||
if(host.actorRef == sender()){
|
||||
users.foreach(_ ! HostLeaveLobby)
|
||||
}
|
||||
if (users.isEmpty) {
|
||||
logger.info(s"Stop lobby with name: $name")
|
||||
logger.info(s"Stop lobby ${self.path.name}")
|
||||
context.stop(self)
|
||||
}
|
||||
case InfoQuery =>
|
||||
sender ! LobbyInfoResponse(name, self.path.name, status.toString())
|
||||
logger.info(s"Info query for lobby ${self.path.name} and host ${host.actorRef.path.name}")
|
||||
sender ! RefreshLobbyInfo(getLobbyInfoResponse)
|
||||
}
|
||||
|
||||
private def getLobbyInfoResponse: LobbyInfo = {
|
||||
val user2Name = secondPlayer.map(_.name).getOrElse("")
|
||||
LobbyInfo(host.name, user2Name, firstPlayerReady, secondPlayerReady, self.path.name, status.toString(), mapsLobby)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
case class BanMap(mapName: String)
|
||||
|
||||
case class MapsUpdate(maps: List[DeciderMap])
|
||||
|
||||
case class MapsHistory(symbol: String, maps: List[DeciderMap])
|
||||
case class MapsUpdate(maps: Set[String])
|
||||
|
||||
case class CreateLobby(userName: String)
|
||||
|
||||
case class JoinLobbyAsPlayer(lobbyName: String)
|
||||
|
||||
case class WatchLobby(lobbyName: String)
|
||||
|
||||
case class LeaveLobby(lobbyName: String)
|
||||
case class JoinLobbyAsPlayer(lobbyUser: LobbyUser)
|
||||
|
||||
case object LeaveLobby
|
||||
|
||||
case object SetReady
|
||||
|
||||
case object SetNotReady
|
||||
|
||||
case object InfoQuery
|
||||
|
||||
case class LobbyInfoResponse(lobbyName: String, lobbyActorName: String, status: String)
|
||||
case class LobbyInfo(user1Name: String,
|
||||
user2Name: String,
|
||||
user1Ready: Boolean,
|
||||
user2Ready: Boolean,
|
||||
lobbyActorName: String,
|
||||
status: String,
|
||||
maps: Set[DeciderMap])
|
||||
|
||||
class LobbyStatus
|
||||
|
||||
|
||||
@@ -16,23 +16,26 @@ class LobbiesActor extends Actor with LazyLogging {
|
||||
|
||||
val lobbies: ListBuffer[String] = ListBuffer()
|
||||
|
||||
def receive = LoggingReceive {
|
||||
case CreateLobby(userName) =>
|
||||
val lobbyActor = context.actorOf(Props(new LobbieActor(userName, sender)),
|
||||
def receive: Receive = LoggingReceive {
|
||||
case CreateLobby(hostName) =>
|
||||
val hostActorRef = sender
|
||||
logger.info(s"Player ${hostActorRef.path.name} create lobby.")
|
||||
val lobbyActor = context.actorOf(Props(new LobbieActor(LobbyUser(hostName,hostActorRef))),
|
||||
s"lobbyActor-${(math.random*100000000L).toLong}")
|
||||
lobbyActor.tell(WatchLobby("watchIt"), sender)
|
||||
lobbyActor.tell(WatchLobby("watchIt"), hostActorRef)
|
||||
case JoinLobbyByActorName(lobbyName, userName) =>
|
||||
// get or create the StockActor for the symbol and forward this message
|
||||
val user = sender
|
||||
context.child(lobbyName) match {
|
||||
case Some(lobbyActor) => lobbyActor ! JoinLobbyAsPlayer(LobbyUser(userName, user))
|
||||
case None => logger.error(s"Can't watch lobby $lobbyName - lobby not exists")
|
||||
}
|
||||
case watchLobby@WatchLobby(lobbyName) =>
|
||||
// get or create the StockActor for the symbol and forward this message
|
||||
context.child(lobbyName) match {
|
||||
case Some(lobbyActor) => lobbyActor forward watchLobby
|
||||
case None => logger.error(s"Can't watch lobby $lobbyName - lobby not exists")
|
||||
}
|
||||
case unwatchLobby@LeaveLobby(symbol) =>
|
||||
// if there is a StockActor for the symbol forward this message
|
||||
context.child(symbol).foreach(_.forward(unwatchLobby))
|
||||
case banMap@BanMap(map) =>
|
||||
logger.info(s"forvard ban $map")
|
||||
context.children.foreach(_.forward(banMap))
|
||||
case UnWatchAllLobbies =>
|
||||
context.children.foreach( _.tell(LeaveLobby, sender))
|
||||
case GetAllLobbies =>
|
||||
@@ -45,4 +48,6 @@ class LobbiesActor extends Actor with LazyLogging {
|
||||
|
||||
case object GetAllLobbies
|
||||
|
||||
case class JoinLobbyByActorName(actorName: String, userName: String)
|
||||
|
||||
case object UnWatchAllLobbies
|
||||
+64
-30
@@ -1,6 +1,6 @@
|
||||
package actors
|
||||
|
||||
import actors.UserActor.GetName
|
||||
import actors.UserActor.{GetName, HostLeaveLobby, RefreshLobbyInfo, SetUserAsHost, SetUserAsSecondPlayer}
|
||||
import akka.actor._
|
||||
import akka.event.LoggingReceive
|
||||
import akka.pattern.ask
|
||||
@@ -18,16 +18,7 @@ class UserActor(out: ActorRef,
|
||||
|
||||
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)))
|
||||
}
|
||||
}
|
||||
var lobbieActor: Option[ActorRef] = None
|
||||
|
||||
implicit val mapJson: Writes[DeciderMap] = new Writes[DeciderMap] {
|
||||
def writes(deciderMap: DeciderMap): JsValue = {
|
||||
@@ -38,6 +29,15 @@ class UserActor(out: ActorRef,
|
||||
}
|
||||
}
|
||||
|
||||
implicit val lobbyWrites: OWrites[LobbyInfo] = Json.writes[LobbyInfo]
|
||||
|
||||
implicit val lobbyResponseWrites: Writes[List[LobbyInfo]] = new Writes[List[LobbyInfo]] {
|
||||
|
||||
override def writes(o: List[LobbyInfo]): JsValue = {
|
||||
JsArray(o.map(lobby => Json.toJson(lobby)))
|
||||
}
|
||||
}
|
||||
|
||||
var name = ""
|
||||
|
||||
override def preStart(): Unit = {
|
||||
@@ -52,14 +52,29 @@ class UserActor(out: ActorRef,
|
||||
|
||||
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 SetUserAsHost(lobbyInfo) =>
|
||||
val lobbyActor = sender()
|
||||
logger.info(s"Receive set user ${self.path.name} as host from ${lobbyActor.path.name}")
|
||||
setUserAsJoinedOrCreatedLobby(lobbyActor, lobbyInfo)
|
||||
|
||||
case SetUserAsSecondPlayer(lobbyInfo) =>
|
||||
val lobbyActor = sender()
|
||||
logger.info(s"Receive set user ${self.path.name} as second player from ${lobbyActor.path.name}")
|
||||
setUserAsJoinedOrCreatedLobby(lobbyActor, lobbyInfo)
|
||||
|
||||
case HostLeaveLobby =>
|
||||
logger.info(s"Host leave from lobby ${sender.path.name}")
|
||||
out ! Json.obj("type" -> "hostLeaveLobby")
|
||||
|
||||
case RefreshLobbyInfo(lobbyInfo) =>
|
||||
logger.trace(s"Refresh lobby info: $lobbyInfo")
|
||||
out ! Json.obj("type" -> "refreshLobby", "lobby" -> lobbyInfo)
|
||||
|
||||
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 {
|
||||
@@ -67,8 +82,8 @@ class UserActor(out: ActorRef,
|
||||
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 => {
|
||||
val userActorsFuture = (userParentActor ? UserParentActor.GetAllUsers).mapTo[Iterable[ActorRef]]
|
||||
userActorsFuture.map(actorRefs => {
|
||||
logger.debug(s"There are ${actorRefs.size} users on site")
|
||||
actorRefs.map(userActorRef => userActorRef ? GetName).map(res => {
|
||||
res.onComplete {
|
||||
@@ -81,23 +96,41 @@ class UserActor(out: ActorRef,
|
||||
lobbiesActor ! CreateLobby(name)
|
||||
|
||||
case Some("leaveDecider") =>
|
||||
lobbiesActor ! LeaveLobby(name)
|
||||
lobbieActor.foreach(lobby => lobby ! LeaveLobby)
|
||||
|
||||
case Some("updateDecider") =>
|
||||
lobbiesActor ! BanMap("map1")
|
||||
case Some("setReady") =>
|
||||
lobbieActor.foreach(lobby => lobby ! SetReady)
|
||||
|
||||
case Some("setNotReady") =>
|
||||
lobbieActor.foreach(lobby => lobby ! SetNotReady)
|
||||
|
||||
case Some("joinDecider") =>
|
||||
val lobbyActorName = (json \ "lobbyActorName").as[String]
|
||||
logger.info(s"Player ${self.path.name} join lobby $lobbyActorName")
|
||||
lobbiesActor ! JoinLobbyByActorName(lobbyActorName, name)
|
||||
|
||||
case Some("banMap") =>
|
||||
val map = (json \ "map").as[String]
|
||||
lobbieActor.foreach(lobby => lobby ! BanMap(map))
|
||||
|
||||
case Some("getLobbies") =>
|
||||
logger.debug("Get all lobby request")
|
||||
(lobbiesActor ? GetAllLobbies).mapTo[List[LobbyInfoResponse]] onComplete {
|
||||
(lobbiesActor ? GetAllLobbies).mapTo[List[RefreshLobbyInfo]] onComplete {
|
||||
case Success(lobbies) => {
|
||||
logger.info(s"Received lobbies: $lobbies")
|
||||
out ! Json.obj("type" -> "lobbies", "lobbies" -> lobbies)
|
||||
out ! Json.obj("type" -> "lobbies", "lobbies" -> lobbies.map(res => res.lobbyInfo))
|
||||
}
|
||||
case Failure(ex) => logger.error("Received error", ex)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private def setUserAsJoinedOrCreatedLobby(lobbyActor: ActorRef, lobbyInfo: LobbyInfo): Unit = {
|
||||
this.lobbieActor = Some(lobbyActor)
|
||||
out ! Json.obj("type" -> "switchToLobby", "lobby" -> lobbyInfo)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class UserParentActor(actorSystem: ActorSystem) extends Actor with ActorLogging {
|
||||
@@ -113,14 +146,6 @@ class UserParentActor(actorSystem: ActorSystem) extends Actor with ActorLogging
|
||||
}
|
||||
}
|
||||
|
||||
class UserStatus
|
||||
|
||||
case class InLobby() extends UserStatus
|
||||
|
||||
case class NotReady() extends UserStatus
|
||||
|
||||
case class Ready() extends UserStatus
|
||||
|
||||
|
||||
object UserParentActor {
|
||||
|
||||
@@ -139,7 +164,16 @@ object UserActor {
|
||||
|
||||
case object GetName
|
||||
|
||||
case class RefreshLobbyInfo(lobbyInfo: LobbyInfo)
|
||||
|
||||
case class SetUserAsHost(lobbyInfo: LobbyInfo)
|
||||
|
||||
case class SetUserAsSecondPlayer(lobbyInfo: LobbyInfo)
|
||||
|
||||
case object CreateLobby
|
||||
|
||||
case object HostLeaveLobby
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user