Tournaments can be configured now

This commit is contained in:
Viktor Kholodov 2021-10-23 14:13:36 +03:00
parent 52baef061b
commit aa692419cf
8 changed files with 93 additions and 41 deletions

View File

@ -20,7 +20,7 @@ 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(hostUser: LobbyUser) extends Actor with LazyLogging {
class LobbieActor(hostUser: LobbyUser, deciderName: String) extends Actor with LazyLogging {
val config = ConfigFactory.load()
logger.info(s"Create lobby... host: ${hostUser.actorRef.path.name}")
@ -46,7 +46,7 @@ class LobbieActor(hostUser: LobbyUser) extends Actor with LazyLogging {
private var isNecrons: Boolean = false
private val mapsLobby: Set[DeciderMap] = {
val configMaps = config.getStringList("maps").asScala
val configMaps = config.getStringList(s"deciders.$deciderName.maps").asScala
configMaps.map(e => {
DeciderMap(e)
}).toSet
@ -57,6 +57,7 @@ class LobbieActor(hostUser: LobbyUser) extends Actor with LazyLogging {
UserInfo(hostUser.name,firstPlayerReady),
UserInfo("", secondPlayerReady),
self.path.name,
deciderName,
status.toString(),
playerTurn,
lobbyType.toString(),
@ -211,6 +212,7 @@ class LobbieActor(hostUser: LobbyUser) extends Actor with LazyLogging {
UserInfo(host.name, firstPlayerReady),
UserInfo(user2Name, secondPlayerReady),
self.path.name,
deciderName,
status.toString(),
playerTurn,
lobbyType.toString(),
@ -223,7 +225,7 @@ case class BanMap(mapName: String)
case class MapsUpdate(maps: Set[String])
case class CreateLobby(userName: String)
case class CreateLobby(userName: String, deciderName: String)
case class JoinLobbyAsPlayer(lobbyUser: LobbyUser)
@ -250,6 +252,7 @@ case class UserInfo(name: String, isReady: Boolean)
case class LobbyInfo(user1Info: UserInfo,
user2Info: UserInfo,
lobbyActorName: String,
deciderName: String,
status: String,
playerTurn: BigDecimal,
selectedType: String,

View File

@ -17,10 +17,10 @@ class LobbiesActor extends Actor with LazyLogging {
val lobbies: ListBuffer[String] = ListBuffer()
def receive: Receive = LoggingReceive {
case CreateLobby(hostName) =>
case CreateLobby(hostName, deciderName) =>
val hostActorRef = sender
logger.info(s"Player ${hostActorRef.path.name} create lobby.")
val lobbyActor = context.actorOf(Props(new LobbieActor(LobbyUser(hostName, hostActorRef))),
val lobbyActor = context.actorOf(Props(new LobbieActor(LobbyUser(hostName, hostActorRef), deciderName)),
s"lobbyActor-${(math.random * 100000000L).toLong}")
lobbyActor.tell(WatchLobby("watchIt"), hostActorRef)
case JoinLobbyByActorName(lobbyName, userName) =>

View File

@ -35,6 +35,7 @@ class UserActor(out: ActorRef,
"user1Info" -> lobby.user1Info,
"user2Info" -> lobby.user2Info,
"lobbyActorName" -> lobby.lobbyActorName,
"deciderName" -> lobby.deciderName,
"status" -> lobby.status,
"playerTurn" -> lobby.playerTurn,
"selectedType" -> lobby.selectedType,
@ -54,6 +55,7 @@ class UserActor(out: ActorRef,
"user1Info" -> lobby.user1Info,
"user2Info" -> lobby.user2Info,
"lobbyActorName" -> lobby.lobbyActorName,
"deciderName" -> lobby.deciderName,
"status" -> lobby.status,
"playerTurn" -> lobby.playerTurn,
"selectedType" -> lobby.selectedType,
@ -129,7 +131,8 @@ class UserActor(out: ActorRef,
logger.debug(s"Set user name: $name for actor ${this.self}")
case Some("createDecider") =>
LobbiesActor.actor ! CreateLobby(name)
val deciderName = (json \ "deciderName").as[String]
LobbiesActor.actor ! CreateLobby(name, deciderName)
case Some("leaveDecider") =>
lobbieActor.foreach(lobby => lobby ! LeaveLobby)

View File

@ -37,6 +37,8 @@ window.onload = function() {
var lobbiesAsTableRows = _.reduce(this.lobbies, function (memo, lobby) {
if ($("#deciderName").html() !== lobby.deciderName) return memo;
var joinButton = (lobby.status === "NotStarted()") ? '<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>' : "";
@ -77,7 +79,8 @@ window.onload = function() {
$("#createDecider").click(function(event) {
event.preventDefault();
ws.send(JSON.stringify({
type: "createDecider"
type: "createDecider",
deciderName: $("#deciderName").html()
}));
});
@ -312,10 +315,12 @@ function renderPlayersAndStats(lobby) {
if(lobby.user1Info.name !== userName){
disabledText = "disabled";
}
//TODO: here from config
resHtml += "<br/><select class=\"form-control\" id = 'deciderOption' onChange='changeLobbyType()' "+disabledText+" >" +
"<option "+looserPickSelected+" value = 'looserpick'>Play on last map (BO1)</option>" +
"<option "+last3Selected+" value = 'last3'>Play on last 3 maps (BO3)</option>" +
"<option "+last5Selected+" value = 'last5'>Play on last 5 maps (BO5)</option>" +
"<option "+looserPickSelected+" value = 'looserpick'>Play on last map</option>" +
//"<option "+last3Selected+" value = 'last3'>Play on last 3 maps</option>" +
//"<option "+last5Selected+" value = 'last5'>Play on last 5 maps</option>" +
//"<option "+superfinalSelected+" value = 'superfinal'>Superfinal (BO7)</option>" +
"</select>";
@ -324,8 +329,10 @@ function renderPlayersAndStats(lobby) {
}else{
disabledText = "";
}
resHtml += "<br/><label><input onchange=\"changeIsNecronSelected()\" id='isNecron' type=\"checkbox\" "+isNecronsSelected +" " + disabledText +">" +
" Necrons are present</label>";
if($("#necronPresence").html() === "true"){
resHtml += "<br/><label><input onchange=\"changeIsNecronSelected()\" id='isNecron' type=\"checkbox\" "+isNecronsSelected +" " + disabledText +">" +
" Necrons are present</label>";
}
resHtml += "</div>";
break;
case "Draft()":

View File

@ -9,6 +9,7 @@ import akka.pattern.ask
import akka.stream._
import akka.stream.scaladsl._
import akka.util.Timeout
import com.typesafe.config.ConfigFactory
import org.reactivestreams.Publisher
import play.api.libs.json._
import play.api.mvc._
@ -16,6 +17,8 @@ import play.api.mvc._
import scala.concurrent.duration._
import scala.concurrent.{ExecutionContext, Future}
case class LastMapsSelectConfig(last1: Boolean, last3: Boolean, last5: Boolean, last7: Boolean)
/**
* This class creates the actions and the websocket needed.
*/
@ -25,6 +28,8 @@ class HomeController @Inject()(cc: ControllerComponents) extends AbstractControl
implicit val actorSystem: ActorSystem = ActorSystem()
implicit val ec: ExecutionContext = defaultExecutionContext
val config = ConfigFactory.load()
// Use a direct reference to SLF4J
private val logger = org.slf4j.LoggerFactory.getLogger("controllers.HomeController")
@ -32,9 +37,13 @@ class HomeController @Inject()(cc: ControllerComponents) extends AbstractControl
val userParentActor: ActorRef = actorSystem.actorOf(Props(classOf[UserParentActor], actorSystem))
// Home page that renders template
def index() = Action { implicit request =>
def index(deciderName: String) = Action { implicit request =>
logger.info(s"Received request from: ${request.remoteAddress}")
Ok(views.html.index())
val deciderHumanName = config.getString(s"deciders.$deciderName.name")
val deciderDescription = config.getString(s"deciders.$deciderName.rules")
val necronPresence = config.getBoolean(s"deciders.$deciderName.necronrestrict")
val lastmapsSettings = LastMapsSelectConfig(true, true, true, true)
Ok(views.html.index(deciderName, deciderHumanName, deciderDescription, necronPresence, lastmapsSettings))
}
/**

View File

@ -1,6 +1,14 @@
@()(implicit r: Request[_])
@(deciderName: String, deciderHumanName: String, rules: String, necronPresence: Boolean, boSettings: LastMapsSelectConfig)(implicit r: Request[_])
<!DOCTYPE html>
<span id="deciderName" style="display: none">@deciderName</span>
<span id="necronPresence" style="display: none">@necronPresence</span>
<span id="last1Presence" style="display: none">@boSettings.last1</span>
<span id="last3Presence" style="display: none">@boSettings.last3</span>
<span id="last5Presence" style="display: none">@boSettings.last5</span>
<span id="last7Presence" style="display: none">@boSettings.last7</span>
<html>
<head>
<title>Soulstorm tournament decider</title>
@ -13,7 +21,7 @@
<script type='text/javascript' src='@routes.Assets.at("lib/backbonejs/backbone.js")'></script>
<script type="text/javascript" src="@routes.Assets.at("lib/jquery-cookie/jquery.cookie.js")"></script>
<script type='text/javascript' src='@routes.Assets.at("javascripts/index.js?180921")'></script>
<script type='text/javascript' src='@routes.Assets.at("javascripts/index.js?231021")'></script>
</head>
<body data-ws-url="@routes.HomeController.ws.webSocketURL()">
<div class="navbar navbar-inverse navbar-fixed-top">
@ -51,10 +59,8 @@
</div>
</div>
<div style="clear: both"></div>
<div><i><b>Правила турнира "Осенняя мясорубка#1"</b><br/>
<p>Выбор карт в БО3 и БО5 осуществляется без лузерпиков, с тремя и пятью десайдерами соответственно.
Игроки вычеркивают по очереди карты из маппула, пока их не останется 3 (для БО3) или 5 (для БО5). На этих картах и проходят все матчи встречи. Затем игроки вычеркивают выбранные карты, пока не останется только одна, на которой и играется первый матч встречи. Тот, кто первым начал вычеркивать из всего маппула, уступает оппоненту право вычеркивания первой карты из оставшихся карт-десайдеров. Во втором и последующем матчах проигравший выбирает карту из числа выбранных 3 (5) десайдеров.
В случае, если один из игроков играет за расу некронов, из маппула исключаются карты MoM и SoE, после чего оба игрока приступают к вычеркиванию карт стандартным образом из 11-картового маппула.</p>
<div><i><b>Правила турнира "@deciderHumanName"</b><br/>
<p>@rules</p>
<br>
</i>
</div>

View File

@ -7,17 +7,45 @@ play.filters.hosts {
play.http.secret.key="QCY?tAnfk?aZ?iwrNwnxIlR6CTf:123123Latabg@5241AB`R5W:1uDFN];Ik@n"
play.server.http.port = 80
maps = ["2p_battle_marshes",
"2p_fallen_city_[Rem]",
"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_deadly_fun_archeology",
"2p_vortex_plateau",
"2p_sugaroasis",
"2p_blood_river_[Rem]"]
deciders{
dvijcup{
maps = ["2p_battle_marshes",
"2p_fallen_city_[Rem]",
"2p_meeting_of_minds",
"2p_quests_triumph",
"2p_shrine_of_excellion_[Rem]",
"2p_titan_fall_[Rem]",
"2p_tranquilitys_end_[Rem]",
"2p_fraziersdemise",
"2p_sugaroasis",
"2p_blood_river_[Rem]",
"2p_deadly_fun_archeology"]
name = "Dvij cup"
rules = """Выбор карт в БО3 и БО5 осуществляется без лузерпиков, с тремя и пятью десайдерами соответственно.
Игроки вычеркивают по очереди карты из маппула, пока их не останется 3 (для БО3) или 5 (для БО5). На этих картах и проходят все матчи встречи.
Затем игроки вычеркивают выбранные карты, пока не останется только одна, на которой и играется первый матч встречи.
Тот, кто первым начал вычеркивать из всего маппула, уступает оппоненту право вычеркивания первой карты из оставшихся карт-десайдеров.
Во втором и последующем матчах проигравший выбирает карту из числа выбранных 3 (5) десайдеров."""
necronrestrict = false
}
newplayerslegue{
necronrestrict = false
maps = ["2p_battle_marshes",
"2p_fallen_city",
"2p_fata_morgana",
"2p_meeting_of_minds",
"2p_outer_reaches",
"2p_quests_triumph",
"2p_shrine_of_excellion",
"2p_titan_fall_[Rem]",
"2p_tranquilitys_end",
"2p_emerald_river",
"2p_vortex_plateau",
"2p_fraziersdemise",
"2p_blood_river"]
name = "Лига новых игроков 2"
rules = """Первую карту вы с оппонентом выбираете, поочередно вычеркивая неудобные для Вас карты из этих тринадцати. Вычеркиваете, пока не остается одна. На ней и играете. В последующих матчах карту выбирает тот, кто проиграл (это называется лузер-пик). Выбирать повторно карту, на которой вы с этим оппонентом уже играли, нельзя. Играть на ремастер-версиях карт можно по обоюдному согласию игроков. Если один из Вас не скачал новые версии карт - играйте на старых."""
necronrestrict = true
}
}

View File

@ -2,15 +2,11 @@
# This file defines all application routes (Higher priority routes first)
# ~~~~
GET /meatgrinder controllers.HomeController.index
GET /bigbossofsummer controllers.HomeController.index
GET /dvijcup controllers.HomeController.index
GET /decider/:name controllers.HomeController.index(name)
GET /ws controllers.HomeController.ws
GET /ws controllers.HomeController.ws
GET /reloadconfig controllers.AdminController.reloadConfig
GET /lobbyadmin controllers.AdminController.viewAllLobbies
GET /lobbyadmin controllers.AdminController.viewAllLobbies
# Map static resources from the /public folder to the /assets URL path
GET /assets/*file controllers.Assets.at(path="/public", file)
GET /assets/*file controllers.Assets.at(path="/public", file)