2019-04-13 08:24:51 -06:00
|
|
|
package views.html
|
|
|
|
package tournament
|
|
|
|
|
2020-08-20 17:19:53 -06:00
|
|
|
import controllers.routes
|
2019-04-13 08:40:21 -06:00
|
|
|
import play.api.data.{ Field, Form }
|
2019-04-13 08:24:51 -06:00
|
|
|
|
|
|
|
import lila.api.Context
|
|
|
|
import lila.app.templating.Environment._
|
|
|
|
import lila.app.ui.ScalatagsTemplate._
|
2020-08-20 17:19:53 -06:00
|
|
|
import lila.hub.LeaderTeam
|
2020-08-24 04:51:01 -06:00
|
|
|
import lila.tournament.{ Condition, Tournament, TournamentForm }
|
2019-04-13 08:24:51 -06:00
|
|
|
|
|
|
|
object form {
|
2019-04-13 08:40:21 -06:00
|
|
|
|
2020-08-20 17:19:53 -06:00
|
|
|
def create(form: Form[_], leaderTeams: List[LeaderTeam])(implicit ctx: Context) =
|
2019-12-13 07:30:20 -07:00
|
|
|
views.html.base.layout(
|
|
|
|
title = trans.newTournament.txt(),
|
|
|
|
moreCss = cssTag("tournament.form"),
|
2020-09-21 10:01:43 -06:00
|
|
|
moreJs = jsModule("tourForm")
|
2019-12-13 07:30:20 -07:00
|
|
|
) {
|
2020-06-19 04:53:17 -06:00
|
|
|
val fields = new TourFields(form, none)
|
2019-10-03 02:41:36 -06:00
|
|
|
main(cls := "page-small")(
|
|
|
|
div(cls := "tour__form box box-pad")(
|
|
|
|
h1(
|
2020-04-02 15:32:37 -06:00
|
|
|
if (fields.isTeamBattle) "New Team Battle"
|
2019-10-03 02:41:36 -06:00
|
|
|
else trans.createANewTournament()
|
|
|
|
),
|
2021-02-08 07:25:21 -07:00
|
|
|
postForm(cls := "form3", action := routes.Tournament.create)(
|
2020-04-02 15:32:37 -06:00
|
|
|
fields.name,
|
|
|
|
form3.split(fields.rated, fields.variant),
|
|
|
|
fields.clock,
|
|
|
|
form3.split(fields.minutes, fields.waitMinutes),
|
2020-10-18 03:43:56 -06:00
|
|
|
form3.split(fields.description(true), fields.startPosition),
|
2019-10-03 02:41:36 -06:00
|
|
|
form3.globalError(form),
|
|
|
|
fieldset(cls := "conditions")(
|
2020-04-02 15:32:37 -06:00
|
|
|
fields.advancedSettings,
|
2019-10-03 02:41:36 -06:00
|
|
|
div(cls := "form")(
|
2020-08-20 17:19:53 -06:00
|
|
|
condition(form, fields, auto = true, teams = leaderTeams, tour = none),
|
2020-04-02 15:32:37 -06:00
|
|
|
fields.startDate
|
2019-04-13 08:24:51 -06:00
|
|
|
)
|
|
|
|
),
|
2020-04-02 15:32:37 -06:00
|
|
|
fields.isTeamBattle option form3.hidden(form("teamBattleByTeam")),
|
2019-10-03 02:41:36 -06:00
|
|
|
form3.actions(
|
2021-02-08 07:25:21 -07:00
|
|
|
a(href := routes.Tournament.home)(trans.cancel()),
|
2021-06-14 01:13:27 -06:00
|
|
|
form3.submit(trans.createANewTournament(), icon = "".some)
|
2019-04-13 08:24:51 -06:00
|
|
|
)
|
|
|
|
)
|
2019-10-03 02:41:36 -06:00
|
|
|
),
|
|
|
|
div(cls := "box box-pad tour__faq")(tournament.faq())
|
|
|
|
)
|
|
|
|
}
|
2019-04-13 08:40:21 -06:00
|
|
|
|
2020-08-20 17:19:53 -06:00
|
|
|
def edit(tour: Tournament, form: Form[_], myTeams: List[LeaderTeam])(implicit ctx: Context) =
|
2020-03-20 17:38:51 -06:00
|
|
|
views.html.base.layout(
|
|
|
|
title = tour.name(),
|
|
|
|
moreCss = cssTag("tournament.form"),
|
2020-09-21 10:01:43 -06:00
|
|
|
moreJs = jsModule("tourForm")
|
2020-03-20 17:38:51 -06:00
|
|
|
) {
|
2020-06-19 04:53:17 -06:00
|
|
|
val fields = new TourFields(form, tour.some)
|
2020-03-20 17:38:51 -06:00
|
|
|
main(cls := "page-small")(
|
|
|
|
div(cls := "tour__form box box-pad")(
|
2020-04-02 15:32:37 -06:00
|
|
|
h1("Edit ", tour.name()),
|
2020-03-20 17:38:51 -06:00
|
|
|
postForm(cls := "form3", action := routes.Tournament.update(tour.id))(
|
2020-04-22 10:46:35 -06:00
|
|
|
form3.split(fields.name, tour.isCreated option fields.startDate),
|
2020-04-02 15:32:37 -06:00
|
|
|
form3.split(fields.rated, fields.variant),
|
|
|
|
fields.clock,
|
2020-04-05 09:01:05 -06:00
|
|
|
form3.split(
|
2020-08-21 14:40:37 -06:00
|
|
|
if (TournamentForm.minutes contains tour.minutes) form3.split(fields.minutes)
|
2020-04-05 09:01:05 -06:00
|
|
|
else
|
|
|
|
form3.group(form("minutes"), trans.duration(), half = true)(
|
|
|
|
form3.input(_)(tpe := "number")
|
|
|
|
)
|
|
|
|
),
|
2020-10-18 04:58:18 -06:00
|
|
|
form3.split(fields.description(true), fields.startPosition),
|
2020-03-20 17:38:51 -06:00
|
|
|
form3.globalError(form),
|
|
|
|
fieldset(cls := "conditions")(
|
2020-04-02 15:32:37 -06:00
|
|
|
fields.advancedSettings,
|
2020-03-20 17:38:51 -06:00
|
|
|
div(cls := "form")(
|
2020-06-03 20:18:45 -06:00
|
|
|
condition(form, fields, auto = true, teams = myTeams, tour = tour.some)
|
2020-03-20 17:38:51 -06:00
|
|
|
)
|
|
|
|
),
|
|
|
|
form3.actions(
|
2020-03-24 13:19:05 -06:00
|
|
|
a(href := routes.Tournament.show(tour.id))(trans.cancel()),
|
2021-06-14 01:13:27 -06:00
|
|
|
form3.submit(trans.save(), icon = "".some)
|
2020-03-20 17:38:51 -06:00
|
|
|
)
|
2020-04-02 15:43:28 -06:00
|
|
|
),
|
|
|
|
postForm(cls := "terminate", action := routes.Tournament.terminate(tour.id))(
|
2021-06-14 01:13:27 -06:00
|
|
|
submitButton(dataIcon := "", cls := "text button button-red confirm")(
|
2020-04-02 15:43:28 -06:00
|
|
|
"Cancel the tournament"
|
|
|
|
)
|
2020-03-20 17:38:51 -06:00
|
|
|
)
|
2020-04-02 16:03:49 -06:00
|
|
|
)
|
2020-03-20 17:38:51 -06:00
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2020-05-05 22:11:15 -06:00
|
|
|
private def autoField(auto: Boolean, field: Field)(visible: Field => Frag) =
|
|
|
|
frag(
|
|
|
|
if (auto) form3.hidden(field) else visible(field)
|
|
|
|
)
|
2019-04-13 08:40:21 -06:00
|
|
|
|
2020-06-03 20:18:45 -06:00
|
|
|
def condition(
|
|
|
|
form: Form[_],
|
|
|
|
fields: TourFields,
|
|
|
|
auto: Boolean,
|
2020-08-20 17:19:53 -06:00
|
|
|
teams: List[LeaderTeam],
|
2020-06-03 20:18:45 -06:00
|
|
|
tour: Option[Tournament]
|
|
|
|
)(implicit
|
2020-05-05 22:11:15 -06:00
|
|
|
ctx: Context
|
|
|
|
) =
|
|
|
|
frag(
|
|
|
|
form3.split(
|
|
|
|
fields.password,
|
2020-08-16 06:37:41 -06:00
|
|
|
(auto && tour.isEmpty && teams.nonEmpty) option {
|
2020-05-05 22:11:15 -06:00
|
|
|
val baseField = form("conditions.teamMember.teamId")
|
|
|
|
val field = ctx.req.queryString get "team" flatMap (_.headOption) match {
|
|
|
|
case None => baseField
|
|
|
|
case Some(team) => baseField.copy(value = team.some)
|
|
|
|
}
|
|
|
|
form3.group(field, frag("Only members of team"), half = true)(
|
|
|
|
form3.select(_, List(("", "No Restriction")) ::: teams.map(_.pair))
|
|
|
|
)
|
2020-04-22 10:39:30 -06:00
|
|
|
}
|
2019-12-13 07:30:20 -07:00
|
|
|
),
|
2020-05-05 22:11:15 -06:00
|
|
|
form3.split(
|
|
|
|
form3.group(form("conditions.nbRatedGame.nb"), frag("Minimum rated games"), half = true)(
|
|
|
|
form3.select(_, Condition.DataForm.nbRatedGameChoices)
|
|
|
|
),
|
|
|
|
autoField(auto, form("conditions.nbRatedGame.perf")) { field =>
|
|
|
|
form3.group(field, frag("In variant"), half = true)(
|
|
|
|
form3.select(_, ("", "Any") :: Condition.DataForm.perfChoices)
|
|
|
|
)
|
|
|
|
}
|
2019-12-13 07:30:20 -07:00
|
|
|
),
|
2020-05-05 22:11:15 -06:00
|
|
|
form3.split(
|
|
|
|
form3.group(form("conditions.minRating.rating"), frag("Minimum rating"), half = true)(
|
|
|
|
form3.select(_, Condition.DataForm.minRatingChoices)
|
|
|
|
),
|
|
|
|
autoField(auto, form("conditions.minRating.perf")) { field =>
|
|
|
|
form3.group(field, frag("In variant"), half = true)(form3.select(_, Condition.DataForm.perfChoices))
|
|
|
|
}
|
2019-12-13 07:30:20 -07:00
|
|
|
),
|
2020-05-05 22:11:15 -06:00
|
|
|
form3.split(
|
|
|
|
form3.group(form("conditions.maxRating.rating"), frag("Maximum weekly rating"), half = true)(
|
|
|
|
form3.select(_, Condition.DataForm.maxRatingChoices)
|
|
|
|
),
|
|
|
|
autoField(auto, form("conditions.maxRating.perf")) { field =>
|
|
|
|
form3.group(field, frag("In variant"), half = true)(form3.select(_, Condition.DataForm.perfChoices))
|
|
|
|
}
|
|
|
|
),
|
|
|
|
form3.split(
|
|
|
|
(ctx.me.exists(_.hasTitle) || isGranted(_.ManageTournament)) ?? {
|
|
|
|
form3.checkbox(
|
|
|
|
form("conditions.titled"),
|
|
|
|
frag("Only titled players"),
|
|
|
|
help = frag("Require an official title to join the tournament").some,
|
|
|
|
half = true
|
|
|
|
)
|
|
|
|
},
|
2019-12-13 07:30:20 -07:00
|
|
|
form3.checkbox(
|
2020-05-05 22:11:15 -06:00
|
|
|
form("berserkable"),
|
|
|
|
frag("Allow Berserk"),
|
|
|
|
help = frag("Let players halve their clock time to gain an extra point").some,
|
2019-12-13 07:30:20 -07:00
|
|
|
half = true
|
2020-05-05 22:11:15 -06:00
|
|
|
),
|
2020-06-25 04:17:27 -06:00
|
|
|
form3.hidden(form("berserkable"), "false".some) // hack to allow disabling berserk
|
2020-04-22 10:39:30 -06:00
|
|
|
),
|
2020-05-05 22:11:15 -06:00
|
|
|
form3.split(
|
|
|
|
form3.checkbox(
|
|
|
|
form("hasChat"),
|
|
|
|
trans.chatRoom(),
|
|
|
|
help = frag("Let players discuss in a chat room").some,
|
|
|
|
half = true
|
|
|
|
),
|
2020-06-25 04:17:27 -06:00
|
|
|
form3.hidden(form("hasChat"), "false".some), // hack to allow disabling chat
|
2020-05-26 20:21:38 -06:00
|
|
|
form3.checkbox(
|
|
|
|
form("streakable"),
|
|
|
|
frag("Arena streaks"),
|
|
|
|
help = frag("After 2 wins, consecutive wins grant 4 points instead of 2.").some,
|
|
|
|
half = true
|
2020-05-26 21:21:30 -06:00
|
|
|
),
|
2020-06-25 04:17:27 -06:00
|
|
|
form3.hidden(form("streakable"), "false".some) // hack to allow disabling streaks
|
2020-05-05 22:11:15 -06:00
|
|
|
)
|
2020-04-22 10:39:30 -06:00
|
|
|
)
|
2019-04-13 08:47:52 -06:00
|
|
|
|
2020-06-19 04:53:17 -06:00
|
|
|
def startingPosition(field: Field, tour: Option[Tournament]) =
|
2020-10-18 03:43:56 -06:00
|
|
|
form3.input(field)(
|
2020-10-18 04:58:18 -06:00
|
|
|
tour.exists(t => !t.isCreated && t.position.isEmpty).option(disabled := true)
|
2019-04-13 08:47:52 -06:00
|
|
|
)
|
2020-10-18 05:34:31 -06:00
|
|
|
|
|
|
|
val positionInputHelp = frag(
|
|
|
|
"Paste a valid FEN to start every game from a given position.",
|
|
|
|
br,
|
|
|
|
"It only works for standard games, not with variants.",
|
|
|
|
br,
|
|
|
|
"You can use the ",
|
2021-02-08 07:25:21 -07:00
|
|
|
a(href := routes.Editor.index, target := "_blank")("board editor"),
|
2020-10-18 05:34:31 -06:00
|
|
|
" to generate a FEN position, then paste it here.",
|
|
|
|
br,
|
|
|
|
"Leave empty to start games from the normal initial position."
|
|
|
|
)
|
2019-04-13 08:24:51 -06:00
|
|
|
}
|
2020-04-02 15:32:37 -06:00
|
|
|
|
2020-06-19 04:53:17 -06:00
|
|
|
final private class TourFields(form: Form[_], tour: Option[Tournament])(implicit ctx: Context) {
|
2020-04-02 15:32:37 -06:00
|
|
|
|
2020-06-19 04:53:17 -06:00
|
|
|
def isTeamBattle = tour.exists(_.isTeamBattle) || form("teamBattleByTeam").value.nonEmpty
|
|
|
|
|
2021-04-14 10:26:51 -06:00
|
|
|
private def disabledAfterStart = tour.exists(!_.isCreated)
|
2020-04-02 15:32:37 -06:00
|
|
|
|
2020-04-05 09:28:18 -06:00
|
|
|
def name =
|
2020-04-02 15:32:37 -06:00
|
|
|
form3.group(form("name"), trans.name()) { f =>
|
|
|
|
div(
|
|
|
|
form3.input(f),
|
|
|
|
" ",
|
|
|
|
if (isTeamBattle) "Team Battle" else "Arena",
|
|
|
|
br,
|
|
|
|
small(cls := "form-help")(
|
|
|
|
trans.safeTournamentName(),
|
|
|
|
br,
|
|
|
|
trans.inappropriateNameWarning(),
|
|
|
|
br,
|
|
|
|
trans.emptyTournamentName()
|
|
|
|
)
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2020-05-05 22:11:15 -06:00
|
|
|
def rated =
|
|
|
|
frag(
|
|
|
|
form3.checkbox(
|
|
|
|
form("rated"),
|
|
|
|
trans.rated(),
|
|
|
|
help = raw("Games are rated<br>and impact players ratings").some
|
|
|
|
),
|
|
|
|
st.input(tpe := "hidden", st.name := form("rated").name, value := "false") // hack allow disabling rated
|
|
|
|
)
|
2020-04-02 15:32:37 -06:00
|
|
|
def variant =
|
|
|
|
form3.group(form("variant"), trans.variant(), half = true)(
|
2020-06-19 04:53:17 -06:00
|
|
|
form3.select(
|
|
|
|
_,
|
|
|
|
translatedVariantChoicesWithVariants.map(x => x._1 -> x._2),
|
|
|
|
disabled = disabledAfterStart
|
|
|
|
)
|
2020-04-02 15:32:37 -06:00
|
|
|
)
|
|
|
|
def startPosition =
|
2020-10-18 03:43:56 -06:00
|
|
|
form3.group(
|
|
|
|
form("position"),
|
|
|
|
trans.startPosition(),
|
|
|
|
klass = "position",
|
|
|
|
half = true,
|
2020-10-18 05:34:31 -06:00
|
|
|
help = tournament.form.positionInputHelp.some
|
2020-10-18 03:43:56 -06:00
|
|
|
)(
|
2020-06-19 04:53:17 -06:00
|
|
|
views.html.tournament.form.startingPosition(_, tour)
|
2020-04-02 15:32:37 -06:00
|
|
|
)
|
|
|
|
def clock =
|
|
|
|
form3.split(
|
|
|
|
form3.group(form("clockTime"), trans.clockInitialTime(), half = true)(
|
2020-08-21 14:40:37 -06:00
|
|
|
form3.select(_, TournamentForm.clockTimeChoices, disabled = disabledAfterStart)
|
2020-04-02 15:32:37 -06:00
|
|
|
),
|
|
|
|
form3.group(form("clockIncrement"), trans.clockIncrement(), half = true)(
|
2020-08-21 14:40:37 -06:00
|
|
|
form3.select(_, TournamentForm.clockIncrementChoices, disabled = disabledAfterStart)
|
2020-04-02 15:32:37 -06:00
|
|
|
)
|
|
|
|
)
|
|
|
|
def minutes =
|
|
|
|
form3.group(form("minutes"), trans.duration(), half = true)(
|
2020-08-21 14:40:37 -06:00
|
|
|
form3.select(_, TournamentForm.minuteChoices)
|
2020-04-02 15:32:37 -06:00
|
|
|
)
|
|
|
|
def waitMinutes =
|
|
|
|
form3.group(form("waitMinutes"), trans.timeBeforeTournamentStarts(), half = true)(
|
2020-08-21 14:40:37 -06:00
|
|
|
form3.select(_, TournamentForm.waitMinuteChoices)
|
2020-04-02 15:32:37 -06:00
|
|
|
)
|
2020-10-18 03:43:56 -06:00
|
|
|
def description(half: Boolean) =
|
2020-04-04 14:31:01 -06:00
|
|
|
form3.group(
|
|
|
|
form("description"),
|
2020-04-22 10:39:30 -06:00
|
|
|
frag("Tournament description"),
|
2020-08-25 03:42:36 -06:00
|
|
|
help = frag(
|
|
|
|
"Anything special you want to tell the participants? Try to keep it short. Markdown links are available: [name](https://url)"
|
2020-10-18 03:43:56 -06:00
|
|
|
).some,
|
|
|
|
half = half
|
2020-08-25 03:42:36 -06:00
|
|
|
)(form3.textarea(_)(rows := 4))
|
2020-04-02 15:32:37 -06:00
|
|
|
def password =
|
2021-04-29 06:07:17 -06:00
|
|
|
form3.group(
|
|
|
|
form("password"),
|
|
|
|
trans.password(),
|
|
|
|
help = trans.makePrivateTournament().some,
|
|
|
|
half = true
|
|
|
|
)(form3.input(_)(autocomplete := "off"))
|
2020-04-02 15:32:37 -06:00
|
|
|
def startDate =
|
|
|
|
form3.group(
|
|
|
|
form("startDate"),
|
2020-04-22 10:39:30 -06:00
|
|
|
frag("Custom start date"),
|
2020-08-24 04:51:01 -06:00
|
|
|
help = frag(
|
|
|
|
"""In your own local timezone. This overrides the "Time before tournament starts" setting"""
|
|
|
|
).some
|
2020-04-02 15:32:37 -06:00
|
|
|
)(form3.flatpickr(_))
|
2020-05-05 22:11:15 -06:00
|
|
|
def advancedSettings =
|
|
|
|
frag(
|
|
|
|
legend(trans.advancedSettings()),
|
|
|
|
errMsg(form("conditions")),
|
|
|
|
p(
|
2021-06-14 01:13:27 -06:00
|
|
|
strong(dataIcon := "", cls := "text")(trans.recommendNotTouching()),
|
2020-05-05 22:11:15 -06:00
|
|
|
" ",
|
|
|
|
trans.fewerPlayers(),
|
|
|
|
" ",
|
|
|
|
a(cls := "show")(trans.showAdvancedSettings())
|
|
|
|
)
|
2020-04-02 15:32:37 -06:00
|
|
|
)
|
|
|
|
}
|