feature: perfection tracker for levels with best number of commands

This commit is contained in:
Patolord 2024-11-18 09:42:39 -03:00
parent 4cfaa0ae02
commit 928577b2dc
6 changed files with 53 additions and 16 deletions

View file

@ -23,7 +23,7 @@ describe('this store', function() {
expect(LevelStore.isLevelSolved(firstLevel.id)) expect(LevelStore.isLevelSolved(firstLevel.id))
.toEqual(false); .toEqual(false);
LevelActions.setLevelSolved(firstLevel.id); LevelActions.setLevelSolved(firstLevel.id, false);
expect(LevelStore.isLevelSolved(firstLevel.id)) expect(LevelStore.isLevelSolved(firstLevel.id))
.toEqual(true); .toEqual(true);
LevelActions.resetLevelsSolved(); LevelActions.resetLevelsSolved();
@ -31,4 +31,21 @@ describe('this store', function() {
.toEqual(false); .toEqual(false);
}); });
it('can solve a level with best status and then reset', function() {
var sequenceMap = LevelStore.getSequenceToLevels();
var firstLevel = sequenceMap[
Object.keys(sequenceMap)[0]
][0];
expect(LevelStore.isLevelBest(firstLevel.id))
.toEqual(false);
LevelActions.setLevelSolved(firstLevel.id, true);
expect(LevelStore.isLevelBest(firstLevel.id))
.toEqual(true);
LevelActions.resetLevelsSolved();
expect(LevelStore.isLevelBest(firstLevel.id))
.toEqual(false);
});
}); });

View file

@ -7,10 +7,11 @@ var ActionTypes = AppConstants.ActionTypes;
var LevelActions = { var LevelActions = {
setLevelSolved: function(levelID) { setLevelSolved: function(levelID, best) {
AppDispatcher.handleViewAction({ AppDispatcher.handleViewAction({
type: ActionTypes.SET_LEVEL_SOLVED, type: ActionTypes.SET_LEVEL_SOLVED,
levelID: levelID levelID: levelID,
best: best
}); });
}, },

View file

@ -477,11 +477,15 @@ var Level = Sandbox.extend({
levelSolved: function(defer) { levelSolved: function(defer) {
this.solved = true; this.solved = true;
if (!this.isShowingSolution) { if (!this.isShowingSolution) {
LevelActions.setLevelSolved(this.level.id); var numCommands = this.gitCommandsIssued.length;
var best = this.getNumSolutionCommands();
var isBest = numCommands <= best;
LevelActions.setLevelSolved(this.level.id, isBest);
log.levelSolved(this.getEnglishName()); log.levelSolved(this.getEnglishName());
} }
this.hideGoal(); this.hideGoal();
var nextLevel = LevelStore.getNextLevel(this.level.id); var nextLevel = LevelStore.getNextLevel(this.level.id);

View file

@ -186,12 +186,18 @@ AppConstants.StoreSubscribePrototype,
}, },
isLevelSolved: function(levelID) { isLevelSolved: function(levelID) {
if (!_levelMap[levelID]) { var levelData = _solvedMap[levelID];
throw new Error('that level doesn\'t exist!'); return levelData ? levelData.solved === true : false;
}
return !!_solvedMap[levelID];
}, },
isLevelBest: function(levelID) {
var levelData = _solvedMap[levelID];
return levelData ? levelData.best === true : false;
},
dispatchToken: AppDispatcher.register(function(payload) { dispatchToken: AppDispatcher.register(function(payload) {
var action = payload.action; var action = payload.action;
var shouldInform = false; var shouldInform = false;
@ -203,7 +209,7 @@ AppConstants.StoreSubscribePrototype,
shouldInform = true; shouldInform = true;
break; break;
case ActionTypes.SET_LEVEL_SOLVED: case ActionTypes.SET_LEVEL_SOLVED:
_solvedMap[action.levelID] = true; _solvedMap[action.levelID] = { solved: true, best: action.best || false };
_syncToStorage(); _syncToStorage();
shouldInform = true; shouldInform = true;
break; break;

View file

@ -402,9 +402,13 @@ var SeriesView = BaseView.extend({
updateSolvedStatus: function() { updateSolvedStatus: function() {
// this is a bit hacky, it really should be some nice model // this is a bit hacky, it really should be some nice model
// property changing but it's the 11th hour... // property changing but it's the 11th hour...
var toLoop = this.$('a.levelIcon').each(function(index, el) { this.$('a.levelIcon').each(function() {
var id = $(el).attr('data-id'); var $el = $(this);
$(el).toggleClass('solved', LevelStore.isLevelSolved(id)); var id = $el.attr('data-id');
var isSolved = LevelStore.isLevelSolved(id);
var isBest = LevelStore.isLevelBest(id);
$el.toggleClass('solved', isSolved);
$el.toggleClass('best', isBest);
}); });
}, },

View file

@ -1010,6 +1010,11 @@ a.levelIcon.solved:active {
background: #5edb15; background: #5edb15;
} }
a.levelIcon.best {
border-color: gold;
background: gold;
}
a.levelIcon div.index { a.levelIcon div.index {
font-weight: 400; font-weight: 400;
text-shadow: 1px 1px 2px #CCC, 0 2px 0 #C9C9C9; text-shadow: 1px 1px 2px #CCC, 0 2px 0 #C9C9C9;