Видосы и параметризованный выбор кол-ва рас

This commit is contained in:
v.holodov 2022-06-03 21:07:54 +03:00
parent aa692419cf
commit d3e90fb01e
34 changed files with 685 additions and 126 deletions

View File

@ -1,20 +1,20 @@
package actors
import actors.UserActor.{BanMapMessage, GetName, HostLeaveLobby, LobbyFatal, Message, RefreshLobbyInfo, SecondPlayerLeaveLobby, SendBanMapMessage, SendMessage, SetUserAsHost, SetUserAsObs, SetUserAsSecondPlayer}
import akka.actor.{Actor, ActorLogging, ActorRef}
import actors.UserActor._
import akka.actor.{Actor, 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 com.typesafe.config.ConfigFactory
import com.typesafe.scalalogging.LazyLogging
import java.util
import scala.collection.JavaConverters.iterableAsScalaIterableConverter
import scala.collection.immutable.{HashSet, Queue}
import scala.concurrent.Await
import scala.collection.immutable.HashSet
import scala.concurrent.duration._
case class LobbyUser(name: String, actorRef: ActorRef)
case class DeciderMap(map: String, var isBanned: Boolean = false)
case class DeciderMap(map: String, description: Option[String] = None, var isBanned: Boolean = false)
/**
* There is one StockActor per stock symbol. The StockActor maintains a list of users watching the stock and the stock
@ -41,20 +41,26 @@ class LobbieActor(hostUser: LobbyUser, deciderName: String) extends Actor with L
private var status: LobbyStatus = NotStarted()
private var lobbyType: LobbyType = Last3()
private var lobbyType: LobbyType = Last1()
private var isNecrons: Boolean = false
private var firstPlayerSelectedRaces: Option[SelectedRaces] = None
private var secondPlayerSelectedRaces: Option[SelectedRaces] = None
private var thirdPlayerSelectedRaces: Option[SelectedRaces] = None
private val mapsLobby: Set[DeciderMap] = {
val configMaps = config.getStringList(s"deciders.$deciderName.maps").asScala
val configMaps = config.getList(s"deciders.$deciderName.maps").asScala
configMaps.map(e => {
DeciderMap(e)
val mapConfig = e.unwrapped().asInstanceOf[util.ArrayList[String]].asScala
DeciderMap(mapConfig.head, mapConfig.tail.headOption)
}).toSet
}
hostUser.actorRef.tell(
SetUserAsHost(LobbyInfo(
UserInfo(hostUser.name,firstPlayerReady),
UserInfo(hostUser.name, firstPlayerReady),
UserInfo("", secondPlayerReady),
self.path.name,
deciderName,
@ -73,23 +79,24 @@ class LobbieActor(hostUser: LobbyUser, deciderName: String) extends Actor with L
// notify watchers
logger.info(s"Ban map $mapName by ${sender.path.name}")
if(status == Draft()){
if((playerTurn == 1 && sender == host.actorRef) ||
(playerTurn == 2 && secondPlayer.exists(_.actorRef == sender))){
if (status == Draft()) {
if ((playerTurn == 1 && sender == host.actorRef) ||
(playerTurn == 2 && secondPlayer.exists(_.actorRef == sender))) {
mapsLobby.find(p => p.map == mapName) match {
case Some(map) =>
if(!map.isBanned){
if (!map.isBanned) {
map.isBanned = true
if (playerTurn== 1) playerTurn = 2 else playerTurn = 1
if(mapsLobby.count(_.isBanned == false) == 3 && lobbyType == Last3() ||
if (playerTurn == 1) playerTurn = 2 else playerTurn = 1
if (mapsLobby.count(_.isBanned == false) == 1 && lobbyType == Last1() ||
mapsLobby.count(_.isBanned == false) == 3 && lobbyType == Last3() ||
mapsLobby.count(_.isBanned == false) == 5 && lobbyType == Last5() ||
mapsLobby.count(_.isBanned == false) == 9 && lobbyType == Superfinal() ||
mapsLobby.count(_.isBanned == false) == 1 && lobbyType == LooserPick()){
mapsLobby.count(_.isBanned == false) == 7 && lobbyType == Last7()
) {
status = Finish()
}
users.foreach(_ ! RefreshLobbyInfo(getLobbyInfoResponse))
val senderName: String = if (sender == host.actorRef) {
val senderName: String = if (sender == host.actorRef) {
host.name
} else secondPlayer.get.name
users.foreach(_ ! SendBanMapMessage(BanMapMessage(senderName, mapName)))
@ -99,23 +106,35 @@ class LobbieActor(hostUser: LobbyUser, deciderName: String) extends Actor with L
case None =>
logger.error(s"Map $mapName not exist")
}
} else{
} 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 lobby status is '$status' status")
}
case selectedRaces: SelectedRaces =>
if (sender == host.actorRef) {
firstPlayerSelectedRaces = Some(selectedRaces)
logger.info(s"First player select $selectedRaces")
} else if (sender == secondPlayer.get.actorRef) {
secondPlayerSelectedRaces = Some(selectedRaces)
logger.info(s"Second player select $selectedRaces")
}
if (firstPlayerSelectedRaces.nonEmpty && secondPlayerSelectedRaces.nonEmpty) {
status = Draft()
users.foreach(_ ! RefreshLobbyInfo(getLobbyInfoResponse))
}
case SetReady =>
// notify watchers
var readyPlayer = sender()
if(readyPlayer == hostUser.actorRef){
if (readyPlayer == hostUser.actorRef) {
firstPlayerReady = true
} else if (secondPlayer.exists(sp => sp.actorRef == readyPlayer)) {
secondPlayerReady = true
}
if(firstPlayerReady && secondPlayerReady){
status = Draft()
if (firstPlayerReady && secondPlayerReady) {
status = SelectRace()
}
users.foreach(_ ! RefreshLobbyInfo(getLobbyInfoResponse))
@ -123,7 +142,7 @@ class LobbieActor(hostUser: LobbyUser, deciderName: String) extends Actor with L
case SetNotReady =>
// notify watchers
var notReadyPlayer = sender()
if(notReadyPlayer == hostUser.actorRef){
if (notReadyPlayer == hostUser.actorRef) {
firstPlayerReady = false
} else if (secondPlayer.exists(sp => sp.actorRef == notReadyPlayer)) {
secondPlayerReady = false
@ -132,22 +151,23 @@ class LobbieActor(hostUser: LobbyUser, deciderName: String) extends Actor with L
case ChangeLobbyType(lobbyTypeNew) =>
lobbyTypeNew match {
case "last1" =>
lobbyType = Last1()
case "last3" =>
lobbyType = Last3()
case "last5" =>
lobbyType = Last5()
case "superfinal" =>
lobbyType = Superfinal()
case "looserpick" =>
lobbyType = LooserPick()
case "last7" =>
lobbyType = Last7()
}
users.foreach(_ ! RefreshLobbyInfo(getLobbyInfoResponse))
case ChangeIsNecronSelected(isSelected) =>
isNecrons = isSelected
if(isSelected) {
mapsLobby.foreach(map => if(map.map == "2p_meeting_of_minds" || map.map == "2p_shrine_of_excellion_[Rem]") map.isBanned = true)
}else{
if (isSelected) {
mapsLobby.foreach(map => if (map.map == "2p_meeting_of_minds" || map.map == "2p_shrine_of_excellion_[Rem]") map.isBanned = true)
} else {
mapsLobby.foreach(map => map.isBanned = false)
}
users.foreach(_ ! RefreshLobbyInfo(getLobbyInfoResponse))
@ -163,7 +183,7 @@ class LobbieActor(hostUser: LobbyUser, deciderName: String) extends Actor with L
case MessageForLobby(message) =>
if (sender() == host.actorRef) {
users.foreach(_ ! SendMessage(Message(host.name, message)))
}else if (secondPlayer.exists(sp => sp.actorRef == sender())){
} else if (secondPlayer.exists(sp => sp.actorRef == sender())) {
users.foreach(_ ! SendMessage(Message(secondPlayer.get.name, message)))
}
case JoinLobbyAsPlayer(sp) =>
@ -184,16 +204,16 @@ class LobbieActor(hostUser: LobbyUser, deciderName: String) extends Actor with L
sender ! SetUserAsObs(getLobbyInfoResponse)
case LeaveLobby =>
users = users - sender
if(host.actorRef == sender()){
if (host.actorRef == sender()) {
users.foreach(_ ! HostLeaveLobby)
context.stop(self)
}else if(secondPlayer.exists(_.actorRef == sender())){
} else if (secondPlayer.exists(_.actorRef == sender())) {
secondPlayerReady = false
secondPlayer = None
if(status == Draft()){
if (status == Draft() || status == SelectRace()) {
users.foreach(_ ! SecondPlayerLeaveLobby)
context.stop(self)
}else {
} else {
users.foreach(_ ! RefreshLobbyInfo(getLobbyInfoResponse))
}
}
@ -209,8 +229,8 @@ class LobbieActor(hostUser: LobbyUser, deciderName: String) extends Actor with L
private def getLobbyInfoResponse: LobbyInfo = {
val user2Name = secondPlayer.map(_.name).getOrElse("")
LobbyInfo(
UserInfo(host.name, firstPlayerReady),
UserInfo(user2Name, secondPlayerReady),
UserInfo(host.name, firstPlayerReady, firstPlayerSelectedRaces),
UserInfo(user2Name, secondPlayerReady, secondPlayerSelectedRaces),
self.path.name,
deciderName,
status.toString(),
@ -247,7 +267,9 @@ case class ChangeIsNecronSelected(isSelected: Boolean)
case object InfoQuery
case class UserInfo(name: String, isReady: Boolean)
case class SelectedRaces(firstRace: Int, secondRace: Int, thirdRace: Int)
case class UserInfo(name: String, isReady: Boolean, selectedRaces: Option[SelectedRaces] = None)
case class LobbyInfo(user1Info: UserInfo,
user2Info: UserInfo,
@ -262,12 +284,21 @@ case class LobbyInfo(user1Info: UserInfo,
class LobbyStatus
sealed case class NotStarted() extends LobbyStatus
sealed case class SelectRace() extends LobbyStatus
sealed case class Draft() extends LobbyStatus
sealed case class Finish() extends LobbyStatus
class LobbyType
sealed case class Last1() extends LobbyType
sealed case class Last3() extends LobbyType
sealed case class Last5() extends LobbyType
sealed case class Last7() extends LobbyType
sealed case class Superfinal() extends LobbyType
sealed case class LooserPick() extends LobbyType

View File

@ -23,11 +23,14 @@ class UserActor(out: ActorRef,
def writes(deciderMap: DeciderMap): JsValue = {
Json.obj(
"map" -> deciderMap.map,
"description" -> deciderMap.description,
"isBanned" -> deciderMap.isBanned
)
}
}
implicit val selectedRacesWrites: OWrites[SelectedRaces] = Json.writes[SelectedRaces]
implicit val userInfoWrites: OWrites[UserInfo] = Json.writes[UserInfo]
implicit val lobbyWrites: Writes[LobbyInfo] = new Writes[LobbyInfo]{
@ -172,6 +175,12 @@ class UserActor(out: ActorRef,
val map = (json \ "map").as[String]
lobbieActor.foreach(lobby => lobby ! BanMap(map))
case Some("selectRace") =>
val firstRace = (json \ "raceFirst").as[Int]
val secondRace = (json \ "raceSecond").as[Int]
val thirdRace = (json \ "raceThird").as[Int]
lobbieActor.foreach(lobby => lobby ! SelectedRaces(firstRace, secondRace, thirdRace))
case Some("getLobbies") =>
logger.debug("Get all lobby request")
(LobbiesActor.actor ? GetAllLobbies).mapTo[List[RefreshLobbyInfo]] onComplete {

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 230 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 236 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -132,6 +132,8 @@
"6p_agamar_desert": "Agamar Desert (6)",
"6p_alvarus": "Alvarus (6)",
"6p_kaurav_city": "Kaurav City (6)",
"6p_snowblind": "Snowblind (6)",
"6p_ruined_greatway": "Ruined Greatway (6)",
"8p_forbidden_jungle": "Forbidden Jungle (8)",
"8p_rhean_jungle": "Rhean Jungle (8)",
"8p_thurabis_plateau": "ThurAbis Plateau (8)",

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

View File

@ -2,6 +2,8 @@ var ws;
var userName = ""
var raceCount = $("#raceCount").html()
window.onload = function() {
'use strict';
@ -78,6 +80,7 @@ window.onload = function() {
$("#createDecider").click(function(event) {
event.preventDefault();
isObserver = false;
ws.send(JSON.stringify({
type: "createDecider",
deciderName: $("#deciderName").html()
@ -104,14 +107,20 @@ window.onload = function() {
$(".navbar").show();
});
if($.cookie('user')=== undefined){
var result = prompt("Enter nickname: ", );
$.cookie('user', result, { expires: 1337 });
userName = result;
}else{
userName = $.cookie('user');
function requestName(){
if($.cookie('user') === undefined || $.cookie('user')=== "null"|| $.cookie('user')=== ""){
var result = prompt("Enter nickname: ", );
$.cookie('user', result, { expires: 1337 });
userName = result;
requestName();
}else{
userName = $.cookie('user');
}
}
requestName();
$("#playerName").html(userName);
@ -121,7 +130,11 @@ window.onload = function() {
message = JSON.parse(event.data);
switch (message.type) {
case "refreshLobby":
renderMaps(message.lobby.maps, message.lobby.status);
if(message.lobby.status === "SelectRace()" && (!isObserver)){
renderRaces();
}else {
renderMaps(message.lobby.maps, message.lobby.status);
}
renderPlayersAndStats(message.lobby);
break;
case "switchToLobby":
@ -202,6 +215,146 @@ function disconnectLobby(error) {
alert(error);
}
// ---------------Выбор рас --------------
function getRaceImageByNumber(number){
switch (number) {
case 1: return "/assets/images/raceIcons/SM.gif";
case 2: return "/assets/images/raceIcons/Chaos.gif";
case 3: return "/assets/images/raceIcons/Eldar.gif";
case 4: return "/assets/images/raceIcons/Orks.gif";
case 5: return "/assets/images/raceIcons/IG.gif";
case 6: return "/assets/images/raceIcons/Nec.gif";
case 7: return "/assets/images/raceIcons/Tau.gif";
case 8: return "/assets/images/raceIcons/Sob.gif";
case 9: return "/assets/images/raceIcons/De.gif";
}
}
function getRaceVideoByNumber(number){
switch (number) {
case 1: return "/assets/video/races/SM.mp4";
case 2: return "/assets/video/races/Chaos.mp4";
case 3: return "/assets/video/races/Eldar.mp4";
case 4: return "/assets/video/races/Orks.mp4";
case 5: return "/assets/video/races/IG.mp4";
case 6: return "/assets/video/races/Nec.mp4";
case 7: return "/assets/video/races/Tau.mp4";
case 8: return "/assets/video/races/Sob.mp4";
case 9: return "/assets/video/races/SM.mp4";
}
}
function renderRaces() {
var resHtml = "";
resHtml += "<div class='col-xs-4'><center><h2>First race</h2>";
for(var i = 1; i <= 9; i++){
var selected = "raceNotSelected";
if($.cookie("race1") == i){
selected = "raceSelected";
selectedMainRace = i;
}
resHtml += '<a href = "#" class="'+selected+' mainRaceIcon" onclick="selectMainRace(this, ' +i+')"><img class="raceIcon" src="'+getRaceImageByNumber(i)+'"></a> ';
}
resHtml += "</center></div>";
if(raceCount >= 2){
resHtml += "<div class='col-xs-4'><center><h2>Second race</h2>";
for(var i = 1; i <= 9; i++){
var selected = "raceNotSelected";
if($.cookie("race2") == i){
selected = "raceSelected";
selectedSecondRace = i;
}
resHtml += '<a href = "#" class="'+selected+' additionalRaceIcon" onclick="selectSecondRace(this, ' +i+')"><img class="raceIcon" src="'+getRaceImageByNumber(i)+'"></a> ';
}
resHtml += "</center></div>";
}
if(raceCount >= 3){
resHtml += "<div class='col-xs-4'><center><h2>Ban race</h2>";
for(var i = 1; i <= 9; i++){
var selected = "raceNotSelected";
var banned = "";
if($.cookie("race3") == i){
selected = "raceSelected";
banned = "bannedRace";
selectedThirdRace = i;
}
resHtml += '<a href = "#" class="'+selected+' thirdRaceIcon" onclick="selectThirdRace(this, ' +i+')"><img class="raceIcon '+banned+'" src="'+getRaceImageByNumber(i)+'"></a> ';
}
resHtml += "</center></div>";
}
resHtml += "<div class='col-xs-4'></div>";
resHtml += "<div style='clear: both;'></div></br>";
resHtml += "<center><button id = 'selectRace' class='btn btn-primary' disabled onclick='sendSelectedRacesToServer()'>OK</button></center>"
$("#mapList").html(resHtml);
checkRaceSelectFinish();
}
var selectedMainRace = 0;
var selectedSecondRace = 0;
var selectedThirdRace = 0;
function selectMainRace(button, race){
selectedMainRace = race;
$.cookie("race1", race, { expires: 1 });
_.each($(".mainRaceIcon"), function (el){
$(el).removeClass("raceSelected");
$(el).addClass("raceNotSelected");
});
$(button).removeClass("raceNotSelected");
$(button).addClass("raceSelected");
checkRaceSelectFinish();
}
function selectSecondRace(button, race){
selectedSecondRace = race;
$.cookie("race2", race, { expires: 1 });
_.each($(".additionalRaceIcon"), function (el){
$(el).removeClass("raceSelected");
$(el).addClass("raceNotSelected");
});
$(button).removeClass("raceNotSelected");
$(button).addClass("raceSelected");
checkRaceSelectFinish();
}
function selectThirdRace(button, race){
selectedThirdRace = race;
$.cookie("race3", race, { expires: 1 });
_.each($(".thirdRaceIcon"), function (el){
$(el).removeClass("raceSelected");
$(el).children('img').removeClass("bannedRace");
$(el).addClass("raceNotSelected");
});
$(button).removeClass("raceNotSelected");
$(button).addClass("raceSelected");
$(button).children("img").addClass("bannedRace");
checkRaceSelectFinish();
}
function checkRaceSelectFinish(){
if(selectedMainRace !== 0 && (raceCount < 2 || selectedSecondRace !== 0) && (raceCount < 3 || selectedThirdRace !== 0)){
$("#selectRace").removeAttr("disabled")
}
}
function sendSelectedRacesToServer(){
ws.send(JSON.stringify({
type: "selectRace",
raceFirst: selectedMainRace,
raceSecond: selectedSecondRace,
raceThird: selectedThirdRace,
}));
$("#mapList").html("<center>Waiting another player...</center>");
}
// ---------------------------------------------
function renderMaps(maps, lobbyStatus) {
var resHtml = "";
@ -217,15 +370,60 @@ function renderMaps(maps, lobbyStatus) {
banClass = "bannedMap";
}
var title = ""
if(map.description != null){
title = "title='"+map.description+"'";
}
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">' +
'<img class="img-rounded center-block" '+title+' style="width:128px;" src="/assets/images/maps/'+encodeURI(map.map)+'.jpg">' +
'</div>'+convertMapName(map.map)+
banHtml + '</button></div>';
})
$("#mapList").html(resHtml);
}
var isObserver = false;
function renderFinish(maps, firstPlayerInfo, secondPlayerInfo) {
var resHtml = "<center>";
_.each(maps, function (map) {
if(!map.isBanned){
resHtml = resHtml + '<div class="col-xs-4 col-md-3 col-lg-2"><button class = "mapSelect" >'+
'<div class="mapImageAndText ">' +
'<img class="img-rounded center-block" style="width:128px;" src="/assets/images/maps/'+encodeURI(map.map)+'.jpg">' +
'</div>'+convertMapName(map.map)+ '</button></div>';
}
})
resHtml += "<div style='clear: both;'>";
resHtml += "<h2>" + firstPlayerInfo.name + "</h2>";
resHtml += "<img class=\"raceIcon\" src="+getRaceImageByNumber(firstPlayerInfo.selectedRaces.firstRace)+"> ";
if(raceCount >= 2){
resHtml += "<img class=\"raceIcon\" src="+getRaceImageByNumber(firstPlayerInfo.selectedRaces.secondRace)+"> ";
}
if(raceCount >= 3){
resHtml += "<img class=\"raceIcon\" src="+getRaceImageByNumber(firstPlayerInfo.selectedRaces.thirdRace)+"> ";
}
resHtml += "<h2>" + secondPlayerInfo.name + "</h2>";
resHtml += "<img class=\"raceIcon\" src="+getRaceImageByNumber(secondPlayerInfo.selectedRaces.firstRace)+"> ";
if(raceCount >= 2){
resHtml += "<img class=\"raceIcon\" src="+getRaceImageByNumber(secondPlayerInfo.selectedRaces.secondRace)+"> ";
}
if(raceCount >= 3){
resHtml += "<img class=\"raceIcon\" src="+getRaceImageByNumber(secondPlayerInfo.selectedRaces.thirdRace)+"> ";
}
resHtml += "</center>"
$("#mapList").html(resHtml);
}
function renderPlayersAndStats(lobby) {
var resHtml = "<center>";
var player1ReadyBtn = "";
@ -269,15 +467,19 @@ function renderPlayersAndStats(lobby) {
}
var lobbyTypeText = "";
var last1Selected = "";
var last3Selected = "";
var last5Selected = "";
var superfinalSelected = "";
var looserPickSelected = "";
var last7Selected = "";
var isNecronsSelected = "";
if(lobby.isNecrons) isNecronsSelected = "checked";
switch (lobby.selectedType) {
case "Last1()":
looserPickSelected = "selected";
lobbyTypeText = "Play on last map";
break;
case "Last3()":
last3Selected = "selected";
lobbyTypeText = "Play on last 3 maps";
@ -286,16 +488,13 @@ function renderPlayersAndStats(lobby) {
last5Selected = "selected";
lobbyTypeText = "Play on last 5 maps";
break;
case "Superfinal()":
superfinalSelected = "selected";
lobbyTypeText = "Draft to select 9 maps for BO7";
break;
case "LooserPick()":
looserPickSelected = "selected";
lobbyTypeText = "Play on last map";
case "Last7()":
last7Selected = "selected";
lobbyTypeText = "Play on last 7 maps";
break;
}
console.log(lobby.status);
switch (lobby.status) {
case "NotStarted()":
resHtml = "<div style='float: left; padding-top: 10px;'> <div>" + lobby.user1Info.name + ": " + player1ReadyBtn +"</div><br/>"
@ -318,10 +517,10 @@ function renderPlayersAndStats(lobby) {
//TODO: here from config
resHtml += "<br/><select class=\"form-control\" id = 'deciderOption' onChange='changeLobbyType()' "+disabledText+" >" +
"<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>" +
"<option "+last1Selected+" value = 'last1'>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 "+last7Selected+" value = 'last7'>Play on last 7 maps</option>" +*/
"</select>";
if(lobby.user1Info.name !== userName && lobby.user2Info.name !== userName){
@ -329,26 +528,37 @@ function renderPlayersAndStats(lobby) {
}else{
disabledText = "";
}
if($("#necronPresence").html() === "true"){
resHtml += "<br/><label><input onchange=\"changeIsNecronSelected()\" id='isNecron' type=\"checkbox\" "+isNecronsSelected +" " + disabledText +">" +
" Necrons are present</label>";
}
/*for(var i = 1; i <= 9; i++){
resHtml += '<a href = "#" class="raceNotSelected mainRaceIcon" style="position: absolute; z-index: -1;"><img class="raceIcon" src="'+getRaceImageByNumber(i)+'"></a> ';
}*/
resHtml += "</div>";
break;
case "SelectRace()":
resHtml = "<center>"+lobby.user1Info.name + " vs " + lobby.user2Info.name + " - " +lobbyTypeText+ "<br/> players select races</center>";
break;
case "Draft()":
console.log(lobby.turn);
var playerTurn = (lobby.playerTurn === 1) ? lobby.user1Info.name : lobby.user2Info.name
resHtml = "<center>"+lobby.user1Info.name + " vs " + lobby.user2Info.name + " - " +lobbyTypeText+ "<br/><b>" + playerTurn +"</b> turn</center>";
resHtml += "<center><img class=\"raceIcon\" src="+getRaceImageByNumber(lobby.user1Info.selectedRaces.firstRace)+"> ";
if(raceCount > 1){
resHtml += "<img class=\"raceIcon\" src="+getRaceImageByNumber(lobby.user1Info.selectedRaces.secondRace)+"> ";
}
if(raceCount > 2){
resHtml += "<img class=\"raceIcon\" src="+getRaceImageByNumber(lobby.user1Info.selectedRaces.thirdRace)+"> ";
}
resHtml += " <span style='font-size: 14px'>VS</span> ";
resHtml += "<img class=\"raceIcon\" src="+getRaceImageByNumber(lobby.user2Info.selectedRaces.firstRace)+">";
if(raceCount > 1){
resHtml += "<img class=\"raceIcon\" src="+getRaceImageByNumber(lobby.user2Info.selectedRaces.secondRace)+"> ";
}
if(raceCount > 2){
resHtml += "<img class=\"raceIcon\" src="+getRaceImageByNumber(lobby.user2Info.selectedRaces.thirdRace)+"> ";
}
break;
case "Finish()":
var lastMaps = _.filter(lobby.maps, function (map){
return map.isBanned === false;
});
resHtml = "<center><b>";
_.forEach(lastMaps,function (map){
resHtml += convertMapName(map.map) + "; "
})
resHtml += "</b></center>";
renderFinish(lobby.maps, lobby.user1Info, lobby.user2Info);
break;
}
resHtml = resHtml + "</center>"
@ -406,6 +616,7 @@ function changeIsNecronSelected(){
}
function joinDecider(actorName){
isObserver = false;
ws.send(JSON.stringify({
type: "joinDecider",
lobbyActorName: actorName
@ -413,6 +624,7 @@ function joinDecider(actorName){
}
function observerDecider(actorName){
isObserver = true;
ws.send(JSON.stringify({
type: "observerDecider",
lobbyActorName: actorName

View File

@ -20,6 +20,13 @@
-webkit-filter: grayscale(1); /* Webkit браузеры */
}
.bannedRace {
height: 96px;
background-color: red;
clip-path: polygon(20% 0%, 0% 20%, 30% 50%, 0% 80%, 20% 100%, 50% 70%, 80% 100%, 100% 80%, 70% 50%, 100% 20%, 80% 0%, 50% 30%);
border: 2px solid red;
}
.mapSelect{
margin: 4px;
position:relative;
@ -29,6 +36,39 @@
overflow: hidden;
}
.raceIcon{
width: 90px;
border-radius: 5px;
margin: 3px;
border: 1px solid;
}
.raceNotSelected{
-webkit-filter: grayscale(1); /* Webkit браузеры */
}
.raceNotSelected:hover{
-webkit-filter: grayscale(0); /* Webkit браузеры */
}
.raceSelected{
-webkit-filter: brightness(1.3);
}
.tooltip span{
border-radius: 5px 5px 5px 5px;
visibility: hidden;
position: absolute;
left: 200px;
background: #fff;
box-shadow: -2px 2px 10px -1px #333;
border-radius: 2px;
}
.tooltip:hover span{
visibility: visible;
}
@keyframes glowing {
0% {
box-shadow: 0 0 2px #074673;

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -16,8 +16,10 @@ import play.api.mvc._
import scala.concurrent.duration._
import scala.concurrent.{ExecutionContext, Future}
import scala.util.Try
case class LastMapsSelectConfig(last1: Boolean, last3: Boolean, last5: Boolean, last7: Boolean)
case class RaceSelect(select: Boolean, showAtStart: Boolean)
/**
* This class creates the actions and the websocket needed.
@ -41,9 +43,10 @@ class HomeController @Inject()(cc: ControllerComponents) extends AbstractControl
logger.info(s"Received request from: ${request.remoteAddress}")
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 raceCount = Try(config.getInt(s"deciders.$deciderName.raceCount")).getOrElse(1)
val lastmapsSettings = LastMapsSelectConfig(true, true, true, true)
Ok(views.html.index(deciderName, deciderHumanName, deciderDescription, necronPresence, lastmapsSettings))
val raceSelect = RaceSelect(true, false)
Ok(views.html.index(deciderName, deciderHumanName, raceCount, deciderDescription, raceSelect, lastmapsSettings))
}
/**
@ -98,7 +101,7 @@ class HomeController @Inject()(cc: ControllerComponents) extends AbstractControl
* Returns true if the value of the Origin header contains an acceptable value.
*/
def originMatches(origin: String, remoteAddress: String): Boolean = {
origin.contains("139.59.210.74") || origin.contains("localhost") || origin.contains("localhost:9000") || origin.contains("localhost:19001")
origin.contains("89.108.83.108") || origin.contains("crosspick.ru") || origin.contains("localhost") || origin.contains("localhost:9000") || origin.contains("localhost:19001")
}
/**

View File

@ -1,8 +1,8 @@
@(deciderName: String, deciderHumanName: String, rules: String, necronPresence: Boolean, boSettings: LastMapsSelectConfig)(implicit r: Request[_])
@(deciderName: String, deciderHumanName: String, raceCount: Int, rules: String, raceSelect: RaceSelect, 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="raceCount" style="display: none">@raceCount</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>
@ -13,15 +13,14 @@
<head>
<title>Soulstorm tournament decider</title>
<link rel='stylesheet' href='@routes.Assets.at("lib/bootstrap/css/bootstrap.min.css")'>
<link rel="stylesheet" media="screen" href="@routes.Assets.at("stylesheets/main.css")">
<link rel="stylesheet" media="screen" href="@routes.Assets.at("stylesheets/main.css?080422")">
<link rel="shortcut icon" type="image/png" href="@routes.Assets.at("images/favicon.png")">
<script type='text/javascript' src='@routes.Assets.at("lib/jquery/jquery.min.js")'></script>
<script type='text/javascript' src='@routes.Assets.at("lib/flot/jquery.flot.js")'></script>
<script type='text/javascript' src='@routes.Assets.at("lib/underscore/underscore.js")'></script>
<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?231021")'></script>
<script type='text/javascript' src='@routes.Assets.at("javascripts/index.js?030622")'></script>
</head>
<body data-ws-url="@routes.HomeController.ws.webSocketURL()">
<div class="navbar navbar-inverse navbar-fixed-top">

View File

@ -18,6 +18,7 @@ libraryDependencies += "org.webjars" % "jquery-cookie" % "1.4.1-1"
libraryDependencies += "org.webjars.npm" % "underscore" % "1.11.0"
libraryDependencies += "org.webjars" % "backbonejs" % "1.3.3"
libraryDependencies += guice
libraryDependencies += "com.typesafe.scala-logging" %% "scala-logging" % "3.9.2"

View File

@ -2,22 +2,58 @@
# https://www.playframework.com/documentation/latest/AllowedHostsFilter
# Allow requests to localhost:9000.
play.filters.hosts {
allowed = ["localhost:9000", "localhost", "139.59.210.74", "*"]
allowed = ["localhost:9000", "localhost", "89.108.83.108", "*", "crosspick.ru"]
}
play.http.secret.key="QCY?tAnfk?aZ?iwrNwnxIlR6CTf:123123Latabg@5241AB`R5W:1uDFN];Ik@n"
play.server.http.port = 80
deciders{
classic{
maps = [["2p_battle_marshes"],
["2p_fallen_city_[Rem]"],
["2p_fata_morgana_[Rem]"],
["2p_quests_triumph"],
["2p_meeting_of_minds"],
["2p_shrine_of_excellion_[Rem]"],
["2p_titan_fall_[Rem]"],
["2p_tranquilitys_end_[Rem]"],
["2p_fraziersdemise"],
["2p_outer_reaches"],
["2p_blood_river_[Rem]"],
["2p_deadly_fun_archeology"],
["2p_bloody_hell_[Ed]"]]
name = "Классический десайдер"
rules = """"""
}
turtleshell{
maps = [["2p_battle_marshes"],
["2p_fallen_city_[Rem]"],
["2p_fata_morgana_[Rem]"],
["2p_quests_triumph"],
["2p_meeting_of_minds"],
["2p_shrine_of_excellion_[Rem]"],
["2p_titan_fall_[Rem]"],
["2p_tranquilitys_end_[Rem]"],
["2p_fraziersdemise"],
["2p_outer_reaches"],
["2p_blood_river_[Rem]"],
["2p_deadly_fun_archeology"],
["2p_bloody_hell_[Ed]"],
["2p_sugaroasis"],
["2p_vortex_plateau"]]
name = "Turtle Shell tournament"
rules = """Выбор карт в BO3: Игроки вычеркивают по очереди карты из маппула, пока их не останется 3 (три). Вычеркивания проводятся вручную в лобби игры или с помощью десайдера, если такая техническая возможность присутствует. Таким образом каждый вычеркнет 6 карт пока не останутся 3 карты."""
}
dvijcup{
maps = ["2p_battle_marshes",
"2p_fallen_city_[Rem]",
"2p_meeting_of_minds",
"2p_fata_morgana_[Rem]",
"2p_quests_triumph",
"2p_shrine_of_excellion_[Rem]",
"2p_titan_fall_[Rem]",
"2p_tranquilitys_end_[Rem]",
"2p_fraziersdemise",
"2p_sugaroasis",
"2p_bloody_hell",
"2p_blood_river_[Rem]",
"2p_deadly_fun_archeology"]
name = "Dvij cup"
@ -26,26 +62,246 @@ deciders{
Затем игроки вычеркивают выбранные карты, пока не останется только одна, на которой и играется первый матч встречи.
Тот, кто первым начал вычеркивать из всего маппула, уступает оппоненту право вычеркивания первой карты из оставшихся карт-десайдеров.
Во втором и последующем матчах проигравший выбирает карту из числа выбранных 3 (5) десайдеров."""
necronrestrict = false
}
newplayerslegue{
necronrestrict = false
meatgrinder{
maps = ["2p_battle_marshes",
"2p_fallen_city",
"2p_fata_morgana",
"2p_fallen_city_[Rem]",
"2p_fata_morgana_[Rem]",
"2p_meeting_of_minds",
"2p_outer_reaches",
"2p_quests_triumph",
"2p_shrine_of_excellion",
"2p_shrine_of_excellion_[Rem]",
"2p_titan_fall_[Rem]",
"2p_tranquilitys_end",
"2p_emerald_river",
"2p_vortex_plateau",
"2p_tranquilitys_end_[Rem]",
"2p_fraziersdemise",
"2p_blood_river"]
name = "Лига новых игроков 2"
rules = """Первую карту вы с оппонентом выбираете, поочередно вычеркивая неудобные для Вас карты из этих тринадцати. Вычеркиваете, пока не остается одна. На ней и играете. В последующих матчах карту выбирает тот, кто проиграл (это называется лузер-пик). Выбирать повторно карту, на которой вы с этим оппонентом уже играли, нельзя. Играть на ремастер-версиях карт можно по обоюдному согласию игроков. Если один из Вас не скачал новые версии карт - играйте на старых."""
necronrestrict = true
"2p_vortex_plateau",
"2p_sugaroasis",
"2p_blood_river_[Rem]"]
name = "Meat grinder"
rules = """Выбор карт в БО3 и БО5 осуществляется без лузерпиков, с тремя и пятью десайдерами соответственно. Игроки вычеркивают по очереди карты из маппула, пока их не останется 3 (для БО3) или 5 (для БО5). На этих картах и проходят все матчи встречи. Затем игроки вычеркивают выбранные карты, пока не останется только одна, на которой и играется первый матч встречи. Тот, кто первым начал вычеркивать из всего маппула, уступает оппоненту право вычеркивания первой карты из оставшихся карт-десайдеров. Во втором и последующем матчах проигравший выбирает карту из числа выбранных 3 (5) десайдеров. В случае, если один из игроков играет за расу некронов, из маппула исключаются карты MoM и SoE, после чего оба игрока приступают к вычеркиванию карт стандартным образом из 11-картового маппула."""
}
medskillcup{
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_fraziersdemise",
"2p_emerald_river",
"2p_deadly_fun_archeology",
"2p_blood_river_[Rem]"]
name = "Med skill cup 4"
rules = """Вы и ваш оппонент перед началом матчей вычеркиваете из маппула карты, пока не останется 3. На них и играете. Для БО1 - та же самая система выбора карт. В суперфинале игрок из верхней сетки начинает с +1 очком, а игрок из нижней сетки - с лузерпиком. Далее оба игрока вычеркивают по 3 карты, и могут лузерпикать из оставшихся 6 в последующих матчах."""
}
burgercup{
maps = [["2p_battle_marshes"],
["2p_fallen_city_[Rem]"],
["2p_fata_morgana_[Rem]"],
["2p_meeting_of_minds"],
["2p_quests_triumph"],
["2p_shrine_of_excellion_[Rem]"],
["2p_titan_fall_[Rem]"],
["2p_tranquilitys_end_[Rem]"],
["2p_fraziersdemise"],
["2p_bloody_hell_[Ed]"],
["2p_deadly_fun_archeology"]]
name = "Burger cup"
raceCount = 2
rules = """Выбор карт в БО3 и БО5 осуществляется без лузерпиков, с тремя и пятью десайдерами соответственно. Игроки вычеркивают по очереди карты из маппула, пока их не останется 3 (для БО3) или 5 (для БО5). На этих картах и проходят все матчи встречи. Затем игроки вычеркивают выбранные карты, пока не останется только одна, на которой и играется первый матч встречи. Тот, кто первым начал вычеркивать из всего маппула, уступает оппоненту право вычеркивания первой карты из оставшихся карт-десайдеров. Во втором и последующем матчах проигравший выбирает карту из числа выбранных 3 (5) десайдеров."""
}
everyonecup{
maps = [["2p_battle_marshes"],
["2p_fallen_city_[Rem]"],
["2p_moonbase"],
["2p_fata_morgana_[Rem]"],
["2p_meeting_of_minds"],
["2p_emperors_valley"],
["2p_titan_fall_[Rem]"],
["2p_tranquilitys_end_[Rem]"],
["2p_fraziersdemise"],
["2p_bloody_hell_[Ed]"],
["2p_blood_river_[Rem]"],
["2p_deadly_fun_archeology"],
["2p_sugaroasis"]]
name = "Everyone cup"
raceCount = 1
rules = """Все матчи БО3. Игроки вычеркивают по очереди карты из маппула, пока их не останется 3. На этих картах и проходят все матчи встречи."""
}
bigbosswinter{
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_bloody_hell_[Ed]",
"2p_emerald_river",
"2p_deadly_fun_archeology",
"2p_winter_confrontation"]
name = "Big boss of winter"
rules = """Выбор карт в БО3 и БО5 осуществляется без лузерпиков, с тремя и пятью десайдерами соответственно. Игроки вычеркивают по очереди карты из маппула, пока их не останется 3 (для БО3) или 5 (для БО5). На этих картах и проходят все матчи встречи. Затем игроки вычеркивают выбранные карты, пока не останется только одна, на которой и играется первый матч встречи. Тот, кто первым начал вычеркивать из всего маппула, уступает оппоненту право вычеркивания первой карты из оставшихся карт-десайдеров. Во втором и последующем матчах проигравший выбирает карту из числа выбранных 3 (5) десайдеров.В суперфинале турнира оба игрока вычеркивают по две карты. После этого из оставшихся 9 карт можно брать любые, выбирает их проигравший в предыдущем матче. Первый лузер-пик - за игроком из нижней сетки, который начинает с -1 очком. """
}
showmatch{
maps = ["2p_battle_marshes",
"2p_fallen_city_[Rem]",
"2p_fata_morgana_[Rem]",
"2p_quests_triumph",
"2p_shrine_of_excellion_[Rem]",
"2p_titan_fall_[Rem]",
"2p_tranquilitys_end_[Rem]",
"2p_fraziersdemise",
"2p_bloody_hell_[Ed]",
"2p_blood_river_[Rem]",
"2p_sugaroasis",
"2p_meeting_of_minds",
"2p_emerald_river",
"2p_velvet_duress",
"2p_deadly_fun_archeology"]
name = "Showmatch"
rules = """ """
}
horusheresycup2{
maps = ["2p_battle_marshes",
"2p_fallen_city_[Rem]",
"2p_fata_morgana_[Rem]",
"2p_quests_triumph",
"2p_shrine_of_excellion_[Rem]",
"2p_titan_fall_[Rem]",
"2p_tranquilitys_end_[Rem]",
"2p_outer_reaches",
"2p_blood_river_[Rem]",
"2p_sugaroasis",
"2p_meeting_of_minds"]
name = "Horus heresy cup 2"
rules = """ Первая карта десайдер выбирается методом вычеркивания, остальные лузер пик. По обоюдному согласию игроков разрешен повтор карт. Сетка турнира Double Elimination.
Сетка виннеров:
Каждая игра до 2х победы (БО3),
В суперфинале игра до 3-х побед (БО5).
Сетка лузеров:
Каждая игра до 1й победы (БО1),
Финал сетки лузеров (БО3).
Игрок, прошедший в суперфинал из верхней сетки, имеет +1 очко. Игрок из нижней сетки начинает с лузерпиком. """
}
shouldercup{
description = true
raceCount = 3
maps = [["6p_paynes_retribution", "Количество точек: 28/2/2\nСпорных точек: 10/0/2\nТермогенераторы: 2"],
["6p_fury_island", "Количество точек: 26/6/1\nСпорных точек: 6 + 1 крит\nТермогенераторы: Отсутствуют"],
["6p_irridene", "Количество точек: 21/6/3\nСпорных точек: 6/0/3\nТермогенераторы: 6"],
["6p_shakun_coast", "Количество точек: 24/4/1\nСпорных точек: 6/2/1\nТермогенераторы: 2"],
["6p_snowblind", "Количество точек: 22/2/3\nСпорных точек: 4/2/3\nТермогенераторы: отсутствуют"],
["6p_temple_cyrene", "Количество точек: 25/4/5\nСпорных точек: 8/0/3\nТермогенераторы: 2"],
["6p_testing_grounds", "Количество точек: 32/6/5\nСпорных точек: 10/2/5\nТермогенераторы: 6"],
["6p_ruined_greatway", "Количество точек: 22/2/1\nСпорных точек: 2/2/1\nТермогенераторы: 2"],
["6p_gear", "Количество точек: 24/2/3\nСпорных точек: 2 крита, но ввиду контактности карты сражение может идти на большинстве внешних точек\nТермогенераторы: 2"]]
name = "Shoulder to shoulder cup"
rules = """Классическая Double elimination с сеткой лузеров. В сетке виннеров - БО3, в сетке лузеров - БО1, в суперфинале - БО5. Игрок, прошедший в суперфинал из верхней сетки, имеет +1 очко. Игрок из нижней сетки начинает с лузерпиком. """
}
springcup{
description = true
maps = [["4p_biffys_peril"],
["4p_cold_war"],
["4p_colosseum_of_deadman"],
["4p_gorhael_crater"],
["4p_imperial_area"],
["4p_saints_square"],
["4p_tartarus_center"],
["4p_testcake"],
["4p_skerries"],
["4p_tiboraxx"],
["4p_torrents"]]
name = "Spring cup 2x2"
rules = """Десайдеры выбирается методом вычеркивания до 3 карт, далее из оставшихся карт методом вычеркивания определяется первая карта. Игрок, начавший вычеркивание из основного пула уступает право начать вычеркивание из оставшихся карт. Исключение суперфинал: Команда прошедшая в суперфинал с верхней сетки имеет преимущество в выборе очередности карт из оставшихся 3 после вычеркивания."""
}
sweatybarrakcup{
description = true
maps =[["2p_chaos_gate"],
["2p_colosseum_suicide"],
["2p_emerald_river"],
["2p_faceoff"],
["2p_moonbase_[Ed]"],
["2p_outer_reaches"],
["2p_fear"],
["2p_fraziersdemise"],
["2p_sugaroasis"],
["2p_terror_psyclaw"],
["2p_titan_fall_[Rem]"],
["2p_tranquilitys_end_[Rem]"],
["2p_velvet_duress"],
["2p_winter_confortation"],
["2p_deadly_fun_archeology"]]
name = "Sweaty barrack cup"
rules = """Перед началом матча, игроки поочередно вычеркивают по одной карте, пока не выберут десайдер. Если иного не сказано в секции "Расы" (см. ограничения для рас). Во второй и всех последующих играх - побежденный выбирает карту.
Чтобы не было повторений карт, игроки могу выбрать всего 1 раз карту из списка. """
}
tpmodcup{
maps = ["2p_battle_marshes",
"2p_fallen_city_[Rem]",
"2p_fata_morgana_[Rem]",
"2p_quests_triumph",
"2p_shrine_of_excellion_[Rem]",
"2p_titan_fall_[Rem]",
"2p_tranquilitys_end_[Rem]",
"2p_blood_river_[Rem]",
"2p_sugaroasis",
"2p_faceoff",
"2p_deadly_fun_archeology",
"2p_terror_psyclaw",
"2p_meeting_of_minds"]
name = "Турнир по ТП моду"
rules = """ Первая карта десайдер выбирается методом вычеркивания, остальные лузер пик."""
}
bestfriendscup{
maps = ["4p_gorhael_crater",
"4p_gurmuns_pass",
"4p_saints_square",
"4p_skerries",
"4p_panrea_lowlands",
"4p_doom_spiral",
"4p_tiboraxx"]
name = "Best friends cup cup"
rules = """ Обе команды вычеркивают по очереди неудобные для себя карты. Каждая команда вычеркивает в общей сложности 3. На оставшейся, седьмой карте, проходит Ваш первый матч - она называется десайдером. Во всех последующих играх карту выбирает команда, проигравшая в последнем матче. Это называется лузерпиком - выбором проигравших. В суперфинале турнира сражается команда из сетки виннеров против финалистов из сетки лузеров, в формате БО5 (до трёх побед). """
}
noweaknesscup{
maps = [["2p_battle_marshes"],
["2p_fallen_city_[Rem]"],
["2p_fata_morgana_[Rem]"],
["2p_quests_triumph"],
["2p_shrine_of_excellion_[Rem]"],
["2p_titan_fall_[Rem]"],
["2p_tranquilitys_end_[Rem]"],
["2p_fraziersdemise"],
["2p_bloody_hell_[Ed]"],
["2p_blood_river_[Rem]"],
["2p_deadly_fun_archeology"]]
name = "No Weakness cup"
rules = """Выбор карт в БО3 и БО5 осуществляется без лузерпиков, с тремя и пятью десайдерами соответственно. Игроки вычеркивают по очереди карты из маппула, пока их не останется 3 (для БО3) или 5 (для БО5). На этих картах и проходят все матчи встречи. Затем игроки вычеркивают выбранные карты, пока не останется только одна, на которой и играется первый матч встречи. Тот, кто первым начал вычеркивать из всего маппула, уступает оппоненту право вычеркивания первой карты из оставшихся карт-десайдеров. Во втором и последующем матчах проигравший выбирает карту из числа выбранных 3 (5) десайдеров. """
}
casinocup {
maps = [["2p_battle_marshes"],
["2p_fallen_city_[Rem]"],
["2p_fata_morgana_[Rem]"],
["2p_quests_triumph"],
["2p_shrine_of_excellion_[Rem]"],
["2p_titan_fall_[Rem]"],
["2p_tranquilitys_end_[Rem]"],
["2p_fraziersdemise"],
["2p_bloody_hell"],
["2p_blood_river_[Rem]"],
["2p_deadly_fun_archeology"],
["2p_outer_reaches"],
["2p_meeting_of_minds"]]
name = "Casino cup"
rules = """Выбор карт без лузерпиков, с тремя и пятью десайдерами соответственно. Игроки вычеркивают по очереди карты из маппула, пока их не останется 3 (для БО3) или 5 (для БО5). На этих картах и проходят все матчи встречи. Затем игроки вычеркивают выбранные карты, пока не останется только одна, на которой и играется первый матч встречи. Тот, кто первым начал вычеркивать из всего маппула, уступает оппоненту право вычеркивания первой карты из оставшихся карт-десайдеров. Во втором и последующем матчах проигравший выбирает карту из числа выбранных 3 (5) десайдеров. """
}
}

View File

@ -1,42 +1,48 @@
<!--
Copyright (C) Lightbend Inc. <https://www.lightbend.com>
-->
<!-- The default logback configuration that Play uses if no other configuration is provided -->
<configuration>
<conversionRule conversionWord="coloredLevel" converterClass="play.api.libs.logback.ColoredLevel"/>
<conversionRule conversionWord="coloredLevel" converterClass="play.api.libs.logback.ColoredLevel" />
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%coloredLevel %logger{15} - %message%n%xException{10}</pattern>
</encoder>
</appender>
<appender name="FILE" class="ch.qos.logback.core.RollingFileAppender">
<file>logs/decider.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- daily rollover -->
<fileNamePattern>logs/decider.%d{yyyy-MM-dd_HH-mm}.log</fileNamePattern>
<appender name="ASYNCSTDOUT" class="ch.qos.logback.classic.AsyncAppender">
<!-- increases the default queue size -->
<queueSize>512</queueSize>
<!-- don't discard messages -->
<discardingThreshold>0</discardingThreshold>
<!-- block when queue is full -->
<neverBlock>false</neverBlock>
<appender-ref ref="STDOUT" />
</appender>
<!-- keep 30 days' worth of history capped at 3GB total size -->
<maxHistory>30</maxHistory>
<totalSizeCap>3GB</totalSizeCap>
</rollingPolicy>
<logger name="play" level="INFO" />
<logger name="com.gargoylesoftware.htmlunit.javascript" level="OFF" />
<appender name="FILE" class="ch.qos.logback.core.FileAppender">
<file>${application.home:-.}/logs/application.log</file>
<encoder>
<pattern>%date [%level] from %logger in %thread - %message%n%xException</pattern>
</encoder>
</appender>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%coloredLevel %logger{15} - [%marker] %message%n%xException{10}</pattern>
</encoder>
<appender name="ASYNCFILE" class="ch.qos.logback.classic.AsyncAppender">
<appender-ref ref="FILE" />
</appender>
<logger name="play" level="INFO"/>
<!-- actors logging -->
<logger name="akka" level="DEBUG"/>
<logger name="actors" level="DEBUG"/>
<!-- controllers -->
<logger name="controllers" level="DEBUG"/>
<root level="INFO">
<appender-ref ref="STDOUT"/>
<appender-ref ref="FILE"/>
<appender-ref ref="ASYNCFILE" />
<appender-ref ref="ASYNCSTDOUT" />
</root>
</configuration>
<shutdownHook class="ch.qos.logback.core.hook.DelayingShutdownHook"/>
</configuration>