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