arbitrary starting positions for swiss tournaments
parent
0068e53d65
commit
e1443f92b7
|
@ -26,7 +26,7 @@ object form {
|
||||||
form3.split(fields.name, fields.nbRounds),
|
form3.split(fields.name, fields.nbRounds),
|
||||||
form3.split(fields.rated, fields.variant),
|
form3.split(fields.rated, fields.variant),
|
||||||
fields.clock,
|
fields.clock,
|
||||||
fields.description,
|
form3.split(fields.description, fields.position),
|
||||||
form3.split(
|
form3.split(
|
||||||
fields.roundInterval,
|
fields.roundInterval,
|
||||||
fields.startsAt
|
fields.startsAt
|
||||||
|
@ -60,7 +60,7 @@ object form {
|
||||||
form3.split(fields.name, fields.nbRounds),
|
form3.split(fields.name, fields.nbRounds),
|
||||||
form3.split(fields.rated, fields.variant),
|
form3.split(fields.rated, fields.variant),
|
||||||
fields.clock,
|
fields.clock,
|
||||||
fields.description,
|
form3.split(fields.description, swiss.settings.position.isDefined option fields.position),
|
||||||
form3.split(
|
form3.split(
|
||||||
fields.roundInterval,
|
fields.roundInterval,
|
||||||
swiss.isCreated option fields.startsAt
|
swiss.isCreated option fields.startsAt
|
||||||
|
@ -168,8 +168,17 @@ final private class SwissFields(form: Form[_])(implicit ctx: Context) {
|
||||||
frag("Tournament description"),
|
frag("Tournament description"),
|
||||||
help = frag(
|
help = frag(
|
||||||
"Anything special you want to tell the participants? Try to keep it short. Markdown links are available: [name](https://url)"
|
"Anything special you want to tell the participants? Try to keep it short. Markdown links are available: [name](https://url)"
|
||||||
).some
|
).some,
|
||||||
|
half = true
|
||||||
)(form3.textarea(_)(rows := 4))
|
)(form3.textarea(_)(rows := 4))
|
||||||
|
def position =
|
||||||
|
form3.group(
|
||||||
|
form("position"),
|
||||||
|
trans.startPosition(),
|
||||||
|
klass = "position",
|
||||||
|
half = true,
|
||||||
|
help = views.html.tournament.form.positionInputHelp.some
|
||||||
|
)(form3.input(_))
|
||||||
def startsAt =
|
def startsAt =
|
||||||
form3.group(
|
form3.group(
|
||||||
form("startsAt"),
|
form("startsAt"),
|
||||||
|
|
|
@ -50,6 +50,20 @@ object side {
|
||||||
st.section(cls := "description")(markdownLinksOrRichText(d))
|
st.section(cls := "description")(markdownLinksOrRichText(d))
|
||||||
},
|
},
|
||||||
s.looksLikePrize option views.html.tournament.bits.userPrizeDisclaimer(s.createdBy),
|
s.looksLikePrize option views.html.tournament.bits.userPrizeDisclaimer(s.createdBy),
|
||||||
|
s.settings.position.flatMap(lila.tournament.Thematic.byFen) map { pos =>
|
||||||
|
div(
|
||||||
|
a(targetBlank, href := pos.url)(strong(pos.eco), " ", pos.name),
|
||||||
|
" • ",
|
||||||
|
a(href := routes.UserAnalysis.parseArg(pos.fen.replace(" ", "_")))(
|
||||||
|
trans.analysis()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
} orElse s.settings.position.map { fen =>
|
||||||
|
div(
|
||||||
|
"Custom position • ",
|
||||||
|
a(href := routes.UserAnalysis.parseArg(fen.value.replace(" ", "_")))(trans.analysis())
|
||||||
|
)
|
||||||
|
},
|
||||||
teamLink(s.teamId),
|
teamLink(s.teamId),
|
||||||
if (verdicts.relevant)
|
if (verdicts.relevant)
|
||||||
st.section(
|
st.section(
|
||||||
|
|
|
@ -1,14 +1,15 @@
|
||||||
package lila.swiss
|
package lila.swiss
|
||||||
|
|
||||||
import scala.concurrent.duration._
|
|
||||||
|
|
||||||
import chess.Clock.{ Config => ClockConfig }
|
import chess.Clock.{ Config => ClockConfig }
|
||||||
|
import chess.format.FEN
|
||||||
import chess.variant.Variant
|
import chess.variant.Variant
|
||||||
import chess.{ Color, StartingPosition }
|
import chess.{ Color, StartingPosition }
|
||||||
|
import reactivemongo.api.bson._
|
||||||
|
import scala.concurrent.duration._
|
||||||
|
|
||||||
import lila.db.BSON
|
import lila.db.BSON
|
||||||
import lila.db.dsl._
|
import lila.db.dsl._
|
||||||
import lila.user.User
|
import lila.user.User
|
||||||
import reactivemongo.api.bson._
|
|
||||||
|
|
||||||
private object BsonHandlers {
|
private object BsonHandlers {
|
||||||
|
|
||||||
|
@ -128,6 +129,7 @@ private object BsonHandlers {
|
||||||
nbRounds = r.get[Int]("n"),
|
nbRounds = r.get[Int]("n"),
|
||||||
rated = r.boolO("r") | true,
|
rated = r.boolO("r") | true,
|
||||||
description = r.strO("d"),
|
description = r.strO("d"),
|
||||||
|
position = r.getO[FEN]("f"),
|
||||||
chatFor = r.intO("c") | Swiss.ChatFor.default,
|
chatFor = r.intO("c") | Swiss.ChatFor.default,
|
||||||
roundInterval = (r.intO("i") | 60).seconds,
|
roundInterval = (r.intO("i") | 60).seconds,
|
||||||
password = r.strO("p"),
|
password = r.strO("p"),
|
||||||
|
@ -138,6 +140,7 @@ private object BsonHandlers {
|
||||||
"n" -> s.nbRounds,
|
"n" -> s.nbRounds,
|
||||||
"r" -> (!s.rated).option(false),
|
"r" -> (!s.rated).option(false),
|
||||||
"d" -> s.description,
|
"d" -> s.description,
|
||||||
|
"f" -> s.position,
|
||||||
"c" -> (s.chatFor != Swiss.ChatFor.default).option(s.chatFor),
|
"c" -> (s.chatFor != Swiss.ChatFor.default).option(s.chatFor),
|
||||||
"i" -> s.roundInterval.toSeconds.toInt,
|
"i" -> s.roundInterval.toSeconds.toInt,
|
||||||
"p" -> s.password,
|
"p" -> s.password,
|
||||||
|
|
|
@ -8,6 +8,7 @@ import scala.concurrent.duration._
|
||||||
import lila.hub.LightTeam.TeamID
|
import lila.hub.LightTeam.TeamID
|
||||||
import lila.rating.PerfType
|
import lila.rating.PerfType
|
||||||
import lila.user.User
|
import lila.user.User
|
||||||
|
import chess.format.FEN
|
||||||
|
|
||||||
case class Swiss(
|
case class Swiss(
|
||||||
_id: Swiss.Id,
|
_id: Swiss.Id,
|
||||||
|
@ -91,6 +92,7 @@ object Swiss {
|
||||||
nbRounds: Int,
|
nbRounds: Int,
|
||||||
rated: Boolean,
|
rated: Boolean,
|
||||||
description: Option[String] = None,
|
description: Option[String] = None,
|
||||||
|
position: Option[FEN],
|
||||||
chatFor: ChatFor = ChatFor.default,
|
chatFor: ChatFor = ChatFor.default,
|
||||||
password: Option[String] = None,
|
password: Option[String] = None,
|
||||||
conditions: SwissCondition.All,
|
conditions: SwissCondition.All,
|
||||||
|
|
|
@ -72,6 +72,7 @@ final class SwissApi(
|
||||||
nbRounds = data.nbRounds,
|
nbRounds = data.nbRounds,
|
||||||
rated = data.rated | true,
|
rated = data.rated | true,
|
||||||
description = data.description,
|
description = data.description,
|
||||||
|
position = data.realPosition,
|
||||||
chatFor = data.realChatFor,
|
chatFor = data.realChatFor,
|
||||||
roundInterval = data.realRoundInterval,
|
roundInterval = data.realRoundInterval,
|
||||||
password = data.password,
|
password = data.password,
|
||||||
|
@ -97,6 +98,9 @@ final class SwissApi(
|
||||||
nbRounds = data.nbRounds,
|
nbRounds = data.nbRounds,
|
||||||
rated = data.rated | old.settings.rated,
|
rated = data.rated | old.settings.rated,
|
||||||
description = data.description orElse old.settings.description,
|
description = data.description orElse old.settings.description,
|
||||||
|
position =
|
||||||
|
if (old.isCreated || old.settings.position.isDefined) data.realPosition
|
||||||
|
else old.settings.position,
|
||||||
chatFor = data.chatFor | old.settings.chatFor,
|
chatFor = data.chatFor | old.settings.chatFor,
|
||||||
roundInterval =
|
roundInterval =
|
||||||
if (data.roundInterval.isDefined) data.realRoundInterval
|
if (data.roundInterval.isDefined) data.realRoundInterval
|
||||||
|
|
|
@ -84,8 +84,11 @@ final private class SwissDirector(
|
||||||
Game
|
Game
|
||||||
.make(
|
.make(
|
||||||
chess = chess.Game(
|
chess = chess.Game(
|
||||||
variantOption = Some(swiss.variant),
|
variantOption = Some {
|
||||||
fen = none
|
if (swiss.settings.position.isEmpty) swiss.variant
|
||||||
|
else chess.variant.FromPosition
|
||||||
|
},
|
||||||
|
fen = swiss.settings.position.map(_.value)
|
||||||
) pipe { g =>
|
) pipe { g =>
|
||||||
val turns = g.player.fold(0, 1)
|
val turns = g.player.fold(0, 1)
|
||||||
g.copy(
|
g.copy(
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package lila.swiss
|
package lila.swiss
|
||||||
|
|
||||||
import chess.Clock.{ Config => ClockConfig }
|
import chess.Clock.{ Config => ClockConfig }
|
||||||
|
import chess.format.FEN
|
||||||
import chess.variant.Variant
|
import chess.variant.Variant
|
||||||
import org.joda.time.DateTime
|
import org.joda.time.DateTime
|
||||||
import play.api.data._
|
import play.api.data._
|
||||||
|
@ -28,6 +29,7 @@ final class SwissForm(implicit mode: Mode) {
|
||||||
"rated" -> optional(boolean),
|
"rated" -> optional(boolean),
|
||||||
"nbRounds" -> number(min = minRounds, max = 100),
|
"nbRounds" -> number(min = minRounds, max = 100),
|
||||||
"description" -> optional(clean(nonEmptyText)),
|
"description" -> optional(clean(nonEmptyText)),
|
||||||
|
"position" -> optional(lila.common.Form.fen.playableStrict),
|
||||||
"chatFor" -> optional(numberIn(chatForChoices.map(_._1))),
|
"chatFor" -> optional(numberIn(chatForChoices.map(_._1))),
|
||||||
"roundInterval" -> optional(numberIn(roundIntervals)),
|
"roundInterval" -> optional(numberIn(roundIntervals)),
|
||||||
"password" -> optional(clean(nonEmptyText)),
|
"password" -> optional(clean(nonEmptyText)),
|
||||||
|
@ -46,6 +48,7 @@ final class SwissForm(implicit mode: Mode) {
|
||||||
rated = true.some,
|
rated = true.some,
|
||||||
nbRounds = 7,
|
nbRounds = 7,
|
||||||
description = none,
|
description = none,
|
||||||
|
position = none,
|
||||||
chatFor = Swiss.ChatFor.default.some,
|
chatFor = Swiss.ChatFor.default.some,
|
||||||
roundInterval = Swiss.RoundInterval.auto.some,
|
roundInterval = Swiss.RoundInterval.auto.some,
|
||||||
password = None,
|
password = None,
|
||||||
|
@ -61,6 +64,7 @@ final class SwissForm(implicit mode: Mode) {
|
||||||
rated = s.settings.rated.some,
|
rated = s.settings.rated.some,
|
||||||
nbRounds = s.settings.nbRounds,
|
nbRounds = s.settings.nbRounds,
|
||||||
description = s.settings.description,
|
description = s.settings.description,
|
||||||
|
position = s.settings.position,
|
||||||
chatFor = s.settings.chatFor.some,
|
chatFor = s.settings.chatFor.some,
|
||||||
roundInterval = s.settings.roundInterval.toSeconds.toInt.some,
|
roundInterval = s.settings.roundInterval.toSeconds.toInt.some,
|
||||||
password = s.settings.password,
|
password = s.settings.password,
|
||||||
|
@ -137,6 +141,7 @@ object SwissForm {
|
||||||
rated: Option[Boolean],
|
rated: Option[Boolean],
|
||||||
nbRounds: Int,
|
nbRounds: Int,
|
||||||
description: Option[String],
|
description: Option[String],
|
||||||
|
position: Option[FEN],
|
||||||
chatFor: Option[Int],
|
chatFor: Option[Int],
|
||||||
roundInterval: Option[Int],
|
roundInterval: Option[Int],
|
||||||
password: Option[String],
|
password: Option[String],
|
||||||
|
@ -160,5 +165,6 @@ object SwissForm {
|
||||||
case i => i
|
case i => i
|
||||||
}
|
}
|
||||||
}.seconds
|
}.seconds
|
||||||
|
def realPosition = position ifTrue realVariant.standard
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@ import flatpickr from "flatpickr";
|
||||||
lichess.load.then(() => {
|
lichess.load.then(() => {
|
||||||
|
|
||||||
const $variant = $('#form3-variant'),
|
const $variant = $('#form3-variant'),
|
||||||
showPosition = () => $('.form3 .position').toggleClass('none', $variant.val() != '1');
|
showPosition = () => $('.form3 .position').toggleClass('none', !['1', 'standard'].includes($variant.val() as string));
|
||||||
|
|
||||||
$variant.on('change', showPosition);
|
$variant.on('change', showPosition);
|
||||||
showPosition();
|
showPosition();
|
||||||
|
|
Loading…
Reference in New Issue