rename learn concepts: (lesson/level)->stage, stage->level
parent
c7fc5c8ab2
commit
c64dba92a7
|
@ -20,15 +20,15 @@ object Learn extends LilaController {
|
|||
}
|
||||
}
|
||||
|
||||
private val levelForm = Form(mapping(
|
||||
"level" -> nonEmptyText,
|
||||
private val stageForm = Form(mapping(
|
||||
"stage" -> nonEmptyText,
|
||||
"score" -> number
|
||||
)(Tuple2.apply)(Tuple2.unapply))
|
||||
|
||||
def level = AuthBody { implicit ctx =>
|
||||
def stage = AuthBody { implicit ctx =>
|
||||
me =>
|
||||
implicit val body = ctx.body
|
||||
levelForm.bindFromRequest.fold(
|
||||
stageForm.bindFromRequest.fold(
|
||||
err => BadRequest.fuccess,
|
||||
data => env.api.setScore(me, data._1, data._2) >>
|
||||
env.api.get(me).map { progress =>
|
||||
|
|
|
@ -137,7 +137,7 @@ GET /study/$id<\w{8}>/$chapterId<\w{8}> controllers.Study.chapter(id: S
|
|||
|
||||
# Learn
|
||||
GET /learn controllers.Learn.index
|
||||
POST /learn/level controllers.Learn.level
|
||||
POST /learn/stage controllers.Learn.stage
|
||||
|
||||
# Round
|
||||
GET /$gameId<\w{8}> controllers.Round.watcher(gameId: String, color: String = "white")
|
||||
|
|
|
@ -6,10 +6,10 @@ import reactivemongo.bson._
|
|||
|
||||
object BSONHandlers {
|
||||
|
||||
private implicit val LevelProgressScoreHandler = intAnyValHandler[LevelProgress.Score](_.value, LevelProgress.Score.apply)
|
||||
private implicit val LevelProgressTriesHandler = intAnyValHandler[LevelProgress.Tries](_.value, LevelProgress.Tries.apply)
|
||||
private implicit val LevelProgressBSONHandler = Macros.handler[LevelProgress]
|
||||
private implicit val StageProgressScoreHandler = intAnyValHandler[StageProgress.Score](_.value, StageProgress.Score.apply)
|
||||
private implicit val StageProgressTriesHandler = intAnyValHandler[StageProgress.Tries](_.value, StageProgress.Tries.apply)
|
||||
private implicit val StageProgressBSONHandler = Macros.handler[StageProgress]
|
||||
|
||||
private implicit val LearnProgressLevelsHandler = BSON.MapDocument.MapHandler[LevelProgress]
|
||||
private implicit val LearnProgressStagesHandler = BSON.MapDocument.MapHandler[StageProgress]
|
||||
implicit val LearnProgressHandler = Macros.handler[LearnProgress]
|
||||
}
|
||||
|
|
|
@ -5,9 +5,9 @@ import lila.common.PimpedJson._
|
|||
|
||||
object JSONHandlers {
|
||||
|
||||
private implicit val LevelProgressScoreWriter = intAnyValWriter[LevelProgress.Score](_.value)
|
||||
private implicit val LevelProgressTriesWriter = intAnyValWriter[LevelProgress.Tries](_.value)
|
||||
implicit val LevelProgressWriter = Json.writes[LevelProgress]
|
||||
private implicit val StageProgressScoreWriter = intAnyValWriter[StageProgress.Score](_.value)
|
||||
private implicit val StageProgressTriesWriter = intAnyValWriter[StageProgress.Tries](_.value)
|
||||
implicit val StageProgressWriter = Json.writes[StageProgress]
|
||||
|
||||
implicit val LearnProgressWriter = Json.writes[LearnProgress]
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@ final class LearnApi(coll: Coll) {
|
|||
private def save(p: LearnProgress): Funit =
|
||||
coll.update($id(p.id), p, upsert = true).void
|
||||
|
||||
def setScore(user: User, level: String, score: Int) = get(user) flatMap { prog =>
|
||||
save(prog.withScore(level, LevelProgress.Score(score)))
|
||||
def setScore(user: User, stage: String, score: Int) = get(user) flatMap { prog =>
|
||||
save(prog.withScore(stage, StageProgress.Score(score)))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,15 +6,15 @@ import lila.user.User
|
|||
|
||||
case class LearnProgress(
|
||||
_id: User.ID,
|
||||
levels: Map[String, LevelProgress],
|
||||
stages: Map[String, StageProgress],
|
||||
createdAt: DateTime,
|
||||
updatedAt: DateTime) {
|
||||
|
||||
def id = _id
|
||||
|
||||
def withScore(level: String, s: LevelProgress.Score) = copy(
|
||||
levels = levels + (
|
||||
level -> levels.getOrElse(level, LevelProgress empty level).withScore(s)
|
||||
def withScore(stage: String, s: StageProgress.Score) = copy(
|
||||
stages = stages + (
|
||||
stage -> stages.getOrElse(stage, StageProgress empty stage).withScore(s)
|
||||
),
|
||||
updatedAt = DateTime.now)
|
||||
}
|
||||
|
@ -23,7 +23,7 @@ object LearnProgress {
|
|||
|
||||
def empty(userId: User.ID) = LearnProgress(
|
||||
_id = userId,
|
||||
levels = Map.empty,
|
||||
stages = Map.empty,
|
||||
createdAt = DateTime.now,
|
||||
updatedAt = DateTime.now)
|
||||
}
|
||||
|
|
|
@ -2,13 +2,13 @@ package lila.learn
|
|||
|
||||
import org.joda.time.DateTime
|
||||
|
||||
case class LevelProgress(
|
||||
level: String,
|
||||
score: LevelProgress.Score,
|
||||
tries: LevelProgress.Tries,
|
||||
case class StageProgress(
|
||||
stage: String,
|
||||
score: StageProgress.Score,
|
||||
tries: StageProgress.Tries,
|
||||
updatedAt: DateTime) {
|
||||
|
||||
import LevelProgress._
|
||||
import StageProgress._
|
||||
|
||||
def withScore(s: Score) = copy(
|
||||
score = Score(score.value max s.value),
|
||||
|
@ -16,10 +16,10 @@ case class LevelProgress(
|
|||
updatedAt = DateTime.now)
|
||||
}
|
||||
|
||||
object LevelProgress {
|
||||
object StageProgress {
|
||||
|
||||
def empty(level: String) = LevelProgress(
|
||||
level = level,
|
||||
def empty(stage: String) = StageProgress(
|
||||
stage = stage,
|
||||
score = Score(0),
|
||||
tries = Tries(0),
|
||||
updatedAt = DateTime.now)
|
||||
|
|
|
@ -407,10 +407,10 @@
|
|||
#learn_side {
|
||||
border: none;
|
||||
}
|
||||
#learn_side .lessons {
|
||||
#learn_side .stages {
|
||||
margin: 10px;
|
||||
}
|
||||
#learn_side .lesson {
|
||||
#learn_side .stage {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
transition: 0.13s;
|
||||
|
@ -419,46 +419,46 @@
|
|||
font-weight: 300;
|
||||
opacity: 0.9;
|
||||
}
|
||||
#learn_side .lesson img,
|
||||
#learn_side .lesson i {
|
||||
#learn_side .stage img,
|
||||
#learn_side .stage i {
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
opacity: 0.9;
|
||||
margin-right: 5px;
|
||||
padding: 10px;
|
||||
}
|
||||
#learn_side .lesson i::before {
|
||||
#learn_side .stage i::before {
|
||||
font-size: 30px;
|
||||
}
|
||||
#learn_side .lesson.home {
|
||||
#learn_side .stage.home {
|
||||
font-weight: bold;
|
||||
}
|
||||
#learn_side .lesson.next img {
|
||||
#learn_side .stage.next img {
|
||||
background: #3893E8;
|
||||
-webkit-filter: brightness(0.9);
|
||||
}
|
||||
#learn_side .lesson.next img:hover {
|
||||
#learn_side .stage.next img:hover {
|
||||
-webkit-filter: brightness(1.2);
|
||||
}
|
||||
#learn_side .lesson.done img {
|
||||
#learn_side .stage.done img {
|
||||
background: #4caf50;
|
||||
}
|
||||
#learn_side .lesson.future img {
|
||||
#learn_side .stage.future img {
|
||||
opacity: 0.7;
|
||||
background: #f57c00;
|
||||
cursor: default;
|
||||
}
|
||||
#learn_side .lesson:hover {
|
||||
#learn_side .stage:hover {
|
||||
-webkit-filter: brightness(1.2);
|
||||
}
|
||||
|
||||
#learn_app .map .lessons {
|
||||
#learn_app .map .stages {
|
||||
display: flex;
|
||||
flex-flow: row wrap;
|
||||
justify-content: space-between;
|
||||
margin: 10px;
|
||||
}
|
||||
#learn_app .map .lesson {
|
||||
#learn_app .map .stage {
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
@ -472,13 +472,13 @@
|
|||
box-shadow: 0 6px 10px 0 rgba(0, 0, 0, 0.3), 0 2px 2px 0 rgba(0, 0, 0, 0.2);
|
||||
white-space: nowrap;
|
||||
}
|
||||
#learn_app .map .lesson img {
|
||||
#learn_app .map .stage img {
|
||||
width: 75px;
|
||||
height: 75px;
|
||||
margin: 5px;
|
||||
opacity: 0.9;
|
||||
}
|
||||
#learn_app .map .lesson h2 {
|
||||
#learn_app .map .stage h2 {
|
||||
font-size: 2em;
|
||||
margin: 0 0 5px -2px;
|
||||
}
|
||||
|
@ -487,36 +487,36 @@
|
|||
-webkit-filter: brightness(1.1);
|
||||
}
|
||||
}
|
||||
#learn_app .map .lesson.next {
|
||||
#learn_app .map .stage.next {
|
||||
background: #3893E8;
|
||||
-webkit-filter: brightness(0.9);
|
||||
}
|
||||
#learn_app .map .lesson.next {
|
||||
#learn_app .map .stage.next {
|
||||
animation: 1.7s soft-bright ease-in-out infinite;
|
||||
}
|
||||
#learn_app .map .lesson.next:hover {
|
||||
#learn_app .map .stage.next:hover {
|
||||
-webkit-filter: brightness(1.2);
|
||||
}
|
||||
#learn_app .map .lesson.done {
|
||||
#learn_app .map .stage.done {
|
||||
background: #4caf50;
|
||||
}
|
||||
#learn_app .map .lesson.future {
|
||||
#learn_app .map .stage.future {
|
||||
opacity: 0.7;
|
||||
background: #f57c00;
|
||||
cursor: default;
|
||||
}
|
||||
#learn_app .map .lesson.future img {
|
||||
#learn_app .map .stage.future img {
|
||||
opacity: 0.7;
|
||||
-webkit-filter: blur(2px);
|
||||
filter: blur(2px);
|
||||
}
|
||||
#learn_app .map a.lesson.current,
|
||||
#learn_app .map a.lesson:hover {
|
||||
#learn_app .map a.stage.current,
|
||||
#learn_app .map a.stage:hover {
|
||||
-webkit-filter: brightness(1.08);
|
||||
transform: scale(1.05);
|
||||
opacity: 1;
|
||||
}
|
||||
#learn_app .map .lesson .ribbon-wrapper {
|
||||
#learn_app .map .stage .ribbon-wrapper {
|
||||
width: 85px;
|
||||
height: 88px;
|
||||
overflow: hidden;
|
||||
|
@ -524,7 +524,7 @@
|
|||
top: -3px;
|
||||
right: -3px;
|
||||
}
|
||||
#learn_app .map .lesson .ribbon {
|
||||
#learn_app .map .stage .ribbon {
|
||||
font-size: 15px;
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
|
@ -539,37 +539,37 @@
|
|||
color: #6a6340;
|
||||
box-shadow: 0px 0px 3px rgba(0,0,0,0.3);
|
||||
}
|
||||
#learn_app .map .lesson .ribbon i {
|
||||
#learn_app .map .stage .ribbon i {
|
||||
color: #d59120;
|
||||
animation: 0.7s soft-hue ease-in-out infinite;
|
||||
}
|
||||
|
||||
#learn_app .map .lesson .ribbon:before,
|
||||
#learn_app .map .lesson .ribbon:after {
|
||||
#learn_app .map .stage .ribbon:before,
|
||||
#learn_app .map .stage .ribbon:after {
|
||||
content: "";
|
||||
border-left: 3px solid transparent;
|
||||
border-right: 3px solid transparent;
|
||||
position:absolute;
|
||||
bottom: -3px;
|
||||
}
|
||||
#learn_app .map .lesson .ribbon:before {
|
||||
#learn_app .map .stage .ribbon:before {
|
||||
left: 0;
|
||||
}
|
||||
#learn_app .map .lesson .ribbon:after {
|
||||
#learn_app .map .stage .ribbon:after {
|
||||
right: 0;
|
||||
}
|
||||
|
||||
#learn_app .map .lesson .ribbon.done {
|
||||
#learn_app .map .stage .ribbon.done {
|
||||
background-color: #BFDC7A;
|
||||
}
|
||||
#learn_app .map .lesson .ribbon.done:before,
|
||||
#learn_app .map .lesson .ribbon.done:after {
|
||||
#learn_app .map .stage .ribbon.done:before,
|
||||
#learn_app .map .stage .ribbon.done:after {
|
||||
border-top: 3px solid #6e8900;
|
||||
}
|
||||
#learn_app .map .lesson .ribbon.next {
|
||||
#learn_app .map .stage .ribbon.next {
|
||||
background-color: #B3E5FC;
|
||||
}
|
||||
#learn_app .map .lesson .ribbon.next:before,
|
||||
#learn_app .map .lesson .ribbon.next:after {
|
||||
#learn_app .map .stage .ribbon.next:before,
|
||||
#learn_app .map .stage .ribbon.next:after {
|
||||
border-top: 3px solid #536DFE;
|
||||
}
|
||||
|
|
|
@ -1,66 +0,0 @@
|
|||
var m = require('mithril');
|
||||
var stageBuilder = require('./stage');
|
||||
var makeProgress = require('./progress').ctrl;
|
||||
var sound = require('./sound');
|
||||
|
||||
module.exports = function(blueprint, opts) {
|
||||
|
||||
var onStageComplete = function() {
|
||||
progress.inc();
|
||||
var s = makeStage(stage.blueprint.id + 1);
|
||||
if (s) {
|
||||
stage = s;
|
||||
}
|
||||
else {
|
||||
vm.completed = true;
|
||||
sound.lessonEnd();
|
||||
opts.setScore(blueprint, vm.score);
|
||||
}
|
||||
m.redraw();
|
||||
};
|
||||
|
||||
var makeStage = function(id) {
|
||||
var stageBlueprint = blueprint.stages[id - 1];
|
||||
if (stageBlueprint) return stageBuilder(stageBlueprint, {
|
||||
onScore: function(score) {
|
||||
vm.score += score;
|
||||
m.redraw();
|
||||
},
|
||||
onComplete: onStageComplete,
|
||||
restart: restartStage
|
||||
})
|
||||
}
|
||||
|
||||
var restartStage = function() {
|
||||
vm.score = vm.score - stage.vm.score;
|
||||
stage = makeStage(stage.blueprint.id);
|
||||
m.redraw();
|
||||
};
|
||||
|
||||
var stage = makeStage(opts.stage || 1);
|
||||
|
||||
var progress = makeProgress({
|
||||
steps: blueprint.stages.length,
|
||||
step: stage.blueprint.id
|
||||
});
|
||||
|
||||
var vm = {
|
||||
score: 0,
|
||||
starting: stage.blueprint.id === 1,
|
||||
completed: false
|
||||
};
|
||||
sound.lessonStart();
|
||||
|
||||
return {
|
||||
blueprint: blueprint,
|
||||
progress: progress,
|
||||
vm: vm,
|
||||
stage: function() {
|
||||
return stage;
|
||||
},
|
||||
start: function() {
|
||||
vm.starting = false;
|
||||
},
|
||||
restartStage: restartStage
|
||||
}
|
||||
};
|
|
@ -0,0 +1,111 @@
|
|||
var m = require('mithril');
|
||||
var makeItems = require('./item').ctrl;
|
||||
var itemView = require('./item').view;
|
||||
var makeChess = require('./chess');
|
||||
var ground = require('./ground');
|
||||
var scoring = require('./score');
|
||||
var sound = require('./sound');
|
||||
var promotion = require('./promotion');
|
||||
|
||||
module.exports = function(blueprint, opts) {
|
||||
|
||||
var items = makeItems({
|
||||
apples: blueprint.apples
|
||||
});
|
||||
|
||||
var vm = {
|
||||
initialized: false,
|
||||
lastStep: false,
|
||||
completed: false,
|
||||
failed: false,
|
||||
score: 0,
|
||||
nbMoves: 0
|
||||
};
|
||||
setTimeout(function() {
|
||||
vm.initialized = true;
|
||||
m.redraw();
|
||||
}, 100);
|
||||
|
||||
var addScore = function(v) {
|
||||
vm.score += v;
|
||||
opts.onScore(v);
|
||||
};
|
||||
|
||||
var complete = function() {
|
||||
setTimeout(function() {
|
||||
if (vm.failed) return opts.restart();
|
||||
vm.lastStep = false;
|
||||
vm.completed = true;
|
||||
sound.levelEnd();
|
||||
var rank = scoring.getLevelRank(blueprint, vm.nbMoves);
|
||||
var bonus = scoring.getLevelBonus(rank);
|
||||
addScore(bonus);
|
||||
ground.stop();
|
||||
m.redraw();
|
||||
setTimeout(opts.onComplete, 1200);
|
||||
}, ground.data().stats.dragged ? 0 : 250);
|
||||
};
|
||||
|
||||
// cheat
|
||||
Mousetrap.bind(['shift+enter'], complete);
|
||||
|
||||
var detectFailure = function() {
|
||||
var failed = false;
|
||||
(blueprint.failure || []).forEach(function(f) {
|
||||
failed = failed || f(chess);
|
||||
});
|
||||
if (failed) sound.failure();
|
||||
return failed;
|
||||
};
|
||||
|
||||
var sendMove = function(orig, dest, prom) {
|
||||
vm.nbMoves++;
|
||||
var move = chess.move(orig, dest, prom);
|
||||
if (!move) throw 'Invalid move!';
|
||||
var appleTaken = false;
|
||||
items.withItem(move.to, function(item) {
|
||||
if (item === 'apple') {
|
||||
addScore(scoring.apple);
|
||||
items.remove(move.to);
|
||||
appleTaken = true;
|
||||
}
|
||||
});
|
||||
if (!items.hasItem('apple')) complete();
|
||||
else if (appleTaken) sound.take();
|
||||
else sound.move();
|
||||
if (vm.completed) return;
|
||||
vm.failed = vm.failed || detectFailure();
|
||||
chess.color(blueprint.color);
|
||||
ground.color(blueprint.color, chess.dests());
|
||||
m.redraw();
|
||||
};
|
||||
|
||||
var onMove = function(orig, dest) {
|
||||
if (!promotion.start(orig, dest, sendMove)) sendMove(orig, dest);
|
||||
};
|
||||
|
||||
var chess = makeChess(
|
||||
blueprint.fen,
|
||||
blueprint.emptyApples ? [] : items.appleKeys());
|
||||
|
||||
ground.set({
|
||||
chess: chess,
|
||||
orientation: blueprint.color,
|
||||
onMove: onMove,
|
||||
items: {
|
||||
render: function(pos, key) {
|
||||
return items.withItem(key, itemView);
|
||||
}
|
||||
},
|
||||
shapes: blueprint.shapes
|
||||
});
|
||||
|
||||
if (blueprint.id !== 1) sound.levelStart();
|
||||
|
||||
return {
|
||||
blueprint: blueprint,
|
||||
items: items,
|
||||
vm: vm,
|
||||
restart: opts.restart
|
||||
};
|
||||
};
|
|
@ -2,7 +2,6 @@ var m = require('mithril');
|
|||
var map = require('./map/mapMain');
|
||||
var mapSide = require('./map/mapSide');
|
||||
var run = require('./run/runMain');
|
||||
var makeLesson = require('./lesson');
|
||||
|
||||
module.exports = function(element, opts) {
|
||||
|
||||
|
@ -10,7 +9,7 @@ module.exports = function(element, opts) {
|
|||
|
||||
m.route(element, '/', {
|
||||
'/': map(opts),
|
||||
'/:id/:stage': run(opts),
|
||||
'/:id/:level': run(opts),
|
||||
'/:id': run(opts)
|
||||
});
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ var mapView = require('./mapView');
|
|||
module.exports = function(opts) {
|
||||
return {
|
||||
controller: function() {
|
||||
opts.lessonId = null;
|
||||
opts.stageId = null;
|
||||
opts.route = 'map';
|
||||
return {
|
||||
data: opts.data
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
var m = require('mithril');
|
||||
var util = require('../util');
|
||||
var lessons = require('../lesson/list');
|
||||
var stages = require('../stage/list');
|
||||
|
||||
module.exports = function(opts) {
|
||||
return {
|
||||
controller: function() {
|
||||
return {
|
||||
data: opts.data,
|
||||
current: opts.lessonId,
|
||||
current: opts.stageId,
|
||||
enabled: function() {
|
||||
return opts.route === 'run';
|
||||
}
|
||||
|
@ -15,28 +15,28 @@ module.exports = function(opts) {
|
|||
},
|
||||
view: function(ctrl) {
|
||||
if (ctrl.enabled()) return m('div.learn.map', [
|
||||
m('div.lessons', [
|
||||
m('a.lesson.home', {
|
||||
m('div.stages', [
|
||||
m('a.stage.home', {
|
||||
href: '/',
|
||||
config: m.route
|
||||
}, [
|
||||
m('i[data-icon=I]'),
|
||||
'Learn chess'
|
||||
]),
|
||||
lessons.list.map(function(l) {
|
||||
var result = ctrl.data.levels[l.key];
|
||||
var previousDone = l.id === 1 ? true : !!ctrl.data.levels[lessons.get(l.id - 1).key];
|
||||
stages.list.map(function(s) {
|
||||
var result = ctrl.data.stages[s.key];
|
||||
var previousDone = s.id === 1 ? true : !!ctrl.data.stages[stages.get(s.id - 1).key];
|
||||
var status = result ? 'done' : (previousDone ? 'next' : 'future')
|
||||
var current = l.id === ctrl.current;
|
||||
var current = s.id === ctrl.current;
|
||||
return m(status === 'future' ? 'span' : 'a', {
|
||||
class: 'lesson ' + status + (current ? ' current' : ''),
|
||||
href: '/' + l.id,
|
||||
class: 'stage ' + status + (current ? ' current' : ''),
|
||||
href: '/' + s.id,
|
||||
config: status === 'future' ? null : m.route
|
||||
}, [
|
||||
m('img', {
|
||||
src: status === 'future' ? util.assetUrl + 'images/learn/help.svg' : l.image
|
||||
src: status === 'future' ? util.assetUrl + 'images/learn/help.svg' : s.image
|
||||
}),
|
||||
m('h2', l.title)
|
||||
m('h2', s.title)
|
||||
]);
|
||||
})
|
||||
])
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
var m = require('mithril');
|
||||
var util = require('../util');
|
||||
var scoring = require('../score');
|
||||
var lessons = require('../lesson/list');
|
||||
var stages = require('../stage/list');
|
||||
|
||||
function makeStars(nb) {
|
||||
var stars = [];
|
||||
|
@ -12,9 +12,9 @@ function makeStars(nb) {
|
|||
return stars;
|
||||
}
|
||||
|
||||
function ribbon(l, status, result) {
|
||||
function ribbon(s, status, result) {
|
||||
if (status === 'future') return;
|
||||
var rank = result ? scoring.getLevelRank(l, result.score) : null;
|
||||
var rank = result ? scoring.getStageRank(s, result.score) : null;
|
||||
var content = rank ? makeStars(rank) : 'play!';
|
||||
return m('div.ribbon-wrapper',
|
||||
m('div.ribbon', {
|
||||
|
@ -25,22 +25,22 @@ function ribbon(l, status, result) {
|
|||
|
||||
module.exports = function(ctrl) {
|
||||
return m('div.learn.map', [
|
||||
m('div.lessons', lessons.list.map(function(l) {
|
||||
var result = ctrl.data.levels[l.key];
|
||||
var previousDone = l.id === 1 ? true : !!ctrl.data.levels[lessons.get(l.id - 1).key];
|
||||
m('div.stages', stages.list.map(function(s) {
|
||||
var result = ctrl.data.stages[s.key];
|
||||
var previousDone = s.id === 1 ? true : !!ctrl.data.stages[stages.get(s.id - 1).key];
|
||||
var status = result ? 'done' : (previousDone ? 'next' : 'future')
|
||||
return m(status === 'future' ? 'span' : 'a', {
|
||||
class: 'lesson ' + status,
|
||||
href: '/' + l.id,
|
||||
class: 'stage ' + status,
|
||||
href: '/' + s.id,
|
||||
config: status === 'future' ? null : m.route
|
||||
}, [
|
||||
ribbon(l, status, result),
|
||||
ribbon(s, status, result),
|
||||
m('img', {
|
||||
src: status === 'future' ? util.assetUrl + 'images/learn/help.svg' : l.image
|
||||
src: status === 'future' ? util.assetUrl + 'images/learn/help.svg' : s.image
|
||||
}),
|
||||
m('div.text', [
|
||||
m('h2', l.title),
|
||||
m('p.subtitle', l.subtitle)
|
||||
m('h2', s.title),
|
||||
m('p.subtitle', s.subtitle)
|
||||
])
|
||||
]);
|
||||
}))
|
||||
|
|
|
@ -1,18 +0,0 @@
|
|||
var m = require('mithril');
|
||||
|
||||
module.exports = function(lesson, next) {
|
||||
return m('div.screen-overlay', {
|
||||
onclick: lesson.start
|
||||
},
|
||||
m('div.screen', [
|
||||
m('h1', 'Level ' + lesson.blueprint.id + ': ' + lesson.blueprint.title),
|
||||
lesson.blueprint.illustration,
|
||||
m('p', m.trust(lesson.blueprint.intro)),
|
||||
m('div.buttons',
|
||||
m('a.next', {
|
||||
onclick: lesson.start
|
||||
}, "Let's go!")
|
||||
)
|
||||
])
|
||||
);
|
||||
};
|
|
@ -1,31 +1,31 @@
|
|||
var m = require('mithril');
|
||||
var lessons = require('../lesson/list');
|
||||
var makeLesson = require('../lesson');
|
||||
var stages = require('../stage/list');
|
||||
var makeStage = require('../stage');
|
||||
var xhr = require('../xhr');
|
||||
|
||||
module.exports = function(opts) {
|
||||
|
||||
var setScore = function(level, score) {
|
||||
xhr.setScore(level.key, score).then(function(data) {
|
||||
var setScore = function(stage, score) {
|
||||
xhr.setScore(stage.key, score).then(function(data) {
|
||||
opts.data = data;
|
||||
});
|
||||
};
|
||||
|
||||
var lesson = makeLesson(lessons.get(m.route.param("id")), {
|
||||
stage: m.route.param('stage') || 1,
|
||||
var stage = makeStage(stages.get(m.route.param("id")), {
|
||||
level: m.route.param('level') || 1,
|
||||
setScore: setScore
|
||||
});
|
||||
|
||||
opts.route = 'run';
|
||||
opts.lessonId = lesson.blueprint.id;
|
||||
opts.stageId = stage.blueprint.id;
|
||||
|
||||
var getNext = function() {
|
||||
return lessons.get(lesson.blueprint.id + 1);
|
||||
return stages.get(stage.blueprint.id + 1);
|
||||
};
|
||||
|
||||
return {
|
||||
lesson: function() {
|
||||
return lesson;
|
||||
stage: function() {
|
||||
return stage;
|
||||
},
|
||||
getNext: getNext
|
||||
};
|
||||
|
|
|
@ -3,55 +3,55 @@ var chessground = require('chessground');
|
|||
var ground = require('../ground');
|
||||
var classSet = chessground.util.classSet;
|
||||
var congrats = require('../congrats');
|
||||
var lessonStarting = require('./lessonStarting');
|
||||
var lessonComplete = require('./lessonComplete');
|
||||
var stageStarting = require('./stageStarting');
|
||||
var stageComplete = require('./stageComplete');
|
||||
var renderPromotion = require('../promotion').view;
|
||||
var renderScore = require('./scoreView');
|
||||
var renderProgress = require('../progress').view;
|
||||
|
||||
function renderFailed(stage) {
|
||||
function renderFailed(level) {
|
||||
return m('div.failed', [
|
||||
m('h2', 'Puzzle failed!'),
|
||||
m('button', {
|
||||
onclick: stage.restart
|
||||
onclick: level.restart
|
||||
}, 'Retry')
|
||||
]);
|
||||
}
|
||||
|
||||
module.exports = function(ctrl) {
|
||||
var lesson = ctrl.lesson();
|
||||
var stage = lesson.stage();
|
||||
var stage = ctrl.stage();
|
||||
var level = stage.level();
|
||||
|
||||
return m('div', {
|
||||
class: classSet({
|
||||
'lichess_game': true,
|
||||
'initialized': stage.vm.initialized,
|
||||
'starting': stage.vm.starting,
|
||||
'completed': stage.vm.completed,
|
||||
'last-step': stage.vm.lastStep
|
||||
}) + ' ' + stage.blueprint.cssClass
|
||||
'initialized': level.vm.initialized,
|
||||
'starting': level.vm.starting,
|
||||
'completed': level.vm.completed,
|
||||
'last-step': level.vm.lastStep
|
||||
}) + ' ' + level.blueprint.cssClass
|
||||
}, [
|
||||
lesson.vm.starting ? lessonStarting(lesson) : null,
|
||||
lesson.vm.completed ? lessonComplete(lesson, ctrl.getNext()) : null,
|
||||
stage.vm.starting ? stageStarting(stage) : null,
|
||||
stage.vm.completed ? stageComplete(stage, ctrl.getNext()) : null,
|
||||
m('div.lichess_board_wrap', [
|
||||
m('div.lichess_board', chessground.view(ground.instance)),
|
||||
renderPromotion(stage),
|
||||
renderPromotion(level),
|
||||
]),
|
||||
m('div.lichess_ground', [
|
||||
m('div.title', [
|
||||
m('img', {
|
||||
src: lesson.blueprint.image
|
||||
src: stage.blueprint.image
|
||||
}),
|
||||
m('div.text', [
|
||||
m('h2', lesson.blueprint.title),
|
||||
m('p.subtitle', lesson.blueprint.subtitle)
|
||||
m('h2', stage.blueprint.title),
|
||||
m('p.subtitle', stage.blueprint.subtitle)
|
||||
])
|
||||
]),
|
||||
stage.vm.failed ? renderFailed(stage) : m('div.goal',
|
||||
stage.vm.completed ? congrats() : m.trust(stage.blueprint.goal)
|
||||
level.vm.failed ? renderFailed(level) : m('div.goal',
|
||||
level.vm.completed ? congrats() : m.trust(level.blueprint.goal)
|
||||
),
|
||||
renderProgress(lesson.progress),
|
||||
renderScore(lesson)
|
||||
renderProgress(stage.progress),
|
||||
renderScore(stage)
|
||||
])
|
||||
]);
|
||||
};
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
var m = require('mithril');
|
||||
|
||||
module.exports = function(lesson) {
|
||||
module.exports = function(stage) {
|
||||
return m('div.score', [
|
||||
m('span.plus', {
|
||||
config: function(el, isUpdate, ctx) {
|
||||
var score = lesson.vm.score;
|
||||
var score = stage.vm.score;
|
||||
if (isUpdate) {
|
||||
var diff = score - (ctx.prev || 0);
|
||||
if (diff > 0) {
|
||||
|
@ -26,11 +26,11 @@ module.exports = function(lesson) {
|
|||
m('span.legend', 'SCORE'),
|
||||
m('span.value', {
|
||||
config: function(el, isUpdate, ctx) {
|
||||
var score = lesson.vm.score;
|
||||
var score = stage.vm.score;
|
||||
if (!ctx.spread) {
|
||||
el.textContent = lichess.numberFormat(score);
|
||||
ctx.spread = $.spreadNumber(el, 50, function() {
|
||||
var diff = lesson.vm.score - ctx.prev;
|
||||
var diff = stage.vm.score - ctx.prev;
|
||||
return Math.min(1000, 5 * diff);
|
||||
}, score);
|
||||
} else if (score !== ctx.prev) ctx.spread(score, (score - ctx.prev) / 5);
|
||||
|
|
|
@ -8,21 +8,21 @@ function makeStars(rank) {
|
|||
return stars;
|
||||
}
|
||||
|
||||
module.exports = function(lesson, next) {
|
||||
module.exports = function(stage, next) {
|
||||
return m('div.screen-overlay', {
|
||||
onclick: function(e) {
|
||||
if (e.target.classList.contains('screen-overlay')) m.route('/');
|
||||
}
|
||||
},
|
||||
m('div.screen', [
|
||||
m('div.stars', makeStars(scoring.getLevelRank(lesson.blueprint, lesson.vm.score))),
|
||||
m('h1', 'Level ' + lesson.blueprint.id + ' complete'),
|
||||
m('div.stars', makeStars(scoring.getStageRank(stage.blueprint, stage.vm.score))),
|
||||
m('h1', 'Stage ' + stage.blueprint.id + ' complete'),
|
||||
m('span.score', [
|
||||
'Your score: ',
|
||||
m('span', {
|
||||
config: function(el, isUpdate) {
|
||||
if (!isUpdate) setTimeout(function() {
|
||||
var score = lesson.vm.score;
|
||||
var score = stage.vm.score;
|
||||
$.spreadNumber(el, 50, function() {
|
||||
return 3000;
|
||||
}, 0)(score);
|
||||
|
@ -31,7 +31,7 @@ module.exports = function(lesson, next) {
|
|||
}, 0)
|
||||
]),
|
||||
m('p', [
|
||||
m.trust(lesson.blueprint.complete)
|
||||
m.trust(stage.blueprint.complete)
|
||||
]),
|
||||
m('div.buttons', [
|
||||
next ? m('a.next', {
|
|
@ -0,0 +1,18 @@
|
|||
var m = require('mithril');
|
||||
|
||||
module.exports = function(stage, next) {
|
||||
return m('div.screen-overlay', {
|
||||
onclick: stage.start
|
||||
},
|
||||
m('div.screen', [
|
||||
m('h1', 'Stage ' + stage.blueprint.id + ': ' + stage.blueprint.title),
|
||||
stage.blueprint.illustration,
|
||||
m('p', m.trust(stage.blueprint.intro)),
|
||||
m('div.buttons',
|
||||
m('a.next', {
|
||||
onclick: stage.start
|
||||
}, "Let's go!")
|
||||
)
|
||||
])
|
||||
);
|
||||
};
|
|
@ -2,43 +2,43 @@ var util = require('./util');
|
|||
|
||||
var apple = 50;
|
||||
|
||||
function getStageRank(s, nbMoves) {
|
||||
function getLevelRank(s, nbMoves) {
|
||||
var late = nbMoves - s.nbMoves;
|
||||
if (late <= 0) return 1;
|
||||
else if (late <= Math.max(1, s.nbMoves / 8)) return 2;
|
||||
return 3;
|
||||
}
|
||||
|
||||
var stageBonus = {
|
||||
var levelBonus = {
|
||||
1: 500,
|
||||
2: 300,
|
||||
3: 100
|
||||
};
|
||||
|
||||
function getStageBonus(rank) {
|
||||
return stageBonus[Math.min(rank, 3)];
|
||||
}
|
||||
|
||||
function getStageMaxScore(l) {
|
||||
return util.readKeys(l.apples).length * apple + stageBonus[1];
|
||||
function getLevelBonus(rank) {
|
||||
return levelBonus[Math.min(rank, 3)];
|
||||
}
|
||||
|
||||
function getLevelMaxScore(l) {
|
||||
return l.stages.reduce(function(sum, s) {
|
||||
return sum + getStageMaxScore(s);
|
||||
return util.readKeys(l.apples).length * apple + levelBonus[1];
|
||||
}
|
||||
|
||||
function getStageMaxScore(l) {
|
||||
return l.levels.reduce(function(sum, s) {
|
||||
return sum + getLevelMaxScore(s);
|
||||
}, 0);
|
||||
}
|
||||
|
||||
function getLevelRank(l, score) {
|
||||
var max = getLevelMaxScore(l);
|
||||
if (score >= max - Math.max(200, l.stages.length * 50)) return 1;
|
||||
if (score >= max - Math.max(200, l.stages.length * 300)) return 2;
|
||||
function getStageRank(l, score) {
|
||||
var max = getStageMaxScore(l);
|
||||
if (score >= max - Math.max(200, l.levels.length * 50)) return 1;
|
||||
if (score >= max - Math.max(200, l.levels.length * 300)) return 2;
|
||||
return 3;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
apple: apple,
|
||||
getStageRank: getStageRank,
|
||||
getStageBonus: getStageBonus,
|
||||
getLevelRank: getLevelRank
|
||||
getLevelRank: getLevelRank,
|
||||
getLevelBonus: getLevelBonus,
|
||||
getStageRank: getStageRank
|
||||
};
|
||||
|
|
|
@ -18,10 +18,10 @@ var make = function(file, volume) {
|
|||
module.exports = {
|
||||
move: make('standard/Move'),
|
||||
take: make('sfx/Tournament3rd', 0.7),
|
||||
stageStart: make('other/ping'),
|
||||
stageEnd: make('other/energy3'),
|
||||
lessonStart: make('other/guitar'),
|
||||
// lessonEnd: make('sfx/Tournament1st'),
|
||||
lessonEnd: make('other/gewonnen'),
|
||||
levelStart: make('other/ping'),
|
||||
levelEnd: make('other/energy3'),
|
||||
stageStart: make('other/guitar'),
|
||||
// stageEnd: make('sfx/Tournament1st'),
|
||||
stageEnd: make('other/gewonnen'),
|
||||
failure: make('other/failure')
|
||||
};
|
||||
|
|
|
@ -1,111 +1,66 @@
|
|||
var m = require('mithril');
|
||||
var makeItems = require('./item').ctrl;
|
||||
var itemView = require('./item').view;
|
||||
var makeChess = require('./chess');
|
||||
var ground = require('./ground');
|
||||
var scoring = require('./score');
|
||||
var levelBuilder = require('./level');
|
||||
var makeProgress = require('./progress').ctrl;
|
||||
var sound = require('./sound');
|
||||
var promotion = require('./promotion');
|
||||
|
||||
module.exports = function(blueprint, opts) {
|
||||
|
||||
var items = makeItems({
|
||||
apples: blueprint.apples
|
||||
var onLevelComplete = function() {
|
||||
progress.inc();
|
||||
var s = makeLevel(level.blueprint.id + 1);
|
||||
if (s) {
|
||||
level = s;
|
||||
}
|
||||
else {
|
||||
vm.completed = true;
|
||||
sound.stageEnd();
|
||||
opts.setScore(blueprint, vm.score);
|
||||
}
|
||||
m.redraw();
|
||||
};
|
||||
|
||||
var makeLevel = function(id) {
|
||||
var levelBlueprint = blueprint.levels[id - 1];
|
||||
if (levelBlueprint) return levelBuilder(levelBlueprint, {
|
||||
onScore: function(score) {
|
||||
vm.score += score;
|
||||
m.redraw();
|
||||
},
|
||||
onComplete: onLevelComplete,
|
||||
restart: restartLevel
|
||||
})
|
||||
}
|
||||
|
||||
var restartLevel = function() {
|
||||
vm.score = vm.score - level.vm.score;
|
||||
level = makeLevel(level.blueprint.id);
|
||||
m.redraw();
|
||||
};
|
||||
|
||||
var level = makeLevel(opts.level || 1);
|
||||
|
||||
var progress = makeProgress({
|
||||
steps: blueprint.levels.length,
|
||||
step: level.blueprint.id
|
||||
});
|
||||
|
||||
var vm = {
|
||||
initialized: false,
|
||||
lastStep: false,
|
||||
completed: false,
|
||||
failed: false,
|
||||
score: 0,
|
||||
nbMoves: 0
|
||||
starting: level.blueprint.id === 1,
|
||||
completed: false
|
||||
};
|
||||
setTimeout(function() {
|
||||
vm.initialized = true;
|
||||
m.redraw();
|
||||
}, 100);
|
||||
|
||||
var addScore = function(v) {
|
||||
vm.score += v;
|
||||
opts.onScore(v);
|
||||
};
|
||||
|
||||
var complete = function() {
|
||||
setTimeout(function() {
|
||||
if (vm.failed) return opts.restart();
|
||||
vm.lastStep = false;
|
||||
vm.completed = true;
|
||||
sound.stageEnd();
|
||||
var rank = scoring.getStageRank(blueprint, vm.nbMoves);
|
||||
var bonus = scoring.getStageBonus(rank);
|
||||
addScore(bonus);
|
||||
ground.stop();
|
||||
m.redraw();
|
||||
setTimeout(opts.onComplete, 1200);
|
||||
}, ground.data().stats.dragged ? 0 : 250);
|
||||
};
|
||||
|
||||
// cheat
|
||||
Mousetrap.bind(['shift+enter'], complete);
|
||||
|
||||
var detectFailure = function() {
|
||||
var failed = false;
|
||||
(blueprint.failure || []).forEach(function(f) {
|
||||
failed = failed || f(chess);
|
||||
});
|
||||
if (failed) sound.failure();
|
||||
return failed;
|
||||
};
|
||||
|
||||
var sendMove = function(orig, dest, prom) {
|
||||
vm.nbMoves++;
|
||||
var move = chess.move(orig, dest, prom);
|
||||
if (!move) throw 'Invalid move!';
|
||||
var appleTaken = false;
|
||||
items.withItem(move.to, function(item) {
|
||||
if (item === 'apple') {
|
||||
addScore(scoring.apple);
|
||||
items.remove(move.to);
|
||||
appleTaken = true;
|
||||
}
|
||||
});
|
||||
if (!items.hasItem('apple')) complete();
|
||||
else if (appleTaken) sound.take();
|
||||
else sound.move();
|
||||
if (vm.completed) return;
|
||||
vm.failed = vm.failed || detectFailure();
|
||||
chess.color(blueprint.color);
|
||||
ground.color(blueprint.color, chess.dests());
|
||||
m.redraw();
|
||||
};
|
||||
|
||||
var onMove = function(orig, dest) {
|
||||
if (!promotion.start(orig, dest, sendMove)) sendMove(orig, dest);
|
||||
};
|
||||
|
||||
var chess = makeChess(
|
||||
blueprint.fen,
|
||||
blueprint.emptyApples ? [] : items.appleKeys());
|
||||
|
||||
ground.set({
|
||||
chess: chess,
|
||||
orientation: blueprint.color,
|
||||
onMove: onMove,
|
||||
items: {
|
||||
render: function(pos, key) {
|
||||
return items.withItem(key, itemView);
|
||||
}
|
||||
},
|
||||
shapes: blueprint.shapes
|
||||
});
|
||||
|
||||
if (blueprint.id !== 1) sound.stageStart();
|
||||
sound.stageStart();
|
||||
|
||||
return {
|
||||
blueprint: blueprint,
|
||||
items: items,
|
||||
progress: progress,
|
||||
vm: vm,
|
||||
restart: opts.restart
|
||||
};
|
||||
level: function() {
|
||||
return level;
|
||||
},
|
||||
start: function() {
|
||||
vm.starting = false;
|
||||
},
|
||||
restartLevel: restartLevel
|
||||
}
|
||||
};
|
||||
|
|
|
@ -11,7 +11,7 @@ module.exports = {
|
|||
illustration: m('div.is2d.no-square',
|
||||
m('piece.bishop.white')
|
||||
),
|
||||
stages: [{
|
||||
levels: [{
|
||||
goal: 'Grab all the stars!',
|
||||
fen: '8/8/8/8/8/5B2/8/8 w - - 0 1',
|
||||
apples: 'd5 g8',
|
||||
|
@ -42,6 +42,6 @@ module.exports = {
|
|||
fen: '8/3B4/8/8/8/2B5/8/8 w - - 0 1',
|
||||
apples: 'a5 b4 c2 c4 c7 e7 f5 f6 g8 h4 h7',
|
||||
nbMoves: 11
|
||||
}].map(util.toStage),
|
||||
}].map(util.toLevel),
|
||||
complete: 'Congratulations! You can command a bishop.'
|
||||
};
|
|
@ -11,7 +11,7 @@ module.exports = {
|
|||
image: imgUrl,
|
||||
intro: 'You are ready for combat! In this level, we will be capturing enemy pieces.',
|
||||
illustration: m('img', {src: imgUrl}),
|
||||
stages: [{
|
||||
levels: [{
|
||||
goal: 'Grab all the stars!',
|
||||
fen: '8/8/8/8/8/5B2/8/8 w - - 0 1',
|
||||
apples: 'd5 g8',
|
||||
|
@ -42,7 +42,7 @@ module.exports = {
|
|||
fen: '8/3B4/8/8/8/2B5/8/8 w - - 0 1',
|
||||
apples: 'a5 b4 c2 c4 c7 e7 f5 f6 g8 h4 h7',
|
||||
nbMoves: 11
|
||||
}].map(util.toStage),
|
||||
}].map(util.toLevel),
|
||||
complete: 'Congratulations! You can command a bishop.'
|
||||
};
|
||||
|
|
@ -11,7 +11,7 @@ module.exports = {
|
|||
image: imgUrl,
|
||||
intro: 'Bring your king to safety, and deploy your rook for attack!',
|
||||
illustration: m('img', {src: imgUrl}),
|
||||
stages: [{
|
||||
levels: [{
|
||||
goal: 'Grab all the stars!',
|
||||
fen: '8/8/8/8/8/5B2/8/8 w - - 0 1',
|
||||
apples: 'd5 g8',
|
||||
|
@ -42,7 +42,7 @@ module.exports = {
|
|||
fen: '8/3B4/8/8/8/2B5/8/8 w - - 0 1',
|
||||
apples: 'a5 b4 c2 c4 c7 e7 f5 f6 g8 h4 h7',
|
||||
nbMoves: 11
|
||||
}].map(util.toStage),
|
||||
}].map(util.toLevel),
|
||||
complete: 'Congratulations! You can command a bishop.'
|
||||
};
|
||||
|
|
@ -11,7 +11,7 @@ module.exports = {
|
|||
image: imgUrl,
|
||||
intro: 'When the opponent pawn moved by two squares, you can take it like if it moved by one square.',
|
||||
illustration: m('img', {src: imgUrl}),
|
||||
stages: [{
|
||||
levels: [{
|
||||
goal: 'Grab all the stars!',
|
||||
fen: '8/8/8/8/8/5B2/8/8 w - - 0 1',
|
||||
apples: 'd5 g8',
|
||||
|
@ -42,7 +42,7 @@ module.exports = {
|
|||
fen: '8/3B4/8/8/8/2B5/8/8 w - - 0 1',
|
||||
apples: 'a5 b4 c2 c4 c7 e7 f5 f6 g8 h4 h7',
|
||||
nbMoves: 11
|
||||
}].map(util.toStage),
|
||||
}].map(util.toLevel),
|
||||
complete: 'Congratulations! You can command a bishop.'
|
||||
};
|
||||
|
|
@ -11,7 +11,7 @@ module.exports = {
|
|||
illustration: m('div.is2d.no-square',
|
||||
m('piece.king.white')
|
||||
),
|
||||
stages: [{
|
||||
levels: [{
|
||||
goal: 'The king is slow.',
|
||||
fen: '8/8/8/8/3K4/8/8/8 w - - 0 1',
|
||||
apples: 'e6',
|
||||
|
@ -28,7 +28,7 @@ module.exports = {
|
|||
apples: 'b5 c5 d6 e3 f3 g4',
|
||||
nbMoves: 8
|
||||
}].map(function(s, i) {
|
||||
s = util.toStage(s, i);
|
||||
s = util.toLevel(s, i);
|
||||
s.emptyApples = true;
|
||||
return s;
|
||||
}),
|
|
@ -11,7 +11,7 @@ module.exports = {
|
|||
illustration: m('div.is2d.no-square',
|
||||
m('piece.knight.white')
|
||||
),
|
||||
stages: [{
|
||||
levels: [{
|
||||
goal: 'Knights have a fancy way<br>of jumping around!',
|
||||
fen: '8/8/8/8/4N3/8/8/8 w - - 0 1',
|
||||
apples: 'c5 d7',
|
||||
|
@ -42,6 +42,6 @@ module.exports = {
|
|||
fen: '8/2n5/8/8/8/8/8/8 b - - 0 1',
|
||||
apples: 'b4 b5 c6 c8 d4 d5 e3 e7 f5',
|
||||
nbMoves: 9
|
||||
}].map(util.toStage),
|
||||
}].map(util.toLevel),
|
||||
complete: 'Congratulations! You have mastered the knight.'
|
||||
};
|
|
@ -1,6 +1,6 @@
|
|||
var util = require('../util');
|
||||
|
||||
var lessons = [
|
||||
var stages = [
|
||||
|
||||
require('./rook'),
|
||||
require('./bishop'),
|
||||
|
@ -13,12 +13,12 @@ var lessons = [
|
|||
require('./castling'),
|
||||
require('./enpassant')
|
||||
|
||||
].map(util.toLesson);
|
||||
].map(util.toStage);
|
||||
|
||||
module.exports = {
|
||||
list: lessons,
|
||||
list: stages,
|
||||
get: function(id) {
|
||||
return lessons.filter(function(l) {
|
||||
return stages.filter(function(l) {
|
||||
return l.id == id;
|
||||
})[0];
|
||||
}
|
|
@ -12,7 +12,7 @@ module.exports = {
|
|||
illustration: m('div.is2d.no-square',
|
||||
m('piece.pawn.white')
|
||||
),
|
||||
stages: [{
|
||||
levels: [{
|
||||
goal: 'Pawns move one square only.<br>But when they reach the other side of the board, they become a stronger piece!',
|
||||
fen: '8/8/8/P7/8/8/8/8 w - - 0 1',
|
||||
apples: 'f3',
|
||||
|
@ -60,6 +60,6 @@ module.exports = {
|
|||
fen: '8/8/8/8/8/8/2PPPP2/8 w - - 0 1',
|
||||
apples: 'c5 d5 e5 f5 d3 e4',
|
||||
nbMoves: 9
|
||||
}].map(util.toStage),
|
||||
}].map(util.toLevel),
|
||||
complete: 'Congratulations! Pawns have no secrets for you.'
|
||||
};
|
|
@ -11,7 +11,7 @@ module.exports = {
|
|||
illustration: m('div.is2d.no-square',
|
||||
m('piece.queen.white')
|
||||
),
|
||||
stages: [{
|
||||
levels: [{
|
||||
goal: 'Grab all the stars!',
|
||||
fen: '8/8/8/8/8/8/4Q3/8 w - - 0 1',
|
||||
apples: 'e5 b8',
|
||||
|
@ -37,6 +37,6 @@ module.exports = {
|
|||
fen: '8/8/8/8/8/8/8/4q3 b - - 0 1',
|
||||
apples: 'a6 d1 f2 f6 g6 g8 h1 h4',
|
||||
nbMoves: 9
|
||||
}].map(util.toStage),
|
||||
}].map(util.toLevel),
|
||||
complete: 'Congratulations! Queens have no secrets for you.'
|
||||
};
|
|
@ -11,7 +11,7 @@ module.exports = {
|
|||
illustration: m('div.is2d.no-square',
|
||||
m('piece.rook.white')
|
||||
),
|
||||
stages: [{
|
||||
levels: [{
|
||||
goal: 'Click on the rook<br>to bring it to the star!',
|
||||
fen: '8/8/8/8/8/8/4R3/8 w - - 0 1',
|
||||
apples: 'e7',
|
||||
|
@ -43,6 +43,6 @@ module.exports = {
|
|||
fen: '8/8/8/8/8/5R2/8/R7 w - - 0 1',
|
||||
apples: 'a8 b7 d5 f2 f7 g4 g7 h5 h8',
|
||||
nbMoves: 11
|
||||
}].map(util.toStage),
|
||||
}].map(util.toLevel),
|
||||
complete: 'Congratulations! You have successfully mastered the rook.'
|
||||
};
|
|
@ -1,9 +1,9 @@
|
|||
module.exports = {
|
||||
toLesson: function(l, it) {
|
||||
toStage: function(l, it) {
|
||||
l.id = it + 1;
|
||||
return l;
|
||||
},
|
||||
toStage: function(s, it) {
|
||||
toLevel: function(s, it) {
|
||||
s.id = it + 1;
|
||||
s.color = / w /.test(s.fen) ? 'white' : 'black';
|
||||
return s;
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
var m = require('mithril');
|
||||
|
||||
function setScore(levelKey, score) {
|
||||
function setScore(stageKey, score) {
|
||||
return m.request({
|
||||
method: 'POST',
|
||||
url: '/learn/level',
|
||||
url: '/learn/stage',
|
||||
data: {
|
||||
level: levelKey,
|
||||
stage: stageKey,
|
||||
score: score
|
||||
}
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue