mirror of
https://github.com/pcottle/learnGitBranching.git
synced 2025-07-29 23:24:44 +02:00
Need to go up to directories from the level arbiter to get to the directory containing level definitions.
164 lines
4.2 KiB
JavaScript
164 lines
4.2 KiB
JavaScript
var _ = require('underscore');
|
|
var Backbone = require('backbone');
|
|
|
|
// Each level is part of a "sequence;" levels within
|
|
// a sequence proceed in order.
|
|
var levelSequences = require('../../levels').levelSequences;
|
|
var sequenceInfo = require('../../levels').sequenceInfo;
|
|
|
|
var Main = require('../app');
|
|
|
|
function LevelArbiter() {
|
|
this.levelMap = {};
|
|
this.levelSequences = levelSequences;
|
|
this.sequences = [];
|
|
this.init();
|
|
|
|
var solvedMap;
|
|
try {
|
|
solvedMap = JSON.parse(localStorage.getItem('solvedMap') || '{}');
|
|
} catch (e) {
|
|
console.warn('local storage failed', e);
|
|
// throw e;
|
|
}
|
|
this.solvedMap = solvedMap || {};
|
|
|
|
Main.getEvents().on('levelSolved', this.levelSolved, this);
|
|
}
|
|
|
|
LevelArbiter.prototype.init = function() {
|
|
var previousLevelID;
|
|
_.each(this.levelSequences, function(levels, levelSequenceName) {
|
|
this.sequences.push(levelSequenceName);
|
|
if (!levels || !levels.length) {
|
|
throw new Error('no empty sequences allowed');
|
|
}
|
|
|
|
// for this particular sequence...
|
|
_.each(levels, function(level, index) {
|
|
this.validateLevel(level);
|
|
|
|
var id = levelSequenceName + String(index + 1);
|
|
var compiledLevel = _.extend(
|
|
{},
|
|
level,
|
|
{
|
|
index: index,
|
|
id: id,
|
|
sequenceName: levelSequenceName
|
|
}
|
|
);
|
|
|
|
// update our internal data
|
|
this.levelMap[id] = compiledLevel;
|
|
this.levelSequences[levelSequenceName][index] = compiledLevel;
|
|
}, this);
|
|
}, this);
|
|
};
|
|
|
|
LevelArbiter.prototype.isLevelSolved = function(id) {
|
|
if (!this.levelMap[id]) {
|
|
throw new Error('that level doesnt exist!');
|
|
}
|
|
return Boolean(this.solvedMap[id]);
|
|
};
|
|
|
|
LevelArbiter.prototype.levelSolved = function(id) {
|
|
// called without an id when we reset solved status
|
|
if (!id) { return; }
|
|
|
|
this.solvedMap[id] = true;
|
|
this.syncToStorage();
|
|
};
|
|
|
|
LevelArbiter.prototype.resetSolvedMap = function() {
|
|
this.solvedMap = {};
|
|
this.syncToStorage();
|
|
Main.getEvents().trigger('levelSolved');
|
|
};
|
|
|
|
LevelArbiter.prototype.syncToStorage = function() {
|
|
try {
|
|
localStorage.setItem('solvedMap', JSON.stringify(this.solvedMap));
|
|
} catch (e) {
|
|
console.warn('local storage fialed on set', e);
|
|
}
|
|
};
|
|
|
|
LevelArbiter.prototype.validateLevel = function(level) {
|
|
level = level || {};
|
|
var requiredFields = [
|
|
'name',
|
|
'goalTreeString',
|
|
//'description',
|
|
'solutionCommand'
|
|
];
|
|
|
|
var optionalFields = [
|
|
'hint',
|
|
'disabledMap',
|
|
'startTree'
|
|
];
|
|
|
|
_.each(requiredFields, function(field) {
|
|
if (level[field] === undefined) {
|
|
console.log(level);
|
|
throw new Error('I need this field for a level: ' + field);
|
|
}
|
|
});
|
|
};
|
|
|
|
LevelArbiter.prototype.getSequenceToLevels = function() {
|
|
return this.levelSequences;
|
|
};
|
|
|
|
LevelArbiter.prototype.getSequences = function() {
|
|
return _.keys(this.levelSequences);
|
|
};
|
|
|
|
LevelArbiter.prototype.getLevelsInSequence = function(sequenceName) {
|
|
if (!this.levelSequences[sequenceName]) {
|
|
throw new Error('that sequecne name ' + sequenceName + 'does not exist');
|
|
}
|
|
return this.levelSequences[sequenceName];
|
|
};
|
|
|
|
LevelArbiter.prototype.getSequenceInfo = function(sequenceName) {
|
|
return sequenceInfo[sequenceName];
|
|
};
|
|
|
|
LevelArbiter.prototype.getLevel = function(id) {
|
|
return this.levelMap[id];
|
|
};
|
|
|
|
LevelArbiter.prototype.getNextLevel = function(id) {
|
|
if (!this.levelMap[id]) {
|
|
console.warn('that level doesnt exist!!!');
|
|
return null;
|
|
}
|
|
|
|
// meh, this method could be better. It's a tradeoff between
|
|
// having the sequence structure be really simple JSON
|
|
// and having no connectivity information between levels, which means
|
|
// you have to build that up yourself on every query
|
|
var level = this.levelMap[id];
|
|
var sequenceName = level.sequenceName;
|
|
var sequence = this.levelSequences[sequenceName];
|
|
|
|
var nextIndex = level.index + 1;
|
|
if (nextIndex < sequence.length) {
|
|
return sequence[nextIndex];
|
|
}
|
|
|
|
var nextSequenceIndex = this.sequences.indexOf(sequenceName) + 1;
|
|
if (nextSequenceIndex < this.sequences.length) {
|
|
var nextSequenceName = this.sequences[nextSequenceIndex];
|
|
return this.levelSequences[nextSequenceName][0];
|
|
}
|
|
|
|
// they finished the last level!
|
|
return null;
|
|
};
|
|
|
|
exports.LevelArbiter = LevelArbiter;
|
|
|