broadcast tournament/round WIP
parent
06d01fd08f
commit
af408f6288
|
@ -5,6 +5,7 @@ import play.api.mvc._
|
|||
|
||||
import lila.api.Context
|
||||
import lila.app._
|
||||
|
||||
// import lila.common.config.MaxPerSecond
|
||||
import lila.relay.{ RelayRound => RoundModel, RelayTour => TourModel, RelayRoundForm }
|
||||
import lila.user.{ User => UserModel }
|
||||
|
@ -41,7 +42,7 @@ final class RelayRound(
|
|||
err => BadRequest(html.relay.roundForm.create(err, trs.tour)).fuccess,
|
||||
setup =>
|
||||
env.relay.api.create(setup, me, trs.tour) map { relay =>
|
||||
Redirect(routes.RelayTour.show(trs.tour.slug, trs.tour.id.value))
|
||||
Redirect(routes.RelayRound.form(trs.tour.id.value))
|
||||
}
|
||||
)
|
||||
}
|
||||
|
@ -129,7 +130,7 @@ final class RelayRound(
|
|||
OpenOrScoped(_.Study.Read)(
|
||||
open = implicit ctx => {
|
||||
pageHit
|
||||
WithRelay(ts, rs, id) { rt =>
|
||||
WithRoundAndTour(ts, rs, id) { rt =>
|
||||
val sc =
|
||||
if (rt.round.sync.ongoing)
|
||||
env.study.chapterRepo relaysAndTagsByStudyId rt.round.studyId flatMap { chapters =>
|
||||
|
@ -150,15 +151,9 @@ final class RelayRound(
|
|||
}
|
||||
)
|
||||
|
||||
def bcShow(@nowarn("unused") slug: String, roundId: String) = Open { implicit ctx =>
|
||||
env.relay.api byIdWithTour RoundModel.Id(roundId) map2 { rt =>
|
||||
Redirect(rt.path)
|
||||
}
|
||||
}
|
||||
|
||||
def chapter(ts: String, rs: String, id: String, chapterId: String) =
|
||||
Open { implicit ctx =>
|
||||
WithRelay(ts, rs, id) { rt =>
|
||||
WithRoundAndTour(ts, rs, id) { rt =>
|
||||
env.study.api.byIdWithChapter(rt.round.studyId, chapterId) flatMap {
|
||||
_ ?? { doShow(rt, _) }
|
||||
}
|
||||
|
@ -189,12 +184,11 @@ final class RelayRound(
|
|||
// }.fuccess
|
||||
// }
|
||||
|
||||
private def WithRelay(ts: String, rs: String, id: String)(
|
||||
private def WithRoundAndTour(ts: String, rs: String, id: String)(
|
||||
f: RoundModel.WithTour => Fu[Result]
|
||||
)(implicit ctx: Context): Fu[Result] =
|
||||
OptionFuResult(env.relay.api byIdWithTour id) { rt =>
|
||||
if (rt.tour.slug != ts) Redirect(rt.path).fuccess
|
||||
if (rt.round.slug != rs) Redirect(rt.path).fuccess
|
||||
if (ctx.req.path != rt.path) Redirect(rt.path).fuccess
|
||||
else f(rt)
|
||||
}
|
||||
|
||||
|
|
|
@ -2,12 +2,13 @@ package controllers
|
|||
|
||||
import play.api.data.Form
|
||||
import play.api.mvc._
|
||||
import scala.annotation.nowarn
|
||||
import views._
|
||||
|
||||
import lila.api.Context
|
||||
import lila.app._
|
||||
import lila.relay.{ RelayRound => RoundModel, RelayTour => TourModel }
|
||||
import lila.user.{ User => UserModel }
|
||||
import views._
|
||||
|
||||
final class RelayTour(env: Env) extends LilaController(env) {
|
||||
|
||||
|
@ -17,7 +18,7 @@ final class RelayTour(env: Env) extends LilaController(env) {
|
|||
for {
|
||||
active <- (page == 1).??(env.relay.api.officialActive)
|
||||
pager <- env.relay.pager.inactive(page)
|
||||
} yield Ok(html.tour.index(active, pager))
|
||||
} yield Ok(html.relay.tour.index(active, pager))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -35,7 +36,7 @@ final class RelayTour(env: Env) extends LilaController(env) {
|
|||
err => BadRequest(html.relay.tourForm.create(err)).fuccess,
|
||||
setup =>
|
||||
env.relay.api.tourCreate(setup, me) map { tour =>
|
||||
Redirect(routes.RelayTour.show(tour.slug, tour.id.value)).flashSuccess
|
||||
Redirect(routes.RelayRound.form(tour.id.value)).flashSuccess
|
||||
}
|
||||
)
|
||||
}
|
||||
|
@ -59,11 +60,25 @@ final class RelayTour(env: Env) extends LilaController(env) {
|
|||
err => BadRequest(html.relay.tourForm.edit(tour, err)).fuccess,
|
||||
setup =>
|
||||
env.relay.api.tourUpdate(tour, setup, me) inject
|
||||
Redirect(routes.RelayTour.show(tour.slug, tour.id.value)).flashSuccess
|
||||
Redirect(routes.RelayTour.edit(tour.id.value)).flashSuccess
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
def redirect(@nowarn("msg=unused") slug: String, anyId: String) = Open { implicit ctx =>
|
||||
env.relay.api byIdWithTour RoundModel.Id(anyId) flatMap {
|
||||
case Some(rt) => Redirect(rt.path).fuccess // BC old broadcast URLs
|
||||
case None => env.relay.api tourById TourModel.Id(anyId) flatMap { _ ?? redirectToTour }
|
||||
}
|
||||
}
|
||||
|
||||
private def redirectToTour(tour: TourModel)(implicit ctx: Context): Fu[Result] =
|
||||
env.relay.api.activeTourNextRound(tour) orElse env.relay.api.tourLastRound(tour) flatMap {
|
||||
case None =>
|
||||
ctx.me.exists(tour.ownedBy) ?? Redirect(routes.RelayRound.form(tour.id.value)).fuccess
|
||||
case Some(round) => Redirect(round.withTour(tour).path).fuccess
|
||||
}
|
||||
|
||||
private def WithTour(id: String)(
|
||||
f: TourModel => Fu[Result]
|
||||
)(implicit ctx: Context): Fu[Result] =
|
||||
|
|
|
@ -300,7 +300,7 @@ final class Study(
|
|||
_ ?? { study =>
|
||||
env.study.api.delete(study) >> env.relay.api.deleteRound(lila.relay.RelayRound.Id(id)).map {
|
||||
case None => Redirect(routes.Study.mine("hot"))
|
||||
case Some(tour) => Redirect(routes.RelayTour.show(tour.slug, tour.id.value))
|
||||
case Some(tour) => Redirect(routes.RelayTour.redirect(tour.slug, tour.id.value))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,13 +16,18 @@ object roundForm {
|
|||
|
||||
def create(form: Form[Data], tour: RelayTour)(implicit ctx: Context) =
|
||||
layout(newBroadcast.txt())(
|
||||
h1(a(href := views.html.relay.tour.url(tour))(tour.name), " • ", addRound()),
|
||||
h1(a(href := routes.RelayTour.redirect(tour.slug, tour.id.value))(tour.name), " • ", addRound()),
|
||||
inner(form, routes.RelayRound.create(tour.id.value), tour)
|
||||
)
|
||||
|
||||
def edit(rt: RelayRound.WithTour, form: Form[Data])(implicit ctx: Context) =
|
||||
layout(rt.fullName)(
|
||||
h1("Edit ", a(href := tour.url(rt.tour))(rt.tour.name), " > ", a(href := rt.path)(rt.round.name)),
|
||||
h1(
|
||||
"Edit ",
|
||||
a(href := routes.RelayTour.redirect(rt.tour.slug, rt.tour.id.value))(rt.tour.name),
|
||||
" > ",
|
||||
a(href := rt.path)(rt.round.name)
|
||||
),
|
||||
inner(form, routes.RelayRound.update(rt.round.id.value), rt.tour),
|
||||
div(cls := "relay-round__actions")(
|
||||
postForm(action := routes.RelayRound.cloneRound(rt.round.id.value))(
|
||||
|
@ -95,7 +100,7 @@ object roundForm {
|
|||
)(form3.input(_, typ = "number"))
|
||||
),
|
||||
form3.actions(
|
||||
a(href := tour.url(t))(trans.cancel()),
|
||||
a(href := routes.RelayTour.redirect(t.slug, t.id.value))(trans.cancel()),
|
||||
form3.submit(trans.apply())
|
||||
)
|
||||
)
|
||||
|
|
|
@ -54,14 +54,14 @@ object tour {
|
|||
}
|
||||
),
|
||||
st.section(cls := "infinite-scroll")(
|
||||
pager.currentPageResults map { tour =>
|
||||
pager.currentPageResults map { rt =>
|
||||
div(cls := "relay-widget paginated", dataIcon := "")(
|
||||
a(cls := "overlay", href := views.html.relay.tour.url(tour)),
|
||||
a(cls := "overlay", href := rt.path),
|
||||
div(
|
||||
h2(tour.name),
|
||||
h2(rt.tour.name),
|
||||
div(cls := "relay-widget__info")(
|
||||
p(tour.description),
|
||||
tour.syncedAt.map(momentFromNow(_))
|
||||
p(rt.tour.description),
|
||||
rt.tour.syncedAt.map(momentFromNow(_))
|
||||
)
|
||||
)
|
||||
)
|
|
@ -27,11 +27,11 @@ object tourForm {
|
|||
|
||||
def edit(t: RelayTour, form: Form[Data])(implicit ctx: Context) =
|
||||
layout(t.name)(
|
||||
h1("Edit ", a(href := tour.url(t))(t.name)),
|
||||
h1("Edit ", a(href := routes.RelayTour.redirect(t.slug, t.id.value))(t.name)),
|
||||
postForm(cls := "form3", action := routes.RelayTour.update(t.id.value))(
|
||||
inner(form),
|
||||
form3.actions(
|
||||
a(href := tour.url(t))(trans.cancel()),
|
||||
a(href := routes.RelayTour.redirect(t.slug, t.id.value))(trans.cancel()),
|
||||
form3.submit(trans.apply())
|
||||
)
|
||||
)
|
||||
|
|
|
@ -169,9 +169,9 @@ GET /study/topic/autocomplete controllers.Study.topicAutocomplete
|
|||
GET /broadcast controllers.RelayTour.index(page: Int ?= 1)
|
||||
GET /broadcast/new controllers.RelayTour.form
|
||||
POST /broadcast/new controllers.RelayTour.create
|
||||
GET /broadcast/:rs/$anyId<\w{8}> controllers.RelayTour.redirect(rs: String, anyId: String)
|
||||
GET /broadcast/$tourId<\w{8}>/edit controllers.RelayTour.edit(tourId: String)
|
||||
POST /broadcast/$tourId<\w{8}>/edit controllers.RelayTour.update(tourId: String)
|
||||
GET /broadcast/:rs/$roundId<\w{8}> controllers.RelayRound.bcShow(rs: String, roundId: String)
|
||||
GET /broadcast/$tourId<\w{8}>/new controllers.RelayRound.form(tourId: String)
|
||||
POST /broadcast/$tourId<\w{8}>/new controllers.RelayRound.create(tourId: String)
|
||||
GET /broadcast/:ts/:rs/$roundId<\w{8}> controllers.RelayRound.show(ts: String, rs: String, roundId: String)
|
||||
|
|
|
@ -61,6 +61,24 @@ final class RelayApi(
|
|||
|
||||
def withRounds(tour: RelayTour) = roundRepo.byTour(tour).dmap(tour.withRounds)
|
||||
|
||||
private val nextRoundSort = $doc(
|
||||
"startedAt" -> 1,
|
||||
"startsAt" -> 1,
|
||||
"name" -> 1
|
||||
)
|
||||
|
||||
def activeTourNextRound(tour: RelayTour): Fu[Option[RelayRound]] = tour.active ??
|
||||
roundRepo.coll
|
||||
.find($doc("tourId" -> tour.id, "finished" -> false))
|
||||
.sort(nextRoundSort)
|
||||
.one[RelayRound]
|
||||
|
||||
def tourLastRound(tour: RelayTour): Fu[Option[RelayRound]] =
|
||||
roundRepo.coll
|
||||
.find($doc("tourId" -> tour.id))
|
||||
.sort($doc("startedAt" -> -1, "startsAt" -> -1))
|
||||
.one[RelayRound]
|
||||
|
||||
def officialActive: Fu[List[RelayTour.ActiveWithNextRound]] =
|
||||
tourRepo.coll
|
||||
.aggregateList(20) { framework =>
|
||||
|
@ -84,14 +102,8 @@ final class RelayApi(
|
|||
)
|
||||
),
|
||||
$doc("$addFields" -> $doc("sync.log" -> $arr())),
|
||||
$doc(
|
||||
"$sort" -> $doc(
|
||||
"startedAt" -> 1,
|
||||
"startsAt" -> 1,
|
||||
"name" -> 1
|
||||
)
|
||||
),
|
||||
$doc("$limit" -> 1)
|
||||
$doc("$sort" -> nextRoundSort),
|
||||
$doc("$limit" -> 1)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
|
|
@ -3,28 +3,65 @@ package lila.relay
|
|||
import reactivemongo.api.ReadPreference
|
||||
|
||||
import lila.common.config.MaxPerPage
|
||||
import lila.common.paginator.Paginator
|
||||
import lila.common.paginator.{ AdapterLike, Paginator }
|
||||
import lila.db.dsl._
|
||||
import lila.db.paginator.{ Adapter, CachedAdapter }
|
||||
|
||||
final class RelayPager(tourRepo: RelayTourRepo)(implicit
|
||||
final class RelayPager(tourRepo: RelayTourRepo, roundRepo: RelayRoundRepo)(implicit
|
||||
ec: scala.concurrent.ExecutionContext
|
||||
) {
|
||||
|
||||
import BSONHandlers._
|
||||
|
||||
def inactive(page: Int): Fu[Paginator[RelayTour]] =
|
||||
def inactive(page: Int): Fu[Paginator[RelayTour.WithLastRound]] =
|
||||
Paginator(
|
||||
adapter = new CachedAdapter(
|
||||
nbResults = fuccess(9999),
|
||||
adapter = new Adapter[RelayTour](
|
||||
collection = tourRepo.coll,
|
||||
selector = tourRepo.selectors.official ++ tourRepo.selectors.inactive,
|
||||
projection = none,
|
||||
sort = $sort desc "syncedAt",
|
||||
readPreference = ReadPreference.secondaryPreferred
|
||||
)
|
||||
),
|
||||
adapter = new AdapterLike[RelayTour.WithLastRound] {
|
||||
|
||||
def nbResults: Fu[Int] = fuccess(9999)
|
||||
|
||||
def slice(offset: Int, length: Int): Fu[List[RelayTour.WithLastRound]] =
|
||||
tourRepo.coll
|
||||
.aggregateList(length, readPreference = ReadPreference.secondaryPreferred) { framework =>
|
||||
import framework._
|
||||
Match(tourRepo.selectors.official ++ tourRepo.selectors.inactive) -> List(
|
||||
Sort(Descending("syncedAt")),
|
||||
PipelineOperator(
|
||||
$doc(
|
||||
"$lookup" -> $doc(
|
||||
"from" -> roundRepo.coll.name,
|
||||
"as" -> "round",
|
||||
"let" -> $doc("id" -> "$_id"),
|
||||
"pipeline" -> $arr(
|
||||
$doc(
|
||||
"$match" -> $doc(
|
||||
"$expr" -> $doc(
|
||||
$doc("$eq" -> $arr("$tourId", "$$id"))
|
||||
)
|
||||
)
|
||||
),
|
||||
$doc(
|
||||
"$sort" -> $doc(
|
||||
"startedAt" -> -1,
|
||||
"startsAt" -> -1,
|
||||
"name" -> -1
|
||||
)
|
||||
),
|
||||
$doc("$limit" -> 1),
|
||||
$doc("$addFields" -> $doc("sync.log" -> $arr()))
|
||||
)
|
||||
)
|
||||
)
|
||||
),
|
||||
UnwindField("round")
|
||||
)
|
||||
}
|
||||
.map { docs =>
|
||||
for {
|
||||
doc <- docs
|
||||
tour <- doc.asOpt[RelayTour]
|
||||
round <- doc.getAsOpt[RelayRound]("round")
|
||||
} yield RelayTour.WithLastRound(tour, round)
|
||||
}
|
||||
},
|
||||
currentPage = page,
|
||||
maxPerPage = MaxPerPage(20)
|
||||
)
|
||||
|
|
|
@ -130,17 +130,19 @@ object RelayRound {
|
|||
case class UpstreamIds(ids: List[lila.game.Game.ID]) extends Upstream
|
||||
}
|
||||
|
||||
case class WithTour(round: RelayRound, tour: RelayTour) {
|
||||
trait AndTour {
|
||||
val round: RelayRound
|
||||
val tour: RelayTour
|
||||
def fullName = s"${tour.name} • ${round.name}"
|
||||
|
||||
def withStudy(study: Study) = WithTourAndStudy(round, tour, study)
|
||||
|
||||
def path: String =
|
||||
s"/broadcast/${tour.slug}/${if (round.slug == tour.slug) "-" else round.slug}/${round.id}"
|
||||
|
||||
def path(chapterId: Chapter.Id): String = s"$path/$chapterId"
|
||||
}
|
||||
|
||||
case class WithTour(round: RelayRound, tour: RelayTour) extends AndTour {
|
||||
def withStudy(study: Study) = WithTourAndStudy(round, tour, study)
|
||||
}
|
||||
|
||||
case class WithTourAndStudy(relay: RelayRound, tour: RelayTour, study: Study) {
|
||||
def path = WithTour(relay, tour).path
|
||||
def fullName = WithTour(relay, tour).fullName
|
||||
|
|
|
@ -36,12 +36,11 @@ object RelayTour {
|
|||
|
||||
case class WithRounds(tour: RelayTour, rounds: List[RelayRound])
|
||||
|
||||
case class ActiveWithNextRound(tour: RelayTour, round: RelayRound) {
|
||||
def path = RelayRound.WithTour(round, tour).path
|
||||
case class ActiveWithNextRound(tour: RelayTour, round: RelayRound) extends RelayRound.AndTour {
|
||||
def ongoing = round.startedAt.isDefined
|
||||
}
|
||||
|
||||
case class WithLastRound(tour: RelayTour, round: RelayRound)
|
||||
case class WithLastRound(tour: RelayTour, round: RelayRound) extends RelayRound.AndTour
|
||||
|
||||
def makeId = Id(lila.common.ThreadLocalRandom nextString 8)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue