diff --git a/app/views/opening/JsData.scala b/app/views/opening/JsData.scala index 4accd37503..25ddf08560 100644 --- a/app/views/opening/JsData.scala +++ b/app/views/opening/JsData.scala @@ -17,13 +17,15 @@ object JsData extends lila.Steroids { Html(Json.stringify(Json.obj( "opening" -> Json.obj( "id" -> opening.id, + "score" -> opening.score.toInt, "attempts" -> opening.attempts, "goal" -> opening.goal, "fen" -> opening.fen, "color" -> opening.color.name, "moves" -> JsArray(opening.qualityMoves.map { case QualityMove(move, quality) => Json.obj( - "first" -> move.first, + "uci" -> move.first, + "san" -> move.line.headOption, "cp" -> move.cp, "line" -> move.line.mkString(" "), "quality" -> quality.name) diff --git a/app/views/opening/layout.scala.html b/app/views/opening/layout.scala.html index e9e3714608..f3d8da2e30 100644 --- a/app/views/opening/layout.scala.html +++ b/app/views/opening/layout.scala.html @@ -7,6 +7,7 @@ } @moreJs = { +@jsTag("vendor/sparkline.min.js") @jsAt(s"compiled/lichess.opening${isProd??(".min")}.js") @evenMoreJs } diff --git a/app/views/opening/show.scala.html b/app/views/opening/show.scala.html index c67bddb2d6..e523393268 100644 --- a/app/views/opening/show.scala.html +++ b/app/views/opening/show.scala.html @@ -14,7 +14,13 @@ trans.toTrackYourProgress, trans.signUp, trans.trainingSignupExplanation, trans.giveUp, -trans.continueTraining +trans.yourTurn, +trans.continueTraining, +trans.openingId, +trans.scoreX, +trans.playedXTimes, +trans.yourOpeningScoreX, +trans.findNbStrongMoves ))) ); } diff --git a/app/views/user/show.scala.html b/app/views/user/show.scala.html index 94e7b65804..a00d113dc0 100644 --- a/app/views/user/show.scala.html +++ b/app/views/user/show.scala.html @@ -48,6 +48,14 @@
} @showPerf(u.perfs.puzzle, PerfType.Puzzle) +
+

OPENING TRAINER

+
+ @u.perfs.opening.averageScore.getOrElse("?") + / @u.perfs.opening.nb.localize Openings + @showProgress(u.perfs.opening.progress) +
+
} diff --git a/conf/messages b/conf/messages index 063d553e70..6929670380 100644 --- a/conf/messages +++ b/conf/messages @@ -309,3 +309,7 @@ youHaveNbSecondsToMakeYourFirstMove=You have %s seconds to make your first move! nbGamesInPlay=%s games in play automaticallyProceedToNextGameAfterMoving=Automatically proceed to next game after moving autoSwitch=Auto switch +openingId=Opening %s +scoreX=Score: %s +yourOpeningScoreX=Your opening score: %s +findNbStrongMoves=Find %s strong moves diff --git a/modules/i18n/src/main/I18nKeys.scala b/modules/i18n/src/main/I18nKeys.scala index e17676a70d..d094d30593 100644 --- a/modules/i18n/src/main/I18nKeys.scala +++ b/modules/i18n/src/main/I18nKeys.scala @@ -333,8 +333,12 @@ final class I18nKeys(translator: Translator) { val `nbGamesInPlay` = new Key("nbGamesInPlay") val `automaticallyProceedToNextGameAfterMoving` = new Key("automaticallyProceedToNextGameAfterMoving") val `autoSwitch` = new Key("autoSwitch") + val `openingId` = new Key("openingId") + val `scoreX` = new Key("scoreX") + val `yourOpeningScoreX` = new Key("yourOpeningScoreX") + val `findNbStrongMoves` = new Key("findNbStrongMoves") - def keys = List(`playWithAFriend`, `playWithTheMachine`, `toInviteSomeoneToPlayGiveThisUrl`, `gameOver`, `waitingForOpponent`, `waiting`, `yourTurn`, `aiNameLevelAiLevel`, `level`, `toggleTheChat`, `toggleSound`, `chat`, `resign`, `checkmate`, `stalemate`, `white`, `black`, `randomColor`, `createAGame`, `whiteIsVictorious`, `blackIsVictorious`, `playWithTheSameOpponentAgain`, `newOpponent`, `playWithAnotherOpponent`, `yourOpponentWantsToPlayANewGameWithYou`, `joinTheGame`, `whitePlays`, `blackPlays`, `theOtherPlayerHasLeftTheGameYouCanForceResignationOrWaitForHim`, `makeYourOpponentResign`, `forceResignation`, `forceDraw`, `talkInChat`, `theFirstPersonToComeOnThisUrlWillPlayWithYou`, `whiteCreatesTheGame`, `blackCreatesTheGame`, `whiteJoinsTheGame`, `blackJoinsTheGame`, `whiteResigned`, `blackResigned`, `whiteLeftTheGame`, `blackLeftTheGame`, `shareThisUrlToLetSpectatorsSeeTheGame`, `youAreViewingThisGameAsASpectator`, `replayAndAnalyse`, `computerAnalysisInProgress`, `theComputerAnalysisHasFailed`, `viewTheComputerAnalysis`, `requestAComputerAnalysis`, `computerAnalysis`, `analysis`, `blunders`, `mistakes`, `inaccuracies`, `moveTimes`, `flipBoard`, `threefoldRepetition`, `claimADraw`, `offerDraw`, `draw`, `nbConnectedPlayers`, `gamesBeingPlayedRightNow`, `viewAllNbGames`, `viewNbCheckmates`, `nbBookmarks`, `nbPopularGames`, `nbAnalysedGames`, `bookmarkedByNbPlayers`, `viewInFullSize`, `logOut`, `signIn`, `newToLichess`, `youNeedAnAccountToDoThat`, `signUp`, `computersAreNotAllowedToPlay`, `games`, `forum`, `xPostedInForumY`, `latestForumPosts`, `players`, `minutesPerSide`, `variant`, `timeControl`, `realTime`, `correspondence`, `daysPerTurn`, `oneDay`, `nbDays`, `nbHours`, `time`, `rating`, `username`, `password`, `haveAnAccount`, `allYouNeedIsAUsernameAndAPassword`, `changePassword`, `changeEmail`, `email`, `emailIsOptional`, `passwordReset`, `forgotPassword`, `learnMoreAboutLichess`, `rank`, `gamesPlayed`, `nbGamesWithYou`, `declineInvitation`, `cancel`, `timeOut`, `drawOfferSent`, `drawOfferDeclined`, `drawOfferAccepted`, `drawOfferCanceled`, `whiteOffersDraw`, `blackOffersDraw`, `whiteDeclinesDraw`, `blackDeclinesDraw`, `yourOpponentOffersADraw`, `accept`, `decline`, `playingRightNow`, `finished`, `abortGame`, `gameAborted`, `standard`, `unlimited`, `mode`, `casual`, `rated`, `thisGameIsRated`, `rematch`, `rematchOfferSent`, `rematchOfferAccepted`, `rematchOfferCanceled`, `rematchOfferDeclined`, `cancelRematchOffer`, `viewRematch`, `play`, `inbox`, `chatRoom`, `spectatorRoom`, `composeMessage`, `noNewMessages`, `subject`, `recipient`, `send`, `incrementInSeconds`, `freeOnlineChess`, `spectators`, `nbWins`, `nbLosses`, `nbDraws`, `exportGames`, `ratingRange`, `giveNbSeconds`, `premoveEnabledClickAnywhereToCancel`, `thisPlayerUsesChessComputerAssistance`, `opening`, `takeback`, `proposeATakeback`, `takebackPropositionSent`, `takebackPropositionDeclined`, `takebackPropositionAccepted`, `takebackPropositionCanceled`, `yourOpponentProposesATakeback`, `bookmarkThisGame`, `search`, `advancedSearch`, `tournament`, `tournaments`, `tournamentPoints`, `viewTournament`, `backToTournament`, `backToGame`, `freeOnlineChessGamePlayChessNowInACleanInterfaceNoRegistrationNoAdsNoPluginRequiredPlayChessWithComputerFriendsOrRandomOpponents`, `teams`, `nbMembers`, `allTeams`, `newTeam`, `myTeams`, `noTeamFound`, `joinTeam`, `quitTeam`, `anyoneCanJoin`, `aConfirmationIsRequiredToJoin`, `joiningPolicy`, `teamLeader`, `teamBestPlayers`, `teamRecentMembers`, `xJoinedTeamY`, `xCreatedTeamY`, `averageElo`, `location`, `settings`, `filterGames`, `reset`, `apply`, `leaderboard`, `pasteTheFenStringHere`, `pasteThePgnStringHere`, `fromPosition`, `continueFromHere`, `importGame`, `nbImportedGames`, `thisIsAChessCaptcha`, `clickOnTheBoardToMakeYourMove`, `notACheckmate`, `colorPlaysCheckmateInOne`, `retry`, `reconnecting`, `onlineFriends`, `noFriendsOnline`, `findFriends`, `favoriteOpponents`, `follow`, `following`, `unfollow`, `block`, `blocked`, `unblock`, `followsYou`, `xStartedFollowingY`, `nbFollowers`, `nbFollowing`, `more`, `memberSince`, `lastLogin`, `challengeToPlay`, `player`, `list`, `graph`, `lessThanNbMinutes`, `xToYMinutes`, `textIsTooShort`, `textIsTooLong`, `required`, `openTournaments`, `duration`, `winner`, `standing`, `createANewTournament`, `join`, `withdraw`, `points`, `wins`, `losses`, `winStreak`, `createdBy`, `waitingForNbPlayers`, `tournamentIsStarting`, `membersOnly`, `boardEditor`, `startPosition`, `clearBoard`, `savePosition`, `loadPosition`, `isPrivate`, `reportXToModerators`, `profile`, `editProfile`, `firstName`, `lastName`, `biography`, `country`, `preferences`, `watchLichessTV`, `previouslyOnLichessTV`, `todaysLeaders`, `onlinePlayers`, `progressToday`, `progressThisWeek`, `progressThisMonth`, `leaderboardThisWeek`, `leaderboardThisMonth`, `activeToday`, `activeThisWeek`, `activePlayers`, `bewareTheGameIsRatedButHasNoClock`, `training`, `yourPuzzleRatingX`, `findTheBestMoveForWhite`, `findTheBestMoveForBlack`, `toTrackYourProgress`, `trainingSignupExplanation`, `recentlyPlayedPuzzles`, `puzzleId`, `puzzleOfTheDay`, `clickToSolve`, `goodMove`, `butYouCanDoBetter`, `bestMove`, `keepGoing`, `puzzleFailed`, `butYouCanKeepTrying`, `victory`, `giveUp`, `puzzleSolvedInXSeconds`, `wasThisPuzzleAnyGood`, `pleaseVotePuzzle`, `thankYou`, `ratingX`, `playedXTimes`, `fromGameLink`, `startTraining`, `continueTraining`, `retryThisPuzzle`, `thisPuzzleIsCorrect`, `thisPuzzleIsWrong`, `youHaveNbSecondsToMakeYourFirstMove`, `nbGamesInPlay`, `automaticallyProceedToNextGameAfterMoving`, `autoSwitch`) + def keys = List(`playWithAFriend`, `playWithTheMachine`, `toInviteSomeoneToPlayGiveThisUrl`, `gameOver`, `waitingForOpponent`, `waiting`, `yourTurn`, `aiNameLevelAiLevel`, `level`, `toggleTheChat`, `toggleSound`, `chat`, `resign`, `checkmate`, `stalemate`, `white`, `black`, `randomColor`, `createAGame`, `whiteIsVictorious`, `blackIsVictorious`, `playWithTheSameOpponentAgain`, `newOpponent`, `playWithAnotherOpponent`, `yourOpponentWantsToPlayANewGameWithYou`, `joinTheGame`, `whitePlays`, `blackPlays`, `theOtherPlayerHasLeftTheGameYouCanForceResignationOrWaitForHim`, `makeYourOpponentResign`, `forceResignation`, `forceDraw`, `talkInChat`, `theFirstPersonToComeOnThisUrlWillPlayWithYou`, `whiteCreatesTheGame`, `blackCreatesTheGame`, `whiteJoinsTheGame`, `blackJoinsTheGame`, `whiteResigned`, `blackResigned`, `whiteLeftTheGame`, `blackLeftTheGame`, `shareThisUrlToLetSpectatorsSeeTheGame`, `youAreViewingThisGameAsASpectator`, `replayAndAnalyse`, `computerAnalysisInProgress`, `theComputerAnalysisHasFailed`, `viewTheComputerAnalysis`, `requestAComputerAnalysis`, `computerAnalysis`, `analysis`, `blunders`, `mistakes`, `inaccuracies`, `moveTimes`, `flipBoard`, `threefoldRepetition`, `claimADraw`, `offerDraw`, `draw`, `nbConnectedPlayers`, `gamesBeingPlayedRightNow`, `viewAllNbGames`, `viewNbCheckmates`, `nbBookmarks`, `nbPopularGames`, `nbAnalysedGames`, `bookmarkedByNbPlayers`, `viewInFullSize`, `logOut`, `signIn`, `newToLichess`, `youNeedAnAccountToDoThat`, `signUp`, `computersAreNotAllowedToPlay`, `games`, `forum`, `xPostedInForumY`, `latestForumPosts`, `players`, `minutesPerSide`, `variant`, `timeControl`, `realTime`, `correspondence`, `daysPerTurn`, `oneDay`, `nbDays`, `nbHours`, `time`, `rating`, `username`, `password`, `haveAnAccount`, `allYouNeedIsAUsernameAndAPassword`, `changePassword`, `changeEmail`, `email`, `emailIsOptional`, `passwordReset`, `forgotPassword`, `learnMoreAboutLichess`, `rank`, `gamesPlayed`, `nbGamesWithYou`, `declineInvitation`, `cancel`, `timeOut`, `drawOfferSent`, `drawOfferDeclined`, `drawOfferAccepted`, `drawOfferCanceled`, `whiteOffersDraw`, `blackOffersDraw`, `whiteDeclinesDraw`, `blackDeclinesDraw`, `yourOpponentOffersADraw`, `accept`, `decline`, `playingRightNow`, `finished`, `abortGame`, `gameAborted`, `standard`, `unlimited`, `mode`, `casual`, `rated`, `thisGameIsRated`, `rematch`, `rematchOfferSent`, `rematchOfferAccepted`, `rematchOfferCanceled`, `rematchOfferDeclined`, `cancelRematchOffer`, `viewRematch`, `play`, `inbox`, `chatRoom`, `spectatorRoom`, `composeMessage`, `noNewMessages`, `subject`, `recipient`, `send`, `incrementInSeconds`, `freeOnlineChess`, `spectators`, `nbWins`, `nbLosses`, `nbDraws`, `exportGames`, `ratingRange`, `giveNbSeconds`, `premoveEnabledClickAnywhereToCancel`, `thisPlayerUsesChessComputerAssistance`, `opening`, `takeback`, `proposeATakeback`, `takebackPropositionSent`, `takebackPropositionDeclined`, `takebackPropositionAccepted`, `takebackPropositionCanceled`, `yourOpponentProposesATakeback`, `bookmarkThisGame`, `search`, `advancedSearch`, `tournament`, `tournaments`, `tournamentPoints`, `viewTournament`, `backToTournament`, `backToGame`, `freeOnlineChessGamePlayChessNowInACleanInterfaceNoRegistrationNoAdsNoPluginRequiredPlayChessWithComputerFriendsOrRandomOpponents`, `teams`, `nbMembers`, `allTeams`, `newTeam`, `myTeams`, `noTeamFound`, `joinTeam`, `quitTeam`, `anyoneCanJoin`, `aConfirmationIsRequiredToJoin`, `joiningPolicy`, `teamLeader`, `teamBestPlayers`, `teamRecentMembers`, `xJoinedTeamY`, `xCreatedTeamY`, `averageElo`, `location`, `settings`, `filterGames`, `reset`, `apply`, `leaderboard`, `pasteTheFenStringHere`, `pasteThePgnStringHere`, `fromPosition`, `continueFromHere`, `importGame`, `nbImportedGames`, `thisIsAChessCaptcha`, `clickOnTheBoardToMakeYourMove`, `notACheckmate`, `colorPlaysCheckmateInOne`, `retry`, `reconnecting`, `onlineFriends`, `noFriendsOnline`, `findFriends`, `favoriteOpponents`, `follow`, `following`, `unfollow`, `block`, `blocked`, `unblock`, `followsYou`, `xStartedFollowingY`, `nbFollowers`, `nbFollowing`, `more`, `memberSince`, `lastLogin`, `challengeToPlay`, `player`, `list`, `graph`, `lessThanNbMinutes`, `xToYMinutes`, `textIsTooShort`, `textIsTooLong`, `required`, `openTournaments`, `duration`, `winner`, `standing`, `createANewTournament`, `join`, `withdraw`, `points`, `wins`, `losses`, `winStreak`, `createdBy`, `waitingForNbPlayers`, `tournamentIsStarting`, `membersOnly`, `boardEditor`, `startPosition`, `clearBoard`, `savePosition`, `loadPosition`, `isPrivate`, `reportXToModerators`, `profile`, `editProfile`, `firstName`, `lastName`, `biography`, `country`, `preferences`, `watchLichessTV`, `previouslyOnLichessTV`, `todaysLeaders`, `onlinePlayers`, `progressToday`, `progressThisWeek`, `progressThisMonth`, `leaderboardThisWeek`, `leaderboardThisMonth`, `activeToday`, `activeThisWeek`, `activePlayers`, `bewareTheGameIsRatedButHasNoClock`, `training`, `yourPuzzleRatingX`, `findTheBestMoveForWhite`, `findTheBestMoveForBlack`, `toTrackYourProgress`, `trainingSignupExplanation`, `recentlyPlayedPuzzles`, `puzzleId`, `puzzleOfTheDay`, `clickToSolve`, `goodMove`, `butYouCanDoBetter`, `bestMove`, `keepGoing`, `puzzleFailed`, `butYouCanKeepTrying`, `victory`, `giveUp`, `puzzleSolvedInXSeconds`, `wasThisPuzzleAnyGood`, `pleaseVotePuzzle`, `thankYou`, `ratingX`, `playedXTimes`, `fromGameLink`, `startTraining`, `continueTraining`, `retryThisPuzzle`, `thisPuzzleIsCorrect`, `thisPuzzleIsWrong`, `youHaveNbSecondsToMakeYourFirstMove`, `nbGamesInPlay`, `automaticallyProceedToNextGameAfterMoving`, `autoSwitch`, `openingId`, `scoreX`, `yourOpeningScoreX`, `findNbStrongMoves`) lazy val count = keys.size } diff --git a/modules/opening/src/main/Finisher.scala b/modules/opening/src/main/Finisher.scala index 6e57289f81..5ee7238576 100644 --- a/modules/opening/src/main/Finisher.scala +++ b/modules/opening/src/main/Finisher.scala @@ -11,12 +11,17 @@ private[opening] final class Finisher( api: OpeningApi, openingColl: Coll) { + private def computeScore(opening: Opening, found: Int, failed: Int): Int = { + val base = 100d * found / goal + + } + def apply(opening: Opening, user: User, found: Int, failed: Int): Fu[Attempt] = api.attempt.find(opening.id, user.id) flatMap { case Some(a) => fuccess(a) case None => val date = DateTime.now - val score = 50 + val score = computeScore(opening, found, failed) val userScorePerf = user.perfs.opening.add(score, DateTime.now) val openingScore = 0.1 * (score - opening.score) + opening.score val a = new Attempt( diff --git a/modules/opening/src/main/Opening.scala b/modules/opening/src/main/Opening.scala index 16eeff6966..ef246ccb06 100644 --- a/modules/opening/src/main/Opening.scala +++ b/modules/opening/src/main/Opening.scala @@ -17,7 +17,7 @@ case class Opening( attempts: Int, score: Double) { - def goal = qualityMoves.size min 5 + lazy val goal = qualityMoves.count(_.quality == Quality.Good) min 5 lazy val qualityMoves: List[QualityMove] = { val bestCp = moves.foldLeft(Int.MaxValue) { diff --git a/modules/opening/src/main/UserInfos.scala b/modules/opening/src/main/UserInfos.scala index 16aef0c0f4..379ecccee1 100644 --- a/modules/opening/src/main/UserInfos.scala +++ b/modules/opening/src/main/UserInfos.scala @@ -46,7 +46,7 @@ object UserInfos { private def makeChart(attempts: List[Attempt]) = JsArray { val scores = attempts.take(chartSize).reverse map (_.score) - val filled = List.fill(chartSize - scores.size)(Glicko.default.intRating) ::: scores + val filled = List.fill(chartSize - scores.size)(0) ::: scores filled map { JsNumber(_) } } } diff --git a/public/font28/fonts/lichess.woff b/public/font28/fonts/lichess.woff deleted file mode 100644 index 615195bf87..0000000000 Binary files a/public/font28/fonts/lichess.woff and /dev/null differ diff --git a/public/font28/fonts/lichess.eot b/public/font29/fonts/lichess.eot similarity index 86% rename from public/font28/fonts/lichess.eot rename to public/font29/fonts/lichess.eot index dfcfb4441c..1380a396c6 100644 Binary files a/public/font28/fonts/lichess.eot and b/public/font29/fonts/lichess.eot differ diff --git a/public/font28/fonts/lichess.svg b/public/font29/fonts/lichess.svg similarity index 94% rename from public/font28/fonts/lichess.svg rename to public/font29/fonts/lichess.svg index 6c99796642..6209469603 100644 --- a/public/font28/fonts/lichess.svg +++ b/public/font29/fonts/lichess.svg @@ -96,4 +96,7 @@ + + + diff --git a/public/font28/fonts/lichess.ttf b/public/font29/fonts/lichess.ttf similarity index 86% rename from public/font28/fonts/lichess.ttf rename to public/font29/fonts/lichess.ttf index 49d3b1b4e7..685e7d5d9f 100644 Binary files a/public/font28/fonts/lichess.ttf and b/public/font29/fonts/lichess.ttf differ diff --git a/public/font29/fonts/lichess.woff b/public/font29/fonts/lichess.woff new file mode 100644 index 0000000000..6bed193e64 Binary files /dev/null and b/public/font29/fonts/lichess.woff differ diff --git a/public/font28/icons-reference.html b/public/font29/icons-reference.html similarity index 97% rename from public/font28/icons-reference.html rename to public/font29/icons-reference.html index 84bd6ec47f..04f35f79cd 100644 --- a/public/font28/icons-reference.html +++ b/public/font29/icons-reference.html @@ -401,6 +401,18 @@ h2{font-size:18px;padding:0 0 21px 5px;margin:45px 0 0 0;text-transform:uppercas
+
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • Character mapping

      @@ -760,6 +772,18 @@ h2{font-size:18px;padding:0 0 21px 5px;margin:45px 0 0 0;text-transform:uppercas
      +
    • +
      + +
    • +
    • +
      + +
    • +
    • +
      + +