diff --git a/rails_project/app/views/demo/index.html.erb b/rails_project/app/views/demo/index.html.erb index 686969b..ce70f35 100644 --- a/rails_project/app/views/demo/index.html.erb +++ b/rails_project/app/views/demo/index.html.erb @@ -2,7 +2,10 @@ -

I am RoofPig. Hear me oink!

+

RoofPig sample zoo.

@@ -23,10 +26,17 @@ + + + - -
-
+
Undrifted
+
+
Drifted
+
+
+
+
diff --git a/source/Alg.js.coffee b/source/Alg.js.coffee index ce94cc1..e945bbe 100644 --- a/source/Alg.js.coffee +++ b/source/Alg.js.coffee @@ -4,9 +4,6 @@ class @Alg constructor: (@move_codes, @world3d, @algdisplay, @speed, @dom) -> - if not @move_codes || @move_codes == "" - throw new Error("Invalid alg: '#{@move_codes}'") - @moves = [] for code in @move_codes.split(' ') if code.length > 0 @@ -96,15 +93,18 @@ class @Alg else new Move(code, @world3d, @speed) - side_drift: -> - result = {U:'U', D:'D', L:'L', R:'R', F:'F', B:'B'} + @side_drift: (moves) -> + new Alg(moves, null, "")._side_drift() + + _side_drift: -> + drift = {U: 'U', D: 'D', L: 'L', R: 'R', F: 'F', B: 'B'} @next = @moves.length until this.at_start() - this.prev_move().track_drift(result) - result + this.prev_move().track_drift(drift) + drift # How to think about this: The 'real' U side is now on drift.U _update_dom: (time = 'later') -> - if @dom + if @dom && @moves.length > 0 if time == 'first time' @dom.init_alg_text(this.display_text().future) diff --git a/source/Colors.js.coffee b/source/Colors.js.coffee index 8f5164d..195646e 100644 --- a/source/Colors.js.coffee +++ b/source/Colors.js.coffee @@ -4,11 +4,11 @@ class @Colors - constructor: (colored, solved, tweaks, colors = "") -> - @colored = new Cubexp(colored || "*") - @solved = new Cubexp(solved) - @tweaks = new Tweaks(tweaks) - @side_colors = Colors._set_colors(colors) + constructor: (side_drift, colored, solved, tweaks, colors = "") -> + @colored = new Cubexp(this._undrift(colored, side_drift) || "*") + @solved = new Cubexp(this._undrift(solved, side_drift)) + @tweaks = new Tweaks(this._undrift(tweaks, side_drift)) + @side_colors = Colors._set_colors(colors, side_drift) to_draw: (piece_name, side) -> result = { hovers: false, color: this.of(side) } @@ -38,13 +38,18 @@ class @Colors throw new Error("Unknown sticker type '#{sticker_type}'") @side_colors[type] - adjust_for: (drift) -> - sc = @side_colors - [sc.U, sc.D, sc.R, sc.L, sc.F, sc.B] = [sc[drift.U], sc[drift.D], sc[drift.R], sc[drift.L], sc[drift.F], - sc[drift.B]] + _undrift: (code, side_drift) -> + return code unless code + + reverse_drift = {} + for own key, value of side_drift + reverse_drift[value] = key + reverse_drift[value.toLowerCase()] = key.toLowerCase() + + (reverse_drift[char] || char for char in code.split('')).join('') DEFAULT_COLORS = {g:'#0d0', b:'#07f', r:'red', o:'orange', y:'yellow', w:'#eee'} - @_set_colors: (overrides) -> + @_set_colors: (overrides, side_drift) -> dc = DEFAULT_COLORS result = {R:dc.g, L:dc.b, F:dc.r, B:dc.o, U:dc.y, D:dc.w, solved:'#444', ignored:'#888', cube:'black'} @@ -52,4 +57,7 @@ class @Colors [type, color] = override.split(':') type = {s:'solved', i:'ignored', c:'cube'}[type] || type result[type] = DEFAULT_COLORS[color] || color + + [r, d] = [result, side_drift] + [r.U, r.D, r.R, r.L, r.F, r.B] = [r[d.U], r[d.D], r[d.R], r[d.L], r[d.F], r[d.B]] result diff --git a/source/Config.js.coffee b/source/Config.js.coffee index 514c12d..263ea06 100644 --- a/source/Config.js.coffee +++ b/source/Config.js.coffee @@ -1,3 +1,4 @@ +#= require roofpig/Alg #= require roofpig/Colors class @Config @@ -7,9 +8,9 @@ class @Config @alg = this.raw(ALG) @algdisplay= this._alg_display() - @colors = new Colors(this.raw(COLORED), this.raw(SOLVED), this.raw(TWEAKS), this.raw(COLORS)) + @colors = new Colors(Alg.side_drift(@alg), this.raw(COLORED), this.raw(SOLVED), this.raw(TWEAKS), this.raw(COLORS)) @flags = this.raw(FLAGS) - @hover = this._hover() + @hover = this._hover() @pov = this.raw(POV, "Ufr") @setup = this.raw(SETUPMOVES) @speed = this.raw(SPEED, 400) diff --git a/source/CubeAnimation.js.coffee b/source/CubeAnimation.js.coffee index 9696fd7..2382f81 100644 --- a/source/CubeAnimation.js.coffee +++ b/source/CubeAnimation.js.coffee @@ -37,18 +37,12 @@ class @CubeAnimation CubeAnimation.webgl_cubes += 1 @renderer = new THREE.WebGLRenderer(antialias: true, alpha: true) - @dom = new Dom(@id, roofpig_div, @renderer) - + @dom = new Dom(@id, roofpig_div, @renderer, @config.alg != "", @config.flag('showalg')) @scene = new THREE.Scene() - @world3d = { camera: new Camera(@config.hover, @config.pov) } - if @config.alg == "" - @alg = { mix: -> } - else - @dom.add_alg_area(@config.flag('showalg')) - @alg = new Alg(@config.alg, @world3d, @config.algdisplay, @config.speed, @dom) - @config.colors.adjust_for(@alg.side_drift()) + @world3d = { camera: new Camera(@config.hover, @config.pov), pieces: new Pieces3D(@scene, @config.hover, + @config.colors, use_canvas) } + @alg = new Alg(@config.alg, @world3d, @config.algdisplay, @config.speed, @dom) - @world3d.pieces = new Pieces3D(@scene, @config.hover, @config.colors, use_canvas) if (@config.setup) then new Alg(@config.setup, @world3d).to_end() @alg.mix() diff --git a/source/Dom.js.coffee b/source/Dom.js.coffee index 9fbdf99..23722a3 100644 --- a/source/Dom.js.coffee +++ b/source/Dom.js.coffee @@ -1,6 +1,6 @@ class @Dom - constructor: (@cube_id, @div, renderer) -> + constructor: (@cube_id, @div, renderer, make_alg_area, showalg) -> @div.css(position:'relative', 'font-family':'"Lucida Sans Unicode", "Lucida Grande", sans-serif') this.has_focus(false) @div.data('cube_id', @cube_id) @@ -11,6 +11,9 @@ class @Dom @scale = @div.width()/400 @hscale = Math.max(@scale, 15.0/40) # Minimum height -> readable text + if make_alg_area + this.add_alg_area(showalg) + has_focus: (has_it) -> color = if has_it then 'gray' else '#eee' cursor = if has_it then 'pointer' else 'default' diff --git a/tests/Alg_spec.js.coffee b/tests/Alg_spec.js.coffee index 8bee2c6..7f5b325 100644 --- a/tests/Alg_spec.js.coffee +++ b/tests/Alg_spec.js.coffee @@ -9,8 +9,9 @@ describe "Alg", -> expect(new Alg(" U F2 D' LZ ").to_s()).to.equal("U F2 D' LZ") expect(new Alg("F D+U'").to_s()).to.equal("F (D U')") - it "fails empty alg", -> - expect(-> new Alg("")).to.throw("Invalid alg: ''") + it "handles empty alg", -> + expect(new Alg("").at_start()).to.be.true + expect(new Alg("").at_end()).to.be.true it "keeps track of moves", -> alg = new Alg('F D') @@ -124,13 +125,16 @@ describe "Alg", -> alg = new Alg("F R> U2+D' F<< LZ D+D>", world, new Config("algdisplay=rotations").algdisplay) expect(alg.display_text().future).to.equal("F R> U2+D' F<< L2 D+D>") - it "#side_drift", -> + it "#_side_drift", -> world = null - expect(new Alg("F", world, "").side_drift()).to.deep.equal(U:'U', D:'D', L:'L', R:'R', F:'F', B:'B') - expect(new Alg("M", world, "").side_drift()).to.deep.equal(U:'B', D:'F', L:'L', R:'R', F:'U', B:'D') - expect(new Alg("M z",world,"").side_drift()).to.deep.equal(U:'L', D:'R', L:'F', R:'B', F:'U', B:'D') - expect(new Alg("MZ", world,"").side_drift()).to.deep.equal(U:'D', D:'U', L:'L', R:'R', F:'B', B:'F') - + expect(new Alg("F", world, "")._side_drift()).to.deep.equal(U: 'U', D: 'D', L: 'L', R: 'R', F: 'F', B: 'B') + expect(new Alg("M", world, "")._side_drift()).to.deep.equal(U: 'B', D: 'F', L: 'L', R: 'R', F: 'U', B: 'D') + expect(new Alg("M z", world, "")._side_drift()).to.deep.equal(U: 'L', D: 'R', L: 'F', R: 'B', F: 'U', B: 'D') + expect(new Alg("MZ", world, "")._side_drift()).to.deep.equal(U: 'D', D: 'U', L: 'L', R: 'R', F: 'B', B: 'F') + + it "@side_drift", -> + expect(Alg.side_drift("F")).to.deep.equal(U: 'U', D: 'D', L: 'L', R: 'R', F: 'F', B: 'B') + expect(Alg.side_drift("M")).to.deep.equal(U: 'B', D: 'F', L: 'L', R: 'R', F: 'U', B: 'D') move_should_be = (move, layer, turns, is_rotation = false) -> expect(move.layer, move.to_s()).to.equal(layer) diff --git a/tests/Colors_spec.js.coffee b/tests/Colors_spec.js.coffee index df48ccd..2504fa2 100644 --- a/tests/Colors_spec.js.coffee +++ b/tests/Colors_spec.js.coffee @@ -2,10 +2,12 @@ #= require roofpig/Colors #= require ../../app/assets/javascripts/roofpig/Layer.js.coffee +nodrift = {U: 'U', D: 'D', L: 'L', R: 'R', F: 'F', B: 'B'} + describe "Colors", -> describe "of", -> it "has default values", -> - colors = new Colors("", "", "") + colors = new Colors(nodrift, "", "", "") expect(colors.of(Layer.R)).to.equal('#0d0') expect(colors.of(Layer.L)).to.equal('#07f') expect(colors.of(Layer.F)).to.equal('red') @@ -21,7 +23,7 @@ describe "Colors", -> expect(-> colors.of('UNKNOWN')).to.throw(Error) it "can change colors", -> - colors = new Colors("", "", "", "R:o L:#abc solved:r c:#123") + colors = new Colors(nodrift, "", "", "", "R:o L:#abc solved:r c:#123") expect(colors.of(Layer.R)).to.equal('orange') expect(colors.of(Layer.L)).to.equal('#abc') @@ -33,26 +35,26 @@ describe "Colors", -> describe "#to_draw", -> it "is colored by default", -> - colors = new Colors("", "") + colors = new Colors(nodrift, "", "") expect(colors.to_draw('UFR','F')).to.deep.equal(color: colors.of('F'), hovers: true) expect(colors.to_draw('DB', 'B')).to.deep.equal(color: colors.of('B'), hovers: true) expect(colors.to_draw('L', 'L')).to.deep.equal(color: colors.of('L'), hovers: true) it "colors only specified stickers", -> - colors = new Colors("U*", "") + colors = new Colors(nodrift, "U*", "") expect(colors.to_draw('UFR','F')).to.deep.equal(color: colors.of('F'), hovers: true) expect(colors.to_draw('DB', 'B')).to.deep.equal(color: colors.of('ignored'), hovers: false) expect(colors.to_draw('L', 'L')).to.deep.equal(color: colors.of('ignored'), hovers: false) it "solved overrides colored", -> - colors = new Colors("U*", "F*") + colors = new Colors(nodrift, "U*", "F*") expect(colors.to_draw('UFR','F')).to.deep.equal(color: colors.of('solved'), hovers: false) expect(colors.to_draw('UR', 'U')).to.deep.equal(color: colors.of('U'), hovers: true) expect(colors.to_draw('F', 'F')).to.deep.equal(color: colors.of('solved'), hovers: false) expect(colors.to_draw('L', 'L')).to.deep.equal(color: colors.of('ignored'), hovers: false) it "last tweak color wins", -> - colors = new Colors("*", "", "R:U* L:F*") + colors = new Colors(nodrift, "*", "", "R:U* L:F*") expect(colors.to_draw('D', 'D')).to.deep.equal(color: colors.of('D'), hovers: true) #untweaked expect(colors.to_draw('U', 'U')).to.deep.equal(color: colors.of('R'), hovers: true) #tweaked expect(colors.to_draw('F', 'F')).to.deep.equal(color: colors.of('L'), hovers: true) #tweaked @@ -60,22 +62,52 @@ describe "Colors", -> describe "tweaks", -> it "sets X and colors", -> - colors = new Colors("", "*", ".Xx:uFR D.L:UfR") + colors = new Colors(nodrift, "", "*", ".Xx:uFR D.L:UfR") expect(colors.to_draw('UFR', 'U')).to.deep.equal(color: colors.of('D'), hovers: true) expect(colors.to_draw('UFR', 'F')).to.deep.equal(color: colors.of('solved'), hovers: true, x_color: 'black') expect(colors.to_draw('UFR', 'R')).to.deep.equal(color: colors.of('L'), hovers: true, x_color: 'white') it "overrides colored and solved", -> - colors = new Colors("U*", "D*", "L:U R:D") + colors = new Colors(nodrift, "U*", "D*", "L:U R:D") expect(colors.to_draw('U', Layer.U).color).to.equal(colors.of(Layer.L)) expect(colors.to_draw('D', Layer.D).color).to.equal(colors.of(Layer.R)) - it "#adjust_for", -> - colors = new Colors("", "", "") - [oldR, oldL, oldF, oldB, oldU, oldD] = [colors.of('R'), colors.of('L'), colors.of('F'), colors.of('B'), - colors.of('U'), colors.of('D')] - colors.adjust_for({U: 'D', D: 'U', R: 'L', L: 'R', F: 'F', B: 'B'}) - expect(colors.of('F'), 1).to.equal(oldF) - expect(colors.of('R'), 22).to.equal(oldL) \ No newline at end of file + describe "side drift adjustments", -> + z_drift = {U: 'L', D: 'R', R: 'U', L: 'D', F: 'F', B: 'B'} + + it "side colors", -> + plain_colors = new Colors(nodrift, "", "", "") + drift_colors = new Colors(z_drift, "", "", "") + expect(drift_colors.of('F')).to.equal(plain_colors.of('F')) + expect(drift_colors.of('R')).to.equal(plain_colors.of('U')) + + it "colored", -> + colors = new Colors(z_drift, "u", "", "") + expect(colors.to_draw('U', 'U')).to.deep.equal(color: colors.of('ignored'), hovers: false) + expect(colors.to_draw('R', 'R')).to.deep.equal(color: colors.of('R'), hovers: true) + + it "solved", -> + colors = new Colors(z_drift, "Ufr", "r", "") + expect(colors.to_draw('R', 'R')).to.deep.equal(color: colors.of('ignored'), hovers: false) + expect(colors.to_draw('D', 'D')).to.deep.equal(color: colors.of('solved'), hovers: false) + + it "tweaks", -> + untweaked = new Colors(z_drift, "", "", "") + expect(untweaked.to_draw('RF', 'R'), 1).to.deep.equal(color: untweaked.of('R'), hovers: true) + expect(untweaked.to_draw('LU', 'L'), 22).to.deep.equal(color: untweaked.of('L'), hovers: true) + + tweaked = new Colors(z_drift, "", "", "X:Uf RF:DL") + expect(tweaked.to_draw('RF', 'R')).to.deep.equal(color: tweaked.of('R'), hovers: true, x_color: 'black') + expect(tweaked.to_draw('LU', 'L')).to.deep.equal(color: tweaked.of('D'), hovers: true) + + describe "#_undrift", -> + drift = {U: 'D', D: 'U', R: 'L', L: 'R', F: 'F', B: 'B'} + colors = new Colors(nodrift, "", "") + + it "handles upper case", -> + expect(colors._undrift("XYZ:URF", drift)).to.equal("XYZ:DLF") + + it "handles lower case", -> + expect(colors._undrift("XYZ:Urf", drift)).to.equal("XYZ:Dlf")