twists.js 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. /*
  2. TWISTS
  3. Why have twist validation code in multiple places when we can create a
  4. Twist class here for all?
  5. */
  6. export function Twist( command, degrees ){
  7. // What group of Cubelets do we intend to twist?
  8. var group = {
  9. X: 'Cube on X',
  10. L: 'Left face',
  11. M: 'Middle slice',
  12. R: 'Right face',
  13. Y: 'Cube on Y',
  14. U: 'Up face',
  15. E: 'Equator slice',
  16. D: 'Down face',
  17. Z: 'Cube on Z',
  18. F: 'Front face',
  19. S: 'Standing slice',
  20. B: 'Back face'
  21. }[ command.toUpperCase() ]
  22. // If we've received a valid twist group to operate on
  23. // then we can proceed. Otherwise return false!
  24. if( group !== undefined ){
  25. // If our degrees of rotation are negative
  26. // then we need to invert the twist direction
  27. // (ie. change clockwise to anticlockwise)
  28. // and take the absolute value of the degrees.
  29. // Remember, it's ok to have degrees === undefined
  30. // which will peg to the nearest degrees % 90 === 0.
  31. if( degrees != undefined && degrees < 0 ){
  32. command = command.invert()
  33. degrees = degrees.absolute()
  34. }
  35. // Now let's note the absolute direction of the rotation
  36. // as both a number and in English.
  37. var
  38. vector = 0,
  39. wise = 'unwise'
  40. if( command === command.toUpperCase() ){
  41. vector = 1
  42. wise = 'clockwise'
  43. }
  44. else if( command === command.toLowerCase() ){
  45. vector = -1
  46. wise = 'anticlockwise'
  47. }
  48. // Finally we're ready to package up all the relevant information
  49. // about this particular twist.
  50. // The constructor will return it of course.
  51. this.command = command // Twist command
  52. this.group = group // Description in English
  53. this.degrees = degrees // Relative degrees (undefined is ok!)
  54. this.vector = vector // Absolute degree polarity
  55. this.wise = wise // Absolute clock direction in English
  56. this.created = Date.now()
  57. // Best to leave this as a function rather than a property.
  58. // I mean... imagine call this constructor if it tried to call itself!
  59. // Infinite loopage mess.
  60. this.getInverse = function(){
  61. return new Twist( command.invert(), degrees )
  62. }
  63. }
  64. else return false
  65. }
  66. Twist.validate = function(){
  67. var
  68. elements = Array.prototype.slice.call( arguments ),
  69. element, i,
  70. pattern, matches, match, m, head, foot
  71. for( i = 0; i < elements.length; i ++ ){
  72. var lookAhead = undefined;
  73. element = elements[ i ]
  74. if( i + 1 < elements.length ) lookAhead = elements[ i + 1 ]
  75. else lookAhead = undefined
  76. if( element instanceof Twist ){
  77. // Example usage:
  78. // cube.twistQueue.add( new Twist( 'U' ))
  79. // cube.twistQueue.add( new Twist( 'U', -17 ))
  80. // AWESOME. Nothing to do here.
  81. }
  82. else if( typeof element === 'string' ){
  83. if( element.length === 1 ){
  84. // Example usage:
  85. // cube.twistQueue.add( 'U' )
  86. // cube.twistQueue.add( 'U', 45 )
  87. if( typeof lookAhead === 'number' ){
  88. elements[ i ] = new Twist( element, lookAhead )
  89. }
  90. else elements[ i ] = new Twist( element )
  91. }
  92. else if( element.length > 1 ){
  93. // Example usage:
  94. // cube.twistQueue.add( 'UdrLf' )
  95. // cube.twistQueue.add( 'Udr10Lf-30b' )
  96. pattern = /(-?\d+|[XLMRYUEDZFSB])/gi
  97. matches = element.match( pattern )
  98. for( m = 0; m < matches.length; m ++ ){
  99. match = matches[ m ]
  100. if( isNumeric( match )) matches[ m ] = +match
  101. else {
  102. head = matches.slice( 0, m )
  103. foot = matches.slice( m + 1 )
  104. match = match.split( '' )
  105. matches = head.concat( match, foot )
  106. }
  107. }
  108. head = elements.slice( 0, i )
  109. foot = elements.slice( i + 1 )
  110. elements = head.concat( matches, foot )
  111. i --// Send it through the loop again to avoid duplicating logic.
  112. }
  113. }
  114. else if( element instanceof Direction ){
  115. // Example usage:
  116. // cube.twistQueue.add( FRONT )
  117. elements[ i ] = element.initial
  118. i --// Send it through the loop again to avoid duplicating logic.
  119. }
  120. else if( element instanceof Array ){
  121. // Example usage:
  122. // cube.twistQueue.add([ ? ])
  123. head = elements.slice( 0, i )
  124. foot = elements.slice( i + 1 )
  125. elements = head.concat( element, foot )
  126. i --// Send it through the loop again to avoid duplicating logic.
  127. }
  128. else {
  129. // Whatever this element is, we don't recognize it.
  130. // (Could be a Number that we're discarding on purpose.)
  131. elements.splice( i, 1 )
  132. i --// Send it through the loop again to avoid duplicating logic.
  133. }
  134. }
  135. return elements
  136. }