decider 2 start
@@ -0,0 +1,19 @@
|
||||
build
|
||||
logs
|
||||
project/project
|
||||
project/target
|
||||
target
|
||||
tmp
|
||||
.history
|
||||
dist
|
||||
/.idea
|
||||
/*.iml
|
||||
/out
|
||||
/.idea_modules
|
||||
/.classpath
|
||||
/.gradle
|
||||
/.project
|
||||
/RUNNING_PID
|
||||
/.settings
|
||||
/project/*-shim.sbt
|
||||
/activator-sbt-*-shim.sbt
|
||||
@@ -0,0 +1,77 @@
|
||||
package actors
|
||||
|
||||
import akka.actor.{Actor, ActorLogging, ActorRef}
|
||||
import akka.event.LoggingReceive
|
||||
import com.typesafe.scalalogging.LazyLogging
|
||||
|
||||
import scala.collection.immutable.{HashSet, Queue}
|
||||
import scala.concurrent.duration._
|
||||
|
||||
case class DeciderMap(map: String, 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 {
|
||||
|
||||
private val name: String = lobbyName
|
||||
|
||||
// user actors
|
||||
protected[this] var users: HashSet[ActorRef] = HashSet.empty[ActorRef]
|
||||
|
||||
private var status = NotStarted
|
||||
|
||||
private var maps: List[DeciderMap] = List(DeciderMap("map1"), DeciderMap("map2"), DeciderMap("map3"))
|
||||
|
||||
private var secondPlayer: Option[ActorRef] = None
|
||||
|
||||
logger.info(s"Create lobby with name $lobbyName")
|
||||
|
||||
|
||||
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)
|
||||
case WatchLobby(_) =>
|
||||
// add the watcher to the list
|
||||
users = users + sender
|
||||
case LeaveLobby =>
|
||||
users = users - sender
|
||||
if(secondPlayer.contains(sender)) secondPlayer = None
|
||||
if (users.isEmpty) {
|
||||
logger.info(s"Stop lobby with name: $name")
|
||||
context.stop(self)
|
||||
}
|
||||
case InfoQuery =>
|
||||
sender ! LobbyInfoResponse(name, self.path.name, status.toString())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
case class BanMap(mapName: String)
|
||||
|
||||
case class MapsUpdate(maps: List[DeciderMap])
|
||||
|
||||
case class MapsHistory(symbol: String, maps: List[DeciderMap])
|
||||
|
||||
case class CreateLobby(userName: String)
|
||||
|
||||
case class JoinLobbyAsPlayer(lobbyName: String)
|
||||
|
||||
case class WatchLobby(lobbyName: String)
|
||||
|
||||
case class LeaveLobby(lobbyName: String)
|
||||
|
||||
case object InfoQuery
|
||||
|
||||
case class LobbyInfoResponse(lobbyName: String, lobbyActorName: String, status: String)
|
||||
|
||||
class LobbyStatus
|
||||
|
||||
sealed case class NotStarted() extends LobbyStatus
|
||||
sealed case class Draft() extends LobbyStatus
|
||||
sealed case class Finish() extends LobbyStatus
|
||||
@@ -0,0 +1,48 @@
|
||||
package actors
|
||||
|
||||
import akka.actor.{Actor, ActorLogging, Props}
|
||||
import akka.event.LoggingReceive
|
||||
import akka.pattern.ask
|
||||
import akka.util.Timeout
|
||||
import com.typesafe.scalalogging.LazyLogging
|
||||
|
||||
import scala.collection.mutable.ListBuffer
|
||||
import scala.concurrent.Await
|
||||
import scala.concurrent.duration.DurationInt
|
||||
|
||||
class LobbiesActor extends Actor with LazyLogging {
|
||||
|
||||
implicit val timeout: Timeout = 1.second
|
||||
|
||||
val lobbies: ListBuffer[String] = ListBuffer()
|
||||
|
||||
def receive = LoggingReceive {
|
||||
case CreateLobby(userName) =>
|
||||
val lobbyActor = context.actorOf(Props(new LobbieActor(userName, sender)),
|
||||
s"lobbyActor-${(math.random*100000000L).toLong}")
|
||||
lobbyActor.tell(WatchLobby("watchIt"), sender)
|
||||
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 =>
|
||||
sender ! context.children.toList.map(lobbyActor =>
|
||||
Await.result(lobbyActor ? InfoQuery, 1.second))
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
case object GetAllLobbies
|
||||
|
||||
case object UnWatchAllLobbies
|
||||
@@ -0,0 +1,145 @@
|
||||
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
|
||||
|
||||
}
|
||||
|
||||
|
After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 9.9 KiB |
|
After Width: | Height: | Size: 15 KiB |
|
After Width: | Height: | Size: 20 KiB |
|
After Width: | Height: | Size: 17 KiB |
|
After Width: | Height: | Size: 15 KiB |
|
After Width: | Height: | Size: 19 KiB |
|
After Width: | Height: | Size: 19 KiB |
|
After Width: | Height: | Size: 9.5 KiB |
|
After Width: | Height: | Size: 18 KiB |
|
After Width: | Height: | Size: 19 KiB |
|
After Width: | Height: | Size: 17 KiB |
|
After Width: | Height: | Size: 274 KiB |
|
After Width: | Height: | Size: 9.6 KiB |
|
After Width: | Height: | Size: 17 KiB |
|
After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 19 KiB |
|
After Width: | Height: | Size: 19 KiB |
|
After Width: | Height: | Size: 18 KiB |
|
After Width: | Height: | Size: 17 KiB |
|
After Width: | Height: | Size: 18 KiB |
|
After Width: | Height: | Size: 18 KiB |
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 18 KiB |
|
After Width: | Height: | Size: 19 KiB |
|
After Width: | Height: | Size: 20 KiB |
|
After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 17 KiB |
|
After Width: | Height: | Size: 18 KiB |
|
After Width: | Height: | Size: 17 KiB |
|
After Width: | Height: | Size: 17 KiB |
|
After Width: | Height: | Size: 17 KiB |
|
After Width: | Height: | Size: 17 KiB |
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 18 KiB |
|
After Width: | Height: | Size: 20 KiB |
|
After Width: | Height: | Size: 19 KiB |
|
After Width: | Height: | Size: 11 KiB |
|
After Width: | Height: | Size: 9.2 KiB |
|
After Width: | Height: | Size: 19 KiB |
|
After Width: | Height: | Size: 20 KiB |
|
After Width: | Height: | Size: 35 KiB |
|
After Width: | Height: | Size: 288 KiB |
|
After Width: | Height: | Size: 18 KiB |
|
After Width: | Height: | Size: 18 KiB |
|
After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 19 KiB |
|
After Width: | Height: | Size: 30 KiB |
|
After Width: | Height: | Size: 17 KiB |
|
After Width: | Height: | Size: 20 KiB |
|
After Width: | Height: | Size: 24 KiB |
|
After Width: | Height: | Size: 18 KiB |
|
After Width: | Height: | Size: 9.6 KiB |
|
After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 8.8 KiB |
|
After Width: | Height: | Size: 17 KiB |
|
After Width: | Height: | Size: 15 KiB |
|
After Width: | Height: | Size: 17 KiB |
|
After Width: | Height: | Size: 17 KiB |
|
After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 17 KiB |
|
After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 21 KiB |
|
After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 18 KiB |
|
After Width: | Height: | Size: 8.9 KiB |
|
After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 18 KiB |
|
After Width: | Height: | Size: 18 KiB |
|
After Width: | Height: | Size: 15 KiB |
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 19 KiB |
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 17 KiB |
|
After Width: | Height: | Size: 15 KiB |
|
After Width: | Height: | Size: 19 KiB |
|
After Width: | Height: | Size: 18 KiB |
|
After Width: | Height: | Size: 19 KiB |
|
After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 15 KiB |
|
After Width: | Height: | Size: 18 KiB |
|
After Width: | Height: | Size: 17 KiB |
|
After Width: | Height: | Size: 17 KiB |
|
After Width: | Height: | Size: 20 KiB |
|
After Width: | Height: | Size: 9.3 KiB |
|
After Width: | Height: | Size: 9.4 KiB |
|
After Width: | Height: | Size: 20 KiB |
|
After Width: | Height: | Size: 9.5 KiB |
|
After Width: | Height: | Size: 18 KiB |
|
After Width: | Height: | Size: 8.8 KiB |
|
After Width: | Height: | Size: 254 KiB |
|
After Width: | Height: | Size: 20 KiB |