explain why tournament join failed - closes #7966
parent
18960667a8
commit
f0df9bba47
|
@ -100,7 +100,7 @@ final class Tournament(
|
|||
html = tourOption
|
||||
.fold(tournamentNotFound.fuccess) { tour =>
|
||||
for {
|
||||
verdicts <- api.verdicts(tour, ctx.me, getUserTeamIds)
|
||||
verdicts <- api.getVerdicts(tour, ctx.me, getUserTeamIds)
|
||||
version <- env.tournament.version(tour.id)
|
||||
json <- jsonView(
|
||||
tour = tour,
|
||||
|
@ -209,13 +209,17 @@ final class Tournament(
|
|||
api.joinWithResult(id, me, password, teamId, getUserTeamIds, isLeader) flatMap { result =>
|
||||
negotiate(
|
||||
html = fuccess {
|
||||
if (result) Redirect(routes.Tournament.show(id))
|
||||
else BadRequestWithReason("wrong password maybe?").pp
|
||||
result.error match {
|
||||
case None => Redirect(routes.Tournament.show(id))
|
||||
case Some(error) => BadRequest(error)
|
||||
}
|
||||
},
|
||||
api = _ =>
|
||||
fuccess {
|
||||
if (result) jsonOkResult
|
||||
else BadRequest(Json.obj("joined" -> false))
|
||||
result.error match {
|
||||
case None => jsonOkResult
|
||||
case Some(error) => BadRequest(Json.obj("joined" -> false, "error" -> error))
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
|
|
@ -221,4 +221,16 @@ object Tournament {
|
|||
def makeId = ThreadLocalRandom nextString 8
|
||||
|
||||
case class PastAndNext(past: List[Tournament], next: List[Tournament])
|
||||
|
||||
sealed abstract class JoinResult(val error: Option[String] = None) {
|
||||
def ok = error.isEmpty
|
||||
}
|
||||
object JoinResult {
|
||||
case object Ok extends JoinResult()
|
||||
case object WrongPassword extends JoinResult("Wrong password".some)
|
||||
case object Paused extends JoinResult("Your pause is not over yet".some)
|
||||
case object Verdicts extends JoinResult("Tournament restrictions".some)
|
||||
case object MissingTeam extends JoinResult("Missing team".some)
|
||||
case object Nope extends JoinResult("Couldn't join for some reason?".some)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -266,7 +266,7 @@ final class TournamentApi(
|
|||
}
|
||||
}
|
||||
|
||||
def verdicts(
|
||||
def getVerdicts(
|
||||
tour: Tournament,
|
||||
me: Option[User],
|
||||
getUserTeamIds: User => Fu[List[TeamID]]
|
||||
|
@ -289,46 +289,47 @@ final class TournamentApi(
|
|||
withTeamId: Option[String],
|
||||
getUserTeamIds: User => Fu[List[TeamID]],
|
||||
asLeader: Boolean,
|
||||
promise: Option[Promise[Boolean]]
|
||||
promise: Option[Promise[Tournament.JoinResult]]
|
||||
): Funit =
|
||||
Sequencing(tourId)(tournamentRepo.enterableById) { tour =>
|
||||
playerRepo.exists(tour.id, me.id) flatMap { playerExists =>
|
||||
val fuJoined =
|
||||
if (tour.password == password || playerExists) {
|
||||
verdicts(tour, me.some, getUserTeamIds) flatMap {
|
||||
_.accepted ?? {
|
||||
pause.canJoin(me.id, tour) ?? {
|
||||
def proceedWithTeam(team: Option[String]) =
|
||||
playerRepo.join(tour.id, me, tour.perfType, team) >>
|
||||
updateNbPlayers(tour.id) >>- {
|
||||
socket.reload(tour.id)
|
||||
publish()
|
||||
} inject true
|
||||
withTeamId match {
|
||||
case None if tour.isTeamBattle => playerExists ?? proceedWithTeam(none)
|
||||
case None => proceedWithTeam(none)
|
||||
case Some(team) =>
|
||||
tour.teamBattle match {
|
||||
case Some(battle) if battle.teams contains team =>
|
||||
getUserTeamIds(me) flatMap { myTeams =>
|
||||
if (myTeams has team) proceedWithTeam(team.some)
|
||||
else fuccess(false)
|
||||
}
|
||||
case _ => fuccess(false)
|
||||
}
|
||||
}
|
||||
import Tournament.JoinResult
|
||||
val fuResult: Fu[JoinResult] =
|
||||
if (!playerExists && tour.password.exists(p => !password.has(p))) fuccess(JoinResult.WrongPassword)
|
||||
else
|
||||
getVerdicts(tour, me.some, getUserTeamIds) flatMap { verdicts =>
|
||||
if (!verdicts.accepted) fuccess(JoinResult.Verdicts)
|
||||
else if (!pause.canJoin(me.id, tour)) fuccess(JoinResult.Paused)
|
||||
else {
|
||||
def proceedWithTeam(team: Option[String]): Fu[JoinResult] =
|
||||
playerRepo.join(tour.id, me, tour.perfType, team) >>
|
||||
updateNbPlayers(tour.id) >>- {
|
||||
socket.reload(tour.id)
|
||||
publish()
|
||||
} inject JoinResult.Ok
|
||||
withTeamId match {
|
||||
case None if tour.isTeamBattle && playerExists => proceedWithTeam(none)
|
||||
case None if tour.isTeamBattle => fuccess(JoinResult.MissingTeam)
|
||||
case None => proceedWithTeam(none)
|
||||
case Some(team) =>
|
||||
tour.teamBattle match {
|
||||
case Some(battle) if battle.teams contains team =>
|
||||
getUserTeamIds(me) flatMap { myTeams =>
|
||||
if (myTeams has team) proceedWithTeam(team.some)
|
||||
else fuccess(JoinResult.MissingTeam)
|
||||
}
|
||||
case _ => fuccess(JoinResult.Nope)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
socket.reload(tour.id)
|
||||
fuccess(false)
|
||||
}
|
||||
fuJoined map { joined =>
|
||||
withTeamId.ifTrue(joined && asLeader && tour.isTeamBattle) foreach {
|
||||
tournamentRepo.setForTeam(tour.id, _)
|
||||
}
|
||||
promise.foreach(_ success joined)
|
||||
fuResult map { result =>
|
||||
if (result.ok)
|
||||
withTeamId.ifTrue(asLeader && tour.isTeamBattle) foreach {
|
||||
tournamentRepo.setForTeam(tour.id, _)
|
||||
}
|
||||
else socket.reload(tour.id)
|
||||
promise.foreach(_ success result)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -340,10 +341,10 @@ final class TournamentApi(
|
|||
teamId: Option[String],
|
||||
getUserTeamIds: User => Fu[List[TeamID]],
|
||||
isLeader: Boolean
|
||||
): Fu[Boolean] = {
|
||||
val promise = Promise[Boolean]()
|
||||
): Fu[Tournament.JoinResult] = {
|
||||
val promise = Promise[Tournament.JoinResult]()
|
||||
join(tourId, me, password, teamId, getUserTeamIds, isLeader, promise.some)
|
||||
promise.future.withTimeoutDefault(5.seconds, false)
|
||||
promise.future.withTimeoutDefault(5.seconds, Tournament.JoinResult.Nope)
|
||||
}
|
||||
|
||||
def pageOf(tour: Tournament, userId: User.ID): Fu[Option[Int]] =
|
||||
|
|
|
@ -29,13 +29,16 @@ export const json = (url: string, init: RequestInit = {}): Promise<any> =>
|
|||
|
||||
/* fetch a string */
|
||||
export const text = (url: string, init: RequestInit = {}): Promise<string> =>
|
||||
textRaw(url, init).then(res => {
|
||||
if (res.ok) return res.text();
|
||||
throw res.statusText;
|
||||
});
|
||||
|
||||
export const textRaw = (url: string, init: RequestInit = {}): Promise<Response> =>
|
||||
fetch(url, {
|
||||
...defaultInit,
|
||||
headers: { ...xhrHeader },
|
||||
...init,
|
||||
}).then(res => {
|
||||
if (res.ok) return res.text();
|
||||
throw res.statusText;
|
||||
});
|
||||
|
||||
/* load a remote script */
|
||||
|
|
|
@ -7,7 +7,7 @@ const onFail = () => lichess.reload();
|
|||
|
||||
export const join = throttle(1000, (ctrl: TournamentController, password?: string, team?: string) =>
|
||||
xhr
|
||||
.text('/tournament/' + ctrl.data.id + '/join', {
|
||||
.textRaw('/tournament/' + ctrl.data.id + '/join', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({
|
||||
p: password || null,
|
||||
|
@ -15,7 +15,9 @@ export const join = throttle(1000, (ctrl: TournamentController, password?: strin
|
|||
}),
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
})
|
||||
.catch(onFail)
|
||||
.then(res => {
|
||||
if (!res.ok) res.text().then(alert);
|
||||
})
|
||||
);
|
||||
|
||||
export const withdraw = throttle(1000, (ctrl: TournamentController) =>
|
||||
|
|
Loading…
Reference in New Issue