convert new puzzle IDs to/from numerical IDs for mobile app BC

pull/7691/head
Thibault Duplessis 2020-12-08 12:57:49 +01:00
parent abd05773f8
commit e1954ca63a
4 changed files with 54 additions and 13 deletions

View File

@ -61,16 +61,6 @@ final class Puzzle(
}
}
def load(id: String) =
Open { implicit ctx =>
NoBot {
XhrOnly {
???
// OptionFuOk(env.puzzle.api.puzzle find Puz.Id(id))(puzzleJson _).dmap(_ as JSON)
}
}
}
private def nextPuzzleForMe(theme: PuzzleTheme.Key)(implicit ctx: Context): Fu[Puz] =
ctx.me match {
case Some(me) => env.puzzle.session.nextPuzzleFor(me, theme)
@ -173,6 +163,17 @@ final class Puzzle(
}
}
def mobileBcLoad(nid: Long) =
Open { implicit ctx =>
negotiate(
html = notFound,
_ =>
OptionFuOk(env.puzzle.api.puzzle find Puz.numericalId(nid)) { puz =>
env.puzzle.jsonView.bc(puzzle = puz, theme = PuzzleTheme.any, user = ctx.me)
}.dmap(_ as JSON)
)
}
/* Mobile API: select a bunch of puzzles for offline use */
def batchSelect =
Auth { implicit ctx => me =>

View File

@ -81,15 +81,16 @@ GET /training controllers.Puzzle.home
GET /training/daily controllers.Puzzle.daily
GET /training/frame controllers.Puzzle.frame
GET /training/export/gif/thumbnail/:id.gif controllers.Export.puzzleThumbnail(id: String)
GET /training/batch controllers.Puzzle.batchSelect
POST /training/batch controllers.Puzzle.batchSolve
GET /training/themes controllers.Puzzle.themes
GET /training/:id/load controllers.Puzzle.mobileBcLoad(id: Long)
GET /training/:themeOrId controllers.Puzzle.show(themeOrId: String)
GET /training/:theme/$id<\w{5}> controllers.Puzzle.showWithTheme(theme: String, id: String)
POST /training/$id<\w{5}>/vote controllers.Puzzle.vote(id: String)
POST /training/$id<\w{5}>/vote/:theme controllers.Puzzle.voteTheme(id: String, theme: String)
POST /training/complete/:theme/$id<\w{5}> controllers.Puzzle.complete(theme: String, id: String)
POST /training/difficulty/:theme controllers.Puzzle.setDifficulty(theme: String)
GET /training/batch controllers.Puzzle.batchSelect
POST /training/batch controllers.Puzzle.batchSolve
# User Analysis
GET /analysis/help controllers.UserAnalysis.help

View File

@ -101,7 +101,7 @@ final class JsonView(
.obj(
"game" -> gameJson,
"puzzle" -> Json.obj(
"id" -> puzzle.id,
"id" -> Puzzle.numericalId(puzzle.id),
"rating" -> puzzle.glicko.intRating,
"attempts" -> puzzle.plays,
"fen" -> puzzle.fenAfterInitialMove,

View File

@ -32,8 +32,47 @@ case class Puzzle(
object Puzzle {
val idSize = 5
case class Id(value: String) extends AnyVal with StringValue
/* The mobile app requires numerical IDs.
* We convert string ids from and to Longs using base 62
*/
object numericalId {
private val powers: List[Long] =
(0 until idSize).toList.map(m => Math.pow(62, m).toLong)
def apply(id: Id): Long = id.value.toList
.zip(powers)
.foldLeft(0L) { case (l, (char, pow)) =>
l + charToInt(char) * pow
}
def apply(l: Long): Id = Id {
powers.reverse
.foldLeft(("", l)) { case ((id, rest), pow) =>
val frac = rest / pow
(s"${intToChar(frac.toInt)}$id", rest - frac * pow)
}
._1
}
private def charToInt(c: Char) = {
val i = c.toInt
if (i > 96) i - 71
else if (i > 64) i - 65
else i + 4
}
private def intToChar(i: Int): Char = {
if (i < 26) i + 65
else if (i < 52) i + 71
else i - 4
}.toChar
}
case class UserResult(
puzzleId: Id,
userId: lila.user.User.ID,