Decider v 0.9
This commit is contained in:
parent
fda47ec522
commit
6398f44d18
@ -1,74 +1,159 @@
|
|||||||
package actors
|
package actors
|
||||||
|
|
||||||
|
import actors.UserActor.{GetName, HostLeaveLobby, RefreshLobbyInfo, SetUserAsHost}
|
||||||
import akka.actor.{Actor, ActorLogging, ActorRef}
|
import akka.actor.{Actor, ActorLogging, ActorRef}
|
||||||
import akka.event.LoggingReceive
|
import akka.event.LoggingReceive
|
||||||
import com.typesafe.scalalogging.LazyLogging
|
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.collection.immutable.{HashSet, Queue}
|
||||||
|
import scala.concurrent.Await
|
||||||
import scala.concurrent.duration._
|
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
|
* 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.
|
* 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]
|
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 {
|
def receive = LoggingReceive {
|
||||||
case BanMap(mapName: String) =>
|
case BanMap(mapName: String) =>
|
||||||
// notify watchers
|
// notify watchers
|
||||||
logger.info(s"Ban map $mapName by ${sender.path.name}")
|
logger.info(s"Ban map $mapName by ${sender.path.name}")
|
||||||
users.foreach(_ ! MapsUpdate( maps))
|
if(status == Draft()){
|
||||||
case JoinLobbyAsPlayer(_) =>
|
if((playerTurn == 1 && sender == host.actorRef) ||
|
||||||
secondPlayer = Some(sender)
|
(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(_) =>
|
case WatchLobby(_) =>
|
||||||
// add the watcher to the list
|
// add the watcher to the list
|
||||||
users = users + sender
|
users = users + sender
|
||||||
case LeaveLobby =>
|
case LeaveLobby =>
|
||||||
users = users - sender
|
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) {
|
if (users.isEmpty) {
|
||||||
logger.info(s"Stop lobby with name: $name")
|
logger.info(s"Stop lobby ${self.path.name}")
|
||||||
context.stop(self)
|
context.stop(self)
|
||||||
}
|
}
|
||||||
case InfoQuery =>
|
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 BanMap(mapName: String)
|
||||||
|
|
||||||
case class MapsUpdate(maps: List[DeciderMap])
|
case class MapsUpdate(maps: Set[String])
|
||||||
|
|
||||||
case class MapsHistory(symbol: String, maps: List[DeciderMap])
|
|
||||||
|
|
||||||
case class CreateLobby(userName: String)
|
case class CreateLobby(userName: String)
|
||||||
|
|
||||||
case class JoinLobbyAsPlayer(lobbyName: String)
|
|
||||||
|
|
||||||
case class WatchLobby(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 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
|
class LobbyStatus
|
||||||
|
|
||||||
|
|||||||
@ -16,23 +16,26 @@ class LobbiesActor extends Actor with LazyLogging {
|
|||||||
|
|
||||||
val lobbies: ListBuffer[String] = ListBuffer()
|
val lobbies: ListBuffer[String] = ListBuffer()
|
||||||
|
|
||||||
def receive = LoggingReceive {
|
def receive: Receive = LoggingReceive {
|
||||||
case CreateLobby(userName) =>
|
case CreateLobby(hostName) =>
|
||||||
val lobbyActor = context.actorOf(Props(new LobbieActor(userName, sender)),
|
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}")
|
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) =>
|
case watchLobby@WatchLobby(lobbyName) =>
|
||||||
// get or create the StockActor for the symbol and forward this message
|
// get or create the StockActor for the symbol and forward this message
|
||||||
context.child(lobbyName) match {
|
context.child(lobbyName) match {
|
||||||
case Some(lobbyActor) => lobbyActor forward watchLobby
|
case Some(lobbyActor) => lobbyActor forward watchLobby
|
||||||
case None => logger.error(s"Can't watch lobby $lobbyName - lobby not exists")
|
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 =>
|
case UnWatchAllLobbies =>
|
||||||
context.children.foreach( _.tell(LeaveLobby, sender))
|
context.children.foreach( _.tell(LeaveLobby, sender))
|
||||||
case GetAllLobbies =>
|
case GetAllLobbies =>
|
||||||
@ -45,4 +48,6 @@ class LobbiesActor extends Actor with LazyLogging {
|
|||||||
|
|
||||||
case object GetAllLobbies
|
case object GetAllLobbies
|
||||||
|
|
||||||
|
case class JoinLobbyByActorName(actorName: String, userName: String)
|
||||||
|
|
||||||
case object UnWatchAllLobbies
|
case object UnWatchAllLobbies
|
||||||
@ -1,6 +1,6 @@
|
|||||||
package actors
|
package actors
|
||||||
|
|
||||||
import actors.UserActor.GetName
|
import actors.UserActor.{GetName, HostLeaveLobby, RefreshLobbyInfo, SetUserAsHost, SetUserAsSecondPlayer}
|
||||||
import akka.actor._
|
import akka.actor._
|
||||||
import akka.event.LoggingReceive
|
import akka.event.LoggingReceive
|
||||||
import akka.pattern.ask
|
import akka.pattern.ask
|
||||||
@ -18,16 +18,7 @@ class UserActor(out: ActorRef,
|
|||||||
|
|
||||||
implicit val timeout: Timeout = 3.seconds
|
implicit val timeout: Timeout = 3.seconds
|
||||||
|
|
||||||
var userStatus: UserStatus = InLobby()
|
var lobbieActor: Option[ActorRef] = None
|
||||||
|
|
||||||
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] {
|
implicit val mapJson: Writes[DeciderMap] = new Writes[DeciderMap] {
|
||||||
def writes(deciderMap: DeciderMap): JsValue = {
|
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 = ""
|
var name = ""
|
||||||
|
|
||||||
override def preStart(): Unit = {
|
override def preStart(): Unit = {
|
||||||
@ -52,14 +52,29 @@ class UserActor(out: ActorRef,
|
|||||||
|
|
||||||
override def receive: Receive = LoggingReceive {
|
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 =>
|
case GetName =>
|
||||||
sender ! name
|
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 =>
|
case json: JsValue =>
|
||||||
// When the user types in a stock in the upper right corner, this is triggered
|
// Обрабатываем запросы с фронта
|
||||||
|
|
||||||
val comType = (json \ "type").asOpt[String]
|
val comType = (json \ "type").asOpt[String]
|
||||||
comType match {
|
comType match {
|
||||||
@ -67,8 +82,8 @@ class UserActor(out: ActorRef,
|
|||||||
name = (json \ "name").as[String]
|
name = (json \ "name").as[String]
|
||||||
logger.debug(s"Set user name: $name for actor ${this.self}")
|
logger.debug(s"Set user name: $name for actor ${this.self}")
|
||||||
case Some("getAllUsers") =>
|
case Some("getAllUsers") =>
|
||||||
val usersActorFuture = (userParentActor ? UserParentActor.GetAllUsers).mapTo[Iterable[ActorRef]]
|
val userActorsFuture = (userParentActor ? UserParentActor.GetAllUsers).mapTo[Iterable[ActorRef]]
|
||||||
usersActorFuture.map(actorRefs => {
|
userActorsFuture.map(actorRefs => {
|
||||||
logger.debug(s"There are ${actorRefs.size} users on site")
|
logger.debug(s"There are ${actorRefs.size} users on site")
|
||||||
actorRefs.map(userActorRef => userActorRef ? GetName).map(res => {
|
actorRefs.map(userActorRef => userActorRef ? GetName).map(res => {
|
||||||
res.onComplete {
|
res.onComplete {
|
||||||
@ -81,23 +96,41 @@ class UserActor(out: ActorRef,
|
|||||||
lobbiesActor ! CreateLobby(name)
|
lobbiesActor ! CreateLobby(name)
|
||||||
|
|
||||||
case Some("leaveDecider") =>
|
case Some("leaveDecider") =>
|
||||||
lobbiesActor ! LeaveLobby(name)
|
lobbieActor.foreach(lobby => lobby ! LeaveLobby)
|
||||||
|
|
||||||
case Some("updateDecider") =>
|
case Some("setReady") =>
|
||||||
lobbiesActor ! BanMap("map1")
|
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") =>
|
case Some("getLobbies") =>
|
||||||
logger.debug("Get all lobby request")
|
logger.debug("Get all lobby request")
|
||||||
(lobbiesActor ? GetAllLobbies).mapTo[List[LobbyInfoResponse]] onComplete {
|
(lobbiesActor ? GetAllLobbies).mapTo[List[RefreshLobbyInfo]] onComplete {
|
||||||
case Success(lobbies) => {
|
case Success(lobbies) => {
|
||||||
logger.info(s"Received lobbies: $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)
|
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 {
|
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 {
|
object UserParentActor {
|
||||||
|
|
||||||
@ -139,7 +164,16 @@ object UserActor {
|
|||||||
|
|
||||||
case object GetName
|
case object GetName
|
||||||
|
|
||||||
|
case class RefreshLobbyInfo(lobbyInfo: LobbyInfo)
|
||||||
|
|
||||||
|
case class SetUserAsHost(lobbyInfo: LobbyInfo)
|
||||||
|
|
||||||
|
case class SetUserAsSecondPlayer(lobbyInfo: LobbyInfo)
|
||||||
|
|
||||||
case object CreateLobby
|
case object CreateLobby
|
||||||
|
|
||||||
|
case object HostLeaveLobby
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
BIN
app/assets/images/buttons/isNotAuto.png
Normal file
BIN
app/assets/images/buttons/isNotAuto.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 18 KiB |
BIN
app/assets/images/maps/2p_blood_river_[Rem].jpg
Normal file
BIN
app/assets/images/maps/2p_blood_river_[Rem].jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 92 KiB |
BIN
app/assets/images/maps/2p_fata_morgana_[Rem].jpg
Normal file
BIN
app/assets/images/maps/2p_fata_morgana_[Rem].jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 85 KiB |
@ -1,8 +1,7 @@
|
|||||||
|
|
||||||
var updateDecider;
|
|
||||||
|
|
||||||
var ws;
|
var ws;
|
||||||
|
|
||||||
|
var userName = ""
|
||||||
|
|
||||||
window.onload = function() {
|
window.onload = function() {
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
@ -11,36 +10,6 @@ window.onload = function() {
|
|||||||
return Math.floor(Math.random() * Math.floor(max));
|
return Math.floor(Math.random() * Math.floor(max));
|
||||||
}
|
}
|
||||||
|
|
||||||
var DeciderLobby = Backbone.View.extend({
|
|
||||||
|
|
||||||
lobbies: undefined,
|
|
||||||
|
|
||||||
initialize: function (number) {
|
|
||||||
console.log(number);
|
|
||||||
this.elCount = number;
|
|
||||||
},
|
|
||||||
|
|
||||||
template: _.template('<td><%= title %></td>' +
|
|
||||||
'<td><%= title %></td>' +
|
|
||||||
'<td><%= content %></td>'),
|
|
||||||
|
|
||||||
events: {
|
|
||||||
"click .title": "check" // Обработчик клика на кнопке "Проверить"
|
|
||||||
},
|
|
||||||
|
|
||||||
check: function () {
|
|
||||||
this.elCount = "azaz" + getRandomInt(100000000);
|
|
||||||
this.render();
|
|
||||||
},
|
|
||||||
|
|
||||||
render: function() {
|
|
||||||
console.log("render");
|
|
||||||
this.$el.html(this.template({title: "Vasyan " + this.elCount, content: "noob"}));
|
|
||||||
console.log(this.$el);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
var LobbyList = Backbone.View.extend({
|
var LobbyList = Backbone.View.extend({
|
||||||
|
|
||||||
lobbies: undefined,
|
lobbies: undefined,
|
||||||
@ -59,28 +28,50 @@ window.onload = function() {
|
|||||||
"click .title": "check" // Обработчик клика на кнопке "Проверить"
|
"click .title": "check" // Обработчик клика на кнопке "Проверить"
|
||||||
},
|
},
|
||||||
|
|
||||||
check: function () {
|
joinAsPlayer: function () {
|
||||||
this.elCount = "azaz" + getRandomInt(100000000);
|
this.elCount = "azaz" + getRandomInt(100000000);
|
||||||
this.render();
|
this.render();
|
||||||
},
|
},
|
||||||
|
|
||||||
render: function() {
|
render: function() {
|
||||||
this.$el.html(this.template());
|
|
||||||
var lobbiesAsTableRows = _.reduce(this.lobbies, function (memo, lobby) {
|
var lobbiesAsTableRows = _.reduce(this.lobbies, function (memo, lobby) {
|
||||||
console.log(lobby, memo);
|
|
||||||
|
var joinButton = '<button class="btn btn-primary join-as-player" onclick="joinDecider(\''+lobby.lobbyActorName+'\')">' +
|
||||||
|
'<img src="assets/images/buttons/isAuto.png" style="height: 25px;"> Join lobby <img src="assets/images/buttons/isAuto.png" style="height: 25px;">' +
|
||||||
|
'</button>';
|
||||||
|
var observerButton = '<button class="btn btn-success join-as-observer" lobbyId="'+lobby.lobbyActorName+'">' +
|
||||||
|
'<img src="assets/images/buttons/Ulthwe.png" style="height: 25px;"> Observer <img src="assets/images/buttons/Ulthwe.png" style="height: 25px;">' +
|
||||||
|
'</button>';
|
||||||
|
|
||||||
return memo + '<tr>\n' +
|
return memo + '<tr>\n' +
|
||||||
' <td>'+ lobby.lobbyName +'</td>\n' +
|
' <td>'+ lobby.user1Name +'</td>\n' +
|
||||||
|
' <td>'+ lobby.user2Name +'</td>\n' +
|
||||||
' <td>'+ lobby.status +'</td>\n' +
|
' <td>'+ lobby.status +'</td>\n' +
|
||||||
' <td>Action</td>' +
|
' <td>' + joinButton + ' ' + observerButton +
|
||||||
|
' </td>' +
|
||||||
'</tr>';
|
'</tr>';
|
||||||
}, "");
|
}, "");
|
||||||
$("#deciderList tbody", this.el).append(lobbiesAsTableRows);
|
|
||||||
return this;
|
var tableStart = '<table id ="deciderList" class="table"><tbody><tr>\n' +
|
||||||
|
' <th>Player1</th>\n' +
|
||||||
|
' <th>Player2</th>\n' +
|
||||||
|
' <th>Status</th>\n' +
|
||||||
|
' <th style="width: 400px;">Action</th></tr>\n';
|
||||||
|
|
||||||
|
var tableEnd = '</tbody></table>';
|
||||||
|
|
||||||
|
var res = tableStart + lobbiesAsTableRows + tableEnd;
|
||||||
|
|
||||||
|
$("#deciderList tbody", res).append(lobbiesAsTableRows);
|
||||||
|
console.log(res);
|
||||||
|
|
||||||
|
this.$el.html(res);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
var lobbyList = new LobbyList;
|
var lobbyList = new LobbyList;
|
||||||
$("#lobbiesList").append(lobbyList.el);
|
$("#lobbiesList").append(lobbyList.$el);
|
||||||
lobbyList.render();
|
lobbyList.render();
|
||||||
|
|
||||||
$("#createDecider").click(function(event) {
|
$("#createDecider").click(function(event) {
|
||||||
@ -104,25 +95,45 @@ window.onload = function() {
|
|||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$("#exit").click(function(event) {
|
||||||
|
event.preventDefault();
|
||||||
|
ws.send(JSON.stringify({
|
||||||
|
type: "leaveDecider"
|
||||||
|
}));
|
||||||
|
$("#decider").hide();
|
||||||
|
$("#lobbies").show();
|
||||||
|
});
|
||||||
|
|
||||||
if($.cookie('user')=== undefined){
|
if($.cookie('user')=== undefined){
|
||||||
result = prompt("Введите ник", );
|
var result = prompt("Введите ник", );
|
||||||
$.cookie('user', result, { expires: 7 });
|
$.cookie('user', result, { expires: 7 });
|
||||||
|
userName = result;
|
||||||
}else{
|
}else{
|
||||||
console.log("Welcome, " + $.cookie('user'));
|
userName = $.cookie('user');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$("#playerName").html(userName);
|
||||||
|
|
||||||
|
|
||||||
ws = new WebSocket($("body").data("ws-url"));
|
ws = new WebSocket($("body").data("ws-url"));
|
||||||
ws.onmessage = function(event) {
|
ws.onmessage = function(event) {
|
||||||
var message;
|
var message;
|
||||||
message = JSON.parse(event.data);
|
message = JSON.parse(event.data);
|
||||||
switch (message.type) {
|
switch (message.type) {
|
||||||
case "maps":
|
case "refreshLobby":
|
||||||
return updateDecider(message);
|
renderMaps(message.lobby.maps);
|
||||||
default:
|
renderPlayersAndStats(message.lobby);
|
||||||
|
break;
|
||||||
|
case "switchToLobby":
|
||||||
|
console.log(message);
|
||||||
|
switchToLobby(message.lobby.maps);
|
||||||
|
renderPlayersAndStats(message.lobby);
|
||||||
|
break;
|
||||||
case "lobbies":
|
case "lobbies":
|
||||||
lobbyList.lobbies = message.lobbies;
|
lobbyList.lobbies = message.lobbies;
|
||||||
lobbyList.render();
|
lobbyList.render();
|
||||||
return console.log(message);
|
return console.log(message);
|
||||||
|
default:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
ws.onopen = function () {
|
ws.onopen = function () {
|
||||||
@ -140,15 +151,144 @@ window.onload = function() {
|
|||||||
|
|
||||||
function changeNick() {
|
function changeNick() {
|
||||||
result = prompt("Введите ник", $.cookie('user'));
|
result = prompt("Введите ник", $.cookie('user'));
|
||||||
|
if(result == null) return;
|
||||||
$.cookie('user', result, { expires: 7 });
|
$.cookie('user', result, { expires: 7 });
|
||||||
ws.send(JSON.stringify({
|
ws.send(JSON.stringify({
|
||||||
type: "userName",
|
type: "userName",
|
||||||
name: $.cookie('user')
|
name: $.cookie('user')
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
userName = $.cookie('user');
|
||||||
|
$("#playerName").html(userName);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
updateDecider = function(message) {
|
// -----ф-ии прихода с сервера
|
||||||
console.log(message.deciderMaps);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
function switchToLobby(maps) {
|
||||||
|
console.log(maps);
|
||||||
|
renderMaps(maps);
|
||||||
|
$("#lobbies").hide();
|
||||||
|
$("#decider").show();
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderMaps(maps) {
|
||||||
|
var resHtml = "";
|
||||||
|
|
||||||
|
_.each(maps, function (map) {
|
||||||
|
|
||||||
|
var banHtml = "";
|
||||||
|
var banClass = "";
|
||||||
|
if(map.isBanned){
|
||||||
|
banHtml = "<div class = 'banX'>✕</div>";
|
||||||
|
banClass = "bannedMap";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
resHtml = resHtml + '<div class="col-xs-4 col-md-3 col-lg-2"><button class = "mapSelect" onmousedown="banMap(\''+map.map+'\')">'+
|
||||||
|
'<div class="mapImageAndText '+banClass+'">' +
|
||||||
|
'<img class="img-rounded center-block" style="width:128px;" src="/assets/images/maps/'+encodeURI(map.map)+'.jpg">' +
|
||||||
|
'</div>'+convertMapName(map.map)+
|
||||||
|
banHtml + '</button></div>';
|
||||||
|
})
|
||||||
|
$("#mapList").html(resHtml);
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderPlayersAndStats(lobby) {
|
||||||
|
var resHtml = "<center>";
|
||||||
|
var player1ReadyBtn = "";
|
||||||
|
var player2ReadyBtn = "";
|
||||||
|
var readyImg = "<img src='/assets/images/buttons/isAuto.png' class='readyImg'/>";
|
||||||
|
var notReadyImg = "<img src='/assets/images/buttons/isNotAuto.png' class='readyImg'/>";
|
||||||
|
|
||||||
|
if(lobby.user1Name === userName){
|
||||||
|
if(lobby.user1Ready){
|
||||||
|
player1ReadyBtn = "<button class='btn btn-default' onclick='setNotReady()'>"+readyImg+" Ready "+readyImg+"</button>"
|
||||||
|
}else{
|
||||||
|
player1ReadyBtn = "<button class='btn btn-default' onclick='setReady()'>"+notReadyImg+" Not ready "+notReadyImg+"</button>"
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
if(lobby.user1Ready){
|
||||||
|
player1ReadyBtn = readyImg
|
||||||
|
}else{
|
||||||
|
player1ReadyBtn = notReadyImg
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(lobby.user2Name === userName){
|
||||||
|
if(lobby.user2Ready){
|
||||||
|
player2ReadyBtn = "<button class='btn btn-default' onclick='setNotReady()'>"+readyImg+" Ready "+readyImg+"</button>"
|
||||||
|
}else{
|
||||||
|
player2ReadyBtn = "<button class='btn btn-default' onclick='setReady()'>"+notReadyImg+" Not ready "+notReadyImg+"</button>"
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if(lobby.user2Ready){
|
||||||
|
player2ReadyBtn = readyImg
|
||||||
|
}else{
|
||||||
|
player2ReadyBtn = notReadyImg
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(lobby);
|
||||||
|
|
||||||
|
switch (lobby.status){
|
||||||
|
case "NotStarted()":
|
||||||
|
resHtml = "<div style='float: left'>" + lobby.user1Name + ": " + player1ReadyBtn +"</div>"
|
||||||
|
if(lobby.user2Name !== ""){
|
||||||
|
var kickBtn = ""
|
||||||
|
if(lobby.user1Name === userName){
|
||||||
|
kickBtn = "<button class='btn btn-danger'>Kick</button>";
|
||||||
|
}
|
||||||
|
resHtml += "<div style='float: right'>" + lobby.user2Name + ": " + player2ReadyBtn + "<br/>" + kickBtn + "</div>"
|
||||||
|
}else{
|
||||||
|
resHtml += "<div style='float: right'>waiting 2-nd player...</div>"
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "Draft()":
|
||||||
|
resHtml = "<center><b>"+lobby.user1Name+ " vs " + lobby.user2Name +"</b></center>";
|
||||||
|
break;
|
||||||
|
case "Finish()":
|
||||||
|
var lastMap = _.find(lobby.maps, function (map){
|
||||||
|
return map.isBanned === false;
|
||||||
|
}).map;
|
||||||
|
resHtml = "<center><b>"+convertMapName(lastMap)+"</b></center>";
|
||||||
|
}
|
||||||
|
|
||||||
|
resHtml = resHtml + "</center>"
|
||||||
|
|
||||||
|
$("#playersStatsList").html(resHtml);
|
||||||
|
}
|
||||||
|
|
||||||
|
function banMap(map){
|
||||||
|
ws.send(JSON.stringify({
|
||||||
|
type: "banMap",
|
||||||
|
map: map
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
function setReady(){
|
||||||
|
ws.send(JSON.stringify({
|
||||||
|
type: "setReady"
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
function setNotReady(){
|
||||||
|
ws.send(JSON.stringify({
|
||||||
|
type: "setNotReady"
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
function joinDecider(actorName){
|
||||||
|
console.log(actorName);
|
||||||
|
ws.send(JSON.stringify({
|
||||||
|
type: "joinDecider",
|
||||||
|
lobbyActorName: actorName
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
function convertMapName (techMapName) {
|
||||||
|
var mapName = techMapName.replace("2p_", "").replaceAll("_", " ") + " (2)";
|
||||||
|
return mapName.charAt(0).toUpperCase() + mapName.slice(1);
|
||||||
|
}
|
||||||
|
|||||||
@ -67,6 +67,36 @@ body {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.readyImg{
|
||||||
|
height: 25px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#playerName{
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.banX{
|
||||||
|
font-size: 128px;
|
||||||
|
margin-top: -174px;
|
||||||
|
left: 34px;
|
||||||
|
color: red;
|
||||||
|
position: absolute;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bannedMap{
|
||||||
|
-webkit-filter: grayscale(1); /* Webkit браузеры */
|
||||||
|
}
|
||||||
|
|
||||||
|
.mapSelect{
|
||||||
|
margin: 10px;
|
||||||
|
position:relative;
|
||||||
|
width: 175px;
|
||||||
|
height: 175px;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
.chart-holder, .details-holder {
|
.chart-holder, .details-holder {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|||||||
@ -17,27 +17,28 @@
|
|||||||
</head>
|
</head>
|
||||||
<body data-ws-url="@routes.HomeController.ws.webSocketURL()">
|
<body data-ws-url="@routes.HomeController.ws.webSocketURL()">
|
||||||
<div class="navbar navbar-inverse navbar-fixed-top">
|
<div class="navbar navbar-inverse navbar-fixed-top">
|
||||||
<div class="navbar-inner">
|
<div class="navbar-inner" style="margin: 10px;">
|
||||||
<div class="container"><br/>
|
<span id="playerName"></span>
|
||||||
<button onclick="changeNick();" class="btn">Change nick</button>
|
<button onclick="changeNick();" style="margin-left: 10px;" >Change nick</button>
|
||||||
<br/><br/>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<br/>
|
|
||||||
<br/>
|
|
||||||
<center>
|
|
||||||
<button id = "createDecider" class="btn btn-primary">Create decider</button>
|
|
||||||
<button id = "getAllUsers" class="btn btn-primary">Refresh</button>
|
|
||||||
<button id = "updateDecider" class="btn btn-primary">Ban</button>
|
|
||||||
</center>
|
|
||||||
|
|
||||||
<br/>
|
<br/>
|
||||||
|
|
||||||
<div class ="container">
|
<div class ="container">
|
||||||
<div id = "lobbiesList"></div>
|
<div id = "lobbies">
|
||||||
<div id = "decider"></div>
|
<center>
|
||||||
|
<button id = "createDecider" class="btn btn-primary">Create decider</button>
|
||||||
|
<button id = "getAllUsers" class="btn btn-primary">Refresh</button>
|
||||||
|
</center><br/>
|
||||||
|
<div id = "lobbiesList"></div>
|
||||||
|
</div>
|
||||||
|
<div id = "decider" style="display:none">
|
||||||
|
<button id = "exit" class="btn btn-primary">Exit</button>
|
||||||
|
<br/>
|
||||||
|
<div id = "mapList"></div>
|
||||||
|
<div style="clear: both"></div>
|
||||||
|
<div id = "playersStatsList"></div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
|
|||||||
@ -7,6 +7,8 @@ play.filters.headers {
|
|||||||
# https://www.playframework.com/documentation/latest/AllowedHostsFilter
|
# https://www.playframework.com/documentation/latest/AllowedHostsFilter
|
||||||
# Allow requests to localhost:9000.
|
# Allow requests to localhost:9000.
|
||||||
play.filters.hosts {
|
play.filters.hosts {
|
||||||
allowed = ["localhost:9000"]
|
allowed = ["localhost:9000", "localhost"]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
maps = ["2p_battle_marshes", "2p_fallen_city", "2p_fata_morgana_[Rem]", "2p_meeting_of_minds", "2p_outer_reaches", "2p_quests_triumph", "2p_shrine_of_excellion_[Rem]", "2p_titan_fall_[Rem]", "2p_tranquilitys_end_[rem]", "2p_blood_river_[Rem]", "2p_emerald_river", "2p_deadly_fun_archeology", "2p_fraziersdemise"]
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user