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")