cubing 0.21.1 → 0.22.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (528) hide show
  1. package/README.md +4 -7
  2. package/{src/cubing/kpuzzle → dist}/.DS_Store +0 -0
  3. package/dist/bin/order.js +16675 -0
  4. package/dist/bin/order.js.map +7 -0
  5. package/dist/bin/puzzle-geometry-bin.js +13 -9
  6. package/dist/bin/puzzle-geometry-bin.js.map +2 -2
  7. package/dist/bundle-global/cubing.bundle-global.js +555 -298
  8. package/dist/esm/3d-M7GBIT3X.js +21 -0
  9. package/dist/esm/3d-M7GBIT3X.js.map +7 -0
  10. package/dist/esm/alg/index.js +1 -1
  11. package/dist/esm/bluetooth/index.js +10 -8
  12. package/dist/esm/bluetooth/index.js.map +3 -3
  13. package/dist/esm/{chunk-RE7MIN5R.js → chunk-4IUYLRHT.js} +2 -2
  14. package/dist/esm/{chunk-RE7MIN5R.js.map → chunk-4IUYLRHT.js.map} +0 -0
  15. package/dist/esm/{chunk-CSVAFZSB.js → chunk-6BZSKSG7.js} +724 -735
  16. package/dist/esm/chunk-6BZSKSG7.js.map +7 -0
  17. package/dist/esm/{chunk-BU5PUJK3.js → chunk-EWRBHQFX.js} +1 -1
  18. package/dist/esm/{chunk-BU5PUJK3.js.map → chunk-EWRBHQFX.js.map} +1 -1
  19. package/dist/esm/{chunk-APIIMJG6.js → chunk-GF76PWEV.js} +450 -1052
  20. package/dist/esm/chunk-GF76PWEV.js.map +7 -0
  21. package/dist/esm/{chunk-MUQMBH2S.js → chunk-R3HRHYIW.js} +16 -4
  22. package/dist/esm/chunk-R3HRHYIW.js.map +7 -0
  23. package/dist/esm/{chunk-YV3RT5PX.js → chunk-X6JHXPDX.js} +2 -2
  24. package/dist/esm/{chunk-YV3RT5PX.js.map → chunk-X6JHXPDX.js.map} +0 -0
  25. package/dist/esm/esm-test-worker.js +2 -2
  26. package/dist/esm/esm-test-worker.js.map +2 -2
  27. package/dist/esm/kpuzzle/index.js +2 -2
  28. package/dist/esm/{node-WEHVBEKP.js → node-HFBX5WHK.js} +2 -2
  29. package/dist/esm/{node-WEHVBEKP.js.map → node-HFBX5WHK.js.map} +1 -1
  30. package/dist/esm/{node-BSAQKO3G.js → node-SP4L2AKI.js} +2 -2
  31. package/dist/esm/{node-BSAQKO3G.js.map → node-SP4L2AKI.js.map} +1 -1
  32. package/dist/esm/notation/index.js +2 -2
  33. package/dist/esm/protocol/index.js +2 -2
  34. package/dist/esm/puzzle-geometry/index.js +14 -10
  35. package/dist/esm/puzzle-geometry/index.js.map +2 -2
  36. package/dist/esm/puzzles/index.js +3 -3
  37. package/dist/esm/scramble/index.js +4 -4
  38. package/dist/esm/search/index.js +4 -4
  39. package/dist/esm/stream/index.js +1 -1
  40. package/dist/esm/twisty/index.js +729 -2346
  41. package/dist/esm/twisty/index.js.map +3 -3
  42. package/dist/esm/worker-inside-generated-string-RQYYANYQ.js +3107 -0
  43. package/dist/esm/worker-inside-generated-string-RQYYANYQ.js.map +7 -0
  44. package/dist/types/alg/index.d.ts +1 -0
  45. package/dist/types/alg/index.d.ts.map +1 -1
  46. package/dist/types/alg/units/leaves/Move.d.ts +1 -1
  47. package/dist/types/alg/units/leaves/Move.d.ts.map +1 -1
  48. package/dist/types/bluetooth/smart-puzzle/gan.d.ts.map +1 -1
  49. package/dist/types/cubing.bundle-global.d.ts +1 -24
  50. package/dist/types/cubing.bundle-global.d.ts.map +1 -1
  51. package/dist/types/cubing.bundle-global.exports.d.ts +25 -0
  52. package/dist/types/cubing.bundle-global.exports.d.ts.map +1 -0
  53. package/dist/types/puzzle-geometry/PGPuzzles.spec.d.ts +3 -0
  54. package/dist/types/puzzle-geometry/PGPuzzles.spec.d.ts.map +1 -1
  55. package/dist/types/puzzle-geometry/PuzzleGeometry.d.ts +7 -3
  56. package/dist/types/puzzle-geometry/PuzzleGeometry.d.ts.map +1 -1
  57. package/dist/types/puzzle-geometry/index.d.ts +1 -1
  58. package/dist/types/puzzle-geometry/index.d.ts.map +1 -1
  59. package/dist/types/puzzles/index.d.ts +1 -1
  60. package/dist/types/puzzles/index.d.ts.map +1 -1
  61. package/dist/types/puzzles/stickerings/cube-stickerings.d.ts.map +1 -1
  62. package/dist/types/search/inside/api.d.ts.map +1 -1
  63. package/dist/types/search/inside/solve/puzzles/4x4x4.d.ts +1 -1
  64. package/dist/types/search/inside/solve/puzzles/4x4x4.d.ts.map +1 -1
  65. package/dist/types/search/inside/solve/puzzles/fto.d.ts +6 -0
  66. package/dist/types/search/inside/solve/puzzles/fto.d.ts.map +1 -0
  67. package/dist/types/search/inside/solve/puzzles/fto.sgs.json.d.ts +5 -0
  68. package/dist/types/search/inside/solve/puzzles/fto.sgs.json.d.ts.map +1 -0
  69. package/dist/types/search/inside/solve/tremble.d.ts.map +1 -1
  70. package/dist/types/search/worker-inside-generated-string.d.ts +1 -1
  71. package/dist/types/search/worker-inside-generated-string.d.ts.map +1 -1
  72. package/dist/types/twisty/{old/animation/cursor/CursorTypes.d.ts → controllers/AnimationTypes.d.ts} +10 -3
  73. package/dist/types/twisty/controllers/AnimationTypes.d.ts.map +1 -0
  74. package/dist/types/twisty/{old/animation → controllers}/RenderScheduler.d.ts +0 -0
  75. package/dist/types/twisty/controllers/RenderScheduler.d.ts.map +1 -0
  76. package/dist/types/twisty/controllers/TwistyAnimationController.d.ts +1 -1
  77. package/dist/types/twisty/controllers/TwistyAnimationController.d.ts.map +1 -1
  78. package/dist/types/twisty/{old/animation → controllers}/easing.d.ts +0 -0
  79. package/dist/types/twisty/controllers/easing.d.ts.map +1 -0
  80. package/dist/types/twisty/{old/animation → controllers}/indexer/AlgDuration.d.ts +2 -2
  81. package/dist/types/twisty/controllers/indexer/AlgDuration.d.ts.map +1 -0
  82. package/dist/types/twisty/{old/animation → controllers}/indexer/AlgIndexer.d.ts +3 -3
  83. package/dist/types/twisty/controllers/indexer/AlgIndexer.d.ts.map +1 -0
  84. package/dist/types/twisty/{old/animation → controllers}/indexer/SimpleAlgIndexer.d.ts +3 -3
  85. package/dist/types/twisty/controllers/indexer/SimpleAlgIndexer.d.ts.map +1 -0
  86. package/dist/types/twisty/{old/animation → controllers}/indexer/simultaneous-moves/SimultaneousMoveIndexer.d.ts +3 -3
  87. package/dist/types/twisty/controllers/indexer/simultaneous-moves/SimultaneousMoveIndexer.d.ts.map +1 -0
  88. package/dist/types/twisty/{old/animation → controllers}/indexer/simultaneous-moves/SimultaneousMoveIndexerV2.d.ts +3 -3
  89. package/dist/types/twisty/controllers/indexer/simultaneous-moves/SimultaneousMoveIndexerV2.d.ts.map +1 -0
  90. package/dist/types/twisty/{old/animation → controllers}/indexer/simultaneous-moves/simul-moves.d.ts +2 -2
  91. package/dist/types/twisty/controllers/indexer/simultaneous-moves/simul-moves.d.ts.map +1 -0
  92. package/dist/types/twisty/{old/animation → controllers}/indexer/tree/AlgWalker.d.ts +2 -2
  93. package/dist/types/twisty/controllers/indexer/tree/AlgWalker.d.ts.map +1 -0
  94. package/dist/types/twisty/{old/animation → controllers}/indexer/tree/TreeAlgIndexer.d.ts +3 -3
  95. package/dist/types/twisty/controllers/indexer/tree/TreeAlgIndexer.d.ts.map +1 -0
  96. package/dist/types/twisty/controllers/indexer/tree/chunkAlgs.d.ts +3 -0
  97. package/dist/types/twisty/controllers/indexer/tree/chunkAlgs.d.ts.map +1 -0
  98. package/dist/types/twisty/{old/animation → controllers}/stream/timeline-move-calculation-draft.d.ts +2 -2
  99. package/dist/types/twisty/controllers/stream/timeline-move-calculation-draft.d.ts.map +1 -0
  100. package/dist/types/twisty/heavy-code-imports/dynamic-entries/3d.d.ts +1 -2
  101. package/dist/types/twisty/heavy-code-imports/dynamic-entries/3d.d.ts.map +1 -1
  102. package/dist/types/twisty/index.d.ts +9 -12
  103. package/dist/types/twisty/index.d.ts.map +1 -1
  104. package/dist/types/twisty/model/TwistyPlayerModel.d.ts +11 -0
  105. package/dist/types/twisty/model/TwistyPlayerModel.d.ts.map +1 -1
  106. package/dist/types/twisty/model/props/TwistyPropDebugger.d.ts +1 -1
  107. package/dist/types/twisty/model/props/TwistyPropDebugger.d.ts.map +1 -1
  108. package/dist/types/twisty/model/props/puzzle/display/FoundationDisplayProp.d.ts +6 -0
  109. package/dist/types/twisty/model/props/puzzle/display/FoundationDisplayProp.d.ts.map +1 -0
  110. package/dist/types/twisty/model/props/puzzle/display/HintFaceletProp.d.ts +5 -1
  111. package/dist/types/twisty/model/props/puzzle/display/HintFaceletProp.d.ts.map +1 -1
  112. package/dist/types/twisty/model/props/puzzle/display/StickeringProp.d.ts +46 -1
  113. package/dist/types/twisty/model/props/puzzle/display/StickeringProp.d.ts.map +1 -1
  114. package/dist/types/twisty/model/props/puzzle/state/AnchoredStartProp.d.ts +2 -2
  115. package/dist/types/twisty/model/props/puzzle/state/AnchoredStartProp.d.ts.map +1 -1
  116. package/dist/types/twisty/model/props/puzzle/state/CurrentLeavesProp.d.ts +1 -1
  117. package/dist/types/twisty/model/props/puzzle/state/CurrentLeavesProp.d.ts.map +1 -1
  118. package/dist/types/twisty/model/props/puzzle/state/CurrentLeavesSimplified.d.ts +1 -1
  119. package/dist/types/twisty/model/props/puzzle/state/CurrentLeavesSimplified.d.ts.map +1 -1
  120. package/dist/types/twisty/model/props/puzzle/state/CurrentTransformationProp.d.ts +1 -1
  121. package/dist/types/twisty/model/props/puzzle/state/CurrentTransformationProp.d.ts.map +1 -1
  122. package/dist/types/twisty/model/props/puzzle/state/IndexerConstructorProp.d.ts +5 -2
  123. package/dist/types/twisty/model/props/puzzle/state/IndexerConstructorProp.d.ts.map +1 -1
  124. package/dist/types/twisty/model/props/puzzle/state/IndexerProp.d.ts +2 -2
  125. package/dist/types/twisty/model/props/puzzle/state/IndexerProp.d.ts.map +1 -1
  126. package/dist/types/twisty/model/props/puzzle/state/LegacyPositionProp.d.ts +2 -2
  127. package/dist/types/twisty/model/props/puzzle/state/LegacyPositionProp.d.ts.map +1 -1
  128. package/dist/types/twisty/model/props/puzzle/state/MovePressInputProp.d.ts +11 -0
  129. package/dist/types/twisty/model/props/puzzle/state/MovePressInputProp.d.ts.map +1 -0
  130. package/dist/types/twisty/model/props/puzzle/state/NaiveMoveCountProp.d.ts +10 -0
  131. package/dist/types/twisty/model/props/puzzle/state/NaiveMoveCountProp.d.ts.map +1 -0
  132. package/dist/types/twisty/model/props/puzzle/state/SetupAnchorProp.d.ts +5 -1
  133. package/dist/types/twisty/model/props/puzzle/state/SetupAnchorProp.d.ts.map +1 -1
  134. package/dist/types/twisty/model/props/puzzle/structure/PuzzleIDProp.d.ts +1 -1
  135. package/dist/types/twisty/model/props/puzzle/structure/PuzzleIDProp.d.ts.map +1 -1
  136. package/dist/types/twisty/model/props/puzzle/structure/PuzzleIDRequestProp.d.ts +19 -1
  137. package/dist/types/twisty/model/props/puzzle/structure/PuzzleIDRequestProp.d.ts.map +1 -1
  138. package/dist/types/twisty/model/props/puzzle/structure/PuzzleLoaderProp.d.ts +1 -1
  139. package/dist/types/twisty/model/props/puzzle/structure/PuzzleLoaderProp.d.ts.map +1 -1
  140. package/dist/types/twisty/model/props/timeline/DetailedTimelineInfoProp.d.ts +2 -3
  141. package/dist/types/twisty/model/props/timeline/DetailedTimelineInfoProp.d.ts.map +1 -1
  142. package/dist/types/twisty/model/props/timeline/PlayingInfoProp.d.ts +1 -1
  143. package/dist/types/twisty/model/props/timeline/PlayingInfoProp.d.ts.map +1 -1
  144. package/dist/types/twisty/model/props/timeline/TimestampRequestProp.d.ts +1 -1
  145. package/dist/types/twisty/model/props/timeline/TimestampRequestProp.d.ts.map +1 -1
  146. package/dist/types/twisty/model/props/viewer/BackViewProp.d.ts +6 -1
  147. package/dist/types/twisty/model/props/viewer/BackViewProp.d.ts.map +1 -1
  148. package/dist/types/twisty/model/props/viewer/BackgroundProp.d.ts +5 -1
  149. package/dist/types/twisty/model/props/viewer/BackgroundProp.d.ts.map +1 -1
  150. package/dist/types/twisty/model/props/viewer/ControlPanelProp.d.ts +5 -1
  151. package/dist/types/twisty/model/props/viewer/ControlPanelProp.d.ts.map +1 -1
  152. package/dist/types/twisty/model/props/viewer/OrbitCoordinatesProp.d.ts +18 -5
  153. package/dist/types/twisty/model/props/viewer/OrbitCoordinatesProp.d.ts.map +1 -1
  154. package/dist/types/twisty/model/props/viewer/OrbitCoordinatesRequestProp.d.ts +6 -6
  155. package/dist/types/twisty/model/props/viewer/OrbitCoordinatesRequestProp.d.ts.map +1 -1
  156. package/dist/types/twisty/model/props/viewer/TimeRangeProp.d.ts +2 -2
  157. package/dist/types/twisty/model/props/viewer/TimeRangeProp.d.ts.map +1 -1
  158. package/dist/types/twisty/model/props/viewer/ViewerLinkProp.d.ts +5 -1
  159. package/dist/types/twisty/model/props/viewer/ViewerLinkProp.d.ts.map +1 -1
  160. package/dist/types/twisty/model/props/viewer/VisualizationProp.d.ts +7 -1
  161. package/dist/types/twisty/model/props/viewer/VisualizationProp.d.ts.map +1 -1
  162. package/dist/types/twisty/model/props/viewer/VisualizationStrategyProp.d.ts +1 -1
  163. package/dist/types/twisty/model/props/viewer/VisualizationStrategyProp.d.ts.map +1 -1
  164. package/dist/types/twisty/views/2D/Twisty2DPuzzle.css.d.ts +3 -0
  165. package/dist/types/twisty/views/2D/Twisty2DPuzzle.css.d.ts.map +1 -0
  166. package/dist/types/twisty/views/2D/Twisty2DPuzzle.d.ts +4 -6
  167. package/dist/types/twisty/views/2D/Twisty2DPuzzle.d.ts.map +1 -1
  168. package/dist/types/twisty/views/2D/Twisty2DPuzzleWrapper.d.ts +1 -1
  169. package/dist/types/twisty/views/2D/Twisty2DPuzzleWrapper.d.ts.map +1 -1
  170. package/dist/types/twisty/views/2D/Twisty2DSceneWrapper.d.ts +2 -2
  171. package/dist/types/twisty/views/2D/Twisty2DSceneWrapper.d.ts.map +1 -1
  172. package/dist/types/twisty/views/3D/DragTracker.d.ts +28 -0
  173. package/dist/types/twisty/views/3D/DragTracker.d.ts.map +1 -0
  174. package/dist/types/twisty/views/3D/RendererPool.d.ts.map +1 -1
  175. package/dist/types/twisty/views/3D/Twisty3DPuzzleWrapper.d.ts +6 -1
  176. package/dist/types/twisty/views/3D/Twisty3DPuzzleWrapper.d.ts.map +1 -1
  177. package/dist/types/twisty/views/3D/Twisty3DSceneWrapper.d.ts +9 -4
  178. package/dist/types/twisty/views/3D/Twisty3DSceneWrapper.d.ts.map +1 -1
  179. package/dist/types/twisty/views/3D/Twisty3DVantage.css.d.ts +3 -0
  180. package/dist/types/twisty/views/3D/Twisty3DVantage.css.d.ts.map +1 -0
  181. package/dist/types/twisty/views/3D/Twisty3DVantage.d.ts +12 -8
  182. package/dist/types/twisty/views/3D/Twisty3DVantage.d.ts.map +1 -1
  183. package/dist/types/twisty/views/3D/TwistyOrbitControls.d.ts +24 -0
  184. package/dist/types/twisty/views/3D/TwistyOrbitControls.d.ts.map +1 -0
  185. package/dist/types/twisty/views/3D/TwistyOrbitControls.spec.d.ts +5 -0
  186. package/dist/types/twisty/views/3D/TwistyOrbitControls.spec.d.ts.map +1 -0
  187. package/dist/types/twisty/views/3D/puzzles/Cube3D.d.ts +4 -4
  188. package/dist/types/twisty/views/3D/puzzles/Cube3D.d.ts.map +1 -1
  189. package/dist/types/twisty/views/3D/puzzles/PG3D.d.ts +17 -10
  190. package/dist/types/twisty/views/3D/puzzles/PG3D.d.ts.map +1 -1
  191. package/dist/types/twisty/views/3D/puzzles/Twisty3DPuzzle.d.ts +1 -1
  192. package/dist/types/twisty/views/3D/puzzles/Twisty3DPuzzle.d.ts.map +1 -1
  193. package/dist/types/twisty/{old/dom/element → views}/ClassListManager.d.ts +0 -0
  194. package/dist/types/twisty/views/ClassListManager.d.ts.map +1 -0
  195. package/dist/types/twisty/{old/dom/element → views}/ManagedCustomElement.d.ts +0 -0
  196. package/dist/types/twisty/views/ManagedCustomElement.d.ts.map +1 -0
  197. package/dist/types/twisty/views/TwistyAlgEditor/LeafTokens.d.ts +1 -1
  198. package/dist/types/twisty/views/TwistyAlgEditor/LeafTokens.d.ts.map +1 -1
  199. package/dist/types/twisty/views/TwistyAlgEditor/TwistyAlgEditor.css.d.ts +1 -1
  200. package/dist/types/twisty/views/TwistyAlgEditor/TwistyAlgEditor.css.d.ts.map +1 -1
  201. package/dist/types/twisty/views/TwistyAlgEditor/TwistyAlgEditor.d.ts +2 -1
  202. package/dist/types/twisty/views/TwistyAlgEditor/TwistyAlgEditor.d.ts.map +1 -1
  203. package/dist/types/twisty/views/TwistyAlgViewer.css.d.ts +1 -1
  204. package/dist/types/twisty/views/TwistyAlgViewer.css.d.ts.map +1 -1
  205. package/dist/types/twisty/views/TwistyAlgViewer.d.ts +2 -2
  206. package/dist/types/twisty/views/TwistyAlgViewer.d.ts.map +1 -1
  207. package/dist/types/twisty/views/TwistyPlayer.css.d.ts +3 -0
  208. package/dist/types/twisty/views/TwistyPlayer.css.d.ts.map +1 -0
  209. package/dist/types/twisty/views/TwistyPlayer.d.ts +7 -3
  210. package/dist/types/twisty/views/TwistyPlayer.d.ts.map +1 -1
  211. package/dist/types/twisty/views/TwistyPlayerSettable.d.ts +7 -4
  212. package/dist/types/twisty/views/TwistyPlayerSettable.d.ts.map +1 -1
  213. package/dist/types/twisty/views/TwistyViewerWrapper.css.d.ts +3 -0
  214. package/dist/types/twisty/views/TwistyViewerWrapper.css.d.ts.map +1 -0
  215. package/dist/types/twisty/{old/dom/viewers → views}/canvas.d.ts +0 -0
  216. package/dist/types/twisty/views/canvas.d.ts.map +1 -0
  217. package/dist/types/twisty/views/control-panel/TwistyButtonsV2.css.d.ts +4 -0
  218. package/dist/types/twisty/views/control-panel/TwistyButtonsV2.css.d.ts.map +1 -0
  219. package/dist/types/twisty/views/control-panel/TwistyButtonsV2.d.ts +1 -1
  220. package/dist/types/twisty/views/control-panel/TwistyButtonsV2.d.ts.map +1 -1
  221. package/dist/types/twisty/views/control-panel/TwistyScrubber.css.d.ts +3 -0
  222. package/dist/types/twisty/{old/dom/controls → views/control-panel}/TwistyScrubber.css.d.ts.map +1 -1
  223. package/dist/types/twisty/views/control-panel/TwistyScrubberV2.d.ts +1 -1
  224. package/dist/types/twisty/views/control-panel/TwistyScrubberV2.d.ts.map +1 -1
  225. package/dist/types/twisty/{old/dom/element → views}/node-custom-element-shims.d.ts +0 -0
  226. package/dist/types/twisty/views/node-custom-element-shims.d.ts.map +1 -0
  227. package/dist/types/twisty/views/stream/TwistyStreamSource.css.d.ts +3 -0
  228. package/dist/types/twisty/views/stream/TwistyStreamSource.css.d.ts.map +1 -0
  229. package/dist/types/twisty/{old/dom → views}/stream/TwistyStreamSource.d.ts +1 -1
  230. package/dist/types/twisty/views/stream/TwistyStreamSource.d.ts.map +1 -0
  231. package/dist/types/{search/vendor → vendor}/comlink-everywhere/inside/index.d.ts +0 -0
  232. package/dist/types/vendor/comlink-everywhere/inside/index.d.ts.map +1 -0
  233. package/dist/types/{search/vendor → vendor}/comlink-everywhere/inside/node.d.ts +0 -0
  234. package/dist/types/vendor/comlink-everywhere/inside/node.d.ts.map +1 -0
  235. package/dist/types/{search/vendor → vendor}/comlink-everywhere/outside/index.d.ts +0 -0
  236. package/dist/types/vendor/comlink-everywhere/outside/index.d.ts.map +1 -0
  237. package/dist/types/{search/vendor → vendor}/comlink-everywhere/outside/node.d.ts +0 -0
  238. package/dist/types/vendor/comlink-everywhere/outside/node.d.ts.map +1 -0
  239. package/dist/types/{search/inside/solve/vendor → vendor}/cstimer/src/js/lib/mathlib.d.ts +0 -0
  240. package/dist/types/vendor/cstimer/src/js/lib/mathlib.d.ts.map +1 -0
  241. package/dist/types/{search/inside/solve/vendor → vendor}/cstimer/src/js/scramble/scramble_444.d.ts +1 -1
  242. package/dist/types/vendor/cstimer/src/js/scramble/scramble_444.d.ts.map +1 -0
  243. package/dist/types/{search/inside/solve/vendor → vendor}/min2phase/gwt.d.ts +0 -0
  244. package/dist/types/vendor/min2phase/gwt.d.ts.map +1 -0
  245. package/dist/types/{search/inside/solve/vendor → vendor}/random-uint-below/get-random-values.d.ts +0 -0
  246. package/dist/types/vendor/random-uint-below/get-random-values.d.ts.map +1 -0
  247. package/dist/types/{search/inside/solve/vendor → vendor}/random-uint-below/index.d.ts +1 -1
  248. package/dist/types/vendor/random-uint-below/index.d.ts.map +1 -0
  249. package/dist/types/{search/inside/solve/vendor → vendor}/random-uint-below/random-choice.d.ts +0 -0
  250. package/dist/types/vendor/random-uint-below/random-choice.d.ts.map +1 -0
  251. package/dist/types/{search/inside/solve/vendor/random-uint-below/random-int.d.ts → vendor/random-uint-below/random53BitValue.d.ts} +1 -1
  252. package/dist/types/vendor/random-uint-below/random53BitValue.d.ts.map +1 -0
  253. package/dist/types/{search/inside/solve/vendor → vendor}/sq12phase/scramble_sq1.d.ts +0 -0
  254. package/dist/types/vendor/sq12phase/scramble_sq1.d.ts.map +1 -0
  255. package/dist/types/{bluetooth/smart-puzzle → vendor/unsafe-raw-aes}/unsafe-raw-aes.d.ts +0 -0
  256. package/dist/types/vendor/unsafe-raw-aes/unsafe-raw-aes.d.ts.map +1 -0
  257. package/docs/.DS_Store +0 -0
  258. package/docs/cubing/.DS_Store +0 -0
  259. package/docs/cubing/api/index.html +11 -52
  260. package/docs/cubing/index.html +67 -27
  261. package/docs/main.css +7 -6
  262. package/package.json +8 -9
  263. package/src/cubing/.DS_Store +0 -0
  264. package/src/cubing/alg/index.ts +1 -0
  265. package/src/cubing/alg/units/leaves/Move.ts +1 -1
  266. package/src/cubing/bluetooth/smart-puzzle/gan.ts +4 -1
  267. package/src/cubing/bluetooth/smart-timer/GanTimer.ts +1 -1
  268. package/src/cubing/cubing.bundle-global.exports.ts +25 -0
  269. package/src/cubing/cubing.bundle-global.ts +3 -27
  270. package/src/cubing/puzzle-geometry/PGPuzzles.spec.ts +4 -0
  271. package/src/cubing/puzzle-geometry/PuzzleGeometry.ts +20 -8
  272. package/src/cubing/puzzle-geometry/index.ts +2 -2
  273. package/src/cubing/puzzles/.DS_Store +0 -0
  274. package/src/cubing/puzzles/implementations/.DS_Store +0 -0
  275. package/src/cubing/puzzles/index.ts +1 -1
  276. package/src/cubing/puzzles/stickerings/cube-stickerings.ts +18 -0
  277. package/src/cubing/puzzles/stickerings/global-custom-stickering-hack.ts +1 -1
  278. package/src/cubing/search/.DS_Store +0 -0
  279. package/src/cubing/search/esm-test-worker.js +1 -1
  280. package/src/cubing/search/inside/.DS_Store +0 -0
  281. package/src/cubing/search/inside/api.ts +3 -0
  282. package/src/cubing/search/inside/entry.js +1 -1
  283. package/src/cubing/search/inside/inside-worker.ts +1 -1
  284. package/src/cubing/search/inside/solve/.DS_Store +0 -0
  285. package/src/cubing/search/inside/solve/addOrientationSuffix.ts +1 -1
  286. package/src/cubing/{alg → search/inside/solve/puzzles}/.DS_Store +0 -0
  287. package/src/cubing/search/inside/solve/puzzles/2x2x2.ts +1 -1
  288. package/src/cubing/search/inside/solve/puzzles/3x3x3/index.ts +2 -2
  289. package/src/cubing/search/inside/solve/puzzles/4x4x4.ts +2 -2
  290. package/src/cubing/search/inside/solve/puzzles/big-cubes.ts +1 -1
  291. package/src/cubing/search/inside/solve/puzzles/clock.ts +1 -1
  292. package/src/cubing/search/inside/solve/puzzles/{FTO.sgs → fto.sgs.json.ts} +116 -80
  293. package/src/cubing/search/inside/solve/puzzles/fto.ts +58 -0
  294. package/src/cubing/search/inside/solve/puzzles/sq1.ts +1 -1
  295. package/src/cubing/search/inside/solve/puzzles/wca-minx.ts +1 -1
  296. package/src/cubing/search/inside/solve/tremble.ts +2 -1
  297. package/src/cubing/search/inside/solve/vendor/.DS_Store +0 -0
  298. package/src/cubing/search/instantiator.ts +1 -1
  299. package/src/cubing/search/worker-inside-generated-string.js +1 -1
  300. package/src/cubing/twisty/.DS_Store +0 -0
  301. package/src/cubing/{alg/units → twisty/controllers}/.DS_Store +0 -0
  302. package/src/cubing/twisty/{old/animation/cursor/CursorTypes.ts → controllers/AnimationTypes.ts} +11 -2
  303. package/src/cubing/twisty/{old/animation → controllers}/RenderScheduler.ts +0 -0
  304. package/src/cubing/twisty/controllers/TwistyAnimationController.ts +4 -4
  305. package/src/cubing/twisty/controllers/animation/.DS_Store +0 -0
  306. package/src/cubing/twisty/{old/animation → controllers}/easing.ts +0 -0
  307. package/src/cubing/{stream → twisty/controllers/indexer}/.DS_Store +0 -0
  308. package/src/cubing/twisty/{old/animation → controllers}/indexer/AlgDuration.ts +2 -2
  309. package/src/cubing/twisty/{old/animation → controllers}/indexer/AlgIndexer.ts +4 -4
  310. package/src/cubing/twisty/{old/animation → controllers}/indexer/SimpleAlgIndexer.ts +4 -4
  311. package/src/cubing/twisty/{old/animation → controllers}/indexer/simultaneous-moves/SimultaneousMoveIndexer.ts +3 -3
  312. package/src/cubing/twisty/{old/animation → controllers}/indexer/simultaneous-moves/SimultaneousMoveIndexerV2.ts +3 -3
  313. package/src/cubing/twisty/{old/animation → controllers}/indexer/simultaneous-moves/simul-moves.ts +2 -2
  314. package/src/cubing/twisty/{old/animation → controllers}/indexer/tree/AlgWalker.ts +4 -4
  315. package/src/cubing/twisty/{old/animation → controllers}/indexer/tree/TreeAlgIndexer.ts +3 -3
  316. package/src/cubing/twisty/{old/animation → controllers}/indexer/tree/chunkAlgs.ts +2 -2
  317. package/src/cubing/twisty/{old/animation → controllers}/stream/timeline-move-calculation-draft.spec.ts.TODO +0 -0
  318. package/src/cubing/twisty/{old/animation → controllers}/stream/timeline-move-calculation-draft.ts +2 -2
  319. package/src/cubing/twisty/heavy-code-imports/.DS_Store +0 -0
  320. package/src/cubing/twisty/heavy-code-imports/dynamic-entries/3d.ts +2 -12
  321. package/src/cubing/twisty/index.ts +12 -19
  322. package/src/cubing/twisty/model/.DS_Store +0 -0
  323. package/src/cubing/twisty/model/TwistyPlayerModel.ts +38 -7
  324. package/src/cubing/twisty/model/props/.DS_Store +0 -0
  325. package/src/cubing/twisty/model/props/TwistyPropDebugger.ts +3 -3
  326. package/src/cubing/twisty/model/props/puzzle/.DS_Store +0 -0
  327. package/src/cubing/twisty/model/props/puzzle/display/FoundationDisplayProp.ts +9 -0
  328. package/src/cubing/twisty/model/props/puzzle/display/HintFaceletProp.ts +6 -1
  329. package/src/cubing/twisty/model/props/puzzle/display/StickeringProp.ts +49 -1
  330. package/src/cubing/twisty/model/props/puzzle/state/AlgTransformationProp.ts +1 -1
  331. package/src/cubing/twisty/model/props/puzzle/state/AnchoredStartProp.ts +2 -2
  332. package/src/cubing/twisty/model/props/puzzle/state/CurrentLeavesProp.ts +2 -2
  333. package/src/cubing/twisty/model/props/puzzle/state/CurrentLeavesSimplified.ts +1 -1
  334. package/src/cubing/twisty/model/props/puzzle/state/CurrentTransformationProp.ts +1 -1
  335. package/src/cubing/twisty/model/props/puzzle/state/IndexerConstructorProp.ts +12 -5
  336. package/src/cubing/twisty/model/props/puzzle/state/IndexerProp.ts +2 -2
  337. package/src/cubing/twisty/model/props/puzzle/state/LegacyPositionProp.ts +2 -2
  338. package/src/cubing/twisty/model/props/puzzle/state/MovePressInputProp.ts +14 -0
  339. package/src/cubing/twisty/model/props/puzzle/state/NaiveMoveCountProp.ts +20 -0
  340. package/src/cubing/twisty/model/props/puzzle/state/SetupAnchorProp.ts +7 -1
  341. package/src/cubing/twisty/model/props/puzzle/structure/PuzzleIDProp.ts +1 -1
  342. package/src/cubing/twisty/model/props/puzzle/structure/PuzzleIDRequestProp.ts +20 -1
  343. package/src/cubing/twisty/model/props/puzzle/structure/PuzzleLoaderProp.ts +1 -1
  344. package/src/cubing/twisty/model/props/timeline/DetailedTimelineInfoProp.ts +5 -3
  345. package/src/cubing/twisty/model/props/timeline/PlayingInfoProp.ts +1 -4
  346. package/src/cubing/twisty/model/props/timeline/TimestampRequestProp.ts +1 -1
  347. package/src/cubing/twisty/model/props/viewer/BackViewProp.ts +7 -1
  348. package/src/cubing/twisty/model/props/viewer/BackgroundProp.ts +6 -1
  349. package/src/cubing/twisty/model/props/viewer/ControlPanelProp.ts +5 -1
  350. package/src/cubing/twisty/model/props/viewer/OrbitCoordinatesProp.ts +83 -12
  351. package/src/cubing/twisty/model/props/viewer/OrbitCoordinatesRequestProp.ts +8 -8
  352. package/src/cubing/twisty/model/props/viewer/TimeRangeProp.ts +2 -2
  353. package/src/cubing/twisty/model/props/viewer/ViewerLinkProp.ts +5 -1
  354. package/src/cubing/twisty/model/props/viewer/VisualizationProp.ts +8 -1
  355. package/src/cubing/twisty/model/props/viewer/VisualizationStrategyProp.ts +1 -1
  356. package/src/cubing/twisty/old/.DS_Store +0 -0
  357. package/src/cubing/twisty/old/animation/.DS_Store +0 -0
  358. package/src/cubing/twisty/old/dom/.DS_Store +0 -0
  359. package/src/cubing/twisty/views/.DS_Store +0 -0
  360. package/src/cubing/twisty/{old/dom/viewers/Twisty2DSVGView.css.ts → views/2D/Twisty2DPuzzle.css.ts} +1 -1
  361. package/src/cubing/twisty/views/2D/Twisty2DPuzzle.ts +8 -12
  362. package/src/cubing/twisty/views/2D/Twisty2DPuzzleWrapper.ts +1 -1
  363. package/src/cubing/twisty/views/2D/Twisty2DSceneWrapper.ts +4 -4
  364. package/src/cubing/{bluetooth → twisty/views/3D}/.DS_Store +0 -0
  365. package/src/cubing/twisty/views/3D/DragTracker.ts +184 -0
  366. package/src/cubing/twisty/views/3D/RendererPool.ts +2 -1
  367. package/src/cubing/twisty/views/3D/Twisty3DPuzzleWrapper.ts +51 -5
  368. package/src/cubing/twisty/views/3D/Twisty3DSceneWrapper.ts +51 -10
  369. package/src/cubing/twisty/{old/dom/viewers/Twisty3DCanvas.css.ts → views/3D/Twisty3DVantage.css.ts} +2 -2
  370. package/src/cubing/twisty/views/3D/Twisty3DVantage.ts +103 -35
  371. package/src/cubing/twisty/views/3D/TwistyOrbitControls.spec.ts +213 -0
  372. package/src/cubing/twisty/views/3D/TwistyOrbitControls.ts +176 -0
  373. package/src/cubing/twisty/views/3D/puzzles/Cube3D.ts +5 -9
  374. package/src/cubing/twisty/views/3D/puzzles/PG3D.ts +127 -37
  375. package/src/cubing/twisty/views/3D/puzzles/Twisty3DPuzzle.ts +1 -1
  376. package/src/cubing/twisty/{old/dom/element → views}/ClassListManager.ts +0 -0
  377. package/src/cubing/twisty/{old/dom/element → views}/ManagedCustomElement.ts +0 -0
  378. package/src/cubing/twisty/views/TwistyAlgEditor/LeafTokens.ts +1 -1
  379. package/src/cubing/twisty/views/TwistyAlgEditor/TwistyAlgEditor.css.ts +1 -1
  380. package/src/cubing/twisty/views/TwistyAlgEditor/TwistyAlgEditor.ts +11 -4
  381. package/src/cubing/twisty/views/TwistyAlgViewer.css.ts +1 -1
  382. package/src/cubing/twisty/views/TwistyAlgViewer.ts +4 -4
  383. package/src/cubing/twisty/{old/dom → views}/TwistyPlayer.css.ts +4 -1
  384. package/src/cubing/twisty/views/TwistyPlayer.ts +16 -25
  385. package/src/cubing/twisty/views/TwistyPlayerSettable.ts +14 -10
  386. package/src/cubing/twisty/{old/dom/viewers → views}/TwistyViewerWrapper.css.ts +1 -1
  387. package/src/cubing/twisty/{old/dom/viewers → views}/canvas.ts +0 -0
  388. package/src/cubing/twisty/{old/dom/controls/buttons.css.ts → views/control-panel/TwistyButtonsV2.css.ts} +1 -1
  389. package/src/cubing/twisty/views/control-panel/TwistyButtonsV2.ts +5 -8
  390. package/src/cubing/twisty/{old/dom/controls → views/control-panel}/TwistyScrubber.css.ts +1 -1
  391. package/src/cubing/twisty/views/control-panel/TwistyScrubberV2.ts +3 -3
  392. package/src/cubing/twisty/{old/dom/element → views}/node-custom-element-shims.ts +2 -2
  393. package/src/cubing/twisty/{old/dom → views}/stream/TwistyStreamSource.css.ts +1 -1
  394. package/src/cubing/twisty/{old/dom → views}/stream/TwistyStreamSource.ts +9 -9
  395. package/src/cubing/vendor/.DS_Store +0 -0
  396. package/src/cubing/{twisty/old/animation/indexer → vendor/comlink-everywhere}/.DS_Store +0 -0
  397. package/src/cubing/{search/vendor → vendor}/comlink-everywhere/comlink-everywhere.webloc +0 -0
  398. package/src/cubing/{search/vendor → vendor}/comlink-everywhere/inside/index.d.ts +0 -0
  399. package/src/cubing/{search/vendor → vendor}/comlink-everywhere/inside/index.js +0 -0
  400. package/src/cubing/{search/vendor → vendor}/comlink-everywhere/inside/node.js +0 -0
  401. package/src/cubing/{search/vendor → vendor}/comlink-everywhere/outside/index.d.ts +0 -0
  402. package/src/cubing/{search/vendor → vendor}/comlink-everywhere/outside/index.js +0 -0
  403. package/src/cubing/{search/vendor → vendor}/comlink-everywhere/outside/node.js +0 -0
  404. package/src/cubing/vendor/cstimer/.DS_Store +0 -0
  405. package/src/cubing/{search/inside/solve/vendor → vendor}/cstimer/LICENSE +0 -0
  406. package/src/cubing/{search/inside/solve/vendor → vendor}/cstimer/src/js/lib/mathlib.ts +0 -0
  407. package/src/cubing/{search/inside/solve/vendor → vendor}/cstimer/src/js/scramble/scramble_444.ts +3 -3
  408. package/src/cubing/{search/inside/solve/vendor → vendor}/min2phase/gwt.d.ts +0 -0
  409. package/src/cubing/{search/inside/solve/vendor → vendor}/min2phase/gwt.js +0 -0
  410. package/src/cubing/vendor/random-uint-below/get-random-values.ts +23 -0
  411. package/src/cubing/{search/inside/solve/vendor → vendor}/random-uint-below/index.ts +2 -2
  412. package/src/cubing/{search/inside/solve/vendor → vendor}/random-uint-below/random-choice.ts +1 -1
  413. package/src/cubing/{search/inside/solve/vendor/random-uint-below/random-int.ts → vendor/random-uint-below/random53BitValue.ts} +0 -0
  414. package/src/cubing/{search/inside/solve/vendor → vendor}/sq12phase/scramble_sq1.js +0 -0
  415. package/src/cubing/{bluetooth/smart-puzzle → vendor/unsafe-raw-aes}/unsafe-raw-aes.ts +18 -20
  416. package/dist/esm/3d-B25DP5PE.js +0 -39
  417. package/dist/esm/3d-B25DP5PE.js.map +0 -7
  418. package/dist/esm/chunk-APIIMJG6.js.map +0 -7
  419. package/dist/esm/chunk-CSVAFZSB.js.map +0 -7
  420. package/dist/esm/chunk-MUQMBH2S.js.map +0 -7
  421. package/dist/esm/worker-inside-generated-string-KDZOUGJF.js +0 -2831
  422. package/dist/esm/worker-inside-generated-string-KDZOUGJF.js.map +0 -7
  423. package/dist/types/bluetooth/smart-puzzle/unsafe-raw-aes.d.ts.map +0 -1
  424. package/dist/types/search/inside/solve/vendor/cstimer/src/js/lib/mathlib.d.ts.map +0 -1
  425. package/dist/types/search/inside/solve/vendor/cstimer/src/js/scramble/scramble_444.d.ts.map +0 -1
  426. package/dist/types/search/inside/solve/vendor/min2phase/gwt.d.ts.map +0 -1
  427. package/dist/types/search/inside/solve/vendor/random-uint-below/get-random-values.d.ts.map +0 -1
  428. package/dist/types/search/inside/solve/vendor/random-uint-below/index.d.ts.map +0 -1
  429. package/dist/types/search/inside/solve/vendor/random-uint-below/random-choice.d.ts.map +0 -1
  430. package/dist/types/search/inside/solve/vendor/random-uint-below/random-int.d.ts.map +0 -1
  431. package/dist/types/search/inside/solve/vendor/sq12phase/scramble_sq1.d.ts.map +0 -1
  432. package/dist/types/search/vendor/comlink-everywhere/inside/index.d.ts.map +0 -1
  433. package/dist/types/search/vendor/comlink-everywhere/inside/node.d.ts.map +0 -1
  434. package/dist/types/search/vendor/comlink-everywhere/outside/index.d.ts.map +0 -1
  435. package/dist/types/search/vendor/comlink-everywhere/outside/node.d.ts.map +0 -1
  436. package/dist/types/twisty/old/animation/RenderScheduler.d.ts.map +0 -1
  437. package/dist/types/twisty/old/animation/Timeline.d.ts +0 -72
  438. package/dist/types/twisty/old/animation/Timeline.d.ts.map +0 -1
  439. package/dist/types/twisty/old/animation/cursor/AlgCursor.d.ts +0 -53
  440. package/dist/types/twisty/old/animation/cursor/AlgCursor.d.ts.map +0 -1
  441. package/dist/types/twisty/old/animation/cursor/CursorTypes.d.ts.map +0 -1
  442. package/dist/types/twisty/old/animation/easing.d.ts.map +0 -1
  443. package/dist/types/twisty/old/animation/indexer/AlgDuration.d.ts.map +0 -1
  444. package/dist/types/twisty/old/animation/indexer/AlgIndexer.d.ts.map +0 -1
  445. package/dist/types/twisty/old/animation/indexer/SimpleAlgIndexer.d.ts.map +0 -1
  446. package/dist/types/twisty/old/animation/indexer/simultaneous-moves/SimultaneousMoveIndexer.d.ts.map +0 -1
  447. package/dist/types/twisty/old/animation/indexer/simultaneous-moves/SimultaneousMoveIndexerV2.d.ts.map +0 -1
  448. package/dist/types/twisty/old/animation/indexer/simultaneous-moves/simul-moves.d.ts.map +0 -1
  449. package/dist/types/twisty/old/animation/indexer/tree/AlgWalker.d.ts.map +0 -1
  450. package/dist/types/twisty/old/animation/indexer/tree/TreeAlgIndexer.d.ts.map +0 -1
  451. package/dist/types/twisty/old/animation/indexer/tree/chunkAlgs.d.ts +0 -3
  452. package/dist/types/twisty/old/animation/indexer/tree/chunkAlgs.d.ts.map +0 -1
  453. package/dist/types/twisty/old/animation/stream/timeline-move-calculation-draft.d.ts.map +0 -1
  454. package/dist/types/twisty/old/dom/TwistyAlgViewerV1.css.d.ts +0 -3
  455. package/dist/types/twisty/old/dom/TwistyAlgViewerV1.css.d.ts.map +0 -1
  456. package/dist/types/twisty/old/dom/TwistyAlgViewerV1.d.ts +0 -52
  457. package/dist/types/twisty/old/dom/TwistyAlgViewerV1.d.ts.map +0 -1
  458. package/dist/types/twisty/old/dom/TwistyPlayer.css.d.ts +0 -3
  459. package/dist/types/twisty/old/dom/TwistyPlayer.css.d.ts.map +0 -1
  460. package/dist/types/twisty/old/dom/TwistyPlayer.d.ts +0 -92
  461. package/dist/types/twisty/old/dom/TwistyPlayer.d.ts.map +0 -1
  462. package/dist/types/twisty/old/dom/TwistyPlayer.spec.d.ts +0 -5
  463. package/dist/types/twisty/old/dom/TwistyPlayer.spec.d.ts.map +0 -1
  464. package/dist/types/twisty/old/dom/TwistyPlayerConfig.d.ts +0 -165
  465. package/dist/types/twisty/old/dom/TwistyPlayerConfig.d.ts.map +0 -1
  466. package/dist/types/twisty/old/dom/controls/TwistyControlElement.d.ts +0 -2
  467. package/dist/types/twisty/old/dom/controls/TwistyControlElement.d.ts.map +0 -1
  468. package/dist/types/twisty/old/dom/controls/TwistyScrubber.css.d.ts +0 -3
  469. package/dist/types/twisty/old/dom/controls/TwistyScrubber.d.ts +0 -14
  470. package/dist/types/twisty/old/dom/controls/TwistyScrubber.d.ts.map +0 -1
  471. package/dist/types/twisty/old/dom/controls/buttons.css.d.ts +0 -4
  472. package/dist/types/twisty/old/dom/controls/buttons.css.d.ts.map +0 -1
  473. package/dist/types/twisty/old/dom/controls/buttons.d.ts +0 -40
  474. package/dist/types/twisty/old/dom/controls/buttons.d.ts.map +0 -1
  475. package/dist/types/twisty/old/dom/controls/buttons.spec.d.ts +0 -5
  476. package/dist/types/twisty/old/dom/controls/buttons.spec.d.ts.map +0 -1
  477. package/dist/types/twisty/old/dom/element/ClassListManager.d.ts.map +0 -1
  478. package/dist/types/twisty/old/dom/element/ElementConfig.d.ts +0 -49
  479. package/dist/types/twisty/old/dom/element/ElementConfig.d.ts.map +0 -1
  480. package/dist/types/twisty/old/dom/element/ManagedCustomElement.d.ts.map +0 -1
  481. package/dist/types/twisty/old/dom/element/node-custom-element-shims.d.ts.map +0 -1
  482. package/dist/types/twisty/old/dom/stream/TwistyStreamSource.css.d.ts +0 -3
  483. package/dist/types/twisty/old/dom/stream/TwistyStreamSource.css.d.ts.map +0 -1
  484. package/dist/types/twisty/old/dom/stream/TwistyStreamSource.d.ts.map +0 -1
  485. package/dist/types/twisty/old/dom/viewers/Twisty2DSVG.d.ts +0 -26
  486. package/dist/types/twisty/old/dom/viewers/Twisty2DSVG.d.ts.map +0 -1
  487. package/dist/types/twisty/old/dom/viewers/Twisty2DSVGView.css.d.ts +0 -3
  488. package/dist/types/twisty/old/dom/viewers/Twisty2DSVGView.css.d.ts.map +0 -1
  489. package/dist/types/twisty/old/dom/viewers/Twisty3DCanvas.css.d.ts +0 -3
  490. package/dist/types/twisty/old/dom/viewers/Twisty3DCanvas.css.d.ts.map +0 -1
  491. package/dist/types/twisty/old/dom/viewers/Twisty3DCanvas.d.ts +0 -41
  492. package/dist/types/twisty/old/dom/viewers/Twisty3DCanvas.d.ts.map +0 -1
  493. package/dist/types/twisty/old/dom/viewers/TwistyOrbitControls.d.ts +0 -59
  494. package/dist/types/twisty/old/dom/viewers/TwistyOrbitControls.d.ts.map +0 -1
  495. package/dist/types/twisty/old/dom/viewers/TwistyViewerElement.d.ts +0 -4
  496. package/dist/types/twisty/old/dom/viewers/TwistyViewerElement.d.ts.map +0 -1
  497. package/dist/types/twisty/old/dom/viewers/TwistyViewerWrapper.css.d.ts +0 -3
  498. package/dist/types/twisty/old/dom/viewers/TwistyViewerWrapper.css.d.ts.map +0 -1
  499. package/dist/types/twisty/old/dom/viewers/TwistyViewerWrapper.d.ts +0 -18
  500. package/dist/types/twisty/old/dom/viewers/TwistyViewerWrapper.d.ts.map +0 -1
  501. package/dist/types/twisty/old/dom/viewers/canvas.d.ts.map +0 -1
  502. package/dist/types/twisty/views/3D/TwistyOrbitControlsV2.d.ts +0 -41
  503. package/dist/types/twisty/views/3D/TwistyOrbitControlsV2.d.ts.map +0 -1
  504. package/dist/types/twisty/views/3D/TwistyOrbitControlsV2.spec.d.ts +0 -5
  505. package/dist/types/twisty/views/3D/TwistyOrbitControlsV2.spec.d.ts.map +0 -1
  506. package/dist/types/twisty/views/3D/puzzles/TwistyTestBox.d.ts +0 -9
  507. package/dist/types/twisty/views/3D/puzzles/TwistyTestBox.d.ts.map +0 -1
  508. package/src/cubing/search/inside/solve/vendor/random-uint-below/get-random-values.ts +0 -38
  509. package/src/cubing/twisty/old/animation/Timeline.ts +0 -378
  510. package/src/cubing/twisty/old/animation/cursor/AlgCursor.ts +0 -252
  511. package/src/cubing/twisty/old/dom/TwistyAlgViewerV1.css.ts +0 -25
  512. package/src/cubing/twisty/old/dom/TwistyAlgViewerV1.ts +0 -516
  513. package/src/cubing/twisty/old/dom/TwistyPlayer.spec.ts +0 -25
  514. package/src/cubing/twisty/old/dom/TwistyPlayer.ts +0 -927
  515. package/src/cubing/twisty/old/dom/TwistyPlayerConfig.ts +0 -378
  516. package/src/cubing/twisty/old/dom/controls/TwistyControlElement.ts +0 -1
  517. package/src/cubing/twisty/old/dom/controls/TwistyScrubber.ts +0 -53
  518. package/src/cubing/twisty/old/dom/controls/buttons.spec.ts +0 -37
  519. package/src/cubing/twisty/old/dom/controls/buttons.ts +0 -326
  520. package/src/cubing/twisty/old/dom/element/ElementConfig.ts +0 -180
  521. package/src/cubing/twisty/old/dom/viewers/Twisty2DSVG.ts +0 -118
  522. package/src/cubing/twisty/old/dom/viewers/Twisty3DCanvas.ts +0 -256
  523. package/src/cubing/twisty/old/dom/viewers/TwistyOrbitControls.ts +0 -420
  524. package/src/cubing/twisty/old/dom/viewers/TwistyViewerElement.ts +0 -5
  525. package/src/cubing/twisty/old/dom/viewers/TwistyViewerWrapper.ts +0 -45
  526. package/src/cubing/twisty/views/3D/TwistyOrbitControlsV2.spec.ts +0 -209
  527. package/src/cubing/twisty/views/3D/TwistyOrbitControlsV2.ts +0 -270
  528. package/src/cubing/twisty/views/3D/puzzles/TwistyTestBox.ts +0 -22
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["../../../src/cubing/twisty/old/animation/cursor/CursorTypes.ts", "../../../src/cubing/twisty/model/PromiseFreshener.ts", "../../../src/cubing/twisty/model/helpers.ts", "../../../src/cubing/twisty/controllers/TwistyAnimationController.ts", "../../../src/cubing/twisty/controllers/TwistyPlayerController.ts", "../../../src/cubing/twisty/old/dom/TwistyPlayer.css.ts", "../../../src/cubing/vendor/p-lazy/p-lazy.ts", "../../../src/cubing/twisty/heavy-code-imports/3d.ts", "../../../src/cubing/twisty/model/props/TwistyProp.ts", "../../../src/cubing/twisty/old/dom/viewers/Twisty2DSVGView.css.ts", "../../../src/cubing/twisty/views/2D/Twisty2DPuzzle.ts", "../../../src/cubing/twisty/views/2D/Twisty2DPuzzleWrapper.ts", "../../../src/cubing/twisty/views/2D/Twisty2DSceneWrapper.ts", "../../../src/cubing/twisty/views/3D/Twisty3DPuzzleWrapper.ts", "../../../src/cubing/twisty/views/3D/RendererPool.ts", "../../../src/cubing/twisty/views/3D/TwistyOrbitControlsV2.ts", "../../../src/cubing/twisty/views/3D/Twisty3DVantage.ts", "../../../src/cubing/twisty/views/3D/Twisty3DSceneWrapper.ts", "../../../src/cubing/twisty/old/dom/controls/buttons.css.ts", "../../../src/cubing/twisty/views/document.ts", "../../../src/cubing/twisty/views/control-panel/webkit-fullscreen.ts", "../../../src/cubing/twisty/model/props/viewer/ButtonAppearanceProp.ts", "../../../src/cubing/twisty/views/control-panel/TwistyButtonsV2.ts", "../../../src/cubing/twisty/old/dom/controls/TwistyScrubber.css.ts", "../../../src/cubing/twisty/views/control-panel/TwistyScrubberV2.ts", "../../../src/cubing/twisty/views/screenshot.ts", "../../../src/cubing/twisty/model/props/puzzle/state/AlgProp.ts", "../../../src/cubing/twisty/model/props/viewer/BackgroundProp.ts", "../../../src/cubing/twisty/model/props/viewer/BackViewProp.ts", "../../../src/cubing/twisty/model/props/viewer/ControlPanelProp.ts", "../../../src/cubing/twisty/model/props/puzzle/display/HintFaceletProp.ts", "../../../src/cubing/twisty/model/props/puzzle/state/IndexerConstructorRequestProp.ts", "../../../src/cubing/twisty/model/props/viewer/LatitudeLimit.ts", "../../../src/cubing/twisty/model/props/viewer/OrbitCoordinatesRequestProp.ts", "../../../src/cubing/twisty/model/props/timeline/PlayingInfoProp.ts", "../../../src/cubing/twisty/model/props/puzzle/structure/PuzzleDescriptionProp.ts", "../../../src/cubing/twisty/model/props/puzzle/structure/PuzzleIDRequestProp.ts", "../../../src/cubing/twisty/model/props/puzzle/structure/PuzzleLoaderProp.ts", "../../../src/cubing/twisty/model/props/puzzle/state/SetupAnchorProp.ts", "../../../src/cubing/twisty/model/props/puzzle/display/StickeringProp.ts", "../../../src/cubing/twisty/model/props/timeline/TempoScaleProp.ts", "../../../src/cubing/twisty/model/props/timeline/TimestampRequestProp.ts", "../../../src/cubing/twisty/model/props/general/URLProp.ts", "../../../src/cubing/twisty/model/props/viewer/ViewerLinkProp.ts", "../../../src/cubing/twisty/model/props/viewer/VisualizationProp.ts", "../../../src/cubing/twisty/model/props/viewer/OrbitCoordinatesProp.ts", "../../../src/cubing/twisty/model/props/puzzle/structure/PuzzleIDProp.ts", "../../../src/cubing/twisty/model/props/puzzle/display/SpriteProp.ts", "../../../src/cubing/twisty/model/props/viewer/VisualizationStrategyProp.ts", "../../../src/cubing/twisty/old/animation/indexer/AlgDuration.ts", "../../../src/cubing/twisty/old/animation/indexer/SimpleAlgIndexer.ts", "../../../src/cubing/twisty/old/animation/indexer/simultaneous-moves/simul-moves.ts", "../../../src/cubing/twisty/old/animation/indexer/simultaneous-moves/SimultaneousMoveIndexerV2.ts", "../../../src/cubing/twisty/old/animation/indexer/tree/chunkAlgs.ts", "../../../src/cubing/twisty/old/animation/indexer/tree/AlgWalker.ts", "../../../src/cubing/twisty/old/animation/indexer/tree/TreeAlgIndexer.ts", "../../../src/cubing/twisty/model/props/puzzle/state/IndexerConstructorProp.ts", "../../../src/cubing/twisty/model/props/puzzle/state/PuzzleAlgProp.ts", "../../../src/cubing/twisty/views/3D/puzzles/KPuzzleWrapper.ts", "../../../src/cubing/twisty/model/props/puzzle/state/AlgTransformationProp.ts", "../../../src/cubing/twisty/model/props/puzzle/state/IndexerProp.ts", "../../../src/cubing/twisty/model/props/puzzle/state/AnchoredStartProp.ts", "../../../src/cubing/twisty/model/props/viewer/TimeRangeProp.ts", "../../../src/cubing/twisty/model/props/timeline/DetailedTimelineInfoProp.ts", "../../../src/cubing/twisty/model/props/timeline/CoarseTimelineInfoProp.ts", "../../../src/cubing/twisty/model/props/puzzle/state/CurrentLeavesProp.ts", "../../../src/cubing/twisty/model/props/puzzle/state/CurrentLeavesSimplified.ts", "../../../src/cubing/twisty/model/props/puzzle/state/CurrentTransformationProp.ts", "../../../src/cubing/twisty/model/props/puzzle/state/LegacyPositionProp.ts", "../../../src/cubing/twisty/model/props/puzzle/structure/PuzzleDefProp.ts", "../../../src/cubing/twisty/model/UserVisibleErrorTracker.ts", "../../../src/cubing/twisty/model/props/puzzle/state/CatchUpMoveProp.ts", "../../../src/cubing/twisty/model/TwistyPlayerModel.ts", "../../../src/cubing/twisty/views/TwistyPlayerSettable.ts", "../../../src/cubing/twisty/views/TwistyPlayer.ts", "../../../src/cubing/twisty/views/TwistyAlgViewer.css.ts", "../../../src/cubing/twisty/views/TwistyAlgViewer.ts", "../../../src/cubing/twisty/views/TwistyAlgEditor/LeafTokens.ts", "../../../src/cubing/twisty/views/TwistyAlgEditor/model.ts", "../../../src/cubing/twisty/views/TwistyAlgEditor/TwistyAlgEditor.css.ts", "../../../src/cubing/twisty/views/TwistyAlgEditor/TwistyAlgEditor.ts", "../../../src/cubing/twisty/old/dom/TwistyPlayer.ts", "../../../src/cubing/twisty/old/animation/cursor/AlgCursor.ts", "../../../src/cubing/twisty/old/animation/indexer/simultaneous-moves/SimultaneousMoveIndexer.ts", "../../../src/cubing/twisty/old/animation/Timeline.ts", "../../../src/cubing/twisty/old/dom/controls/buttons.ts", "../../../src/cubing/twisty/old/dom/controls/TwistyScrubber.ts", "../../../src/cubing/twisty/old/dom/viewers/Twisty2DSVG.ts", "../../../src/cubing/twisty/old/dom/TwistyAlgViewerV1.css.ts", "../../../src/cubing/twisty/old/dom/TwistyAlgViewerV1.ts"],
4
- "sourcesContent": ["import type { Move } from \"../../../../alg\";\nimport type { Transformation as KPuzzleState } from \"../../../../kpuzzle\";\n\nexport type MillisecondTimestamp = number;\n\n// TODO: unify duration/timstamp types\nexport type Duration = MillisecondTimestamp; // Duration in milliseconds\n// TODO: Extend `number`, introduce MoveSequenceTimestamp vs. EpochTimestamp,\n// force Duration to be a difference.\nexport type Timestamp = MillisecondTimestamp; // Duration since a particular epoch.\n\nexport type Fraction = number; // Value from 0 to 1.\n\n// 1, 0, -1 are used as scalars for `directionScalar` below.\nexport enum Direction {\n Forwards = 1,\n Paused = 0,\n Backwards = -1,\n}\n\nexport function directionScalar(direction: Direction): MillisecondTimestamp {\n return direction;\n}\n\nexport interface MoveInProgress {\n move: Move;\n direction: Direction;\n fraction: number;\n}\n\nexport type PuzzlePosition = {\n state: KPuzzleState;\n movesInProgress: MoveInProgress[];\n};\n\nexport enum BoundaryType {\n Move = \"move\",\n EntireTimeline = \"entire-timeline\",\n}\n\n// export type DurationForAmount = (amount: number) => Duration;\n", "// TODO: Pick a much better name.\nexport class PromiseFreshener<T> {\n #latestAssignedIdx = 0;\n #latestResolvedIdx = 0;\n\n // TODO: reject instead? Drop?\n async queue(\n p: Promise<T>,\n ): Promise<{ fresh: false } | { fresh: true; result: T }> {\n const idx = ++this.#latestAssignedIdx;\n const result = await p;\n if (idx > this.#latestResolvedIdx) {\n this.#latestResolvedIdx = idx;\n return {\n fresh: true,\n result: result,\n };\n } else {\n return { fresh: false };\n }\n }\n}\n\n// This will silenty drop a queued Promise (i.e. not resolve it) if a\n// newer queued one already resolved first. This is useful for classes that want\n// to know the \"latest\" state of something without jumping back to an older\n// value by accident.\n// TODO: Remove this because it's too easy to misuse?\nexport class StaleDropper<T> {\n #latestAssignedIdx = 0;\n #latestResolvedIdx = 0;\n\n queue(p: Promise<T>): Promise<T> {\n // This is a very rare case where we *do* want to drop a Promise sometimes.\n // eslint-disable-next-line no-async-promise-executor\n return new Promise(async (resolve, reject) => {\n try {\n const idx = ++this.#latestAssignedIdx;\n const result = await p;\n if (idx > this.#latestResolvedIdx) {\n this.#latestResolvedIdx = idx;\n resolve(result);\n }\n } catch (e) {\n reject(e);\n }\n });\n }\n}\n", "export function arrayEquals<T>(a: readonly T[], b: readonly T[]): boolean {\n if (a === b) {\n return true;\n }\n if (a.length !== b.length) {\n return false;\n }\n for (let i = 0; i < a.length; i++) {\n if (a[i] !== b[i]) {\n return false;\n }\n }\n return true;\n}\n\nexport function arrayEqualsCompare<T>(\n a: readonly T[],\n b: readonly T[],\n compare: (a: T, b: T) => boolean,\n): boolean {\n if (a === b) {\n return true;\n }\n if (a.length !== b.length) {\n return false;\n }\n for (let i = 0; i < a.length; i++) {\n if (!compare(a[i], b[i])) {\n return false;\n }\n }\n return true;\n}\n\n// Assumes `offset > 0`. Will produce invalid values if not!\n// We don't check for that, since this can be a hot path.\nexport function mod(v: number, m: number, offset = 0): number {\n return (((v % m) + m + offset) % m) - offset;\n}\n\nexport function modIntoRange(\n v: number,\n rangeMin: number,\n rangeMax: number,\n): number {\n return mod(v - rangeMin, rangeMax - rangeMin) + rangeMin;\n}\n", "import type { TimeRange } from \"../old/animation/cursor/AlgCursor\";\nimport {\n BoundaryType,\n Direction,\n directionScalar,\n MillisecondTimestamp,\n} from \"../old/animation/cursor/CursorTypes\";\nimport { RenderScheduler } from \"../old/animation/RenderScheduler\";\nimport type {\n PlayingInfo,\n SimpleDirection,\n} from \"../model/props/timeline/PlayingInfoProp\";\nimport type { TwistyPlayerModel } from \"../model/TwistyPlayerModel\";\nimport { StaleDropper } from \"../model/PromiseFreshener\";\nimport type { CurrentMoveInfo } from \"../old/animation/indexer/AlgIndexer\";\nimport type { TimestampRequest } from \"../model/props/timeline/TimestampRequestProp\";\nimport { modIntoRange } from \"../model/helpers\";\nimport type { CatchUpMove } from \"../model/props/puzzle/state/CatchUpMoveProp\";\n\n// TODO: Figure out a better way for the controller to instruct the player.\nexport interface TwistyAnimationControllerDelegate {\n flash(): void;\n}\n\n// We use a separate helper to separate the anim frame callbacks (and their cancellations).\n// TODO: fold this into the main controller\nclass CatchUpHelper {\n catchingUp: boolean = false;\n pendingFrame = false;\n\n constructor(private model: TwistyPlayerModel) {}\n\n private scheduler: RenderScheduler = new RenderScheduler(\n this.animFrame.bind(this),\n );\n\n start(): void {\n if (!this.catchingUp) {\n this.lastTimestamp = performance.now();\n }\n this.catchingUp = true;\n this.pendingFrame = true;\n this.scheduler.requestAnimFrame();\n }\n\n stop(): void {\n this.catchingUp = false;\n this.scheduler.cancelAnimFrame();\n }\n\n catchUpMs = 500;\n lastTimestamp = 0;\n animFrame(timestamp: MillisecondTimestamp): void {\n this.scheduler.requestAnimFrame();\n const delta = (timestamp - this.lastTimestamp) / this.catchUpMs;\n this.lastTimestamp = timestamp;\n\n this.model.catchUpMoveProp.set(\n (async () => {\n const previousCatchUpMove = await this.model.catchUpMoveProp.get();\n if (previousCatchUpMove.move === null) {\n return previousCatchUpMove;\n }\n\n const amount = previousCatchUpMove.amount + delta; // TODO: use tempo scale?\n if (amount >= 1) {\n this.pendingFrame = true;\n this.stop();\n this.model.timestampRequestProp.set(\"end\");\n return {\n move: null,\n amount: 0,\n };\n }\n this.pendingFrame = false;\n return {\n move: previousCatchUpMove.move,\n amount: amount,\n };\n })(),\n );\n }\n}\n\n// This controls the logic for animation, so that the main controller can focus on the right API abstractions.\nexport class TwistyAnimationController {\n // TODO: #private?\n private playing: boolean = false;\n private direction: Direction = Direction.Forwards;\n\n private catchUpHelper: CatchUpHelper;\n\n private model: TwistyPlayerModel;\n\n private lastDatestamp: MillisecondTimestamp = 0;\n private lastTimestampPromise: Promise<MillisecondTimestamp>;\n\n private scheduler: RenderScheduler = new RenderScheduler(\n this.animFrame.bind(this),\n );\n\n constructor(\n model: TwistyPlayerModel,\n private delegate: TwistyAnimationControllerDelegate,\n ) {\n this.model = model;\n this.lastTimestampPromise = this.#effectiveTimestampMilliseconds();\n\n this.model.playingInfoProp.addFreshListener(this.onPlayingProp.bind(this)); // TODO\n\n this.catchUpHelper = new CatchUpHelper(this.model);\n this.model.catchUpMoveProp.addFreshListener(\n this.onCatchUpMoveProp.bind(this),\n ); // TODO\n }\n\n // TODO: Do we need this?\n async onPlayingProp(playingInfo: PlayingInfo): Promise<void> {\n if (playingInfo.playing !== this.playing) {\n playingInfo.playing ? this.play(playingInfo) : this.pause();\n }\n }\n\n // TODO: Do we need this?\n async onCatchUpMoveProp(catchUpMove: CatchUpMove): Promise<void> {\n const catchingUp = catchUpMove.move !== null;\n if (catchingUp !== this.catchUpHelper.catchingUp) {\n catchingUp ? this.catchUpHelper.start() : this.catchUpHelper.stop();\n }\n this.scheduler.requestAnimFrame();\n }\n\n async #effectiveTimestampMilliseconds(): Promise<MillisecondTimestamp> {\n return (await this.model.detailedTimelineInfoProp.get()).timestamp;\n }\n\n // TODO: Return the animation we've switched to.\n jumpToStart(options?: { flash: boolean }): void {\n this.model.timestampRequestProp.set(\"start\");\n this.pause();\n if (options?.flash) {\n this.delegate.flash();\n }\n }\n\n // TODO: Return the animation we've switched to.\n jumpToEnd(options?: { flash: boolean }): void {\n this.model.timestampRequestProp.set(\"end\");\n this.pause();\n if (options?.flash) {\n this.delegate.flash();\n }\n }\n\n // TODO: Return the playing info we've switched to.\n playPause(): void {\n if (this.playing) {\n this.pause();\n } else {\n this.play(); // TODO: Resume direction and looping behaviour?\n }\n }\n\n // TODO: bundle playing direction, and boundary into `toggle`.\n async play(options?: {\n direction?: SimpleDirection;\n untilBoundary?: BoundaryType;\n autoSkipToOtherEndIfStartingAtBoundary?: boolean; // TODO What's a good short name that doesn't imply a more general looping concept?\n loop?: boolean;\n }): Promise<void> {\n // TODO: We might need to cache all playing info?\n // Or maybe we don't have to worry about short-circuiting, since this is idempotent?\n // if (this.playing) {\n // return;\n // }\n\n const direction = options?.direction ?? Direction.Forwards;\n\n const coarseTimelineInfo = await this.model.coarseTimelineInfoProp.get(); // TODO: Why do we need to read this if we don't use it?\n if (options?.autoSkipToOtherEndIfStartingAtBoundary ?? true) {\n if (direction === Direction.Forwards && coarseTimelineInfo.atEnd) {\n this.model.timestampRequestProp.set(\"start\");\n this.delegate.flash();\n }\n if (direction === Direction.Backwards && coarseTimelineInfo.atStart) {\n this.model.timestampRequestProp.set(\"end\");\n this.delegate.flash();\n }\n }\n this.model.playingInfoProp.set({\n playing: true,\n direction,\n untilBoundary: options?.untilBoundary ?? BoundaryType.EntireTimeline,\n loop: options?.loop ?? false,\n });\n\n this.playing = true;\n this.lastDatestamp = performance.now(); // TODO: Take from event.\n this.lastTimestampPromise = this.#effectiveTimestampMilliseconds();\n\n // TODO: Save timestamp from model?\n this.scheduler.requestAnimFrame();\n }\n\n pause(): void {\n this.playing = false;\n this.scheduler.cancelAnimFrame();\n this.model.playingInfoProp.set({\n playing: false,\n untilBoundary: BoundaryType.EntireTimeline,\n });\n }\n\n #animFrameEffectiveTimestampStaleDropper: StaleDropper<\n [PlayingInfo, MillisecondTimestamp, TimeRange, number, CurrentMoveInfo]\n > = new StaleDropper<\n [PlayingInfo, MillisecondTimestamp, TimeRange, number, CurrentMoveInfo]\n >();\n\n async animFrame(frameDatestamp: MillisecondTimestamp): Promise<void> {\n if (this.playing) {\n this.scheduler.requestAnimFrame();\n }\n\n const lastDatestamp = this.lastDatestamp;\n const freshenerResult =\n await this.#animFrameEffectiveTimestampStaleDropper.queue(\n Promise.all([\n this.model.playingInfoProp.get(),\n this.lastTimestampPromise,\n this.model.timeRangeProp.get(),\n this.model.tempoScaleProp.get(),\n this.model.currentLeavesProp.get(),\n ]),\n );\n\n const [playingInfo, lastTimestamp, timeRange, tempoScale, currentMoveInfo] =\n freshenerResult;\n\n // TODO: Get this without wasting time on the others?\n if (!playingInfo.playing) {\n this.playing = false;\n // TODO: Ideally we'd cancel the anim frame from the top of this method.\n // But `this.scheduler.cancelAnimFrame();` might accidentally cancel a\n // legit freshly scheduled frame. We should modify `RenderScheduler` to\n // either have individually cancellable requests, or to have something\n // like a \"default\" anim frame re-request that can be canceled separately.\n //\n // Note that we can't wait until here to call\n // `this.scheduler.requestAnimFrame();`, because that would slow down the\n // frame rate.\n return;\n }\n\n let end = currentMoveInfo.earliestEnd; // timeRange.end\n if (\n currentMoveInfo.currentMoves.length === 0 ||\n playingInfo.untilBoundary === BoundaryType.EntireTimeline\n ) {\n end = timeRange.end;\n }\n\n let start = currentMoveInfo.latestStart; // timeRange.end\n if (\n currentMoveInfo.currentMoves.length === 0 ||\n playingInfo.untilBoundary === BoundaryType.EntireTimeline\n ) {\n start = timeRange.start;\n }\n // const start = currentMoveInfo.latestStart; // timeRange.start // TODO\n\n let delta =\n (frameDatestamp - lastDatestamp) *\n directionScalar(this.direction) *\n tempoScale;\n delta = Math.max(delta, 1); // TODO: This guards against the timestamp going in the wrong direction by accident. Can we avoid it?\n delta *= playingInfo.direction;\n let newTimestamp = lastTimestamp + delta; // TODO: Pre-emptively clamp.\n let newSmartTimestampRequest: Exclude<TimestampRequest, number> | null =\n null;\n\n if (newTimestamp >= end) {\n if (playingInfo.loop) {\n newTimestamp = modIntoRange(\n newTimestamp,\n timeRange.start,\n timeRange.end,\n );\n } else {\n if (newTimestamp === timeRange.end) {\n newSmartTimestampRequest = \"end\";\n } else {\n newTimestamp = end;\n }\n this.playing = false;\n this.model.playingInfoProp.set({\n playing: false,\n });\n }\n } else if (newTimestamp <= start) {\n if (playingInfo.loop) {\n newTimestamp = modIntoRange(\n newTimestamp,\n timeRange.start,\n timeRange.end,\n );\n } else {\n if (newTimestamp === timeRange.start) {\n newSmartTimestampRequest = \"start\";\n } else {\n newTimestamp = start;\n }\n this.playing = false;\n this.model.playingInfoProp.set({\n playing: false,\n });\n }\n }\n this.lastDatestamp = frameDatestamp;\n this.lastTimestampPromise = Promise.resolve(newTimestamp); // TODO: Save this earlier? / Do we need to worry about the effecitve timestamp disagreeing?\n this.model.timestampRequestProp.set(\n newSmartTimestampRequest ?? newTimestamp,\n );\n }\n}\n", "import type { TwistyPlayerModel } from \"../model/TwistyPlayerModel\";\nimport {\n TwistyAnimationController,\n TwistyAnimationControllerDelegate,\n} from \"./TwistyAnimationController\";\n\nexport class TwistyPlayerController {\n animationController: TwistyAnimationController;\n\n constructor(\n private model: TwistyPlayerModel,\n delegate: TwistyAnimationControllerDelegate,\n ) {\n this.animationController = new TwistyAnimationController(model, delegate);\n }\n\n jumpToStart(options?: { flash: boolean }): void {\n this.animationController.jumpToStart(options);\n }\n\n jumpToEnd(options?: { flash: boolean }): void {\n this.animationController.jumpToEnd(options);\n }\n\n togglePlay(play?: boolean) {\n if (typeof play === \"undefined\") {\n this.animationController.playPause();\n }\n play ? this.animationController.play() : this.animationController.pause();\n }\n\n public async visitTwizzleLink(): Promise<void> {\n const a = document.createElement(\"a\");\n a.href = await this.model.twizzleLink();\n a.target = \"_blank\";\n a.click();\n }\n}\n", "import { CSSSource } from \"./element/ManagedCustomElement\";\n\n// TODO: figure out why `:host(twisty-player):fullscreen { background-color: white }` doesn't work.\nexport const twistyPlayerCSS = new CSSSource(`\n:host {\n width: 384px;\n height: 256px;\n display: grid;\n}\n\n.wrapper {\n display: grid;\n overflow: hidden;\n grid-template-rows: 7fr 1em 1fr;\n}\n\n.wrapper > * {\n width: inherit;\n height: inherit;\n overflow: hidden;\n}\n\n.wrapper.controls-none {\n grid-template-rows: 7fr;\n}\n\n.wrapper.controls-none twisty-scrubber,\n.wrapper.controls-none twisty-control-button-panel ,\n.wrapper.controls-none twisty-scrubber-v2,\n.wrapper.controls-none twisty-buttons-v2 {\n display: none;\n}\n\ntwisty-scrubber {\n background: rgba(196, 196, 196, 0.5);\n}\n\n.wrapper.checkered {\n background-color: #EAEAEA;\n background-image: linear-gradient(45deg, #DDD 25%, transparent 25%, transparent 75%, #DDD 75%, #DDD),\n linear-gradient(45deg, #DDD 25%, transparent 25%, transparent 75%, #DDD 75%, #DDD);\n background-size: 32px 32px;\n background-position: 0 0, 16px 16px;\n}\n\n.visualization-wrapper > * {\n width: 100%;\n height: 100%;\n}\n\n.error-elem {\n width: 100%;\n height: 100%;\n display: none;\n place-content: center;\n font-family: sans-serif;\n box-shadow: inset 0 0 2em rgb(255, 0, 0);\n color: red;\n text-shadow: 0 0 0.2em white;\n background: rgba(255, 255, 255, 0.25);\n}\n\n.wrapper.error .visualization-wrapper {\n display: none;\n}\n\n.wrapper.error .error-elem {\n display: grid;\n}\n`);\n", "// eslint-disable-next-line @typescript-eslint/ban-ts-comment\n// @ts-nocheck\n\n// TODO: Use private class fields when ESLint support it.\n\nexport class PLazy<T> extends Promise<T> {\n constructor(executor) {\n super((resolve) => {\n resolve();\n });\n\n this._executor = executor;\n }\n\n static from(function_) {\n return new PLazy((resolve) => {\n resolve(function_());\n });\n }\n\n static resolve(value) {\n return new PLazy((resolve) => {\n resolve(value);\n });\n }\n\n static reject(error) {\n return new PLazy((_resolve, reject) => {\n reject(error);\n });\n }\n\n then(onFulfilled, onRejected) {\n this._promise = this._promise || new Promise(this._executor);\n\n // eslint-disable-next-line @typescript-eslint/no-unsafe-return\n return this._promise.then(onFulfilled, onRejected);\n }\n\n catch(onRejected) {\n this._promise = this._promise || new Promise(this._executor);\n\n // eslint-disable-next-line @typescript-eslint/no-unsafe-return\n return this._promise.catch(onRejected);\n }\n}\n\nexport function from<T>(function_): Promise<T> {\n return new PLazy((resolve) => {\n resolve(function_());\n });\n}\n", "import { from } from \"../../vendor/p-lazy/p-lazy\";\n\n// TODO can we remove the cached proxy?\n\n// In theory we can, but we've run into situations where imports are not properly cached.\nlet cachedConstructorProxy: Promise<\n typeof import(\"./dynamic-entries/3d\")\n> | null = null;\n\nexport async function proxy3D(): Promise<\n typeof import(\"./dynamic-entries/3d\")\n> {\n return (cachedConstructorProxy ??= import(\"./dynamic-entries/3d\"));\n}\n\nexport const THREEJS: Promise<typeof import(\"three\")> = from(\n async () => (await proxy3D()).T3I,\n);\n", "import { from } from \"../../../vendor/p-lazy/p-lazy\";\nimport { StaleDropper } from \"../PromiseFreshener\";\nimport type { UserVisibleErrorTracker } from \"../UserVisibleErrorTracker\";\n\n/*eslint @typescript-eslint/ban-types:off */\ntype InputRecord = {};\n\nexport type InputProps<T extends InputRecord> = {\n [s in keyof T]: TwistyPropParent<T[s]>;\n};\n\ntype InputPromises<T extends InputRecord> = {\n [s in keyof T]: Promise<T[s]>;\n};\n\ninterface SourceEventDetail<OutputType> {\n sourceProp: TwistyPropSource<OutputType, any>;\n value: Promise<OutputType>; // TODO: remove?\n generation: number;\n}\n\ntype SourceEvent<T> = CustomEvent<SourceEventDetail<T>>;\n\ntype PromiseOrValue<T> = T | Promise<T>;\n\n// Values of T must be immutable.\nlet globalSourceGeneration = 0; // This is incremented before being used, so 1 will be the first active value.\nexport abstract class TwistyPropParent<T> {\n public abstract get(): Promise<T>;\n\n // Don't overwrite this. Overwrite `canReuseValue` instead.\n canReuse(v1: T, v2: T): boolean {\n return v1 === v2 || this.canReuseValue(v1, v2);\n }\n\n // Overwrite with a cheap semantic comparison when possible.\n // Note that this is not called if `v1 === v2` (in which case the value is automatically reused).\n canReuseValue(_v1: T, _v2: T): boolean {\n return false;\n }\n\n debugGetChildren(): Array<TwistyPropDerived<any, any>> {\n return Array.from(this.#children.values());\n }\n\n // Propagation\n\n #children: Set<TwistyPropDerived<any, any>> = new Set();\n protected addChild(child: TwistyPropDerived<any, any>): void {\n this.#children.add(child);\n }\n\n protected removeChild(child: TwistyPropDerived<any, any>): void {\n this.#children.delete(child);\n }\n\n protected lastSourceGeneration: number = 0;\n // Synchronously marks all descendants as stale. This doesn't actually\n // literally mark as stale, but it updates the last source generation, which\n // is used to tell if a cahced result is stale.\n protected markStale(sourceEvent: SourceEvent<any>): void {\n if (sourceEvent.detail.generation !== globalSourceGeneration) {\n // The full stale propagation is synchronous, so there should not be a new one yet.\n throw new Error(\"A TwistyProp was marked stale too late!\");\n }\n if (this.lastSourceGeneration === sourceEvent.detail.generation) {\n // Already propagated.\n return;\n }\n this.lastSourceGeneration = sourceEvent.detail.generation;\n for (const child of this.#children) {\n child.markStale(sourceEvent);\n }\n // We schedule sending out events *after* the (synchronous) propagation has happened, in\n // case one of the listeners updates a source again.\n this.#scheduleRawDispatch();\n }\n\n #rawListeners: Set<() => void> = new Set();\n /** @deprecated */\n addRawListener(listener: () => void, options?: { initial: boolean }): void {\n this.#rawListeners.add(listener);\n if (options?.initial) {\n listener(); // TODO: wrap in a try?\n }\n }\n\n /** @deprecated */\n removeRawListener(listener: () => void): void {\n this.#rawListeners.delete(listener);\n }\n\n /** @deprecated */\n #scheduleRawDispatch(): void {\n if (!this.#rawDispatchPending) {\n this.#rawDispatchPending = true;\n setTimeout(() => this.#dispatchRawListeners(), 0);\n }\n }\n\n #rawDispatchPending: boolean = false;\n #dispatchRawListeners(): void {\n if (!this.#rawDispatchPending) {\n throw new Error(\"Invalid dispatch state!\");\n }\n for (const listener of this.#rawListeners) {\n listener(); // TODO: wrap in a try?\n }\n this.#rawDispatchPending = false;\n }\n\n #freshListeners: Map<(value: T) => void, () => void> = new Map();\n // TODO: Pick a better name.\n addFreshListener(listener: (value: T) => void): void {\n const staleDropper: StaleDropper<T> = new StaleDropper<T>();\n let lastResult: T | null = null;\n const callback = async () => {\n const result = await staleDropper.queue(this.get());\n if (lastResult !== null && this.canReuse(lastResult, result)) {\n return;\n }\n lastResult = result;\n listener(result);\n };\n this.#freshListeners.set(listener, callback);\n this.addRawListener(callback, { initial: true });\n }\n\n removeFreshListener(listener: (value: T) => void): void {\n this.removeRawListener(this.#freshListeners.get(listener)!); // TODO: throw a custom error?\n this.#freshListeners.delete(listener);\n }\n}\n\nexport abstract class TwistyPropSource<\n OutputType,\n InputType = OutputType,\n> extends TwistyPropParent<OutputType> {\n #value: Promise<OutputType>;\n\n public abstract getDefaultValue(): PromiseOrValue<OutputType>;\n\n constructor(initialValue?: PromiseOrValue<InputType>) {\n super();\n this.#value = from(() => this.getDefaultValue());\n if (initialValue) {\n this.#value = this.deriveFromPromiseOrValue(initialValue, this.#value);\n }\n }\n\n set(input: PromiseOrValue<InputType>): void {\n this.#value = this.deriveFromPromiseOrValue(input, this.#value);\n\n const sourceEventDetail: SourceEventDetail<OutputType> = {\n sourceProp: this,\n value: this.#value,\n generation: ++globalSourceGeneration,\n };\n this.markStale(\n new CustomEvent<SourceEventDetail<OutputType>>(\"stale\", {\n detail: sourceEventDetail,\n }),\n );\n }\n\n async get(): Promise<OutputType> {\n return this.#value;\n }\n\n async deriveFromPromiseOrValue(\n input: PromiseOrValue<InputType>,\n oldValuePromise: Promise<OutputType>,\n ): Promise<OutputType> {\n return this.derive(await input, oldValuePromise);\n }\n\n // TODO: add an indirect layer to cache the derivation?\n protected abstract derive(\n input: InputType,\n oldValuePromise: Promise<OutputType>,\n ): PromiseOrValue<OutputType>;\n}\n\nexport abstract class SimpleTwistyPropSource<\n SimpleType,\n> extends TwistyPropSource<SimpleType> {\n derive(input: SimpleType): PromiseOrValue<SimpleType> {\n return input;\n }\n}\n\n// TODO: Can we support `null` as a valid output value without loosening type\n// safety?\nexport const NO_VALUE = Symbol(\"no value\");\nexport type NoValueType = typeof NO_VALUE;\n\nexport abstract class TwistyPropDerived<\n InputTypes extends InputRecord,\n OutputType,\n> extends TwistyPropParent<OutputType> {\n // cachedInputs:\n #parents: InputProps<InputTypes>;\n\n constructor(\n parents: InputProps<InputTypes>,\n protected userVisibleErrorTracker?: UserVisibleErrorTracker,\n ) {\n super();\n this.#parents = parents;\n for (const parent of Object.values(parents)) {\n (\n parent as TwistyPropDerived<InputProps<InputTypes>, OutputType>\n ).addChild(this);\n }\n }\n\n #cachedLastSuccessfulCalculation: {\n inputs: InputTypes;\n output: Promise<OutputType>;\n generation: number;\n } | null = null;\n\n #cachedLatestGenerationCalculation: {\n output: Promise<OutputType>;\n generation: number;\n } | null = null;\n\n public async get(): Promise<OutputType> {\n const generation = this.lastSourceGeneration;\n\n if (this.#cachedLatestGenerationCalculation?.generation === generation) {\n return this.#cachedLatestGenerationCalculation.output;\n }\n\n const latestGenerationCalculation = {\n generation,\n output: this.#cacheDerive(\n this.#getParents(),\n generation,\n this.#cachedLastSuccessfulCalculation,\n ),\n };\n this.#cachedLatestGenerationCalculation = latestGenerationCalculation;\n\n this.userVisibleErrorTracker?.reset();\n return latestGenerationCalculation.output;\n }\n\n async #getParents(): Promise<InputTypes> {\n const inputValuePromises: InputPromises<InputRecord> = {} as any; // TODO\n for (const [key, parent] of Object.entries(this.#parents)) {\n (inputValuePromises as Record<string, Promise<unknown>>)[key] = (\n parent as TwistyPropParent<unknown>\n ).get();\n }\n\n const inputs: InputTypes = {} as any; // TODO\n for (const key in this.#parents) {\n inputs[key] = (await (\n inputValuePromises as Record<string, Promise<unknown>>\n )[key]) as any;\n }\n return inputs;\n }\n\n async #cacheDerive(\n inputsPromise: PromiseOrValue<InputTypes>,\n generation: number,\n cachedLatestGenerationCalculation: {\n inputs: InputTypes;\n output: Promise<OutputType>;\n generation: number;\n } | null = null,\n ): Promise<OutputType> {\n const inputs = await inputsPromise;\n\n const cache = (output: OutputType): OutputType => {\n this.#cachedLastSuccessfulCalculation = {\n inputs,\n output: Promise.resolve(output),\n generation,\n };\n return output;\n };\n\n if (!cachedLatestGenerationCalculation) {\n return cache(await this.derive(inputs));\n }\n\n const cachedInputs = cachedLatestGenerationCalculation.inputs;\n for (const key in this.#parents) {\n const parent = this.#parents[key];\n if (!parent.canReuse(inputs[key], cachedInputs[key])) {\n return cache(await this.derive(inputs));\n }\n }\n\n return cachedLatestGenerationCalculation.output;\n }\n\n protected abstract derive(input: InputTypes): PromiseOrValue<OutputType>;\n}\n\nexport class FreshListenerManager {\n #disconnectionFunctions: (() => void)[] = [];\n\n addListener<T>(\n prop: TwistyPropParent<T>,\n listener: (value: T) => void,\n ): void {\n let disconnected = false;\n const wrappedListener = (value: T) => {\n if (disconnected) {\n // TODO\n // console.warn(\"Should be disconnected!\");\n return;\n }\n listener(value);\n };\n\n prop.addFreshListener(wrappedListener);\n\n this.#disconnectionFunctions.push(() => {\n prop.removeFreshListener(wrappedListener);\n disconnected = true;\n });\n }\n\n addMultiListener<U, V>(\n props: [TwistyPropParent<U>, TwistyPropParent<V>],\n listener: (values: [U, V]) => void,\n ) {\n let disconnected = false;\n const wrappedListener = async (_: any) => {\n if (disconnected) {\n // TODO\n // console.warn(\"Should be disconnected!\");\n return;\n }\n // We rely on `TwistyProp` caching to give us the full set of latest\n // values efficiently.\n const promises = (props as TwistyPropParent<any>[]).map((prop) =>\n prop.get(),\n );\n const values = await Promise.all(promises);\n listener(values as any); // TODO: fix up types\n };\n\n for (const prop of props) {\n prop.addFreshListener(wrappedListener);\n }\n\n this.#disconnectionFunctions.push(() => {\n for (const prop of props) {\n prop.removeFreshListener(wrappedListener);\n }\n disconnected = true;\n });\n }\n\n disconnect(): void {\n for (const disconnectionFunction of this.#disconnectionFunctions) {\n disconnectionFunction();\n }\n }\n}\n", "import { CSSSource } from \"../element/ManagedCustomElement\";\n\n// TODO: Can we do this without so much nesting, and styling all the nested elems?\nexport const twisty2DSVGCSS = new CSSSource(`\n:host {\n width: 384px;\n height: 256px;\n display: grid;\n}\n\n.wrapper {\n width: 100%;\n height: 100%;\n display: grid;\n overflow: hidden;\n}\n\n.svg-wrapper,\ntwisty-2d-svg,\nsvg {\n width: 100%;\n height: 100%;\n display: grid;\n min-height: 0;\n}\n`);\n", "import {\n combineTransformations,\n KPuzzleDefinition,\n KPuzzleSVGWrapper,\n transformationForMove,\n} from \"../../../kpuzzle\";\nimport type { PuzzleLoader } from \"../../../puzzles/PuzzleLoader\";\nimport type { PuzzleAppearance } from \"../../../puzzles/stickerings/appearance\";\nimport type { PositionListener } from \"../../old/animation/cursor/AlgCursor\";\nimport {\n Direction,\n PuzzlePosition,\n} from \"../../old/animation/cursor/CursorTypes\";\nimport { RenderScheduler } from \"../../old/animation/RenderScheduler\";\nimport { ManagedCustomElement } from \"../../old/dom/element/ManagedCustomElement\";\nimport { customElementsShim } from \"../../old/dom/element/node-custom-element-shims\";\nimport type { TwistyPlayerModel } from \"../../model/TwistyPlayerModel\";\nimport { FreshListenerManager } from \"../../model/props/TwistyProp\";\nimport type {\n ExperimentalStickering,\n PuzzleID,\n} from \"../../old/dom/TwistyPlayerConfig\";\nimport { twisty2DSVGCSS } from \"../../old/dom/viewers/Twisty2DSVGView.css\";\nimport type { TwistyViewerElement } from \"../../old/dom/viewers/TwistyViewerElement\";\n\nexport interface Twisty2DPuzzleOptions {\n experimentalStickering?: ExperimentalStickering;\n}\n\n// <twisty-2d-svg>\nexport class Twisty2DPuzzle\n extends ManagedCustomElement\n implements TwistyViewerElement, PositionListener\n{\n private definition: KPuzzleDefinition;\n public svg: KPuzzleSVGWrapper;\n private scheduler = new RenderScheduler(this.render.bind(this));\n #cachedPosition: PuzzlePosition | null = null; // TODO: pull when needed.\n constructor(\n private model?: TwistyPlayerModel,\n def?: KPuzzleDefinition,\n private svgSource?: string,\n private options?: Twisty2DPuzzleOptions,\n private puzzleLoader?: PuzzleLoader,\n ) {\n super();\n this.addCSS(twisty2DSVGCSS);\n\n this.definition = def!;\n this.resetSVG(); // TODO: do this in `connectedCallback()`?\n\n this.#freshListenerManager.addListener(\n this.model!.puzzleIDProp,\n (puzzleID: PuzzleID) => {\n if (puzzleLoader?.id !== puzzleID) {\n this.disconnect();\n }\n },\n );\n\n this.#freshListenerManager.addListener(\n this.model!.legacyPositionProp,\n this.onPositionChange.bind(this),\n );\n\n if (this.options?.experimentalStickering) {\n this.experimentalSetStickering(this.options.experimentalStickering);\n }\n }\n\n #freshListenerManager = new FreshListenerManager();\n disconnect(): void {\n this.#freshListenerManager.disconnect();\n }\n\n onPositionChange(position: PuzzlePosition): void {\n try {\n if (position.movesInProgress.length > 0) {\n const move = position.movesInProgress[0].move;\n\n const def = this.definition;\n let partialMove = move;\n if (position.movesInProgress[0].direction === Direction.Backwards) {\n partialMove = move.invert();\n }\n const newState = combineTransformations(\n def,\n position.state,\n transformationForMove(def, partialMove),\n );\n // TODO: move to render()\n this.svg.draw(\n this.definition,\n position.state,\n newState,\n position.movesInProgress[0].fraction,\n );\n } else {\n this.svg.draw(this.definition, position.state);\n this.#cachedPosition = position;\n }\n } catch (e) {\n console.warn(\n \"Bad position (this doesn't necessarily mean something is wrong). Pre-emptively disconnecting:\",\n this.puzzleLoader?.id,\n e,\n );\n this.disconnect();\n }\n }\n\n scheduleRender(): void {\n this.scheduler.requestAnimFrame();\n }\n\n experimentalSetStickering(stickering: ExperimentalStickering): void {\n (async () => {\n if (!this.puzzleLoader?.appearance) {\n return;\n }\n const appearance = await this.puzzleLoader.appearance(stickering);\n this.resetSVG(appearance);\n })();\n }\n\n // TODO: do this without constructing a new SVG.\n private resetSVG(appearance?: PuzzleAppearance): void {\n if (this.svg) {\n this.removeElement(this.svg.element);\n }\n if (!this.definition) {\n return; // TODO\n }\n this.svg = new KPuzzleSVGWrapper(\n this.definition,\n this.svgSource!,\n appearance,\n ); // TODO\n this.addElement(this.svg.element);\n if (this.#cachedPosition) {\n this.onPositionChange(this.#cachedPosition);\n }\n }\n\n private render(): void {\n /*...*/\n }\n}\n\ncustomElementsShim.define(\"twisty-2d-puzzle\", Twisty2DPuzzle);\n", "import type { PuzzleLoader } from \"../../../puzzles\";\nimport type { ExperimentalStickering } from \"../../../twisty\";\nimport type { TwistyPlayerModel } from \"../../model/TwistyPlayerModel\";\nimport { FreshListenerManager } from \"../../model/props/TwistyProp\";\nimport type { Schedulable } from \"../../old/animation/RenderScheduler\";\nimport { Twisty2DPuzzle } from \"./Twisty2DPuzzle\";\n\nexport class Twisty2DPuzzleWrapper implements Schedulable {\n constructor(\n private model: TwistyPlayerModel,\n public schedulable: Schedulable,\n private puzzleLoader: PuzzleLoader,\n private effectiveVisualization: \"2D\" | \"experimental-2D-LL\",\n ) {\n this.twisty2DPuzzle(); // Start constructing.\n\n this.#freshListenerManager.addListener(\n this.model.stickeringProp,\n async (stickering: ExperimentalStickering) => {\n (await this.twisty2DPuzzle()).experimentalSetStickering(stickering);\n },\n );\n }\n\n #freshListenerManager = new FreshListenerManager();\n disconnect(): void {\n this.#freshListenerManager.disconnect();\n }\n\n // TODO: Hook this up nicely.\n scheduleRender(): void {\n // Nothing\n }\n\n #cachedTwisty2DPuzzle: Promise<Twisty2DPuzzle> | null = null;\n // TODO: Stale dropper?\n async twisty2DPuzzle(): Promise<Twisty2DPuzzle> {\n return (this.#cachedTwisty2DPuzzle ??= (async () => {\n const svgPromise =\n this.effectiveVisualization === \"experimental-2D-LL\"\n ? this.puzzleLoader.llSVG!()\n : this.puzzleLoader.svg();\n return new Twisty2DPuzzle(\n this.model,\n await this.puzzleLoader.def(),\n await svgPromise,\n {},\n this.puzzleLoader,\n );\n })());\n }\n}\n", "import type { Scene as ThreeScene } from \"three\";\nimport type { PuzzleLoader } from \"../../../puzzles\";\nimport { THREEJS } from \"../../heavy-code-imports/3d\";\nimport type { TwistyPlayerModel } from \"../../model/TwistyPlayerModel\";\nimport { FreshListenerManager } from \"../../model/props/TwistyProp\";\nimport type { Schedulable } from \"../../old/animation/RenderScheduler\";\nimport { ManagedCustomElement } from \"../../old/dom/element/ManagedCustomElement\";\nimport { customElementsShim } from \"../../old/dom/element/node-custom-element-shims\";\nimport { twistyViewerWrapperCSS } from \"../../old/dom/viewers/TwistyViewerWrapper.css\";\nimport { Twisty2DPuzzleWrapper } from \"./Twisty2DPuzzleWrapper\";\n\nexport class Twisty2DSceneWrapper\n extends ManagedCustomElement\n implements Schedulable\n{\n #freshListenerManager = new FreshListenerManager();\n disconnect(): void {\n this.#freshListenerManager.disconnect();\n }\n\n constructor(\n public model?: TwistyPlayerModel,\n private effectiveVisualization?: \"2D\" | \"experimental-2D-LL\",\n ) {\n super();\n }\n\n async connectedCallback(): Promise<void> {\n this.addCSS(twistyViewerWrapperCSS);\n if (this.model) {\n this.#freshListenerManager.addListener(\n this.model.puzzleLoaderProp,\n this.onPuzzleLoader.bind(this),\n );\n }\n }\n\n #cachedScene: Promise<ThreeScene> | null;\n async scene(): Promise<ThreeScene> {\n return (this.#cachedScene ??= (async () => new (await THREEJS).Scene())());\n }\n\n scheduleRender(): void {\n this.#currentTwisty2DPuzzleWrapper?.scheduleRender();\n }\n\n #currentTwisty2DPuzzleWrapper: Twisty2DPuzzleWrapper | null = null;\n currentTwisty2DPuzzleWrapper(): Twisty2DPuzzleWrapper | null {\n return this.#currentTwisty2DPuzzleWrapper;\n }\n\n // #oldTwisty3DPuzzleWrappers: Twisty3DPuzzleWrapper[] = []; // TODO: Animate these out.\n async setCurrentTwisty2DPuzzleWrapper(\n twisty2DPuzzleWrapper: Twisty2DPuzzleWrapper,\n ): Promise<void> {\n const old = this.#currentTwisty2DPuzzleWrapper;\n this.#currentTwisty2DPuzzleWrapper = twisty2DPuzzleWrapper;\n old?.disconnect(); // TODO: Disconnect properly.\n const twisty2DPuzzlePromise = twisty2DPuzzleWrapper.twisty2DPuzzle();\n this.contentWrapper.textContent = \"\"; // Clear existing ones.\n this.addElement(await twisty2DPuzzlePromise);\n }\n\n async onPuzzleLoader(puzzleLoader: PuzzleLoader): Promise<void> {\n this.#currentTwisty2DPuzzleWrapper?.disconnect();\n const twisty2DPuzzleWrapper = new Twisty2DPuzzleWrapper(\n this.model!,\n this,\n puzzleLoader,\n this.effectiveVisualization!,\n );\n\n this.setCurrentTwisty2DPuzzleWrapper(twisty2DPuzzleWrapper);\n }\n}\n\ncustomElementsShim.define(\"twisty-2d-scene-wrapper\", Twisty2DSceneWrapper);\n", "import type { Texture as ThreeTexture } from \"three\";\nimport { experimentalCubeAppearance, PuzzleLoader } from \"../../../puzzles\";\nimport type { ExperimentalStickering } from \"../../../twisty\";\nimport { proxy3D } from \"../../heavy-code-imports/3d\";\nimport type { Cube3D, PG3D } from \"../../heavy-code-imports/dynamic-entries/3d\";\nimport type { HintFaceletStyleWithAuto } from \"../../model/props/puzzle/display/HintFaceletProp\";\nimport type { VisualizationStrategy } from \"../../model/props/viewer/VisualizationStrategyProp\";\nimport type { TwistyPlayerModel } from \"../../model/TwistyPlayerModel\";\nimport { FreshListenerManager } from \"../../model/props/TwistyProp\";\nimport type { PuzzlePosition } from \"../../old/animation/cursor/CursorTypes\";\nimport type { Schedulable } from \"../../old/animation/RenderScheduler\";\nimport type { Twisty3DPuzzle } from \"./puzzles/Twisty3DPuzzle\";\n\nexport class Twisty3DPuzzleWrapper implements Schedulable {\n constructor(\n private model: TwistyPlayerModel,\n public schedulable: Schedulable,\n private puzzleLoader: PuzzleLoader,\n private visualizationStrategy: VisualizationStrategy,\n ) {\n this.twisty3DPuzzle(); // Start constructing.\n\n // TODO: Hook up listeners before loading the heavy code in the async constructor, so we get any intermediate updates?\n // Repro: Switch to 40x40x40 a fraction of a second before animation finishes. When it's loaded the itmeline is at the end, but the 40x40x40 is rendered with an earlier position.\n\n this.#freshListenerManager.addListener(\n this.model.puzzleLoaderProp,\n (puzzleLoader: PuzzleLoader) => {\n if (this.puzzleLoader.id !== puzzleLoader.id) {\n this.disconnect();\n }\n },\n );\n this.#freshListenerManager.addListener(\n this.model.legacyPositionProp,\n async (position: PuzzlePosition) => {\n try {\n (await this.twisty3DPuzzle()).onPositionChange(position);\n this.scheduleRender();\n } catch (e) {\n // TODO\n // console.warn(\n // \"Bad position (this doesn't necessarily mean something is wrong). Pre-emptively disconnecting:\",\n // this.puzzleLoader.id,\n // e,\n // );\n this.disconnect();\n }\n },\n );\n\n this.#freshListenerManager.addListener(\n this.model.hintFaceletProp,\n async (hintFaceletStyle: HintFaceletStyleWithAuto) => {\n (\n (await this.twisty3DPuzzle()) as Cube3D | PG3D\n ).experimentalUpdateOptions({\n hintFacelets:\n hintFaceletStyle === \"auto\" ? \"floating\" : hintFaceletStyle,\n });\n this.scheduleRender();\n },\n );\n this.#freshListenerManager.addListener(\n this.model.stickeringProp,\n async (stickering: ExperimentalStickering) => {\n if (\"setStickering\" in (await this.twisty3DPuzzle())) {\n ((await this.twisty3DPuzzle()) as Cube3D).setStickering(stickering);\n this.scheduleRender();\n } else {\n if (\n [\n \"experimental-global-custom-1\",\n \"experimental-global-custom-2\",\n ].includes(stickering)\n ) {\n const [twisty3D] = await Promise.all([this.twisty3DPuzzle()]);\n (twisty3D as PG3D).experimentalSetAppearance(\n await experimentalCubeAppearance(this.puzzleLoader, stickering),\n );\n this.scheduleRender();\n return;\n }\n\n // TODO: create a prop to handle this.\n if (\"appearance\" in this.puzzleLoader) {\n const [twisty3D, appearancePromise] = await Promise.all([\n this.twisty3DPuzzle(),\n this.puzzleLoader.appearance!(stickering ?? \"full\"),\n ]);\n (twisty3D as PG3D).experimentalSetAppearance(appearancePromise);\n this.scheduleRender();\n }\n }\n },\n );\n\n this.#freshListenerManager.addMultiListener(\n [this.model.foundationStickerSprite, this.model.hintStickerSprite],\n async (\n inputs: [\n foundationSprite: ThreeTexture | null,\n hintSprite: ThreeTexture | null,\n ],\n ) => {\n if (\"experimentalUpdateTexture\" in (await this.twisty3DPuzzle())) {\n ((await this.twisty3DPuzzle()) as PG3D).experimentalUpdateTexture(\n true,\n ...inputs,\n );\n this.scheduleRender();\n }\n },\n );\n }\n\n #freshListenerManager = new FreshListenerManager();\n disconnect(): void {\n this.#freshListenerManager.disconnect();\n }\n\n scheduleRender(): void {\n this.schedulable.scheduleRender();\n }\n\n #cachedTwisty3DPuzzle: Promise<Twisty3DPuzzle> | null = null;\n async twisty3DPuzzle(): Promise<Twisty3DPuzzle> {\n return (this.#cachedTwisty3DPuzzle ??= (async () => {\n const proxyPromise = proxy3D();\n if (\n this.puzzleLoader.id === \"3x3x3\" &&\n this.visualizationStrategy === \"Cube3D\"\n ) {\n // TODO: synchronize\n const [foundationSprite, hintSprite, experimentalStickering] =\n await Promise.all([\n this.model.foundationStickerSprite.get(),\n this.model.hintStickerSprite.get(),\n this.model.stickeringProp.get(),\n ]);\n return (await proxyPromise).cube3DShim({\n foundationSprite,\n hintSprite,\n experimentalStickering,\n });\n } else {\n const [hintFacelets, foundationSprite, hintSprite] = await Promise.all([\n this.model.hintFaceletProp.get(),\n this.model.foundationStickerSprite.get(),\n this.model.hintStickerSprite.get(),\n ]);\n const pg3d = (await proxyPromise).pg3dShim(\n this.puzzleLoader,\n hintFacelets === \"auto\" ? \"floating\" : hintFacelets,\n );\n // TODO: Figure out how to do this in one place using the listener.\n pg3d.then((p) =>\n p.experimentalUpdateTexture(\n true,\n foundationSprite ?? undefined,\n hintSprite ?? undefined,\n ),\n );\n return pg3d;\n }\n })());\n }\n}\n", "// TODO: https://stackoverflow.com/a/40443642\n\n// let shareAllNewRenderers: boolean = false;\n\n// // WARNING: The current shared renderer implementation is not every efficient.\n// // Avoid using for players that are likely to have dimensions approaching 1 megapixel or higher.\n// // TODO: use a dedicated renderer while fullscreen?\n// export function experimentalSetShareAllNewRenderers(share: boolean): void {\n// shareAllNewRenderers = share;\n// }\n\n// const sharedRenderer: WebGLRenderer | null = null;\n\nimport { THREEJS } from \"../../heavy-code-imports/3d\";\nimport type { Camera, Scene, WebGLRenderer } from \"three\";\nimport { pixelRatio } from \"../../old/dom/viewers/canvas\";\n\nconst renderers: Promise<WebGLRenderer>[] = [];\n\n// let haveSet = false;\nexport async function renderPooled(\n width: number,\n height: number,\n canvas: HTMLCanvasElement,\n scene: Scene,\n camera: Camera,\n): Promise<void> {\n if (width === 0 || height === 0) {\n return;\n }\n // At most one in the pool for now.\n if (renderers.length === 0) {\n renderers.push(newRenderer());\n }\n const renderer = await renderers[0];\n // TODO: scissoring\n renderer.setSize(width, height); // TODO: is it faster if we cache values and only call this when necessary?\n renderer.render(scene, camera);\n\n const context = canvas.getContext(\"2d\")!;\n context.clearRect(0, 0, canvas.width, canvas.height);\n context.drawImage(renderer.domElement, 0, 0);\n}\n\nexport async function newRenderer(): Promise<WebGLRenderer> {\n const rendererConstructor = (await THREEJS).WebGLRenderer;\n const renderer = new rendererConstructor({\n antialias: true,\n alpha: true,\n });\n renderer.setPixelRatio(pixelRatio());\n return renderer;\n}\n", "import { Spherical, Vector3 } from \"three\";\nimport { DEGREES_PER_RADIAN } from \"./TAU\";\nimport { RenderScheduler } from \"../../old/animation/RenderScheduler\";\nimport type { OrbitCoordinatesV2 } from \"../../model/props/viewer/OrbitCoordinatesRequestProp\";\nimport type { TwistyPlayerModel } from \"../../model/TwistyPlayerModel\";\nimport type { CameraLatitudeLimits } from \"../../old/dom/TwistyPlayerConfig\";\n\nconst INERTIA_DEFAULT: boolean = true;\nconst LATITUDE_LIMITS_DEFAULT: CameraLatitudeLimits = \"auto\";\n\nconst INERTIA_DURATION_MS = 500;\n// If the first inertial render is this long after the last move, we assume the\n// user has halted the cursor and we consider inertia to have \"timed out\". We\n// never begin animating the inertia.\nconst INERTIA_TIMEOUT_MS = 50;\n\nconst VERTICAL_MOVEMENT_BASE_SCALE = 0.75;\n\n// progress is from 0 to 1.\nfunction momentumScale(progress: number) {\n // This is the exponential curve flipped so that\n // - The slope at progress = 0 is 1 (this corresponds to \"x = 1\" on the normal\n // curve).\n // - The scale exponentially \"decays\" until progress = 1.\n // This means the scale at the end will be about 0.418\n return (Math.exp(1 - progress) - (1 - progress)) / (1 - Math.E) + 1;\n}\n\nclass Inertia {\n private scheduler = new RenderScheduler(this.render.bind(this));\n private lastTimestamp: number;\n constructor(\n private startTimestamp: number,\n private momentumX: number,\n private momentumY: number,\n private callback: (movementX: number, movementY: number) => void,\n ) {\n this.scheduler.requestAnimFrame();\n this.lastTimestamp = startTimestamp;\n }\n\n private render(now: DOMHighResTimeStamp) {\n const progressBefore =\n (this.lastTimestamp - this.startTimestamp) / INERTIA_DURATION_MS;\n const progressAfter = Math.min(\n 1,\n (now - this.startTimestamp) / INERTIA_DURATION_MS,\n );\n\n if (\n progressBefore === 0 &&\n progressAfter > INERTIA_TIMEOUT_MS / INERTIA_DURATION_MS\n ) {\n // The user has already paused for a while. Don't start any inertia.\n return;\n }\n\n const delta = momentumScale(progressAfter) - momentumScale(progressBefore);\n\n // TODO: For now, we only carry horizontal momentum. If this should stay, we\n // can remove the plumbing for the Y dimension.\n this.callback(this.momentumX * delta * 1000, this.momentumY * delta * 1000);\n\n if (progressAfter < 1) {\n this.scheduler.requestAnimFrame();\n }\n this.lastTimestamp = now;\n }\n}\n\n// export interface OrbitCoordinates {\n// latitude: number;\n// longitude: number;\n// distance: number;\n// }\n\nexport function positionToOrbitCoordinates(\n position: Vector3,\n): OrbitCoordinatesV2 {\n const spherical = new Spherical();\n spherical.setFromVector3(position);\n return {\n latitude: 90 - spherical.phi * DEGREES_PER_RADIAN,\n longitude: spherical.theta * DEGREES_PER_RADIAN,\n distance: spherical.radius,\n };\n}\n\n// TODO: change mouse cursor while moving.\nexport class TwistyOrbitControlsV2 {\n /** @deprecated */\n experimentalInertia: boolean = INERTIA_DEFAULT;\n /** @deprecated */\n experimentalLatitudeLimits: CameraLatitudeLimits = LATITUDE_LIMITS_DEFAULT;\n private lastTouchClientX: number = 0;\n private lastTouchClientY: number = 0;\n private currentTouchID: number | null = null; // TODO: support multiple touches?\n private onMoveBound = this.onMove.bind(this);\n private onMouseMoveBound = this.onMouseMove.bind(this);\n private onMouseEndBound = this.onMouseEnd.bind(this);\n private onTouchMoveBound = this.onTouchMove.bind(this);\n private onTouchEndBound = this.onTouchEnd.bind(this);\n private lastTouchTimestamp: number = 0;\n private lastTouchMoveMomentumX: number = 0;\n private lastTouchMoveMomentumY: number = 0;\n private lastMouseTimestamp: number = 0;\n private lastMouseMoveMomentumX: number = 0;\n private lastMouseMoveMomentumY: number = 0;\n public experimentalHasBeenMoved: boolean = false;\n constructor(\n private model: TwistyPlayerModel,\n private mirror: boolean,\n private canvas: HTMLCanvasElement,\n ) {\n canvas.addEventListener(\"mousedown\", this.onMouseStart.bind(this));\n canvas.addEventListener(\"touchstart\", this.onTouchStart.bind(this));\n }\n\n // f is the fraction of the canvas traversed per ms.\n temperMovement(f: number): number {\n // This is scaled to be linear for small values, but to reduce large values\n // by a significant factor.\n return (Math.sign(f) * Math.log(Math.abs(f * 10) + 1)) / 6;\n }\n\n onMouseStart(e: MouseEvent): void {\n window.addEventListener(\"mousemove\", this.onMouseMoveBound);\n window.addEventListener(\"mouseup\", this.onMouseEndBound);\n this.onStart(e);\n\n this.lastMouseTimestamp = e.timeStamp;\n }\n\n onMouseMove(e: MouseEvent): void {\n if (e.buttons === 0) {\n // Certain elements (e.g. disabled buttons) can capture the `mouseup`\n // event. So if we notice that there are no mouse buttons pressed, we stop\n // the movement.\n this.onMouseEnd(e);\n return;\n }\n\n if (e.movementX === 0 && e.movementY === 0) {\n // Short-circuit\n return;\n }\n\n const minDim = Math.min(this.canvas.offsetWidth, this.canvas.offsetHeight);\n const movementX = this.temperMovement(e.movementX / minDim);\n const movementY = this.temperMovement(\n (e.movementY / minDim) * VERTICAL_MOVEMENT_BASE_SCALE,\n );\n this.onMove(movementX, movementY);\n\n const deltaMs = e.timeStamp - this.lastMouseTimestamp;\n if (deltaMs > 0) {\n this.lastMouseMoveMomentumX = movementX / deltaMs;\n this.lastMouseMoveMomentumY = movementY / deltaMs;\n this.lastMouseTimestamp = e.timeStamp;\n }\n }\n\n onMouseEnd(e: MouseEvent): void {\n window.removeEventListener(\"mousemove\", this.onMouseMoveBound);\n window.removeEventListener(\"mouseup\", this.onMouseEndBound);\n this.onEnd(e);\n\n if (this.experimentalInertia) {\n new Inertia(\n this.lastMouseTimestamp,\n this.lastMouseMoveMomentumX,\n this.lastMouseMoveMomentumY,\n this.onMoveBound,\n );\n }\n }\n\n onTouchStart(e: TouchEvent): void {\n if (this.currentTouchID === null) {\n if (e.touches[0].clientX === 0 && e.touches[0].clientY === 0) {\n // Short-circuit\n return;\n }\n this.currentTouchID = e.changedTouches[0].identifier;\n this.lastTouchClientX = e.touches[0].clientX;\n this.lastTouchClientY = e.touches[0].clientY;\n window.addEventListener(\"touchmove\", this.onTouchMoveBound);\n window.addEventListener(\"touchend\", this.onTouchEndBound);\n window.addEventListener(\"touchcancel\", this.onTouchEndBound);\n this.onStart(e);\n\n this.lastTouchTimestamp = e.timeStamp;\n }\n }\n\n onTouchMove(e: TouchEvent): void {\n for (let i = 0; i < e.changedTouches.length; i++) {\n const touch = e.changedTouches[i];\n if (touch.identifier === this.currentTouchID) {\n const minDim = Math.min(\n this.canvas.offsetWidth,\n this.canvas.offsetHeight,\n );\n const movementX = this.temperMovement(\n (touch.clientX - this.lastTouchClientX) / minDim,\n );\n const movementY = this.temperMovement(\n ((touch.clientY - this.lastTouchClientY) / minDim) *\n VERTICAL_MOVEMENT_BASE_SCALE,\n );\n this.onMove(movementX, movementY);\n this.lastTouchClientX = touch.clientX;\n this.lastTouchClientY = touch.clientY;\n\n const deltaMs = e.timeStamp - this.lastTouchTimestamp;\n if (deltaMs > 0) {\n this.lastTouchMoveMomentumX = movementX / deltaMs;\n this.lastTouchMoveMomentumY = movementY / deltaMs;\n this.lastTouchTimestamp = e.timeStamp;\n }\n }\n }\n }\n\n onTouchEnd(e: TouchEvent): void {\n for (let i = 0; i < e.changedTouches.length; i++) {\n const touch = e.changedTouches[i];\n if (touch.identifier === this.currentTouchID) {\n this.currentTouchID = null;\n window.removeEventListener(\"touchmove\", this.onTouchMoveBound);\n window.removeEventListener(\"touchend\", this.onTouchEndBound);\n window.removeEventListener(\"touchcancel\", this.onTouchEndBound);\n this.onEnd(e);\n }\n }\n\n if (this.experimentalInertia) {\n new Inertia(\n this.lastTouchTimestamp,\n this.lastTouchMoveMomentumX,\n this.lastTouchMoveMomentumY,\n this.onMoveBound,\n );\n }\n }\n\n onStart(e: MouseEvent | TouchEvent): void {\n e.preventDefault();\n }\n\n async onMove(movementX: number, movementY: number): Promise<void> {\n const scale = this.mirror ? -1 : 1;\n this.model.orbitCoordinatesRequestProp.set(\n (async () => {\n const prevCoords = await this.model.orbitCoordinatesProp.get();\n const newCoords = {\n latitude:\n prevCoords.latitude + 2 * movementY * DEGREES_PER_RADIAN * scale,\n longitude: prevCoords.longitude - 2 * movementX * DEGREES_PER_RADIAN,\n };\n // console.log(\"coords\", prevCoords, newCoords);\n return newCoords;\n })(),\n );\n }\n\n onEnd(e: MouseEvent | TouchEvent): void {\n e.preventDefault();\n }\n}\n", "import type { PerspectiveCamera, WebGLRenderer } from \"three\";\nimport { Stats } from \"../../../vendor/three/examples/jsm/libs/stats.modified.module\";\nimport { THREEJS } from \"../../heavy-code-imports/3d\";\nimport { StaleDropper } from \"../../model/PromiseFreshener\";\nimport type { TwistyPropParent } from \"../../model/props/TwistyProp\";\nimport type { OrbitCoordinatesV2 } from \"../../model/props/viewer/OrbitCoordinatesRequestProp\";\nimport type { TwistyPlayerModel } from \"../../model/TwistyPlayerModel\";\nimport { RenderScheduler } from \"../../old/animation/RenderScheduler\";\nimport { ManagedCustomElement } from \"../../old/dom/element/ManagedCustomElement\";\nimport { customElementsShim } from \"../../old/dom/element/node-custom-element-shims\";\nimport { pixelRatio } from \"../../old/dom/viewers/canvas\";\nimport { twisty3DCanvasCSS } from \"../../old/dom/viewers/Twisty3DCanvas.css\";\nimport { newRenderer, renderPooled } from \"./RendererPool\";\nimport { DEGREES_PER_RADIAN } from \"./TAU\";\nimport type { Twisty3DSceneWrapper } from \"./Twisty3DSceneWrapper\";\nimport { TwistyOrbitControlsV2 } from \"./TwistyOrbitControlsV2\";\n\nlet SHOW_STATS = false;\nexport function showStats(enable: boolean): void {\n SHOW_STATS = enable;\n}\n\nexport async function setCameraFromOrbitCoordinates(\n camera: PerspectiveCamera,\n orbitCoordinates: OrbitCoordinatesV2,\n backView: boolean = false,\n): Promise<void> {\n const spherical = new (await THREEJS).Spherical(\n orbitCoordinates.distance,\n (90 - (backView ? -1 : 1) * orbitCoordinates.latitude) / DEGREES_PER_RADIAN,\n ((backView ? 180 : 0) + orbitCoordinates.longitude) / DEGREES_PER_RADIAN,\n );\n spherical.makeSafe();\n camera.position.setFromSpherical(spherical);\n camera.lookAt(0, 0, 0);\n}\n\nlet shareAllNewRenderers: boolean | null = null;\n\n// WARNING: The current shared renderer implementation is not every efficient.\n// Avoid using for players that are likely to have dimensions approaching 1 megapixel or higher.\n// TODO: use a dedicated renderer while fullscreen?\nexport function experimentalSetShareAllNewRenderers(share: boolean): void {\n shareAllNewRenderers = share;\n}\n\nlet anyRenderersSofar = false;\nfunction shareRenderer(): boolean {\n if (shareAllNewRenderers !== null) {\n return shareAllNewRenderers;\n }\n if (!anyRenderersSofar) {\n anyRenderersSofar = true;\n return false;\n }\n return true;\n}\n\nexport class Twisty3DVantage extends ManagedCustomElement {\n scene: Twisty3DSceneWrapper | null = null;\n\n stats: Stats | null = null;\n\n private rendererIsShared: boolean = shareRenderer();\n\n constructor(\n private model?: TwistyPlayerModel,\n scene?: Twisty3DSceneWrapper,\n private options?: { backView?: boolean },\n ) {\n super();\n this.scene = scene ?? null;\n\n if (SHOW_STATS) {\n this.stats = new Stats();\n this.stats.dom.style.position = \"absolute\";\n this.contentWrapper.appendChild(this.stats.dom);\n }\n }\n\n async connectedCallback(): Promise<void> {\n this.addCSS(twisty3DCanvasCSS);\n this.addElement(await this.canvas());\n\n this.#onResize();\n const observer = new ResizeObserver(this.#onResize.bind(this));\n observer.observe(this.contentWrapper);\n this.orbitControls(); // TODO\n this.scheduleRender();\n }\n\n #onResizeStaleDropper = new StaleDropper<PerspectiveCamera>();\n\n // TODO: Why doesn't this work for the top-right back view height?\n #width: number = 0;\n #height: number = 0;\n async #onResize(): Promise<void> {\n const camera = await this.#onResizeStaleDropper.queue(this.camera());\n\n const w = this.contentWrapper.clientWidth;\n const h = this.contentWrapper.clientHeight;\n this.#width = w;\n this.#height = h;\n const off = 0;\n let yoff = 0;\n let excess = 0;\n if (h > w) {\n excess = h - w;\n yoff = -Math.floor(0.5 * excess);\n }\n camera.aspect = w / h;\n camera.setViewOffset(w, h - excess, off, yoff, w, h);\n camera.updateProjectionMatrix(); // TODO\n\n if (this.rendererIsShared) {\n const canvas = await this.canvas();\n canvas.width = w * pixelRatio();\n canvas.height = h * pixelRatio();\n canvas.style.width = w.toString();\n canvas.style.height = w.toString();\n } else {\n (await this.renderer()).setSize(w, h, true);\n }\n\n this.scheduleRender();\n }\n\n #cachedRenderer: Promise<WebGLRenderer> | null = null;\n async renderer(): Promise<WebGLRenderer> {\n if (this.rendererIsShared) {\n throw new Error(\"renderer expected to be shared.\");\n }\n return (this.#cachedRenderer ??= newRenderer());\n }\n\n #cachedCanvas: Promise<HTMLCanvasElement> | null = null;\n async canvas(): Promise<HTMLCanvasElement> {\n return (this.#cachedCanvas ??= (async () => {\n if (this.rendererIsShared) {\n return this.addElement(document.createElement(\"canvas\"));\n }\n const renderer = await this.renderer();\n return this.addElement(renderer.domElement);\n })());\n }\n\n #cachedCamera: Promise<PerspectiveCamera> | null = null;\n async camera(): Promise<PerspectiveCamera> {\n return (this.#cachedCamera ??= (async () => {\n const camera = new (await THREEJS).PerspectiveCamera(\n 20,\n 1, // We rely on the resize logic to handle this.\n 0.1,\n 20,\n );\n camera.position.copy(\n new (await THREEJS).Vector3(2, 4, 4).multiplyScalar(\n this.options?.backView ? -1 : 1,\n ),\n );\n camera.lookAt(0, 0, 0);\n // TODO: `TwistyOrbitControls` breaks isolateion\n return camera;\n })());\n }\n\n #cachedOrbitControls: Promise<TwistyOrbitControlsV2> | null = null;\n async orbitControls(): Promise<TwistyOrbitControlsV2> {\n return (this.#cachedOrbitControls ??= (async () => {\n const orbitControls = new TwistyOrbitControlsV2(\n this.model!,\n !!this.options?.backView,\n await this.canvas(),\n );\n\n if (this.model) {\n this.addListener(\n this.model.orbitCoordinatesProp,\n async (orbitCoordinates: OrbitCoordinatesV2) => {\n const camera = await this.camera();\n setCameraFromOrbitCoordinates(\n camera,\n orbitCoordinates,\n this.options?.backView,\n );\n // TODO: Wrap in StaleDropper?\n\n this.scheduleRender();\n },\n );\n }\n\n return orbitControls;\n })());\n }\n\n addListener<T>(\n prop: TwistyPropParent<T>,\n listener: (value: T) => void,\n ): void {\n prop.addFreshListener(listener);\n this.#disconnectionFunctions.push(() => {\n prop.removeFreshListener(listener);\n // disconnected = true; // TODO\n });\n }\n\n #disconnectionFunctions: (() => void)[] = [];\n disconnect(): void {\n for (const fn of this.#disconnectionFunctions) {\n fn();\n }\n this.#disconnectionFunctions = []; // TODO: Encapsulate this.\n }\n\n async render(): Promise<void> {\n if (!this.scene) {\n throw new Error(\"Attempted to render without a scene\");\n }\n\n this.stats?.begin();\n\n const [scene, camera, canvas] = await Promise.all([\n this.scene.scene(),\n this.camera(),\n this.canvas(),\n ]);\n if (this.rendererIsShared) {\n renderPooled(this.#width, this.#height, canvas, scene, camera);\n } else {\n (await this.renderer()).render(scene, camera);\n }\n\n this.stats?.end();\n }\n\n #scheduler = new RenderScheduler(this.render.bind(this));\n scheduleRender(): void {\n // console.log(\"scheduling\", this);\n this.#scheduler.requestAnimFrame();\n }\n}\n\ncustomElementsShim.define(\"twisty-3d-vantage-v2\", Twisty3DVantage);\n", "import type { Scene as ThreeScene } from \"three\";\nimport type { PuzzleLoader } from \"../../../puzzles\";\nimport { THREEJS } from \"../../heavy-code-imports/3d\";\nimport type { BackViewLayoutWithAuto } from \"../../model/props/viewer/BackViewProp\";\nimport type { VisualizationStrategy } from \"../../model/props/viewer/VisualizationStrategyProp\";\nimport { StaleDropper } from \"../../model/PromiseFreshener\";\nimport type { TwistyPlayerModel } from \"../../model/TwistyPlayerModel\";\nimport { FreshListenerManager } from \"../../model/props/TwistyProp\";\nimport type { Schedulable } from \"../../old/animation/RenderScheduler\";\nimport { ClassListManager } from \"../../old/dom/element/ClassListManager\";\nimport { ManagedCustomElement } from \"../../old/dom/element/ManagedCustomElement\";\nimport { customElementsShim } from \"../../old/dom/element/node-custom-element-shims\";\nimport type { BackViewLayout } from \"../../old/dom/viewers/TwistyViewerWrapper\";\nimport { twistyViewerWrapperCSS } from \"../../old/dom/viewers/TwistyViewerWrapper.css\";\nimport { Twisty3DPuzzleWrapper } from \"./Twisty3DPuzzleWrapper\";\nimport { Twisty3DVantage } from \"./Twisty3DVantage\";\n\nexport class Twisty3DSceneWrapper\n extends ManagedCustomElement\n implements Schedulable\n{\n #backViewClassListManager: ClassListManager<BackViewLayoutWithAuto> =\n new ClassListManager(this, \"back-view-\", [\n \"auto\",\n \"none\",\n \"side-by-side\",\n \"top-right\",\n ]);\n\n #freshListenerManager = new FreshListenerManager();\n disconnect(): void {\n this.#freshListenerManager.disconnect();\n }\n\n constructor(public model?: TwistyPlayerModel) {\n super();\n }\n\n async connectedCallback(): Promise<void> {\n this.addCSS(twistyViewerWrapperCSS);\n const vantage = new Twisty3DVantage(this.model, this);\n this.addVantage(vantage);\n if (this.model) {\n this.#freshListenerManager.addMultiListener(\n [this.model.puzzleLoaderProp, this.model.visualizationStrategyProp],\n this.onPuzzle.bind(this),\n );\n this.#freshListenerManager.addListener(\n this.model.backViewProp,\n this.onBackView.bind(this),\n );\n }\n this.scheduleRender();\n }\n\n #backViewVantage: Twisty3DVantage | null = null;\n setBackView(backView: BackViewLayout): void {\n const shouldHaveBackView = [\"side-by-side\", \"top-right\"].includes(backView);\n const hasBackView = this.#backViewVantage !== null;\n\n this.#backViewClassListManager.setValue(backView);\n if (shouldHaveBackView) {\n if (!hasBackView) {\n this.#backViewVantage = new Twisty3DVantage(this.model, this, {\n backView: true,\n });\n this.addVantage(this.#backViewVantage);\n this.scheduleRender();\n }\n } else {\n if (this.#backViewVantage) {\n this.removeVantage(this.#backViewVantage);\n this.#backViewVantage = null;\n }\n }\n }\n\n onBackView(backView: BackViewLayout): void {\n this.setBackView(backView);\n }\n\n #cachedScene: Promise<ThreeScene> | null;\n async scene(): Promise<ThreeScene> {\n return (this.#cachedScene ??= (async () => new (await THREEJS).Scene())());\n }\n\n #vantages: Set<Twisty3DVantage> = new Set();\n addVantage(vantage: Twisty3DVantage) {\n this.#vantages.add(vantage);\n this.contentWrapper.appendChild(vantage);\n }\n\n removeVantage(vantage: Twisty3DVantage) {\n this.#vantages.delete(vantage);\n vantage.remove();\n vantage.disconnect();\n this.#currentTwisty3DPuzzleWrapper?.disconnect();\n }\n\n experimentalVantages(): Iterable<Twisty3DVantage> {\n return this.#vantages.values();\n }\n\n scheduleRender(): void {\n for (const vantage of this.#vantages) {\n vantage.scheduleRender();\n }\n }\n\n #currentTwisty3DPuzzleWrapper: Twisty3DPuzzleWrapper | null = null;\n // #oldTwisty3DPuzzleWrappers: Twisty3DPuzzleWrapper[] = []; // TODO: Animate these out.\n async setCurrentTwisty3DPuzzleWrapper(\n scene: ThreeScene,\n twisty3DPuzzleWrapper: Twisty3DPuzzleWrapper,\n ): Promise<void> {\n const old = this.#currentTwisty3DPuzzleWrapper;\n this.#currentTwisty3DPuzzleWrapper = twisty3DPuzzleWrapper;\n old?.disconnect();\n scene.add(await twisty3DPuzzleWrapper.twisty3DPuzzle());\n if (old) {\n // We wait for the new puzzle to be in place before removing the old one.\n scene.remove(await old.twisty3DPuzzle());\n }\n }\n\n #twisty3DStaleDropper: StaleDropper<[ThreeScene, Twisty3DPuzzleWrapper]> =\n new StaleDropper<[ThreeScene, Twisty3DPuzzleWrapper]>();\n\n async onPuzzle(\n inputs: [\n puzzleLoader: PuzzleLoader,\n visualizationStrategy: VisualizationStrategy,\n ],\n ): Promise<void> {\n this.#currentTwisty3DPuzzleWrapper?.disconnect();\n const [scene, twisty3DPuzzleWrapper] =\n await this.#twisty3DStaleDropper.queue(\n Promise.all([\n this.scene(),\n new Twisty3DPuzzleWrapper(this.model!, this, inputs[0], inputs[1]), // TODO\n ]),\n );\n\n this.setCurrentTwisty3DPuzzleWrapper(scene, twisty3DPuzzleWrapper);\n }\n}\n\ncustomElementsShim.define(\"twisty-3d-scene-wrapper\", Twisty3DSceneWrapper);\n", "import { CSSSource } from \"../element/ManagedCustomElement\";\n\nexport const buttonGridCSS = new CSSSource(`\n:host {\n width: 384px;\n height: 24px;\n display: grid;\n}\n\n.wrapper {\n width: 100%;\n height: 100%;\n display: grid;\n overflow: hidden;\n backdrop-filter: blur(4px);\n -webkit-backdrop-filter: blur(4px);\n}\n\n.wrapper {\n grid-auto-flow: column;\n}\n\n.viewer-link-none .twizzle-link-button {\n display: none;\n}\n\n.wrapper twisty-button-v2,\n.wrapper twisty-control-button {\n width: inherit;\n height: inherit;\n}\n`);\n\nexport const buttonCSS = new CSSSource(`\n:host:not([hidden]) {\n display: grid;\n}\n\n:host {\n width: 48px;\n height: 24px;\n}\n\n.wrapper {\n width: 100%;\n height: 100%;\n}\n\nbutton {\n width: 100%;\n height: 100%;\n border: none;\n \n background-position: center;\n background-repeat: no-repeat;\n background-size: contain;\n\n background-color: rgba(196, 196, 196, 0.75);\n}\n\nbutton:enabled {\n background-color: rgba(196, 196, 196, 0.75)\n}\n\nbutton:disabled {\n background-color: rgba(0, 0, 0, 0.4);\n opacity: 0.25;\n pointer-events: none;\n}\n\nbutton:enabled:hover {\n background-color: rgba(255, 255, 255, 0.75);\n box-shadow: 0 0 1em rgba(0, 0, 0, 0.25);\n cursor: pointer;\n}\n\n/* TODO: fullscreen icons have too much padding?? */\n.svg-skip-to-start button,\nbutton.svg-skip-to-start {\n background-image: url(\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIzNTg0IiBoZWlnaHQ9IjM1ODQiIHZpZXdCb3g9IjAgMCAzNTg0IDM1ODQiPjxwYXRoIGQ9Ik0yNjQzIDEwMzdxMTktMTkgMzItMTN0MTMgMzJ2MTQ3MnEwIDI2LTEzIDMydC0zMi0xM2wtNzEwLTcxMHEtOS05LTEzLTE5djcxMHEwIDI2LTEzIDMydC0zMi0xM2wtNzEwLTcxMHEtOS05LTEzLTE5djY3OHEwIDI2LTE5IDQ1dC00NSAxOUg5NjBxLTI2IDAtNDUtMTl0LTE5LTQ1VjEwODhxMC0yNiAxOS00NXQ0NS0xOWgxMjhxMjYgMCA0NSAxOXQxOSA0NXY2NzhxNC0xMSAxMy0xOWw3MTAtNzEwcTE5LTE5IDMyLTEzdDEzIDMydjcxMHE0LTExIDEzLTE5eiIvPjwvc3ZnPg==\");\n}\n\n.svg-skip-to-end button,\nbutton.svg-skip-to-end {\n background-image: url(\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIzNTg0IiBoZWlnaHQ9IjM1ODQiIHZpZXdCb3g9IjAgMCAzNTg0IDM1ODQiPjxwYXRoIGQ9Ik05NDEgMjU0N3EtMTkgMTktMzIgMTN0LTEzLTMyVjEwNTZxMC0yNiAxMy0zMnQzMiAxM2w3MTAgNzEwcTggOCAxMyAxOXYtNzEwcTAtMjYgMTMtMzJ0MzIgMTNsNzEwIDcxMHE4IDggMTMgMTl2LTY3OHEwLTI2IDE5LTQ1dDQ1LTE5aDEyOHEyNiAwIDQ1IDE5dDE5IDQ1djE0MDhxMCAyNi0xOSA0NXQtNDUgMTloLTEyOHEtMjYgMC00NS0xOXQtMTktNDV2LTY3OHEtNSAxMC0xMyAxOWwtNzEwIDcxMHEtMTkgMTktMzIgMTN0LTEzLTMydi03MTBxLTUgMTAtMTMgMTl6Ii8+PC9zdmc+\");\n}\n\n.svg-step-forward button,\nbutton.svg-step-forward {\n background-image: url(\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIzNTg0IiBoZWlnaHQ9IjM1ODQiIHZpZXdCb3g9IjAgMCAzNTg0IDM1ODQiPjxwYXRoIGQ9Ik0yNjg4IDE1NjhxMCAyNi0xOSA0NWwtNTEyIDUxMnEtMTkgMTktNDUgMTl0LTQ1LTE5cS0xOS0xOS0xOS00NXYtMjU2aC0yMjRxLTk4IDAtMTc1LjUgNnQtMTU0IDIxLjVxLTc2LjUgMTUuNS0xMzMgNDIuNXQtMTA1LjUgNjkuNXEtNDkgNDIuNS04MCAxMDF0LTQ4LjUgMTM4LjVxLTE3LjUgODAtMTcuNSAxODEgMCA1NSA1IDEyMyAwIDYgMi41IDIzLjV0Mi41IDI2LjVxMCAxNS04LjUgMjV0LTIzLjUgMTBxLTE2IDAtMjgtMTctNy05LTEzLTIydC0xMy41LTMwcS03LjUtMTctMTAuNS0yNC0xMjctMjg1LTEyNy00NTEgMC0xOTkgNTMtMzMzIDE2Mi00MDMgODc1LTQwM2gyMjR2LTI1NnEwLTI2IDE5LTQ1dDQ1LTE5cTI2IDAgNDUgMTlsNTEyIDUxMnExOSAxOSAxOSA0NXoiLz48L3N2Zz4=\");\n}\n\n.svg-step-backward button,\nbutton.svg-step-backward {\n background-image: url(\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIzNTg0IiBoZWlnaHQ9IjM1ODQiIHZpZXdCb3g9IjAgMCAzNTg0IDM1ODQiPjxwYXRoIGQ9Ik0yNjg4IDIwNDhxMCAxNjYtMTI3IDQ1MS0zIDctMTAuNSAyNHQtMTMuNSAzMHEtNiAxMy0xMyAyMi0xMiAxNy0yOCAxNy0xNSAwLTIzLjUtMTB0LTguNS0yNXEwLTkgMi41LTI2LjV0Mi41LTIzLjVxNS02OCA1LTEyMyAwLTEwMS0xNy41LTE4MXQtNDguNS0xMzguNXEtMzEtNTguNS04MC0xMDF0LTEwNS41LTY5LjVxLTU2LjUtMjctMTMzLTQyLjV0LTE1NC0yMS41cS03Ny41LTYtMTc1LjUtNmgtMjI0djI1NnEwIDI2LTE5IDQ1dC00NSAxOXEtMjYgMC00NS0xOWwtNTEyLTUxMnEtMTktMTktMTktNDV0MTktNDVsNTEyLTUxMnExOS0xOSA0NS0xOXQ0NSAxOXExOSAxOSAxOSA0NXYyNTZoMjI0cTcxMyAwIDg3NSA0MDMgNTMgMTM0IDUzIDMzM3oiLz48L3N2Zz4=\");\n}\n\n.svg-pause button,\nbutton.svg-pause {\n background-image: url(\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIzNTg0IiBoZWlnaHQ9IjM1ODQiIHZpZXdCb3g9IjAgMCAzNTg0IDM1ODQiPjxwYXRoIGQ9Ik0yNTYwIDEwODh2MTQwOHEwIDI2LTE5IDQ1dC00NSAxOWgtNTEycS0yNiAwLTQ1LTE5dC0xOS00NVYxMDg4cTAtMjYgMTktNDV0NDUtMTloNTEycTI2IDAgNDUgMTl0MTkgNDV6bS04OTYgMHYxNDA4cTAgMjYtMTkgNDV0LTQ1IDE5aC01MTJxLTI2IDAtNDUtMTl0LTE5LTQ1VjEwODhxMC0yNiAxOS00NXQ0NS0xOWg1MTJxMjYgMCA0NSAxOXQxOSA0NXoiLz48L3N2Zz4=\");\n}\n\n.svg-play button,\nbutton.svg-play {\n background-image: url(\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIzNTg0IiBoZWlnaHQ9IjM1ODQiIHZpZXdCb3g9IjAgMCAzNTg0IDM1ODQiPjxwYXRoIGQ9Ik0yNDcyLjUgMTgyM2wtMTMyOCA3MzhxLTIzIDEzLTM5LjUgM3QtMTYuNS0zNlYxMDU2cTAtMjYgMTYuNS0zNnQzOS41IDNsMTMyOCA3MzhxMjMgMTMgMjMgMzF0LTIzIDMxeiIvPjwvc3ZnPg==\");\n}\n\n.svg-enter-fullscreen button,\nbutton.svg-enter-fullscreen {\n background-image: url(\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGhlaWdodD0iMjgiIHZpZXdCb3g9IjAgMCAyOCAyOCIgd2lkdGg9IjI4Ij48cGF0aCBkPSJNMiAyaDI0djI0SDJ6IiBmaWxsPSJub25lIi8+PHBhdGggZD0iTTkgMTZIN3Y1aDV2LTJIOXYtM3ptLTItNGgyVjloM1Y3SDd2NXptMTIgN2gtM3YyaDV2LTVoLTJ2M3pNMTYgN3YyaDN2M2gyVjdoLTV6Ii8+PC9zdmc+\");\n}\n\n.svg-exit-fullscreen button,\nbutton.svg-exit-fullscreen {\n background-image: url(\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGhlaWdodD0iMjgiIHZpZXdCb3g9IjAgMCAyOCAyOCIgd2lkdGg9IjI4Ij48cGF0aCBkPSJNMiAyaDI0djI0SDJ6IiBmaWxsPSJub25lIi8+PHBhdGggZD0iTTcgMThoM3YzaDJ2LTVIN3Yyem0zLThIN3YyaDVWN2gtMnYzem02IDExaDJ2LTNoM3YtMmgtNXY1em0yLTExVjdoLTJ2NWg1di0yaC0zeiIvPjwvc3ZnPg==\");\n}\n\n.svg-twizzle-tw button,\nbutton.svg-twizzle-tw {\n background-image: url(\"data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iODY0IiBoZWlnaHQ9IjYwMCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cGF0aCBkPSJNMzk3LjU4MSAxNTEuMTh2NTcuMDg0aC04OS43MDN2MjQwLjM1MmgtNjYuOTU1VjIwOC4yNjRIMTUxLjIydi01Ny4wODNoMjQ2LjM2MXptNTQuMzEgNzEuNjc3bDcuNTEyIDMzLjY5MmMyLjcxOCAxMi4xNiA1LjU4IDI0LjY4IDguNTg0IDM3LjU1NWEyMTgwLjc3NSAyMTgwLjc3NSAwIDAwOS40NDIgMzguODQzIDEyNjYuMyAxMjY2LjMgMCAwMDEwLjA4NiAzNy41NTVjMy43Mi0xMi41OSA3LjM2OC0yNS40NjYgMTAuOTQ1LTM4LjYyOCAzLjU3Ni0xMy4xNjIgNy4wMS0yNi4xMSAxMC4zLTM4Ljg0M2w1Ljc2OS0yMi40NTZjMS4yNDgtNC44ODcgMi40NzItOS43MDUgMy42NzQtMTQuNDU1IDMuMDA0LTExLjg3NSA1LjY1MS0yMi45NjIgNy45NC0zMy4yNjNoNDYuMzU0bDIuMzg0IDEwLjU2M2EyMDAwLjc3IDIwMDAuNzcgMCAwMDMuOTM1IDE2LjgyOGw2LjcxMSAyNy43MWMxLjIxMyA0Ljk1NiAyLjQ1IDkuOTggMy43MDkgMTUuMDczYTMxMTkuNzc3IDMxMTkuNzc3IDAgMDA5Ljg3MSAzOC44NDMgMTI0OS4yMjcgMTI0OS4yMjcgMCAwMDEwLjczIDM4LjYyOCAxOTA3LjYwNSAxOTA3LjYwNSAwIDAwMTAuMzAxLTM3LjU1NSAxMzk3Ljk0IDEzOTcuOTQgMCAwMDkuNjU3LTM4Ljg0M2w0LjQtMTkuMDQ2Yy43MTUtMy4xMyAxLjQyMS02LjIzNiAyLjExOC05LjMyMWw5LjU3Ny00Mi44OGg2Ni41MjZhMjk4OC43MTggMjk4OC43MTggMCAwMS0xOS41MjkgNjYuMzExbC01LjcyOCAxOC40ODJhMzIzNy40NiAzMjM3LjQ2IDAgMDEtMTQuMDE1IDQzLjc1MmMtNi40MzggMTkuNi0xMi43MzMgMzcuNjk4LTE4Ljg4NSA1NC4yOTRsLTMuMzA2IDguODI1Yy00Ljg4NCAxMi44OTgtOS40MzMgMjQuMjYzLTEzLjY0NyAzNC4wOTVoLTQ5Ljc4N2E4NDE3LjI4OSA4NDE3LjI4OSAwIDAxLTIxLjAzMS02NC44MDkgMTI4OC42ODYgMTI4OC42ODYgMCAwMS0xOC44ODUtNjQuODEgMTk3Mi40NDQgMTk3Mi40NDQgMCAwMS0xOC4yNCA2NC44MSAyNTc5LjQxMiAyNTc5LjQxMiAwIDAxLTIwLjM4OCA2NC44MWgtNDkuNzg3Yy00LjY4Mi0xMC45MjYtOS43Mi0yMy43NDMtMTUuMTEtMzguNDUxbC0xLjYyOS00LjQ3Yy01LjI1OC0xNC41MjEtMTAuNjgtMzAuMTkyLTE2LjI2Ni00Ny4wMTRsLTIuNDA0LTcuMjhjLTYuNDM4LTE5LjYtMTMuMDItNDAuMzQ0LTE5Ljc0My02Mi4yMzRhMjk4OC43MDcgMjk4OC43MDcgMCAwMS0xOS41MjktNjYuMzExaDY3LjM4NXoiIGZpbGw9IiM0Mjg1RjQiIGZpbGwtcnVsZT0ibm9uemVybyIvPjwvc3ZnPg==\");\n}\n`);\n\n// Sized against full-screen dimensions.\n// button.svg-twizzle-tw {\n// background-image: url(\"data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNzc3IiBoZWlnaHQ9IjUxMyIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cGF0aCBkPSJNMzU0LjU4MSAxMDcuMTh2NTcuMDg0aC04OS43MDN2MjQwLjM1MmgtNjYuOTU1VjE2NC4yNjRIMTA4LjIydi01Ny4wODNoMjQ2LjM2MXptNTQuMzEgNzEuNjc3bDcuNTEyIDMzLjY5MmMyLjcxOCAxMi4xNiA1LjU4IDI0LjY4IDguNTg0IDM3LjU1NWEyMTgwLjc3NSAyMTgwLjc3NSAwIDAwOS40NDIgMzguODQzIDEyNjYuMyAxMjY2LjMgMCAwMDEwLjA4NiAzNy41NTVjMy43Mi0xMi41OSA3LjM2OC0yNS40NjYgMTAuOTQ1LTM4LjYyOCAzLjU3Ni0xMy4xNjIgNy4wMS0yNi4xMSAxMC4zLTM4Ljg0M2w1Ljc2OS0yMi40NTZjMS4yNDgtNC44ODcgMi40NzItOS43MDUgMy42NzQtMTQuNDU1IDMuMDA0LTExLjg3NSA1LjY1MS0yMi45NjIgNy45NC0zMy4yNjNoNDYuMzU0bDIuMzg0IDEwLjU2M2EyMDAwLjc3IDIwMDAuNzcgMCAwMDMuOTM1IDE2LjgyOGw2LjcxMSAyNy43MWMxLjIxMyA0Ljk1NiAyLjQ1IDkuOTggMy43MDkgMTUuMDczYTMxMTkuNzc3IDMxMTkuNzc3IDAgMDA5Ljg3MSAzOC44NDMgMTI0OS4yMjcgMTI0OS4yMjcgMCAwMDEwLjczIDM4LjYyOCAxOTA3LjYwNSAxOTA3LjYwNSAwIDAwMTAuMzAxLTM3LjU1NSAxMzk3Ljk0IDEzOTcuOTQgMCAwMDkuNjU3LTM4Ljg0M2w0LjQtMTkuMDQ2Yy43MTUtMy4xMyAxLjQyMS02LjIzNiAyLjExOC05LjMyMWw5LjU3Ny00Mi44OGg2Ni41MjZhMjk4OC43MTggMjk4OC43MTggMCAwMS0xOS41MjkgNjYuMzExbC01LjcyOCAxOC40ODJhMzIzNy40NiAzMjM3LjQ2IDAgMDEtMTQuMDE1IDQzLjc1MmMtNi40MzggMTkuNi0xMi43MzMgMzcuNjk4LTE4Ljg4NSA1NC4yOTRsLTMuMzA2IDguODI1Yy00Ljg4NCAxMi44OTgtOS40MzMgMjQuMjYzLTEzLjY0NyAzNC4wOTVoLTQ5Ljc4N2E4NDE3LjI4OSA4NDE3LjI4OSAwIDAxLTIxLjAzMS02NC44MDkgMTI4OC42ODYgMTI4OC42ODYgMCAwMS0xOC44ODUtNjQuODEgMTk3Mi40NDQgMTk3Mi40NDQgMCAwMS0xOC4yNCA2NC44MSAyNTc5LjQxMiAyNTc5LjQxMiAwIDAxLTIwLjM4OCA2NC44MWgtNDkuNzg3Yy00LjY4Mi0xMC45MjYtOS43Mi0yMy43NDMtMTUuMTEtMzguNDUxbC0xLjYyOS00LjQ3Yy01LjI1OC0xNC41MjEtMTAuNjgtMzAuMTkyLTE2LjI2Ni00Ny4wMTRsLTIuNDA0LTcuMjhjLTYuNDM4LTE5LjYtMTMuMDItNDAuMzQ0LTE5Ljc0My02Mi4yMzRhMjk4OC43MDcgMjk4OC43MDcgMCAwMS0xOS41MjktNjYuMzExaDY3LjM4NXoiIGZpbGw9IiM0Mjg1RjQiIGZpbGwtcnVsZT0ibm9uemVybyIvPjwvc3ZnPg==\");\n// }\n", "// Use like this:\n// const enabled = globalSafeDocument?.fullscreenEnabled;\nexport const globalSafeDocument: Document | null =\n typeof document === \"undefined\" ? null : document;\n", "// Ponyfills for prefixing in Safari.\n\nimport { globalSafeDocument } from \"../document\";\n\ndeclare global {\n interface Document {\n webkitFullscreenEnabled?: boolean;\n webkitExitFullscreen?: () => Promise<void>;\n webkitFullscreenElement?: Element | null;\n }\n\n interface Element {\n webkitRequestFullscreen: () => Promise<void>;\n }\n}\n\n// TODO: Can `webkitFullscreenEnabled` change after it's cached at page load?\nexport const fullscreenEnabled: boolean =\n globalSafeDocument?.fullscreenEnabled ||\n !!globalSafeDocument?.webkitFullscreenEnabled;\n\nexport function documentExitFullscreen(): Promise<void> {\n if (document.exitFullscreen) {\n return document.exitFullscreen();\n } else {\n return document.webkitExitFullscreen!(); // YOLO\n }\n}\n\nexport function documentFullscreenElement(): Element | null {\n if (document.fullscreenElement) {\n return document.fullscreenElement;\n } else {\n return document.webkitFullscreenElement ?? null;\n }\n}\n\nexport function requestFullscreen(element: Element): Promise<void> {\n if (element.requestFullscreen) {\n return element.requestFullscreen();\n } else {\n return element.webkitRequestFullscreen();\n }\n}\n", "import type { ButtonCommand } from \"../../../views/control-panel/TwistyButtonsV2\";\nimport { fullscreenEnabled } from \"../../../views/control-panel/webkit-fullscreen\";\nimport type { ViewerLinkPageWithAuto } from \"./ViewerLinkProp\";\nimport type { CoarseTimelineInfo as CoarseTimelineInfo } from \"../timeline/CoarseTimelineInfoProp\";\nimport { TwistyPropDerived } from \"../TwistyProp\";\n\nexport const buttonIcons = [\n \"skip-to-start\",\n \"skip-to-end\",\n \"step-forward\",\n \"step-backward\",\n \"pause\",\n \"play\",\n \"enter-fullscreen\",\n \"exit-fullscreen\",\n \"twizzle-tw\",\n];\nexport type ButtonIcon = typeof buttonIcons[number];\n\ninterface ButtonAppearance {\n enabled: boolean;\n icon: ButtonIcon;\n title: string;\n hidden?: boolean;\n}\nexport type ButtonAppearances = Record<ButtonCommand, ButtonAppearance>;\n\n// TODO: reduce inputs to avoid unnecessary updates.\ninterface ButtonAppearancePropInputs {\n coarseTimelineInfo: CoarseTimelineInfo;\n viewerLink: ViewerLinkPageWithAuto;\n}\n\nexport class ButtonAppearanceProp extends TwistyPropDerived<\n ButtonAppearancePropInputs,\n ButtonAppearances\n> {\n // TODO: This still seems to fire twice for play/pause?\n derive(inputs: ButtonAppearancePropInputs): ButtonAppearances {\n const buttonAppearances = {\n \"fullscreen\": {\n // TODO: Cache?// TODO: Cache?\n enabled: fullscreenEnabled,\n icon:\n // TODO: Check against the expected element?\n // TODO: This will *not* update when we enter/leave fullscreen. We need to work more closely with the controller.\n document.fullscreenElement === null\n ? \"enter-fullscreen\"\n : \"exit-fullscreen\",\n title: \"Enter fullscreen\",\n },\n \"jump-to-start\": {\n enabled: !inputs.coarseTimelineInfo.atStart,\n icon: \"skip-to-start\",\n title: \"Restart\",\n },\n \"play-step-backwards\": {\n enabled: !inputs.coarseTimelineInfo.atStart,\n icon: \"step-backward\",\n title: \"Step backward\",\n },\n \"play-pause\": {\n enabled: true,\n icon: inputs.coarseTimelineInfo.playing ? \"pause\" : \"play\",\n title: inputs.coarseTimelineInfo.playing ? \"Pause\" : \"Play\",\n },\n \"play-step\": {\n enabled: !inputs.coarseTimelineInfo.atEnd,\n icon: \"step-forward\",\n title: \"Step forward\",\n },\n \"jump-to-end\": {\n enabled: !inputs.coarseTimelineInfo.atEnd,\n icon: \"skip-to-end\",\n title: \"Skip to End\",\n },\n \"twizzle-link\": {\n enabled: true,\n icon: \"twizzle-tw\",\n title: \"View at Twizzle\",\n hidden: inputs.viewerLink === \"none\",\n },\n };\n return buttonAppearances;\n }\n}\n", "import {\n BoundaryType,\n Direction,\n} from \"../../old/animation/cursor/CursorTypes\";\nimport { buttonCSS, buttonGridCSS } from \"../../old/dom/controls/buttons.css\";\nimport { ClassListManager } from \"../../old/dom/element/ClassListManager\";\nimport { ManagedCustomElement } from \"../../old/dom/element/ManagedCustomElement\";\nimport { customElementsShim } from \"../../old/dom/element/node-custom-element-shims\";\nimport {\n ButtonAppearances,\n ButtonIcon,\n buttonIcons,\n} from \"../../model/props/viewer/ButtonAppearanceProp\";\nimport type { TwistyPlayerModel } from \"../../model/TwistyPlayerModel\";\nimport type { TwistyPlayerController } from \"../../controllers/TwistyPlayerController\";\nimport {\n documentExitFullscreen,\n documentFullscreenElement,\n requestFullscreen,\n} from \"./webkit-fullscreen\";\n\nconst buttonCommands = {\n \"fullscreen\": true,\n \"jump-to-start\": true,\n \"play-step-backwards\": true,\n \"play-pause\": true,\n \"play-step\": true,\n \"jump-to-end\": true,\n \"twizzle-link\": true,\n};\n\nexport type ButtonCommand = keyof typeof buttonCommands;\n\nexport class TwistyButtonsV2 extends ManagedCustomElement {\n buttons: Record<ButtonCommand, TwistyButtonV2> | null = null;\n\n // TODO: Privacy\n constructor(\n public model?: TwistyPlayerModel,\n public controller?: TwistyPlayerController,\n private fullscreenElement?: HTMLElement,\n ) {\n super();\n }\n\n connectedCallback(): void {\n this.addCSS(buttonGridCSS);\n const buttons: Partial<Record<ButtonCommand, TwistyButtonV2>> = {};\n for (const command in buttonCommands) {\n const button = new TwistyButtonV2();\n buttons[command as ButtonCommand] = button;\n // Why does this still fire with the `disabled` attribute?\n button.addEventListener(\"click\", () =>\n this.#onCommand(command as ButtonCommand),\n );\n this.addElement(button);\n }\n this.buttons = buttons as Record<ButtonCommand, TwistyButtonV2>;\n\n this.model?.buttonAppearanceProp.addFreshListener(this.update.bind(this));\n }\n\n #onCommand(command: ButtonCommand) {\n switch (command) {\n case \"fullscreen\":\n this.onFullscreenButton();\n break;\n case \"jump-to-start\":\n this.controller?.jumpToStart({ flash: true });\n break;\n case \"play-step-backwards\":\n this.controller?.animationController.play({\n direction: Direction.Backwards,\n untilBoundary: BoundaryType.Move,\n });\n break;\n case \"play-pause\":\n this.controller?.togglePlay();\n break;\n case \"play-step\":\n this.controller?.animationController.play({\n direction: Direction.Forwards,\n untilBoundary: BoundaryType.Move,\n });\n break;\n case \"jump-to-end\":\n this.controller?.jumpToEnd({ flash: true });\n break;\n case \"twizzle-link\":\n this.controller?.visitTwizzleLink();\n break;\n default:\n throw new Error(\"Missing command\");\n }\n }\n\n // TODO: Should we have a prop, or a way to query if we're fullscreen?\n // https://developer.mozilla.org/en-US/docs/Web/API/Element/requestFullScreen\n async onFullscreenButton(): Promise<void> {\n if (!this.fullscreenElement) {\n throw new Error(\"Attempted to go fullscreen without an element.\");\n }\n\n if (documentFullscreenElement() === this.fullscreenElement) {\n documentExitFullscreen();\n } else {\n // TODO: Propagate button info to `ButtonAppearanceProp`.\n this.buttons?.fullscreen.setIcon(\"exit-fullscreen\");\n\n requestFullscreen(this.fullscreenElement);\n\n const onFullscreen = (): void => {\n if (documentFullscreenElement() !== this.fullscreenElement) {\n this.buttons?.fullscreen.setIcon(\"enter-fullscreen\");\n window.removeEventListener(\"fullscreenchange\", onFullscreen);\n }\n };\n window.addEventListener(\"fullscreenchange\", onFullscreen);\n }\n }\n\n async update(buttonAppearances: ButtonAppearances): Promise<void> {\n // TODO: Check that we have every command?\n for (const command in buttonCommands) {\n // TODO: Why doesn't `command` have the type `ButtonCommand`?\n const button = this.buttons![command as ButtonCommand];\n // TODO: track individual changes?\n const info = buttonAppearances[command as ButtonCommand];\n button.button.disabled = !info.enabled;\n button.button.title = info.title;\n button.setIcon(info.icon);\n button.hidden = !!info.hidden;\n // button.textContent = info.icon;\n }\n }\n}\n\ncustomElementsShim.define(\"twisty-buttons-v2\", TwistyButtonsV2);\n\nclass TwistyButtonV2 extends ManagedCustomElement {\n button: HTMLButtonElement = document.createElement(\"button\"); // TODO: async?\n\n connectedCallback() {\n this.addCSS(buttonCSS);\n this.addElement(this.button);\n }\n\n #iconManager: ClassListManager<ButtonIcon> = new ClassListManager(\n this,\n \"svg-\",\n buttonIcons,\n );\n\n setIcon(iconName: ButtonIcon): void {\n this.#iconManager.setValue(iconName);\n }\n}\n\ncustomElementsShim.define(\"twisty-button-v2\", TwistyButtonV2);\n", "import { CSSSource } from \"../element/ManagedCustomElement\";\n\nexport const twistyScrubberCSS = new CSSSource(`\n:host {\n width: 384px;\n height: 16px;\n display: grid;\n}\n\n.wrapper {\n width: 100%;\n height: 100%;\n display: grid;\n overflow: hidden;\n backdrop-filter: blur(4px);\n -webkit-backdrop-filter: blur(4px);\n}\n\ninput {\n margin: 0; width: 100%;\n}\n\ninput {\n background: none;\n}\n\n::-moz-range-track {\n background: rgba(0, 0, 0, 0.25);\n height: 50%;\n border: 1px solid rgba(0, 0, 0, 0.1);\n}\n\n::-webkit-slider-runnable-track {\n background: rgba(0, 0, 0, 0.05);\n}\n\n::-moz-range-progress {\n background: #3273F6;\n height: 50%;\n border: 1px solid rgba(0, 0, 0, 0.1);\n}\n\n::-ms-fill-lower {\n background: #3273F6;\n height: 50%;\n border: 1px solid rgba(0, 0, 0, 0.1);\n}\n`);\n", "import { twistyScrubberCSS } from \"../../old/dom/controls/TwistyScrubber.css\";\nimport { ManagedCustomElement } from \"../../old/dom/element/ManagedCustomElement\";\nimport { customElementsShim } from \"../../old/dom/element/node-custom-element-shims\";\nimport type { DetailedTimelineInfo } from \"../../model/props/timeline/DetailedTimelineInfoProp\";\nimport type { TwistyPlayerModel } from \"../../model/TwistyPlayerModel\";\nimport { globalSafeDocument } from \"../document\";\n\nconst SLOW_DOWN_SCRUBBING = false;\n\nlet isMouseDown = false;\n\nglobalSafeDocument?.addEventListener(\n \"mousedown\",\n function (event) {\n if (event.which) isMouseDown = true;\n },\n true,\n);\n\nglobalSafeDocument?.addEventListener(\n \"mouseup\",\n function (event) {\n if (event.which) isMouseDown = false;\n },\n true,\n);\n\n// var x = 0;\nlet y = 0;\nlet clickNum = 0;\n\nglobalSafeDocument?.addEventListener(\n \"mousedown\",\n () => {\n clickNum++;\n },\n false,\n);\n\nglobalSafeDocument?.addEventListener(\"mousemove\", onMouseUpdate, false);\nglobalSafeDocument?.addEventListener(\"mouseenter\", onMouseUpdate, false);\n\nfunction onMouseUpdate(e: MouseEvent) {\n // x = e.pageX;\n y = e.pageY;\n // console.log(x, y);\n}\n\nconst lastVal = 0;\nlet lastPreval = 0;\nlet scaling: boolean = false;\nlet currentClickNum = 0;\n\n// Values are integers.\nexport class TwistyScrubberV2 extends ManagedCustomElement {\n constructor(public model?: TwistyPlayerModel) {\n super();\n }\n\n async onDetailedTimelineInfo(\n detailedTimelineInfo: DetailedTimelineInfo,\n ): Promise<void> {\n // TODO: is this efficient enough?\n const inputElem = await this.inputElem();\n inputElem.min = detailedTimelineInfo.timeRange.start.toString();\n inputElem.max = detailedTimelineInfo.timeRange.end.toString();\n inputElem.value = detailedTimelineInfo.timestamp.toString();\n }\n\n async connectedCallback(): Promise<void> {\n this.addCSS(twistyScrubberCSS);\n this.addElement(await this.inputElem());\n }\n\n #inputElem: Promise<HTMLInputElement> | null = null;\n async inputElem(): Promise<HTMLInputElement> {\n // console.log(\"inputElem\", this.#inputElem);\n return (this.#inputElem ??= (async () => {\n const elem = document.createElement(\"input\");\n elem.type = \"range\";\n\n // console.log(\"1\");\n this.model?.detailedTimelineInfoProp.addFreshListener(\n this.onDetailedTimelineInfo.bind(this),\n );\n // console.log(\"3\");\n elem.addEventListener(\"input\", this.onInput.bind(this));\n\n return elem;\n })());\n }\n\n async onInput(e: Event): Promise<void> {\n if (scaling) {\n return; // TODO\n }\n const inputElem = await this.inputElem();\n await this.slowDown(e, inputElem); // TODO\n\n const value = parseInt(inputElem.value);\n // console.log(\"on input\", value);\n this.model?.playingInfoProp.set({ playing: false });\n this.model?.timestampRequestProp.set(value);\n }\n\n async slowDown(e: Event, inputElem: HTMLInputElement): Promise<void> {\n if (!SLOW_DOWN_SCRUBBING) {\n return; // TODO\n }\n\n if (isMouseDown) {\n const rect = inputElem.getBoundingClientRect();\n const sliderY = rect.top + rect.height / 2;\n console.log(sliderY, e, y, isMouseDown);\n\n const yDist = Math.abs(sliderY - y);\n let scale = 1;\n if (yDist > 64) {\n scale = Math.max(Math.pow(2, -(yDist - 64) / 64), 1 / 32);\n }\n const preVal = parseInt(inputElem.value);\n console.log(\"cl\", currentClickNum, clickNum, preVal);\n if (currentClickNum === clickNum) {\n const delta = (preVal - lastPreval) * scale;\n console.log(\"delta\", delta, yDist);\n scaling = true;\n let newVal = preVal;\n newVal =\n lastVal +\n delta * scale +\n (preVal - lastVal) *\n Math.min(1, Math.pow(1 / 2, (yDist * yDist) / 64));\n inputElem.value = newVal.toString();\n console.log(scale);\n scaling = false;\n this.contentWrapper.style.opacity = scale.toString();\n } else {\n currentClickNum = clickNum;\n }\n lastPreval = preVal;\n }\n }\n}\n\ncustomElementsShim.define(\"twisty-scrubber-v2\", TwistyScrubberV2);\n", "import { PerspectiveCamera, WebGLRenderer } from \"three\";\nimport { THREEJS } from \"../heavy-code-imports/3d\";\nimport type { TwistyPlayerModel } from \"../model/TwistyPlayerModel\";\nimport { Twisty3DPuzzleWrapper } from \"./3D/Twisty3DPuzzleWrapper\";\nimport { setCameraFromOrbitCoordinates } from \"./3D/Twisty3DVantage\";\n\nexport interface TwistyPlayerScreenshot {\n dataURL: string;\n download: (filename?: string) => Promise<void>;\n}\n\n// TODO: cache\nlet cachedCamera: PerspectiveCamera | null = null;\nexport async function screenshot(\n model: TwistyPlayerModel,\n options?: { width: number; height: number },\n): Promise<TwistyPlayerScreenshot> {\n // TODO: improve async caching\n\n const width = options?.width ?? 2048;\n const height = options?.height ?? 2048;\n const aspectRatio = width / height;\n const camera = (cachedCamera ??= await (async () => {\n return new (await THREEJS).PerspectiveCamera(20, aspectRatio, 0.1, 20);\n })());\n\n const scene = new (await THREEJS).Scene();\n\n const twisty3DWrapper = new Twisty3DPuzzleWrapper(\n model,\n { scheduleRender: () => {} },\n await model.puzzleLoaderProp.get(),\n await model.visualizationStrategyProp.get(),\n );\n\n // TODO: Pass the stickering to the constructor so we don't have to wait..\n await model.stickeringProp.get();\n await new Promise((resolve) => setTimeout(resolve, 1000));\n\n // TODO: Find a more robust way to do this.\n await model.legacyPositionProp.get(); // Force the 3D puzzle listeners for the state to fire.\n\n scene.add(await twisty3DWrapper.twisty3DPuzzle());\n\n const orbitCoordinates = await model.orbitCoordinatesProp.get();\n await setCameraFromOrbitCoordinates(camera, orbitCoordinates);\n\n const renderer = new WebGLRenderer({\n antialias: true,\n alpha: true,\n });\n renderer.setSize(width, height);\n\n renderer.render(scene, camera);\n const dataURL = renderer.domElement.toDataURL();\n\n const defaultFilename = await getDefaultFilename(model);\n\n return {\n dataURL,\n download: async (filename?: string) => {\n downloadURL(dataURL, filename ?? defaultFilename);\n },\n };\n}\n\nexport async function getDefaultFilename(\n model: TwistyPlayerModel,\n): Promise<string> {\n const [puzzleID, algWithIssues] = await Promise.all([\n model.puzzleIDProp.get(),\n model.algProp.get(),\n ]);\n return `[${puzzleID}]${\n algWithIssues.alg.experimentalNumUnits() === 0\n ? \"\"\n : \" \" + algWithIssues.alg.toString()\n }`;\n}\n\nexport function downloadURL(\n url: string,\n name: string,\n extension: string = \"png\",\n): void {\n const a = document.createElement(\"a\");\n a.href = url;\n a.download = `${name}.${extension}`;\n a.click();\n}\n", "import { Alg } from \"../../../../../alg\";\nimport { arrayEquals } from \"../../../helpers\";\nimport { TwistyPropSource } from \"../../TwistyProp\";\n\nexport class AlgIssues {\n // TODO: (string | Error)[]\n\n readonly warnings: readonly string[];\n readonly errors: readonly string[];\n\n constructor(issues?: { warnings?: string[]; errors?: string[] }) {\n // TODO: clone inputs?\n this.warnings = Object.freeze(issues?.warnings ?? []);\n this.errors = Object.freeze(issues?.errors ?? []);\n Object.freeze(this);\n }\n\n add(issues?: { warnings?: string[]; errors?: string[] }) {\n return new AlgIssues({\n warnings: this.warnings.concat(issues?.warnings ?? []),\n errors: this.errors.concat(issues?.errors ?? []),\n });\n }\n\n /** @deprecated */\n log() {\n if (this.errors.length > 0) {\n console.error(`\uD83D\uDEA8 ${this.errors[0]}`);\n } else if (this.warnings.length > 0) {\n console.warn(`\u26A0\uFE0F ${this.warnings[0]}`);\n } else {\n console.info(\"\uD83D\uDE0E No issues!\");\n }\n }\n}\n\nexport interface AlgWithIssues {\n alg: Alg;\n issues: AlgIssues;\n}\n\nexport function algWithIssuesFromString(s: string): AlgWithIssues {\n try {\n const alg = Alg.fromString(s); // TODO: is this safe?\n const warnings = [];\n if (alg.toString() !== s) {\n // TODO: Push this check into the parser and return semantic info (so they can be e.g. highlighted).\n warnings.push(`Alg is non-canonical!`);\n }\n return {\n alg,\n issues: new AlgIssues({ warnings }),\n };\n } catch (e) {\n return {\n alg: new Alg(),\n issues: new AlgIssues({\n errors: [`Malformed alg: ${(e as Error).toString()}`],\n }),\n };\n }\n}\n\nfunction algWithIssuesEquals(a1: AlgWithIssues, a2: AlgWithIssues): boolean {\n return (\n a1.alg.isIdentical(a2.alg) &&\n arrayEquals(a1.issues.warnings, a2.issues.warnings) &&\n arrayEquals(a1.issues.errors, a2.issues.errors)\n );\n}\n\nexport class AlgProp extends TwistyPropSource<AlgWithIssues, Alg | string> {\n getDefaultValue(): AlgWithIssues {\n return { alg: new Alg(), issues: new AlgIssues() };\n }\n\n canReuseValue(v1: AlgWithIssues, v2: AlgWithIssues) {\n return algWithIssuesEquals(v1, v2);\n }\n\n async derive(newAlg: Alg | string): Promise<AlgWithIssues> {\n if (typeof newAlg === \"string\") {\n return algWithIssuesFromString(newAlg);\n } else {\n return {\n alg: newAlg,\n issues: new AlgIssues(),\n };\n }\n }\n}\n", "import type { BackgroundTheme } from \"../../../old/dom/TwistyPlayerConfig\";\nimport { SimpleTwistyPropSource } from \"../TwistyProp\";\n\nexport type BackgroundThemeWithAuto = BackgroundTheme | \"auto\";\n\nexport class BackgroundProp extends SimpleTwistyPropSource<BackgroundThemeWithAuto> {\n getDefaultValue(): BackgroundThemeWithAuto {\n return \"auto\";\n }\n}\n", "import type { BackViewLayout } from \"../../../old/dom/viewers/TwistyViewerWrapper\";\nimport { SimpleTwistyPropSource } from \"../TwistyProp\";\n\nexport type BackViewLayoutWithAuto = BackViewLayout | \"auto\";\n\nexport class BackViewProp extends SimpleTwistyPropSource<BackViewLayoutWithAuto> {\n getDefaultValue(): BackViewLayoutWithAuto {\n return \"auto\";\n }\n}\n", "import type { ControlsLocation } from \"../../../old/dom/TwistyPlayerConfig\";\nimport { SimpleTwistyPropSource } from \"../TwistyProp\";\n\nexport type ControlPanelThemeWithAuto = ControlsLocation | \"auto\";\n\nexport class ControlPanelProp extends SimpleTwistyPropSource<ControlPanelThemeWithAuto> {\n getDefaultValue(): ControlPanelThemeWithAuto {\n return \"auto\";\n }\n}\n", "import type { HintFaceletStyle } from \"../../../../old/dom/TwistyPlayerConfig\";\nimport { SimpleTwistyPropSource } from \"../../TwistyProp\";\n\nexport type HintFaceletStyleWithAuto = HintFaceletStyle | \"auto\";\n\nexport class HintFaceletProp extends SimpleTwistyPropSource<HintFaceletStyleWithAuto> {\n getDefaultValue(): HintFaceletStyleWithAuto {\n return \"auto\";\n }\n}\n", "import { SimpleTwistyPropSource } from \"../../TwistyProp\";\n\nexport const indexerStrategyNames = {\n auto: true,\n simple: true,\n tree: true,\n simultaneous: true,\n};\nexport type IndexerStrategyName = keyof typeof indexerStrategyNames;\n\nexport class IndexerConstructorRequestProp extends SimpleTwistyPropSource<IndexerStrategyName> {\n getDefaultValue(): IndexerStrategyName {\n return \"auto\";\n }\n}\n", "import { SimpleTwistyPropSource } from \"../TwistyProp\";\nimport type { CoordinateDegrees } from \"./OrbitCoordinatesRequestProp\";\n\n// Similar to https://alg.cubing.net/\nconst DEFAULT_LATITUDE_LIMIT = 35;\n\nexport class LatitudeLimitProp extends SimpleTwistyPropSource<CoordinateDegrees> {\n getDefaultValue(): CoordinateDegrees {\n return DEFAULT_LATITUDE_LIMIT;\n }\n}\n", "import { mod } from \"../../helpers\";\nimport { TwistyPropSource } from \"../TwistyProp\";\n\nexport type CoordinateDegrees = number;\n\nexport interface OrbitCoordinatesV2 {\n latitude: CoordinateDegrees;\n longitude: CoordinateDegrees;\n distance: number;\n}\n\nexport function orbitCoordinatesEqual(\n c1: OrbitCoordinatesV2,\n c2: OrbitCoordinatesV2,\n): boolean {\n return (\n c1.latitude === c2.latitude &&\n c1.longitude === c2.longitude &&\n c1.distance === c2.distance\n );\n}\n\n// TOOD: Check if freezing affects perf.\n// const DEFAULT_COORDINATES = Object.freeze({\n// latitude: 35,\n// longitude: 30,\n// distance: 6,\n// });\n\nexport type OrbitCoordinatesRequest = Partial<OrbitCoordinatesV2> | \"auto\";\n\n// TODO: Put the \"auto\" calculations in a separate place.\nexport class OrbitCoordinatesRequestProp extends TwistyPropSource<\n OrbitCoordinatesRequest,\n Partial<OrbitCoordinatesV2> | \"auto\"\n> {\n getDefaultValue(): OrbitCoordinatesRequest {\n return \"auto\";\n }\n\n canReuseValue(v1: OrbitCoordinatesV2, v2: OrbitCoordinatesV2) {\n return v1 === v2 || orbitCoordinatesEqual(v1, v2);\n }\n\n async derive(\n newCoordinates: Partial<OrbitCoordinatesV2> | \"auto\",\n oldValuePromise: Promise<OrbitCoordinatesRequest>,\n ): Promise<OrbitCoordinatesRequest> {\n if (newCoordinates === \"auto\") {\n return \"auto\";\n }\n\n let oldValue = await oldValuePromise;\n if (oldValue === \"auto\") {\n oldValue = {};\n }\n\n const newValue: Partial<OrbitCoordinatesV2> = Object.assign({}, oldValue);\n Object.assign(newValue, newCoordinates);\n\n if (typeof newValue.latitude !== \"undefined\") {\n newValue.latitude = Math.min(Math.max(newValue.latitude, -90), 90);\n }\n if (typeof newValue.longitude !== \"undefined\") {\n newValue.longitude = mod(newValue.longitude, 360, 180);\n }\n return newValue;\n }\n}\n", "import {\n BoundaryType,\n Direction,\n} from \"../../../old/animation/cursor/CursorTypes\";\nimport { TwistyPropSource } from \"../TwistyProp\";\n\nexport type SimpleDirection = Direction.Forwards | Direction.Backwards;\n\nexport interface PlayingInfo {\n playing: boolean;\n direction: SimpleDirection;\n untilBoundary: BoundaryType; // TODO: allows this to be optional in the setter?\n // TODO: Is `loop` responsible to add at this point? Maybe we should wait until we've figured out autoplay?\n // TODO: Combine `loop` into something with BoundaryType?\n loop: boolean;\n}\n\n// TODO: direction,\nexport class PlayingInfoProp extends TwistyPropSource<\n PlayingInfo,\n Partial<PlayingInfo>\n> {\n async getDefaultValue(): Promise<PlayingInfo> {\n return {\n direction: Direction.Forwards,\n playing: false,\n untilBoundary: BoundaryType.EntireTimeline,\n loop: false,\n };\n }\n\n async derive(\n newInfo: Partial<PlayingInfo>,\n oldValuePromise: Promise<PlayingInfo>,\n ): Promise<PlayingInfo> {\n const oldValue = await oldValuePromise;\n\n const newValue: PlayingInfo = Object.assign({}, oldValue);\n Object.assign(newValue, newInfo);\n return newValue;\n }\n\n canReuseValue(v1: PlayingInfo, v2: PlayingInfo) {\n return (\n v1.direction === v2.direction &&\n v1.playing === v2.playing &&\n v1.untilBoundary === v2.untilBoundary &&\n v1.loop === v2.loop\n );\n }\n}\n", "import type { PuzzleDescriptionString } from \"../../../../../puzzle-geometry/PGPuzzles\";\nimport {\n NoValueType,\n NO_VALUE,\n SimpleTwistyPropSource,\n} from \"../../TwistyProp\";\n\nexport class PGPuzzleDescriptionStringProp extends SimpleTwistyPropSource<\n PuzzleDescriptionString | NoValueType\n> {\n getDefaultValue(): PuzzleDescriptionString | NoValueType {\n return NO_VALUE;\n }\n}\n", "import type { PuzzleID } from \"../../../../old/dom/TwistyPlayerConfig\";\nimport {\n NoValueType,\n NO_VALUE,\n SimpleTwistyPropSource,\n} from \"../../TwistyProp\";\n\n// TODO: Ideally we'd use `null` to mean \"no value\", but `null` has a special meaning\n// for `TwistyProp` and might mess with caching.\n// https://github.com/cubing/cubing.js/blob/63b0a55b83963f68410bb117a2e481052a07e086/src/cubing/twisty/model/TwistyProp.ts#L189-L189\nexport class PuzzleIDRequestProp extends SimpleTwistyPropSource<\n PuzzleID | NoValueType\n> {\n getDefaultValue(): PuzzleID | NoValueType {\n return NO_VALUE;\n }\n}\n", "import type { PuzzleDescriptionString } from \"../../../../../puzzle-geometry/PGPuzzles\";\nimport {\n cube3x3x3,\n experimentalCustomPGPuzzleLoader,\n PuzzleLoader,\n puzzles,\n} from \"../../../../../puzzles\";\nimport type { PuzzleID } from \"../../../../old/dom/TwistyPlayerConfig\";\nimport { NoValueType, NO_VALUE, TwistyPropDerived } from \"../../TwistyProp\";\n8;\ninterface PuzzleLoaderPropInputs {\n puzzleIDRequest: PuzzleID | NoValueType;\n puzzleDescriptionRequest: PuzzleDescriptionString | NoValueType;\n}\n\nexport class PuzzleLoaderProp extends TwistyPropDerived<\n PuzzleLoaderPropInputs,\n PuzzleLoader\n> {\n derive(inputs: PuzzleLoaderPropInputs): PuzzleLoader {\n if (inputs.puzzleIDRequest && inputs.puzzleIDRequest !== NO_VALUE) {\n const puzzleLoader = puzzles[inputs.puzzleIDRequest];\n if (!puzzleLoader) {\n this.userVisibleErrorTracker!.set({\n errors: [`Invalid puzzle ID: ${inputs.puzzleIDRequest}`],\n });\n }\n return puzzleLoader;\n }\n if (\n inputs.puzzleDescriptionRequest &&\n inputs.puzzleDescriptionRequest !== NO_VALUE\n ) {\n return experimentalCustomPGPuzzleLoader(inputs.puzzleDescriptionRequest);\n }\n return cube3x3x3;\n }\n}\n", "import type { SetupToLocation } from \"../../../../old/dom/TwistyPlayerConfig\";\nimport { SimpleTwistyPropSource } from \"../../TwistyProp\";\n\nexport class SetupAnchorProp extends SimpleTwistyPropSource<SetupToLocation> {\n getDefaultValue(): SetupToLocation {\n return \"start\";\n }\n}\n", "import type { ExperimentalStickering } from \"../../../..\";\nimport { SimpleTwistyPropSource } from \"../../TwistyProp\";\n\nexport class StickeringProp extends SimpleTwistyPropSource<ExperimentalStickering> {\n getDefaultValue(): ExperimentalStickering {\n return \"full\"; // TODO: auto\n }\n}\n", "import { TwistyPropSource } from \"../TwistyProp\";\n\n// TODO: Pick a better name. `speed` is probably good, although that could mean\n// something else (e.g. shorter, faster moves but still with the same spacing).\nexport class TempoScaleProp extends TwistyPropSource<number, number> {\n getDefaultValue(): number {\n return 1;\n }\n\n derive(v: number): number {\n return v < 0 ? 1 : v;\n }\n}\n", "import type { MillisecondTimestamp } from \"../../../old/animation/cursor/CursorTypes\";\nimport { SimpleTwistyPropSource } from \"../TwistyProp\";\n\nconst smartTimestamps = {\n \"start\": true,\n \"end\": true,\n \"anchor\": true,\n \"opposite-anchor\": true,\n};\n\nexport type TimestampRequest =\n | MillisecondTimestamp\n | keyof typeof smartTimestamps;\n\nexport class TimestampRequestProp extends SimpleTwistyPropSource<TimestampRequest> {\n getDefaultValue(): TimestampRequest {\n return \"opposite-anchor\";\n }\n\n // TODO: Support `Promise`\n set(v: TimestampRequest) {\n if (!this.validInput(v)) {\n // TODO: Generalize this to more props. How do we surface this? Throw an error and catch it from sync setters that call into this?\n return;\n }\n super.set(v);\n }\n\n validInput(v: TimestampRequest): boolean {\n if (typeof v === \"number\") {\n return true;\n }\n if (smartTimestamps[v]) {\n return true;\n }\n return false;\n }\n}\n", "import { TwistyPropSource } from \"../TwistyProp\";\n\nexport class URLProp extends TwistyPropSource<URL | null, URL | string | null> {\n getDefaultValue(): URL | null {\n return null;\n }\n\n derive(input: URL | string | null): URL | null {\n if (typeof input === \"string\") {\n return new URL(input, location.href); // TODO\n }\n return input;\n }\n}\n", "import type { ViewerLinkPage } from \"../../../old/dom/TwistyPlayerConfig\";\nimport { SimpleTwistyPropSource } from \"../TwistyProp\";\n\nexport type ViewerLinkPageWithAuto = ViewerLinkPage | \"auto\";\n\nexport class ViewerLinkProp extends SimpleTwistyPropSource<ViewerLinkPageWithAuto> {\n getDefaultValue(): ViewerLinkPageWithAuto {\n return \"auto\";\n }\n}\n", "import type { VisualizationFormat } from \"../../../old/dom/TwistyPlayerConfig\";\nimport { SimpleTwistyPropSource } from \"../TwistyProp\";\n\nexport type VisualizationFormatWithAuto = VisualizationFormat | \"auto\";\n\nexport class VisualizationFormatProp extends SimpleTwistyPropSource<VisualizationFormatWithAuto> {\n getDefaultValue(): VisualizationFormatWithAuto {\n return \"auto\";\n }\n}\n", "import {\n defaultCameraOrbitCoordinates,\n PuzzleID,\n} from \"../../../old/dom/TwistyPlayerConfig\";\nimport {\n CoordinateDegrees,\n orbitCoordinatesEqual,\n OrbitCoordinatesRequest,\n OrbitCoordinatesV2,\n} from \"./OrbitCoordinatesRequestProp\";\nimport { TwistyPropDerived } from \"../TwistyProp\";\nimport type { VisualizationStrategy } from \"./VisualizationStrategyProp\";\n\ninterface OrbitCoordinatesPropInputs {\n orbitCoordinatesRequest: OrbitCoordinatesRequest;\n latitudeLimit: CoordinateDegrees;\n puzzleID: PuzzleID;\n strategy: VisualizationStrategy;\n}\n\nexport class OrbitCoordinatesProp extends TwistyPropDerived<\n OrbitCoordinatesPropInputs,\n OrbitCoordinatesV2\n> {\n canReuseValue(v1: OrbitCoordinatesV2, v2: OrbitCoordinatesV2) {\n return orbitCoordinatesEqual(v1, v2);\n }\n\n async derive(\n inputs: OrbitCoordinatesPropInputs,\n ): Promise<OrbitCoordinatesV2> {\n if (inputs.orbitCoordinatesRequest === \"auto\") {\n return defaultCameraOrbitCoordinates(inputs.puzzleID, inputs.strategy);\n }\n\n const req: OrbitCoordinatesV2 = Object.assign(\n Object.assign(\n {},\n defaultCameraOrbitCoordinates(inputs.puzzleID, inputs.strategy),\n inputs.orbitCoordinatesRequest,\n ),\n );\n\n if (Math.abs(req.latitude) <= inputs.latitudeLimit) {\n return req;\n } else {\n const { latitude, longitude, distance } = req;\n // TODO: Should we re-normalize the request, so we don't depend on normalization in the input?\n return {\n latitude: inputs.latitudeLimit * Math.sign(latitude),\n longitude,\n distance,\n };\n }\n }\n}\n", "import type { PuzzleLoader } from \"../../../../../puzzles\";\nimport type { PuzzleID } from \"../../../../old/dom/TwistyPlayerConfig\";\nimport { TwistyPropDerived } from \"../../TwistyProp\";\n\nexport class PuzzleIDProp extends TwistyPropDerived<\n { puzzleLoader: PuzzleLoader },\n PuzzleID\n> {\n async derive(inputs: { puzzleLoader: PuzzleLoader }): Promise<PuzzleID> {\n return inputs.puzzleLoader.id as PuzzleID;\n }\n}\n", "import type { Texture, TextureLoader } from \"three\";\nimport { THREEJS } from \"../../../../heavy-code-imports/3d\";\nimport { TwistyPropDerived } from \"../../TwistyProp\";\n\nlet cachedLoader: TextureLoader | null = null;\nasync function loader(): Promise<TextureLoader> {\n return (cachedLoader ??= new (await THREEJS).TextureLoader());\n}\n\ntype SpritePropInputs = {\n spriteURL: URL | null;\n};\n\n// TODO: Find a way to make the 3D elements own this, instead of the main `TwistyPlayerModel`.\nexport class SpriteProp extends TwistyPropDerived<\n SpritePropInputs,\n Texture | null\n> {\n async derive(inputs: SpritePropInputs): Promise<Texture | null> {\n const { spriteURL: textureURL } = inputs;\n if (textureURL === null) {\n return null;\n }\n // eslint-disable-next-line no-async-promise-executor\n return new Promise(async (resolve, _reject) => {\n const onLoadingError = (): void => {\n console.warn(\"Could not load sprite:\", textureURL.toString());\n resolve(null);\n };\n // TODO: provide a way to listen for errors?\n try {\n (await loader()).load(\n textureURL.toString(),\n resolve,\n onLoadingError,\n onLoadingError,\n );\n } catch (e) {\n onLoadingError();\n }\n });\n }\n}\n", "import type { PuzzleID } from \"../../../old/dom/TwistyPlayerConfig\";\nimport type { VisualizationFormatWithAuto } from \"./VisualizationProp\";\nimport { TwistyPropDerived } from \"../TwistyProp\";\n\ntype VisualizationStrategyPropInputs = {\n visualizationRequest: VisualizationFormatWithAuto;\n puzzleID: PuzzleID;\n};\n\nexport type VisualizationStrategy =\n | \"Cube3D\"\n | \"2D\"\n | \"experimental-2D-LL\"\n | \"PG3D\";\n\nexport class VisualizationStrategyProp extends TwistyPropDerived<\n VisualizationStrategyPropInputs,\n VisualizationStrategy\n> {\n derive(inputs: VisualizationStrategyPropInputs): VisualizationStrategy {\n switch (inputs.puzzleID) {\n case \"clock\":\n case \"square1\":\n return \"2D\";\n case \"3x3x3\":\n switch (inputs.visualizationRequest) {\n case \"auto\":\n case \"3D\":\n return \"Cube3D\";\n default:\n return inputs.visualizationRequest;\n }\n default:\n switch (inputs.visualizationRequest) {\n case \"auto\":\n case \"3D\":\n return \"PG3D\";\n case \"experimental-2D-LL\":\n return \"2D\";\n default:\n return inputs.visualizationRequest;\n }\n }\n }\n}\n", "import {\n Alg,\n Grouping,\n LineComment,\n Commutator,\n Conjugate,\n Move,\n Newline,\n Pause,\n TraversalUp,\n} from \"../../../../alg\";\nimport type { Duration } from \"../cursor/CursorTypes\";\n\nexport function constantDurationForAmount(_amount: number): Duration {\n return 1000;\n}\n\nexport function defaultDurationForAmount(amount: number): Duration {\n switch (Math.abs(amount)) {\n case 0:\n return 0;\n case 1:\n return 1000;\n case 2:\n return 1500;\n default:\n return 2000;\n }\n}\n// eslint-disable-next-line no-inner-declarations\nexport function ExperimentalScaledDefaultDurationForAmount(\n scale: number,\n amount: number,\n): Duration {\n switch (Math.abs(amount)) {\n case 0:\n return 0;\n case 1:\n return scale * 1000;\n case 2:\n return scale * 1500;\n default:\n return scale * 2000;\n }\n}\n\nexport class AlgDuration extends TraversalUp<Duration> {\n // TODO: Pass durationForAmount as Down type instead?\n constructor(\n public durationForAmount: (\n amount: number,\n ) => Duration = defaultDurationForAmount,\n ) {\n super();\n }\n\n public traverseAlg(alg: Alg): Duration {\n let total = 0;\n for (const unit of alg.units()) {\n total += this.traverseUnit(unit);\n }\n return total;\n }\n\n public traverseGrouping(grouping: Grouping): Duration {\n return grouping.amount * this.traverseAlg(grouping.alg);\n }\n\n public traverseMove(move: Move): Duration {\n return this.durationForAmount(move.amount);\n }\n\n public traverseCommutator(commutator: Commutator): Duration {\n return (\n 2 * (this.traverseAlg(commutator.A) + this.traverseAlg(commutator.B))\n );\n }\n\n public traverseConjugate(conjugate: Conjugate): Duration {\n return 2 * this.traverseAlg(conjugate.A) + this.traverseAlg(conjugate.B);\n }\n\n public traversePause(_pause: Pause): Duration {\n return this.durationForAmount(1);\n }\n\n public traverseNewline(_newline: Newline): Duration {\n return this.durationForAmount(1);\n }\n\n public traverseLineComment(_comment: LineComment): Duration {\n return this.durationForAmount(0);\n }\n}\n", "import { Alg, Move, TraversalUp } from \"../../../../alg\";\nimport { countAnimatedLeaves } from \"../../../../notation\";\nimport type {\n PuzzleWrapper,\n State,\n} from \"../../../views/3D/puzzles/KPuzzleWrapper\";\nimport type { Duration, Timestamp } from \"../cursor/CursorTypes\";\nimport { AlgDuration, defaultDurationForAmount } from \"./AlgDuration\";\nimport type { AlgIndexer } from \"./AlgIndexer\";\n\nexport class SimpleAlgIndexer<P extends PuzzleWrapper>\n implements AlgIndexer<P>\n{\n private moves: Alg;\n // TODO: Allow custom `durationFn`.\n private durationFn: TraversalUp<Duration> = new AlgDuration(\n defaultDurationForAmount,\n );\n\n constructor(private puzzle: P, alg: Alg) {\n // TODO: Avoid assuming all base moves are block moves.\n this.moves = new Alg(alg.experimentalExpand());\n }\n\n public getAnimLeaf(index: number): Move {\n return Array.from(this.moves.units())[index] as Move; // TODO: perf\n }\n\n public indexToMoveStartTimestamp(index: number): Timestamp {\n const alg = new Alg(Array.from(this.moves.units()).slice(0, index)); // TODO\n return this.durationFn.traverseAlg(alg);\n }\n\n public timestampToIndex(timestamp: Timestamp): number {\n let cumulativeTime = 0;\n let i;\n for (i = 0; i < this.numAnimatedLeaves(); i++) {\n cumulativeTime += this.durationFn.traverseMove(this.getAnimLeaf(i));\n if (cumulativeTime >= timestamp) {\n return i;\n }\n }\n return i;\n }\n\n public stateAtIndex(index: number): State<P> {\n return this.puzzle.combine(\n this.puzzle.startState(),\n this.transformAtIndex(index),\n );\n }\n\n public transformAtIndex(index: number): State<P> {\n let state = this.puzzle.identity();\n for (const move of Array.from(this.moves.units()).slice(0, index)) {\n state = this.puzzle.combine(\n state,\n this.puzzle.stateFromMove(move as Move),\n );\n }\n return state;\n }\n\n public algDuration(): Duration {\n return this.durationFn.traverseAlg(this.moves);\n }\n\n public numAnimatedLeaves(): number {\n // TODO: Cache internally once performance matters.\n return countAnimatedLeaves(this.moves);\n }\n\n public moveDuration(index: number): number {\n return this.durationFn.traverseMove(this.getAnimLeaf(index));\n }\n}\n", "import {\n LineComment,\n Commutator,\n Conjugate,\n Pause,\n TraversalUp,\n Move,\n Alg,\n Grouping,\n Newline,\n} from \"../../../../../alg\";\nimport type { MillisecondTimestamp } from \"../../cursor/CursorTypes\";\nimport { defaultDurationForAmount } from \"../AlgDuration\";\n\nexport type AnimatedLeafUnit = Move | Pause;\nexport interface LocalAnimLeavesWithRange {\n animLeafUnit: AnimatedLeafUnit;\n msUntilNext: MillisecondTimestamp;\n duration: MillisecondTimestamp;\n}\n\nexport interface AnimLeafWithRange {\n animLeaf: AnimatedLeafUnit;\n start: MillisecondTimestamp;\n end: MillisecondTimestamp;\n}\n\nconst axisLookup: Record<string, \"x\" | \"y\" | \"z\"> = {\n u: \"y\",\n l: \"x\",\n f: \"z\",\n r: \"x\",\n b: \"z\",\n d: \"y\",\n m: \"x\",\n e: \"y\",\n s: \"z\",\n x: \"x\",\n y: \"y\",\n z: \"z\",\n};\n\nfunction isSameAxis(move1: Move, move2: Move): boolean {\n return (\n axisLookup[move1.family[0].toLowerCase()] ===\n axisLookup[move2.family[0].toLowerCase()]\n );\n}\n\n// TODO: Replace this with an optimized implementation.\n// TODO: Consider `(x U)` and `(U x F)` to be simultaneous.\nexport class LocalSimulMoves extends TraversalUp<LocalAnimLeavesWithRange[]> {\n public traverseAlg(alg: Alg): LocalAnimLeavesWithRange[] {\n const processed: LocalAnimLeavesWithRange[][] = [];\n for (const nestedUnit of alg.units()) {\n processed.push(this.traverseUnit(nestedUnit));\n }\n return Array.prototype.concat(...processed) as LocalAnimLeavesWithRange[];\n }\n\n public traverseGroupingOnce(alg: Alg): LocalAnimLeavesWithRange[] {\n if (alg.experimentalIsEmpty()) {\n return [];\n }\n\n for (const unit of alg.units()) {\n if (!unit.is(Move))\n // TODO: define the type statically on the class?\n return this.traverseAlg(alg);\n }\n\n const moves = Array.from(alg.units()) as Move[];\n let maxSimulDur = defaultDurationForAmount(moves[0].amount);\n for (let i = 0; i < moves.length - 1; i++) {\n for (let j = 1; j < moves.length; j++) {\n if (!isSameAxis(moves[i], moves[j])) {\n return this.traverseAlg(alg);\n }\n }\n maxSimulDur = Math.max(\n maxSimulDur,\n defaultDurationForAmount(moves[i].amount),\n );\n }\n\n const localMovesWithRange: LocalAnimLeavesWithRange[] = moves.map(\n (blockMove): LocalAnimLeavesWithRange => {\n return {\n animLeafUnit: blockMove,\n msUntilNext: 0,\n duration: maxSimulDur,\n };\n },\n );\n localMovesWithRange[localMovesWithRange.length - 1].msUntilNext =\n maxSimulDur;\n return localMovesWithRange;\n }\n\n public traverseGrouping(grouping: Grouping): LocalAnimLeavesWithRange[] {\n const processed: LocalAnimLeavesWithRange[][] = [];\n\n const segmentOnce: Alg =\n grouping.amount > 0 ? grouping.alg : grouping.alg.invert();\n for (let i = 0; i < Math.abs(grouping.amount); i++) {\n processed.push(this.traverseGroupingOnce(segmentOnce));\n }\n return Array.prototype.concat(...processed) as LocalAnimLeavesWithRange[];\n }\n\n public traverseMove(move: Move): LocalAnimLeavesWithRange[] {\n const duration = defaultDurationForAmount(move.amount);\n return [\n {\n animLeafUnit: move,\n msUntilNext: duration,\n duration,\n },\n ];\n }\n\n public traverseCommutator(\n commutator: Commutator,\n ): LocalAnimLeavesWithRange[] {\n const processed: LocalAnimLeavesWithRange[][] = [];\n const segmentsOnce: Alg[] = [\n commutator.A,\n commutator.B,\n commutator.A.invert(),\n commutator.B.invert(),\n ];\n for (const segment of segmentsOnce) {\n processed.push(this.traverseGroupingOnce(segment));\n }\n return Array.prototype.concat(...processed) as LocalAnimLeavesWithRange[];\n }\n\n public traverseConjugate(conjugate: Conjugate): LocalAnimLeavesWithRange[] {\n const processed: LocalAnimLeavesWithRange[][] = [];\n const segmentsOnce: Alg[] = [\n conjugate.A,\n conjugate.B,\n conjugate.A.invert(),\n ];\n for (const segment of segmentsOnce) {\n processed.push(this.traverseGroupingOnce(segment));\n }\n return Array.prototype.concat(...processed) as LocalAnimLeavesWithRange[];\n }\n\n public traversePause(pause: Pause): LocalAnimLeavesWithRange[] {\n const duration = defaultDurationForAmount(1);\n return [\n {\n animLeafUnit: pause,\n msUntilNext: duration, // TODO\n duration,\n },\n ];\n }\n\n public traverseNewline(_newline: Newline): LocalAnimLeavesWithRange[] {\n return [];\n }\n\n public traverseLineComment(\n _comment: LineComment,\n ): LocalAnimLeavesWithRange[] {\n return [];\n }\n}\n\nconst localSimulMovesInstance = new LocalSimulMoves();\n\nconst localSimulMoves = localSimulMovesInstance.traverseAlg.bind(\n localSimulMovesInstance,\n) as (a: Alg) => LocalAnimLeavesWithRange[];\n\nexport function simulMoves(a: Alg): AnimLeafWithRange[] {\n let timestamp = 0;\n const l = localSimulMoves(a).map(\n (localSimulMove: LocalAnimLeavesWithRange): AnimLeafWithRange => {\n const leafWithRange = {\n animLeaf: localSimulMove.animLeafUnit,\n start: timestamp,\n end: timestamp + localSimulMove.duration,\n };\n timestamp += localSimulMove.msUntilNext;\n return leafWithRange;\n },\n );\n return l;\n}\n", "import { Alg, Move } from \"../../../../../alg\";\nimport type {\n PuzzleWrapper,\n State,\n} from \"../../../../views/3D/puzzles/KPuzzleWrapper\";\nimport {\n Direction,\n Duration,\n PuzzlePosition,\n Timestamp,\n} from \"../../cursor/CursorTypes\";\nimport type { AlgIndexer, CurrentMove, CurrentMoveInfo } from \"../AlgIndexer\";\nimport { AnimatedLeafUnit, AnimLeafWithRange, simulMoves } from \"./simul-moves\";\n\nconst demos: Record<string, AnimLeafWithRange[]> = {\n \"y' y' U' E D R2 r2 F2 B2 U E D' R2 L2' z2 S2 U U D D S2 F2' B2\": [\n { animLeaf: new Move(\"y\", -1), start: 0, end: 1000 },\n { animLeaf: new Move(\"y\", -1), start: 1000, end: 2000 },\n { animLeaf: new Move(\"U\", -1), start: 1000, end: 1600 },\n { animLeaf: new Move(\"E\", 1), start: 1200, end: 1800 },\n { animLeaf: new Move(\"D\"), start: 1400, end: 2000 },\n { animLeaf: new Move(\"R\", 2), start: 2000, end: 3500 },\n { animLeaf: new Move(\"r\", 2), start: 2000, end: 3500 },\n { animLeaf: new Move(\"F\", 2), start: 3500, end: 4200 },\n { animLeaf: new Move(\"B\", 2), start: 3800, end: 4500 },\n { animLeaf: new Move(\"U\", 1), start: 4500, end: 5500 },\n { animLeaf: new Move(\"E\", 1), start: 4500, end: 5500 },\n { animLeaf: new Move(\"D\", -1), start: 4500, end: 5500 },\n { animLeaf: new Move(\"R\", 2), start: 5500, end: 6500 },\n { animLeaf: new Move(\"L\", -2), start: 5500, end: 6500 },\n { animLeaf: new Move(\"z\", 2), start: 5500, end: 6500 },\n { animLeaf: new Move(\"S\", 2), start: 6500, end: 7500 },\n { animLeaf: new Move(\"U\"), start: 7500, end: 8000 },\n { animLeaf: new Move(\"D\"), start: 7750, end: 8250 },\n { animLeaf: new Move(\"U\"), start: 8000, end: 8500 },\n { animLeaf: new Move(\"D\"), start: 8250, end: 8750 },\n { animLeaf: new Move(\"S\", 2), start: 8750, end: 9250 },\n { animLeaf: new Move(\"F\", -2), start: 8750, end: 10000 },\n { animLeaf: new Move(\"B\", 2), start: 8750, end: 10000 },\n ],\n \"M' R' U' D' M R\": [\n { animLeaf: new Move(\"M\", -1), start: 0, end: 1000 },\n { animLeaf: new Move(\"R\", -1), start: 0, end: 1000 },\n { animLeaf: new Move(\"U\", -1), start: 1000, end: 2000 },\n { animLeaf: new Move(\"D\", -1), start: 1000, end: 2000 },\n { animLeaf: new Move(\"M\"), start: 2000, end: 3000 },\n { animLeaf: new Move(\"R\"), start: 2000, end: 3000 },\n ],\n \"U' E' r E r2' E r U E\": [\n { animLeaf: new Move(\"U\", -1), start: 0, end: 1000 },\n { animLeaf: new Move(\"E\", -1), start: 0, end: 1000 },\n { animLeaf: new Move(\"r\"), start: 1000, end: 2500 },\n { animLeaf: new Move(\"E\"), start: 2500, end: 3500 },\n { animLeaf: new Move(\"r\", -2), start: 3500, end: 5000 },\n { animLeaf: new Move(\"E\"), start: 5000, end: 6000 },\n { animLeaf: new Move(\"r\"), start: 6000, end: 7000 },\n { animLeaf: new Move(\"U\"), start: 7000, end: 8000 },\n { animLeaf: new Move(\"E\"), start: 7000, end: 8000 },\n ],\n};\n\nexport class SimultaneousMoveIndexerV2<P extends PuzzleWrapper>\n implements AlgIndexer<P>\n{\n private animLeaves: AnimLeafWithRange[];\n // TODO: Allow custom `durationFn`.\n\n constructor(private puzzle: P, alg: Alg) {\n this.animLeaves = demos[alg.toString()] ?? simulMoves(alg);\n // TODO: Avoid assuming all base moves are block moves.\n }\n\n public getAnimLeaf(index: number): AnimatedLeafUnit | null {\n return (\n this.animLeaves[Math.min(index, this.animLeaves.length - 1)]?.animLeaf ??\n null\n );\n }\n\n private getAnimLeafWithRange(index: number): AnimLeafWithRange {\n return this.animLeaves[Math.min(index, this.animLeaves.length - 1)];\n }\n\n public indexToMoveStartTimestamp(index: number): Timestamp {\n let start = 0;\n if (this.animLeaves.length > 0) {\n start =\n this.animLeaves[Math.min(index, this.animLeaves.length - 1)].start;\n }\n return start;\n }\n\n public timestampToIndex(timestamp: Timestamp): number {\n let i = 0;\n for (i = 0; i < this.animLeaves.length; i++) {\n if (this.animLeaves[i].start >= timestamp) {\n return Math.max(0, i - 1);\n }\n }\n return Math.max(0, i - 1);\n }\n\n public timestampToPosition(\n timestamp: Timestamp,\n startTransformation?: State<P>,\n ): PuzzlePosition {\n const currentMoveInfo = this.currentMoveInfo(timestamp);\n\n let state = startTransformation ?? this.puzzle.identity();\n for (const leafWithRange of this.animLeaves.slice(\n 0,\n currentMoveInfo.stateIndex,\n )) {\n const move = leafWithRange.animLeaf.as(Move);\n if (move !== null) {\n state = this.puzzle.combine(state, this.puzzle.stateFromMove(move));\n }\n }\n\n return {\n state: state as any,\n movesInProgress: currentMoveInfo.currentMoves,\n };\n }\n\n // TODO: Caching\n public currentMoveInfo(timestamp: Timestamp): CurrentMoveInfo {\n // The starting timestamp of the earliest active move.\n let windowEarliestTimestamp = Infinity;\n for (const leafWithRange of this.animLeaves) {\n if (leafWithRange.start <= timestamp && leafWithRange.end >= timestamp) {\n windowEarliestTimestamp = Math.min(\n windowEarliestTimestamp,\n leafWithRange.start,\n );\n } else if (leafWithRange.start > timestamp) {\n break;\n }\n }\n\n const currentMoves: CurrentMove[] = [];\n const movesStarting: CurrentMove[] = [];\n const movesFinishing: CurrentMove[] = [];\n const movesFinished: CurrentMove[] = [];\n let latestStart: number = -Infinity; // TODO: is there a better way to accumulate this?\n let earliestEnd: number = Infinity; // TODO: is there a better way to accumulate this?\n\n let stateIndex: number = 0;\n for (const leafWithRange of this.animLeaves) {\n if (leafWithRange.end <= windowEarliestTimestamp) {\n stateIndex++;\n } else if (leafWithRange.start > timestamp) {\n break;\n } else {\n const move = leafWithRange.animLeaf.as(Move);\n if (move !== null) {\n let fraction =\n (timestamp - leafWithRange.start) /\n (leafWithRange.end - leafWithRange.start);\n let moveFinished = false;\n if (fraction > 1) {\n fraction = 1;\n moveFinished = true;\n }\n const currentMove = {\n move: move,\n direction: Direction.Forwards,\n fraction: fraction,\n startTimestamp: leafWithRange.start,\n endTimestamp: leafWithRange.end,\n };\n switch (fraction) {\n case 0:\n movesStarting.push(currentMove);\n break;\n case 1:\n // Generalize this to avoid reordering commuting moves.\n if (moveFinished) {\n movesFinished.push(currentMove);\n } else {\n movesFinishing.push(currentMove);\n }\n break;\n default:\n currentMoves.push(currentMove);\n latestStart = Math.max(latestStart, leafWithRange.start);\n earliestEnd = Math.min(earliestEnd, leafWithRange.end);\n }\n }\n }\n }\n return {\n stateIndex,\n currentMoves,\n latestStart,\n earliestEnd,\n movesStarting,\n movesFinishing,\n movesFinished,\n };\n }\n\n public stateAtIndex(index: number, startTransformation?: State<P>): State<P> {\n let state = startTransformation ?? this.puzzle.startState();\n for (let i = 0; i < this.animLeaves.length && i < index; i++) {\n const leafWithRange = this.animLeaves[i];\n const move = leafWithRange.animLeaf.as(Move);\n if (move !== null) {\n state = this.puzzle.combine(state, this.puzzle.stateFromMove(move));\n }\n }\n return state;\n }\n\n public transformAtIndex(index: number): State<P> {\n let state = this.puzzle.identity();\n for (const leafWithRange of this.animLeaves.slice(0, index)) {\n const move = leafWithRange.animLeaf.as(Move);\n if (move !== null) {\n state = this.puzzle.combine(state, this.puzzle.stateFromMove(move));\n }\n }\n return state;\n }\n\n public algDuration(): Duration {\n let max = 0;\n for (const leafWithRange of this.animLeaves) {\n max = Math.max(max, leafWithRange.end);\n }\n return max;\n }\n\n public numAnimatedLeaves(): number {\n // TODO: Cache internally once performance matters.\n return this.animLeaves.length;\n }\n\n public moveDuration(index: number): number {\n const move = this.getAnimLeafWithRange(index);\n return move.end - move.start;\n }\n}\n", "import {\n Alg,\n Commutator,\n Conjugate,\n Grouping,\n LineComment,\n Move,\n Newline,\n Pause,\n TraversalUp,\n Unit,\n} from \"../../../../../alg\";\nimport { AlgBuilder } from \"../../../../../alg\";\n\nconst MIN_CHUNKING_THRESHOLD = 16;\n\nfunction chunkifyAlg(alg: Alg, chunkMaxLength: number): Alg {\n const mainAlgBuilder = new AlgBuilder();\n const chunkAlgBuilder = new AlgBuilder();\n for (const unit of alg.units()) {\n chunkAlgBuilder.push(unit);\n if (chunkAlgBuilder.experimentalNumUnits() >= chunkMaxLength) {\n mainAlgBuilder.push(new Grouping(chunkAlgBuilder.toAlg()));\n chunkAlgBuilder.reset();\n }\n }\n mainAlgBuilder.push(new Grouping(chunkAlgBuilder.toAlg()));\n return mainAlgBuilder.toAlg();\n}\n\nclass ChunkAlgs extends TraversalUp<Alg, Unit> {\n traverseAlg(alg: Alg): Alg {\n const algLength = alg.experimentalNumUnits();\n if (algLength < MIN_CHUNKING_THRESHOLD) {\n return alg;\n }\n return chunkifyAlg(alg, Math.ceil(Math.sqrt(algLength)));\n }\n\n traverseGrouping(grouping: Grouping): Unit {\n return new Grouping(\n this.traverseAlg(grouping.alg),\n grouping.amount, // TODO\n );\n }\n\n traverseMove(move: Move): Unit {\n return move;\n }\n\n traverseCommutator(commutator: Commutator): Unit {\n return new Conjugate(\n this.traverseAlg(commutator.A),\n this.traverseAlg(commutator.B),\n );\n }\n\n traverseConjugate(conjugate: Conjugate): Unit {\n return new Conjugate(\n this.traverseAlg(conjugate.A),\n this.traverseAlg(conjugate.B),\n );\n }\n\n traversePause(pause: Pause): Unit {\n return pause;\n }\n\n traverseNewline(newline: Newline): Unit {\n return newline;\n }\n\n traverseLineComment(comment: LineComment): Unit {\n return comment;\n }\n}\n\nconst chunkAlgsInstance = new ChunkAlgs();\nexport const chunkAlgs = chunkAlgsInstance.traverseAlg.bind(\n chunkAlgsInstance,\n) as (alg: Alg) => Alg;\n", "import {\n Alg,\n Grouping,\n LineComment,\n Commutator,\n Conjugate,\n Move,\n Newline,\n Pause,\n TraversalDownUp,\n TraversalUp,\n Unit,\n} from \"../../../../../alg\";\nimport {\n experimentalDirectedGenerator,\n ExperimentalIterationDirection,\n} from \"../../../../../alg\";\nimport type {\n PuzzleWrapper,\n State,\n} from \"../../../../views/3D/puzzles/KPuzzleWrapper\";\nimport type { Duration } from \"../../cursor/CursorTypes\";\nimport { AlgDuration, defaultDurationForAmount } from \"../AlgDuration\";\n\nexport class AlgPartDecoration<P extends PuzzleWrapper> {\n constructor(\n _puz: PuzzleWrapper,\n public moveCount: number,\n public duration: number,\n public forward: State<P>,\n public backward: State<P>,\n public children: Array<AlgPartDecoration<P>> = [],\n ) {}\n}\nexport class DecoratorConstructor<P extends PuzzleWrapper> extends TraversalUp<\n AlgPartDecoration<P>\n> {\n private identity: State<P>;\n private dummyLeaf: AlgPartDecoration<P>;\n private durationFn: TraversalUp<Duration> = new AlgDuration(\n defaultDurationForAmount,\n );\n\n private cache: { [key: string]: AlgPartDecoration<P> } = {};\n\n constructor(private puz: PuzzleWrapper) {\n super();\n this.identity = puz.identity();\n this.dummyLeaf = new AlgPartDecoration<P>(\n puz,\n 0,\n 0,\n this.identity,\n this.identity,\n [],\n );\n }\n\n public traverseAlg(alg: Alg): AlgPartDecoration<P> {\n let moveCount = 0;\n let duration = 0;\n let state = this.identity;\n const child: Array<AlgPartDecoration<P>> = [];\n for (const unit of alg.units()) {\n const apd = this.traverseUnit(unit);\n moveCount += apd.moveCount;\n duration += apd.duration;\n if (state === this.identity) {\n state = apd.forward;\n } else {\n state = this.puz.combine(state, apd.forward);\n }\n child.push(apd);\n }\n return new AlgPartDecoration<P>(\n this.puz,\n moveCount,\n duration,\n state,\n this.puz.invert(state),\n child,\n );\n }\n\n public traverseGrouping(grouping: Grouping): AlgPartDecoration<P> {\n const dec = this.traverseAlg(grouping.alg);\n return this.mult(dec, grouping.amount, [dec]);\n }\n\n public traverseMove(move: Move): AlgPartDecoration<P> {\n const key = move.toString();\n let r: AlgPartDecoration<P> | undefined = this.cache[key];\n if (r) {\n return r;\n }\n r = new AlgPartDecoration<P>(\n this.puz,\n 1,\n this.durationFn.traverseUnit(move),\n this.puz.stateFromMove(move),\n this.puz.stateFromMove(move.invert()),\n );\n this.cache[key] = r;\n return r;\n }\n\n public traverseCommutator(commutator: Commutator): AlgPartDecoration<P> {\n const decA = this.traverseAlg(commutator.A);\n const decB = this.traverseAlg(commutator.B);\n const AB = this.puz.combine(decA.forward, decB.forward);\n const ApBp = this.puz.combine(decA.backward, decB.backward);\n const ABApBp = this.puz.combine(AB, ApBp);\n const dec = new AlgPartDecoration<P>(\n this.puz,\n 2 * (decA.moveCount + decB.moveCount),\n 2 * (decA.duration + decB.duration),\n ABApBp,\n this.puz.invert(ABApBp),\n [decA, decB],\n );\n return this.mult(dec, 1, [dec, decA, decB]);\n }\n\n public traverseConjugate(conjugate: Conjugate): AlgPartDecoration<P> {\n const decA = this.traverseAlg(conjugate.A);\n const decB = this.traverseAlg(conjugate.B);\n const AB = this.puz.combine(decA.forward, decB.forward);\n const ABAp = this.puz.combine(AB, decA.backward);\n const dec = new AlgPartDecoration<P>(\n this.puz,\n 2 * decA.moveCount + decB.moveCount,\n 2 * decA.duration + decB.duration,\n ABAp,\n this.puz.invert(ABAp),\n [decA, decB],\n );\n return this.mult(dec, 1, [dec, decA, decB]);\n }\n\n public traversePause(pause: Pause): AlgPartDecoration<P> {\n return new AlgPartDecoration<P>(\n this.puz,\n 1,\n this.durationFn.traverseUnit(pause),\n this.identity,\n this.identity,\n );\n }\n\n public traverseNewline(_newline: Newline): AlgPartDecoration<P> {\n return this.dummyLeaf;\n }\n\n public traverseLineComment(_comment: LineComment): AlgPartDecoration<P> {\n return this.dummyLeaf;\n }\n\n private mult(\n apd: AlgPartDecoration<P>,\n n: number,\n child: Array<AlgPartDecoration<P>>,\n ): AlgPartDecoration<P> {\n const absn = Math.abs(n);\n const st = this.puz.multiply(apd.forward, n);\n return new AlgPartDecoration<P>(\n this.puz,\n apd.moveCount * absn,\n apd.duration * absn,\n st,\n this.puz.invert(st),\n child,\n );\n }\n}\nclass WalkerDown<P extends PuzzleWrapper> {\n constructor(public apd: AlgPartDecoration<P>, public back: boolean) {\n /**/\n }\n}\nexport class AlgWalker<P extends PuzzleWrapper> extends TraversalDownUp<\n WalkerDown<P>,\n boolean\n> {\n public move?: Unit;\n public moveDuration: number;\n public back: boolean;\n public st: State<P>;\n public root: WalkerDown<P>;\n public i: number;\n public dur: number;\n private goali: number;\n private goaldur: number;\n constructor(\n public puz: P,\n public algOrUnit: Alg | Unit, // TODO: can we keep these separate?\n public apd: AlgPartDecoration<P>,\n ) {\n super();\n this.i = -1;\n this.dur = -1;\n this.goali = -1;\n this.goaldur = -1;\n this.move = undefined;\n this.back = false;\n this.moveDuration = 0;\n this.st = this.puz.identity();\n this.root = new WalkerDown(this.apd, false);\n }\n\n public moveByIndex(loc: number): boolean {\n if (this.i >= 0 && this.i === loc) {\n return this.move !== undefined;\n }\n return this.dosearch(loc, Infinity);\n }\n\n public moveByDuration(dur: number): boolean {\n if (\n this.dur >= 0 &&\n this.dur < dur &&\n this.dur + this.moveDuration >= dur\n ) {\n return this.move !== undefined;\n }\n return this.dosearch(Infinity, dur);\n }\n\n public dosearch(loc: number, dur: number): boolean {\n this.goali = loc;\n this.goaldur = dur;\n this.i = 0;\n this.dur = 0;\n this.move = undefined;\n this.moveDuration = 0;\n this.back = false;\n this.st = this.puz.identity();\n const r = this.algOrUnit.is(Alg)\n ? this.traverseAlg(this.algOrUnit as Alg, this.root)\n : this.traverseUnit(this.algOrUnit as Unit, this.root); // TODO\n return r;\n }\n\n public traverseAlg(alg: Alg, wd: WalkerDown<P>): boolean {\n if (!this.firstcheck(wd)) {\n return false;\n }\n let i = wd.back ? alg.experimentalNumUnits() - 1 : 0;\n for (const unit of experimentalDirectedGenerator(\n alg.units(),\n wd.back\n ? ExperimentalIterationDirection.Backwards\n : ExperimentalIterationDirection.Forwards,\n )) {\n if (\n this.traverseUnit(unit, new WalkerDown(wd.apd.children[i], wd.back))\n ) {\n return true;\n }\n i += wd.back ? -1 : 1;\n }\n return false;\n }\n\n public traverseGrouping(grouping: Grouping, wd: WalkerDown<P>): boolean {\n if (!this.firstcheck(wd)) {\n return false;\n }\n const back = this.domult(wd, grouping.amount);\n return this.traverseAlg(\n grouping.alg,\n new WalkerDown(wd.apd.children[0], back),\n );\n }\n\n public traverseMove(move: Move, wd: WalkerDown<P>): boolean {\n if (!this.firstcheck(wd)) {\n return false;\n }\n this.move = move;\n this.moveDuration = wd.apd.duration;\n this.back = wd.back;\n return true;\n }\n\n public traverseCommutator(\n commutator: Commutator,\n wd: WalkerDown<P>,\n ): boolean {\n if (!this.firstcheck(wd)) {\n return false;\n }\n const back = this.domult(wd, 1);\n if (back) {\n return (\n this.traverseAlg(\n commutator.B,\n new WalkerDown(wd.apd.children[2], !back),\n ) ||\n this.traverseAlg(\n commutator.A,\n new WalkerDown(wd.apd.children[1], !back),\n ) ||\n this.traverseAlg(\n commutator.B,\n new WalkerDown(wd.apd.children[2], back),\n ) ||\n this.traverseAlg(commutator.A, new WalkerDown(wd.apd.children[1], back))\n );\n } else {\n return (\n this.traverseAlg(\n commutator.A,\n new WalkerDown(wd.apd.children[1], back),\n ) ||\n this.traverseAlg(\n commutator.B,\n new WalkerDown(wd.apd.children[2], back),\n ) ||\n this.traverseAlg(\n commutator.A,\n new WalkerDown(wd.apd.children[1], !back),\n ) ||\n this.traverseAlg(\n commutator.B,\n new WalkerDown(wd.apd.children[2], !back),\n )\n );\n }\n }\n\n public traverseConjugate(conjugate: Conjugate, wd: WalkerDown<P>): boolean {\n if (!this.firstcheck(wd)) {\n return false;\n }\n const back = this.domult(wd, 1);\n if (back) {\n return (\n this.traverseAlg(\n conjugate.A,\n new WalkerDown(wd.apd.children[1], !back),\n ) ||\n this.traverseAlg(\n conjugate.B,\n new WalkerDown(wd.apd.children[2], back),\n ) ||\n this.traverseAlg(conjugate.A, new WalkerDown(wd.apd.children[1], back))\n );\n } else {\n return (\n this.traverseAlg(\n conjugate.A,\n new WalkerDown(wd.apd.children[1], back),\n ) ||\n this.traverseAlg(\n conjugate.B,\n new WalkerDown(wd.apd.children[2], back),\n ) ||\n this.traverseAlg(conjugate.A, new WalkerDown(wd.apd.children[1], !back))\n );\n }\n }\n\n public traversePause(pause: Pause, wd: WalkerDown<P>): boolean {\n if (!this.firstcheck(wd)) {\n return false;\n }\n this.move = pause;\n this.moveDuration = wd.apd.duration;\n this.back = wd.back;\n return true;\n }\n\n public traverseNewline(_newline: Newline, _wd: WalkerDown<P>): boolean {\n return false;\n }\n\n public traverseLineComment(\n _lineComment: LineComment,\n _wd: WalkerDown<P>,\n ): boolean {\n return false;\n }\n\n private firstcheck(wd: WalkerDown<P>): boolean {\n if (\n wd.apd.moveCount + this.i <= this.goali &&\n wd.apd.duration + this.dur < this.goaldur\n ) {\n return this.keepgoing(wd);\n }\n return true;\n }\n\n private domult(wd: WalkerDown<P>, amount: number): boolean {\n let back = wd.back;\n if (amount === 0) {\n // I don't believe this will ever happen\n return back;\n }\n if (amount < 0) {\n back = !back;\n amount = -amount;\n }\n const base = wd.apd.children[0];\n const full = Math.min(\n Math.floor((this.goali - this.i) / base.moveCount),\n Math.ceil((this.goaldur - this.dur) / base.duration - 1),\n );\n if (full > 0) {\n this.keepgoing(new WalkerDown<P>(base, back), full);\n }\n return back;\n }\n\n private keepgoing(wd: WalkerDown<P>, mul: number = 1): boolean {\n this.i += mul * wd.apd.moveCount;\n this.dur += mul * wd.apd.duration;\n if (mul !== 1) {\n if (wd.back) {\n this.st = this.puz.combine(\n this.st,\n this.puz.multiply(wd.apd.backward, mul),\n );\n } else {\n this.st = this.puz.combine(\n this.st,\n this.puz.multiply(wd.apd.forward, mul),\n );\n }\n } else {\n if (wd.back) {\n this.st = this.puz.combine(this.st, wd.apd.backward);\n } else {\n this.st = this.puz.combine(this.st, wd.apd.forward);\n }\n }\n return false;\n }\n}\n", "import type { Alg, Move } from \"../../../../../alg\";\nimport type {\n PuzzleWrapper,\n State,\n} from \"../../../../views/3D/puzzles/KPuzzleWrapper\";\nimport type { Duration, Timestamp } from \"../../cursor/CursorTypes\";\nimport type { AlgIndexer } from \"../AlgIndexer\";\nimport { chunkAlgs } from \"./chunkAlgs\";\nimport {\n AlgPartDecoration,\n AlgWalker,\n DecoratorConstructor,\n} from \"./AlgWalker\";\n\nexport class TreeAlgIndexer implements AlgIndexer<PuzzleWrapper> {\n private decoration: AlgPartDecoration<PuzzleWrapper>;\n private walker: AlgWalker<PuzzleWrapper>;\n constructor(private puzzle: PuzzleWrapper, alg: Alg) {\n const deccon = new DecoratorConstructor<PuzzleWrapper>(this.puzzle);\n\n const chunkedAlg = chunkAlgs(alg);\n\n this.decoration = deccon.traverseAlg(chunkedAlg);\n this.walker = new AlgWalker<PuzzleWrapper>(\n this.puzzle,\n chunkedAlg,\n this.decoration,\n );\n }\n\n public getAnimLeaf(index: number): Move | null {\n // FIXME need to support Pause\n if (this.walker.moveByIndex(index)) {\n if (!this.walker.move) {\n throw new Error(\"`this.walker.mv` missing\");\n }\n const move = this.walker.move as Move;\n // TODO: this type of negation needs to be in alg\n if (this.walker.back) {\n return move.invert();\n }\n return move;\n }\n return null;\n }\n\n public indexToMoveStartTimestamp(index: number): Timestamp {\n if (this.walker.moveByIndex(index) || this.walker.i === index) {\n return this.walker.dur;\n }\n throw new Error(`Out of algorithm: index ${index}`);\n }\n\n public indexToMovesInProgress(index: number): Timestamp {\n if (this.walker.moveByIndex(index) || this.walker.i === index) {\n return this.walker.dur;\n }\n throw new Error(`Out of algorithm: index ${index}`);\n }\n\n public stateAtIndex(\n index: number,\n startTransformation?: State<PuzzleWrapper>,\n ): State<PuzzleWrapper> {\n this.walker.moveByIndex(index);\n return this.puzzle.combine(\n startTransformation ?? this.puzzle.startState(),\n this.walker.st,\n );\n }\n\n // TransformAtIndex does not reflect the start state; it only reflects\n // the change from the start state to the current move index. If you\n // want the actual state, use stateAtIndex.\n public transformAtIndex(index: number): State<PuzzleWrapper> {\n this.walker.moveByIndex(index);\n return this.walker.st;\n }\n\n public numAnimatedLeaves(): number {\n return this.decoration.moveCount;\n }\n\n public timestampToIndex(timestamp: Timestamp): number {\n this.walker.moveByDuration(timestamp);\n return this.walker.i;\n }\n\n public algDuration(): Duration {\n return this.decoration.duration;\n }\n\n public moveDuration(index: number): number {\n this.walker.moveByIndex(index);\n return this.walker.moveDuration;\n }\n}\n", "import { countMoves } from \"../../../../../notation\";\nimport type { IndexerConstructor } from \"../../../../old/animation/cursor/AlgCursor\";\nimport { SimpleAlgIndexer } from \"../../../../old/animation/indexer/SimpleAlgIndexer\";\nimport { SimultaneousMoveIndexerV2 } from \"../../../../old/animation/indexer/simultaneous-moves/SimultaneousMoveIndexerV2\";\nimport { TreeAlgIndexer } from \"../../../../old/animation/indexer/tree/TreeAlgIndexer\";\nimport type { PuzzleID } from \"../../../../old/dom/TwistyPlayerConfig\";\nimport type { AlgWithIssues } from \"./AlgProp\";\nimport type { IndexerStrategyName } from \"./IndexerConstructorRequestProp\";\nimport type { VisualizationStrategy } from \"../../viewer/VisualizationStrategyProp\";\nimport { TwistyPropDerived } from \"../../TwistyProp\";\n\ninterface IndexerConstructorPropInputs {\n puzzle: PuzzleID;\n alg: AlgWithIssues;\n visualizationStrategy: VisualizationStrategy;\n indexerConstructorRequest: IndexerStrategyName;\n}\n\n// TODO: Also handle PG3D vs. 3D\nexport class IndexerConstructorProp extends TwistyPropDerived<\n IndexerConstructorPropInputs,\n IndexerConstructor\n> {\n derive(inputs: IndexerConstructorPropInputs): IndexerConstructor {\n switch (inputs.indexerConstructorRequest) {\n case \"auto\":\n if (\n countMoves(inputs.alg.alg) < 100 &&\n inputs.puzzle === \"3x3x3\" &&\n inputs.visualizationStrategy === \"Cube3D\"\n ) {\n return SimultaneousMoveIndexerV2;\n } else {\n return TreeAlgIndexer;\n }\n case \"tree\":\n return TreeAlgIndexer;\n case \"simple\":\n return SimpleAlgIndexer;\n case \"simultaneous\":\n return SimultaneousMoveIndexerV2;\n default:\n throw new Error(\"Invalid indexer request!\");\n }\n }\n}\n", "import { Alg } from \"../../../../../alg\";\nimport { KPuzzle, KPuzzleDefinition } from \"../../../../../kpuzzle\";\nimport { AlgIssues, AlgWithIssues } from \"./AlgProp\";\nimport { TwistyPropDerived } from \"../../TwistyProp\";\n\nexport class PuzzleAlgProp extends TwistyPropDerived<\n { algWithIssues: AlgWithIssues; puzzleDef: KPuzzleDefinition },\n AlgWithIssues\n> {\n async derive(inputs: {\n algWithIssues: AlgWithIssues;\n puzzleDef: KPuzzleDefinition;\n }): Promise<AlgWithIssues> {\n try {\n const kpuzzle = new KPuzzle(inputs.puzzleDef);\n kpuzzle.applyAlg(inputs.algWithIssues.alg);\n // Looks like we could apply the alg!\n return inputs.algWithIssues;\n } catch (e) {\n return {\n alg: new Alg(),\n issues: new AlgIssues({\n errors: [`Invalid alg for puzzle: ${(e as Error).toString()}`],\n }),\n };\n }\n }\n}\n", "import type { Move } from \"../../../../alg\";\nimport {\n combineTransformations,\n areStatesEquivalent,\n identityTransformation,\n invertTransformation,\n KPuzzleDefinition,\n transformationForMove,\n Transformation,\n} from \"../../../../kpuzzle\";\nimport { puzzles } from \"../../../../puzzles\";\n\nexport type MoveName = string;\n\nexport interface MoveProgress {\n move: Move;\n fraction: number;\n}\n\n// eslint-disable-next-line @typescript-eslint/no-empty-interface, @typescript-eslint/no-unused-vars\nexport interface State<T extends PuzzleWrapper> {}\n\nexport abstract class PuzzleWrapper {\n public abstract startState(): State<PuzzleWrapper>;\n public abstract invert(state: State<PuzzleWrapper>): State<PuzzleWrapper>;\n public abstract combine(\n s1: State<PuzzleWrapper>,\n s2: State<PuzzleWrapper>,\n ): State<PuzzleWrapper>;\n\n public multiply(\n state: State<PuzzleWrapper>,\n amount: number,\n ): State<PuzzleWrapper> {\n if (amount < 0) {\n return this.invert(this.multiply(state, -amount));\n }\n if (amount === 0) {\n return this.identity();\n }\n while (amount % 2 === 0) {\n amount = amount / 2;\n state = this.combine(state, state);\n }\n let newState = state;\n amount--;\n while (amount > 0) {\n if (amount % 2 === 1) {\n newState = this.combine(newState, state);\n }\n amount = Math.floor(amount / 2);\n if (amount > 0) {\n state = this.combine(state, state);\n }\n }\n return newState;\n }\n\n public abstract stateFromMove(move: Move): State<PuzzleWrapper>;\n public abstract identity(): State<PuzzleWrapper>;\n public abstract equivalent(\n s1: State<PuzzleWrapper>,\n s2: State<PuzzleWrapper>,\n ): boolean;\n}\n\nexport interface KSolvePuzzleState\n extends Transformation,\n State<KPuzzleWrapper> {}\n\nexport class KPuzzleWrapper extends PuzzleWrapper {\n // don't work the underlying kdefinition/multiply so hard\n public static async fromID(id: string): Promise<KPuzzleWrapper> {\n return new KPuzzleWrapper(await puzzles[id].def());\n }\n\n public moveCache: { [key: string]: Transformation } = {};\n constructor(private definition: KPuzzleDefinition) {\n super();\n }\n\n public startState(): KSolvePuzzleState {\n return this.definition.startPieces;\n }\n\n public invert(state: KSolvePuzzleState): KSolvePuzzleState {\n return invertTransformation(this.definition, state);\n }\n\n public combine(\n s1: KSolvePuzzleState,\n s2: KSolvePuzzleState,\n ): KSolvePuzzleState {\n return combineTransformations(this.definition, s1, s2);\n }\n\n public stateFromMove(move: Move): KSolvePuzzleState {\n const key = move.toString();\n if (!this.moveCache[key]) {\n this.moveCache[key] = transformationForMove(this.definition, move);\n }\n return this.moveCache[key];\n }\n\n public identity(): KSolvePuzzleState {\n return identityTransformation(this.definition);\n }\n\n public equivalent(s1: KSolvePuzzleState, s2: KSolvePuzzleState): boolean {\n return areStatesEquivalent(this.definition, s1, s2);\n }\n}\n\nclass QTMCounterState implements State<QTMCounterPuzzle> {\n constructor(public value: number) {}\n}\n\nexport class QTMCounterPuzzle extends PuzzleWrapper {\n public startState(): QTMCounterState {\n return new QTMCounterState(0);\n }\n\n public invert(state: QTMCounterState): QTMCounterState {\n return new QTMCounterState(-state.value);\n }\n\n public combine(s1: QTMCounterState, s2: QTMCounterState): QTMCounterState {\n return new QTMCounterState(s1.value + s2.value);\n }\n\n public stateFromMove(move: Move): QTMCounterState {\n return new QTMCounterState(Math.abs(move.amount));\n }\n\n public identity(): QTMCounterState {\n return new QTMCounterState(0);\n }\n\n public equivalent(s1: QTMCounterState, s2: QTMCounterState): boolean {\n return s1.value === s2.value;\n }\n}\n", "import type { Alg } from \"../../../../../alg\";\nimport type { KPuzzleDefinition, Transformation } from \"../../../../../kpuzzle\";\nimport { KPuzzleWrapper } from \"../../../../views/3D/puzzles/KPuzzleWrapper\";\nimport { TreeAlgIndexer } from \"../../../../old/animation/indexer/tree/TreeAlgIndexer\";\nimport type { AlgWithIssues } from \"./AlgProp\";\nimport { TwistyPropDerived } from \"../../TwistyProp\";\n\ntype AlgTransformationPropInputs = {\n alg: AlgWithIssues;\n def: KPuzzleDefinition;\n};\n\nexport class AlgTransformationProp extends TwistyPropDerived<\n AlgTransformationPropInputs,\n Transformation\n> {\n derive(input: AlgTransformationPropInputs): Transformation {\n return this.applyAlg(input.def, input.alg.alg);\n }\n\n applyAlg(def: KPuzzleDefinition, alg: Alg): Transformation {\n const kpuzzleWrapper = new KPuzzleWrapper(def); // TODO: Remove this layer.\n const indexer = new TreeAlgIndexer(kpuzzleWrapper, alg); // TODO: Use a direct efficient traversal in `cubing/kpuzzle` instead of instantiating a whole indexer.\n return indexer.transformAtIndex(\n indexer.numAnimatedLeaves(),\n ) as Transformation;\n }\n}\n", "import type { KPuzzleDefinition } from \"../../../../../kpuzzle\";\nimport { KPuzzleWrapper } from \"../../../../views/3D/puzzles/KPuzzleWrapper\";\nimport type { IndexerConstructor } from \"../../../../old/animation/cursor/AlgCursor\";\nimport type { AlgIndexer } from \"../../../../old/animation/indexer/AlgIndexer\";\nimport type { AlgWithIssues } from \"./AlgProp\";\nimport { TwistyPropDerived } from \"../../TwistyProp\";\n\ntype IndexerPropInputs = {\n indexerConstructor: IndexerConstructor;\n algWithIssues: AlgWithIssues;\n def: KPuzzleDefinition;\n};\nexport class IndexerProp extends TwistyPropDerived<\n IndexerPropInputs,\n AlgIndexer<any>\n> {\n derive(input: IndexerPropInputs): AlgIndexer<any> {\n const kpuzzleWrapper = new KPuzzleWrapper(input.def); // TODO: Remove this layer.\n return new input.indexerConstructor(\n kpuzzleWrapper,\n input.algWithIssues.alg,\n );\n }\n}\n", "import {\n combineTransformations,\n invertTransformation,\n KPuzzleDefinition,\n Transformation,\n} from \"../../../../../kpuzzle\";\nimport type { AlgIndexer } from \"../../../../old/animation/indexer/AlgIndexer\";\nimport type { SetupToLocation } from \"../../../../old/dom/TwistyPlayerConfig\";\nimport { TwistyPropDerived } from \"../../TwistyProp\";\n\ninterface AnchoredStartPropInputs {\n setupAnchor: SetupToLocation;\n setupTransformation: Transformation;\n indexer: AlgIndexer<any>;\n def: KPuzzleDefinition;\n}\n\nexport class AnchoredStartProp extends TwistyPropDerived<\n AnchoredStartPropInputs,\n Transformation\n> {\n derive(inputs: AnchoredStartPropInputs): Transformation {\n switch (inputs.setupAnchor) {\n case \"start\":\n return inputs.setupTransformation;\n case \"end\": {\n const algTransformation = inputs.indexer.transformAtIndex(\n inputs.indexer.numAnimatedLeaves(),\n ) as Transformation;\n const inverseAlgTransformation = invertTransformation(\n inputs.def,\n algTransformation,\n );\n return combineTransformations(\n inputs.def,\n inputs.setupTransformation,\n inverseAlgTransformation,\n );\n }\n default:\n throw new Error(\"Unimplemented!\");\n }\n }\n}\n", "import type { TimeRange } from \"../../../old/animation/cursor/AlgCursor\";\nimport type { AlgIndexer } from \"../../../old/animation/indexer/AlgIndexer\";\nimport { TwistyPropDerived } from \"../TwistyProp\";\n\nexport class TimeRangeProp extends TwistyPropDerived<\n { indexer: AlgIndexer<any> },\n TimeRange\n> {\n derive(inputs: { indexer: AlgIndexer<any> }): TimeRange {\n return {\n start: 0,\n end: inputs.indexer.algDuration(),\n };\n }\n}\n", "import type { TimeRange } from \"../../../old/animation/cursor/AlgCursor\";\nimport type { MillisecondTimestamp } from \"../../../old/animation/cursor/CursorTypes\";\nimport type { SetupToLocation } from \"../../../old/dom/TwistyPlayerConfig\";\nimport type { TimestampRequest } from \"./TimestampRequestProp\";\nimport { TwistyPropDerived } from \"../TwistyProp\";\n\ninterface DetailedTimelineInfoInputs {\n timestampRequest: TimestampRequest;\n timeRange: TimeRange;\n setupAnchor: SetupToLocation;\n}\n\nexport interface DetailedTimelineInfo {\n timestamp: MillisecondTimestamp;\n timeRange: TimeRange; // TODO: Don't incluede this, and let fresh listeners listen to multiple inputs?\n // Note: `atStart` and `atEnd` can both be true. This is the case with the\n // default (empty) alg, which has a duration of 0 ms.\n atStart: boolean;\n atEnd: boolean;\n}\n\nexport class DetailedTimelineInfoProp extends TwistyPropDerived<\n DetailedTimelineInfoInputs,\n DetailedTimelineInfo\n> {\n derive(inputs: DetailedTimelineInfoInputs): DetailedTimelineInfo {\n let timestamp = this.#requestedTimestampToMilliseconds(inputs);\n let atStart: boolean = false;\n let atEnd: boolean = false;\n if (timestamp >= inputs.timeRange.end) {\n atEnd = true;\n timestamp = Math.min(inputs.timeRange.end, timestamp);\n }\n if (timestamp <= inputs.timeRange.start) {\n atStart = true;\n timestamp = Math.max(inputs.timeRange.start, timestamp);\n }\n return {\n timestamp,\n timeRange: inputs.timeRange,\n atStart,\n atEnd,\n };\n }\n\n #requestedTimestampToMilliseconds(\n inputs: DetailedTimelineInfoInputs,\n ): MillisecondTimestamp {\n switch (inputs.timestampRequest) {\n case \"start\":\n return inputs.timeRange.start;\n case \"end\":\n return inputs.timeRange.end;\n case \"anchor\":\n return inputs.setupAnchor === \"start\"\n ? inputs.timeRange.start\n : inputs.timeRange.end;\n case \"opposite-anchor\":\n return inputs.setupAnchor === \"start\"\n ? inputs.timeRange.end\n : inputs.timeRange.start;\n default:\n return inputs.timestampRequest;\n }\n }\n\n canReuse(v1: DetailedTimelineInfo, v2: DetailedTimelineInfo) {\n return (\n v1.timestamp === v2.timestamp &&\n v1.timeRange.start === v2.timeRange.start &&\n v1.timeRange.end === v2.timeRange.end &&\n v1.atStart === v2.atStart &&\n v1.atEnd === v2.atEnd\n );\n }\n}\n", "import type { ButtonCommand } from \"../../../views/control-panel/TwistyButtonsV2\";\nimport type { PlayingInfo } from \"./PlayingInfoProp\";\nimport type { DetailedTimelineInfo } from \"./DetailedTimelineInfoProp\";\nimport { TwistyPropDerived } from \"../TwistyProp\";\n\ninterface ButtonAppearance {\n enabled: boolean;\n icon: string;\n title: string;\n}\nexport type ButtonAppearances = Record<ButtonCommand, ButtonAppearance>;\n\ninterface CoarseTimelineInfoInputs {\n playingInfo: PlayingInfo;\n detailedTimelineInfo: DetailedTimelineInfo;\n}\n\nexport interface CoarseTimelineInfo {\n playing: boolean;\n atStart: boolean;\n atEnd: boolean;\n}\n\n// This started as a version of `EffectiveTimestamp` without the actual\n// timestamp, to enable easier caching.\nexport class CoarseTimelineInfoProp extends TwistyPropDerived<\n CoarseTimelineInfoInputs,\n CoarseTimelineInfo\n> {\n derive(inputs: CoarseTimelineInfoInputs): CoarseTimelineInfo {\n return {\n playing: inputs.playingInfo.playing,\n atStart: inputs.detailedTimelineInfo.atStart,\n atEnd: inputs.detailedTimelineInfo.atEnd,\n };\n }\n\n canReuseValue(v1: CoarseTimelineInfo, v2: CoarseTimelineInfo): boolean {\n return (\n v1.playing === v2.playing &&\n v1.atStart === v2.atStart &&\n v1.atEnd === v2.atEnd\n );\n }\n}\n", "import { Move } from \"../../../../../alg\";\nimport { Direction } from \"../../../../old/animation/cursor/CursorTypes\";\nimport type {\n AlgIndexer,\n CurrentMoveInfo,\n} from \"../../../../old/animation/indexer/AlgIndexer\";\nimport type { DetailedTimelineInfo } from \"../../timeline/DetailedTimelineInfoProp\";\nimport { TwistyPropDerived } from \"../../TwistyProp\";\nimport type { CatchUpMove } from \"./CatchUpMoveProp\";\n\ninterface PositionPropInputs {\n indexer: AlgIndexer<any>;\n detailedTimelineInfo: DetailedTimelineInfo;\n catchUpMove: CatchUpMove;\n}\n\n// TODO: Rename \"current\" (implies a single one) to \"active\"?\nexport class CurrentLeavesProp extends TwistyPropDerived<\n PositionPropInputs,\n CurrentMoveInfo\n> {\n derive(inputs: PositionPropInputs): CurrentMoveInfo {\n function addCatchUpMove(currentMoveInfo: CurrentMoveInfo): CurrentMoveInfo {\n if (\n inputs.detailedTimelineInfo.atEnd &&\n inputs.catchUpMove.move !== null\n ) {\n currentMoveInfo.currentMoves.push({\n move: inputs.catchUpMove.move,\n direction: Direction.Backwards,\n fraction: 1 - inputs.catchUpMove.amount,\n startTimestamp: -1, // TODO\n endTimestamp: -1, // TODO\n });\n }\n return currentMoveInfo;\n }\n\n // Copied from AlgCursor\n if (inputs.indexer.currentMoveInfo) {\n return addCatchUpMove(\n inputs.indexer.currentMoveInfo(inputs.detailedTimelineInfo.timestamp),\n );\n } else {\n const idx = inputs.indexer.timestampToIndex(\n inputs.detailedTimelineInfo.timestamp,\n );\n const currentMoveInfo: CurrentMoveInfo = {\n stateIndex: idx,\n currentMoves: [],\n movesFinishing: [],\n movesFinished: [],\n movesStarting: [],\n latestStart: -Infinity,\n earliestEnd: Infinity,\n };\n\n if (inputs.indexer.numAnimatedLeaves() > 0) {\n const move = inputs.indexer.getAnimLeaf(idx)?.as(Move);\n if (!move) {\n return addCatchUpMove(currentMoveInfo);\n }\n const start = inputs.indexer.indexToMoveStartTimestamp(idx);\n const duration = inputs.indexer.moveDuration(idx);\n const fraction =\n (inputs.detailedTimelineInfo.timestamp - start) / duration;\n const end = start + duration;\n const currentMove = {\n move,\n direction: Direction.Forwards,\n fraction,\n startTimestamp: start,\n endTimestamp: end,\n };\n if (fraction === 0) {\n currentMoveInfo.movesStarting.push(currentMove);\n // // TODO: push this into the indexer\n // position.state = combineTransformations(\n // inputs.def,\n // state,\n // transformationForMove(inputs.def, move),\n // ) as Transformation;\n } else if (fraction === 1) {\n currentMoveInfo.movesFinishing.push(currentMove);\n // // TODO: push this into the indexer\n // position.state = combineTransformations(\n // inputs.def,\n // state,\n // transformationForMove(inputs.def, move),\n // ) as Transformation;\n } else {\n // TODO\n currentMoveInfo.currentMoves.push(currentMove);\n currentMoveInfo.latestStart = Math.max(\n currentMoveInfo.latestStart,\n start,\n );\n currentMoveInfo.earliestEnd = Math.min(\n currentMoveInfo.earliestEnd,\n end,\n );\n }\n // }\n // }\n }\n return addCatchUpMove(currentMoveInfo);\n }\n }\n}\n", "import type { Move } from \"../../../../../alg\";\nimport type { CurrentMoveInfo } from \"../../../../old/animation/indexer/AlgIndexer\";\nimport { arrayEqualsCompare } from \"../../../helpers\";\nimport { TwistyPropDerived } from \"../../TwistyProp\";\n\ninterface CurrentLeavesSimplifiedPropInputs {\n currentMoveInfo: CurrentMoveInfo;\n}\n\nexport interface CurrentLeavesSimplified {\n stateIndex: number;\n movesFinishing: Move[];\n movesFinished: Move[];\n}\n\n// This started as a version of `CurrentLeaves` without highly timestamp-sensitive info like fractions, to enable easier caching.\nexport class CurrentLeavesSimplifiedProp extends TwistyPropDerived<\n CurrentLeavesSimplifiedPropInputs,\n CurrentLeavesSimplified\n> {\n derive(inputs: CurrentLeavesSimplifiedPropInputs): CurrentLeavesSimplified {\n return {\n stateIndex: inputs.currentMoveInfo.stateIndex,\n movesFinishing: inputs.currentMoveInfo.movesFinishing.map(\n (currentMoveInfo) => currentMoveInfo.move,\n ),\n movesFinished: inputs.currentMoveInfo.movesFinished.map(\n (currentMoveInfo) => currentMoveInfo.move,\n ),\n };\n }\n\n canReuse(v1: CurrentLeavesSimplified, v2: CurrentLeavesSimplified): boolean {\n return (\n v1.stateIndex === v2.stateIndex &&\n arrayEqualsCompare(\n v1.movesFinishing,\n v2.movesFinishing,\n (m1: Move, m2: Move) => m1.isIdentical(m2),\n ) &&\n arrayEqualsCompare(\n v1.movesFinished,\n v2.movesFinished,\n (m1: Move, m2: Move) => m1.isIdentical(m2),\n )\n );\n }\n}\n", "import { KSolvePuzzle } from \"../../../..\";\nimport {\n combineTransformations,\n KPuzzleDefinition,\n Transformation,\n} from \"../../../../../kpuzzle\";\nimport type { AlgIndexer } from \"../../../../old/animation/indexer/AlgIndexer\";\nimport type { CurrentLeavesSimplified } from \"./CurrentLeavesSimplified\";\nimport { TwistyPropDerived } from \"../../TwistyProp\";\n\ninterface CurrentTransformationPropInputs {\n anchoredStart: Transformation;\n currentLeavesSimplified: CurrentLeavesSimplified;\n indexer: AlgIndexer<any>;\n def: KPuzzleDefinition;\n}\n\n// TODO: Make this so we don't have to handle the finishing moves?\nexport class CurrentTransformationProp extends TwistyPropDerived<\n CurrentTransformationPropInputs,\n Transformation\n> {\n derive(inputs: CurrentTransformationPropInputs): Transformation {\n let state: Transformation = inputs.indexer.transformAtIndex(\n inputs.currentLeavesSimplified.stateIndex,\n ) as any;\n state = combineTransformations(inputs.def, inputs.anchoredStart, state);\n const ksolvePuzzle = new KSolvePuzzle(inputs.def); // TODO: put this elsewhere.\n // TODO: handle non-commutative finished/finishing/current moves.\n for (const finishingMove of inputs.currentLeavesSimplified.movesFinishing) {\n state = combineTransformations(\n inputs.def,\n state,\n ksolvePuzzle.stateFromMove(finishingMove),\n );\n }\n for (const finishedMove of inputs.currentLeavesSimplified.movesFinished) {\n state = combineTransformations(\n inputs.def,\n state,\n ksolvePuzzle.stateFromMove(finishedMove),\n );\n }\n return state;\n }\n}\n", "import type { Transformation } from \"../../../../../kpuzzle\";\nimport type { PuzzlePosition } from \"../../../../old/animation/cursor/CursorTypes\";\nimport type { CurrentMoveInfo } from \"../../../../old/animation/indexer/AlgIndexer\";\nimport { TwistyPropDerived } from \"../../TwistyProp\";\n\nexport interface LegacyPositionPropInputs {\n currentMoveInfo: CurrentMoveInfo;\n transformation: Transformation;\n}\n\n// TODO: This exist as a convenience for old `Twisty3D` implementations. Get rid of this.\nexport class LegacyPositionProp extends TwistyPropDerived<\n LegacyPositionPropInputs,\n PuzzlePosition\n> {\n derive(inputs: LegacyPositionPropInputs): PuzzlePosition {\n return {\n state: inputs.transformation,\n movesInProgress: inputs.currentMoveInfo.currentMoves,\n };\n }\n}\n", "import type { KPuzzleDefinition } from \"../../../../../kpuzzle\";\nimport type { PuzzleLoader } from \"../../../../../puzzles\";\nimport { TwistyPropDerived } from \"../../TwistyProp\";\n\nexport class PuzzleDefProp extends TwistyPropDerived<\n { puzzleLoader: PuzzleLoader },\n KPuzzleDefinition\n> {\n async derive(inputs: {\n puzzleLoader: PuzzleLoader;\n }): Promise<KPuzzleDefinition> {\n return inputs.puzzleLoader.def();\n }\n}\n", "import { arrayEquals } from \"./helpers\";\nimport { SimpleTwistyPropSource } from \"./props/TwistyProp\";\n\ninterface UserVisibleError {\n errors: string[];\n}\n\nconst EMPTY_ERRORS = { errors: [] };\n\nexport class UserVisibleErrorTracker extends SimpleTwistyPropSource<UserVisibleError> {\n override getDefaultValue(): UserVisibleError {\n return EMPTY_ERRORS;\n }\n\n reset() {\n this.set(this.getDefaultValue());\n }\n\n canReuseValue(_v1: UserVisibleError, _v2: UserVisibleError): boolean {\n return arrayEquals(_v1.errors, _v2.errors);\n }\n}\n", "import type { Move } from \"../../../../../alg\";\nimport { SimpleTwistyPropSource } from \"../../TwistyProp\";\n\nexport interface CatchUpMove {\n move: Move | null;\n amount: number;\n}\n\nexport class CatchUpMoveProp extends SimpleTwistyPropSource<CatchUpMove> {\n getDefaultValue(): CatchUpMove {\n return { move: null, amount: 0 };\n }\n\n canReuseValue(v1: CatchUpMove, v2: CatchUpMove) {\n return v1.move === v2.move && v1.amount === v2.amount;\n }\n}\n", "import { AlgProp } from \"./props/puzzle/state/AlgProp\";\nimport { BackgroundProp } from \"./props/viewer/BackgroundProp\";\nimport { BackViewProp } from \"./props/viewer/BackViewProp\";\nimport { ControlPanelProp } from \"./props/viewer/ControlPanelProp\";\nimport { HintFaceletProp } from \"./props/puzzle/display/HintFaceletProp\";\nimport { IndexerConstructorRequestProp } from \"./props/puzzle/state/IndexerConstructorRequestProp\";\nimport { LatitudeLimitProp } from \"./props/viewer/LatitudeLimit\";\nimport { OrbitCoordinatesRequestProp } from \"./props/viewer/OrbitCoordinatesRequestProp\";\nimport { PlayingInfoProp } from \"./props/timeline/PlayingInfoProp\";\nimport { PGPuzzleDescriptionStringProp } from \"./props/puzzle/structure/PuzzleDescriptionProp\";\nimport { PuzzleIDRequestProp } from \"./props/puzzle/structure/PuzzleIDRequestProp\";\nimport { PuzzleLoaderProp } from \"./props/puzzle/structure/PuzzleLoaderProp\";\nimport { SetupAnchorProp } from \"./props/puzzle/state/SetupAnchorProp\";\nimport { StickeringProp } from \"./props/puzzle/display/StickeringProp\";\nimport { TempoScaleProp } from \"./props/timeline/TempoScaleProp\";\nimport { TimestampRequestProp } from \"./props/timeline/TimestampRequestProp\";\nimport { URLProp } from \"./props/general/URLProp\";\nimport { ViewerLinkProp } from \"./props/viewer/ViewerLinkProp\";\nimport { VisualizationFormatProp } from \"./props/viewer/VisualizationProp\";\nimport { OrbitCoordinatesProp } from \"./props/viewer/OrbitCoordinatesProp\";\nimport { PuzzleIDProp } from \"./props/puzzle/structure/PuzzleIDProp\";\nimport { SpriteProp } from \"./props/puzzle/display/SpriteProp\";\nimport { VisualizationStrategyProp } from \"./props/viewer/VisualizationStrategyProp\";\nimport { IndexerConstructorProp } from \"./props/puzzle/state/IndexerConstructorProp\";\nimport { PuzzleAlgProp } from \"./props/puzzle/state/PuzzleAlgProp\";\nimport { AlgTransformationProp } from \"./props/puzzle/state/AlgTransformationProp\";\nimport { IndexerProp } from \"./props/puzzle/state/IndexerProp\";\nimport { AnchoredStartProp } from \"./props/puzzle/state/AnchoredStartProp\";\nimport { TimeRangeProp } from \"./props/viewer/TimeRangeProp\";\nimport { DetailedTimelineInfoProp } from \"./props/timeline/DetailedTimelineInfoProp\";\nimport { CoarseTimelineInfoProp } from \"./props/timeline/CoarseTimelineInfoProp\";\nimport { CurrentLeavesProp } from \"./props/puzzle/state/CurrentLeavesProp\";\nimport { ButtonAppearanceProp } from \"./props/viewer/ButtonAppearanceProp\";\nimport { CurrentLeavesSimplifiedProp } from \"./props/puzzle/state/CurrentLeavesSimplified\";\nimport { CurrentTransformationProp } from \"./props/puzzle/state/CurrentTransformationProp\";\nimport { LegacyPositionProp } from \"./props/puzzle/state/LegacyPositionProp\";\nimport { PuzzleDefProp } from \"./props/puzzle/structure/PuzzleDefProp\";\nimport { UserVisibleErrorTracker } from \"./UserVisibleErrorTracker\";\nimport { CatchUpMoveProp } from \"./props/puzzle/state/CatchUpMoveProp\";\n\nexport class TwistyPlayerModel {\n // TODO: incorporate error handling into the entire prop graph.\n // TODO: Make this something that can't get confused with normal props?\n userVisibleErrorTracker = new UserVisibleErrorTracker();\n\n // TODO: Redistribute and group props with controllers.\n\n // Depth 0\n algProp = new AlgProp();\n backgroundProp = new BackgroundProp();\n backViewProp = new BackViewProp();\n controlPanelProp = new ControlPanelProp();\n catchUpMoveProp = new CatchUpMoveProp();\n foundationStickerSpriteURL = new URLProp();\n hintFaceletProp = new HintFaceletProp();\n hintStickerSpriteURL = new URLProp();\n indexerConstructorRequestProp = new IndexerConstructorRequestProp();\n latitudeLimitProp = new LatitudeLimitProp();\n orbitCoordinatesRequestProp: OrbitCoordinatesRequestProp =\n new OrbitCoordinatesRequestProp();\n\n playingInfoProp = new PlayingInfoProp();\n puzzleDescriptionRequestProp = new PGPuzzleDescriptionStringProp();\n puzzleIDRequestProp = new PuzzleIDRequestProp();\n setupAnchorProp = new SetupAnchorProp();\n setupProp = new AlgProp();\n stickeringProp = new StickeringProp();\n tempoScaleProp = new TempoScaleProp();\n timestampRequestProp = new TimestampRequestProp();\n viewerLinkProp = new ViewerLinkProp();\n visualizationFormatProp = new VisualizationFormatProp();\n\n // Depth 1\n foundationStickerSprite = new SpriteProp({\n spriteURL: this.foundationStickerSpriteURL,\n });\n\n hintStickerSprite = new SpriteProp({\n spriteURL: this.hintStickerSpriteURL,\n });\n\n puzzleLoaderProp = new PuzzleLoaderProp(\n {\n puzzleIDRequest: this.puzzleIDRequestProp,\n puzzleDescriptionRequest: this.puzzleDescriptionRequestProp,\n },\n this.userVisibleErrorTracker,\n );\n\n // Depth 2\n puzzleDefProp = new PuzzleDefProp({ puzzleLoader: this.puzzleLoaderProp });\n\n puzzleIDProp = new PuzzleIDProp({ puzzleLoader: this.puzzleLoaderProp });\n\n // Depth 3\n\n puzzleAlgProp = new PuzzleAlgProp({\n algWithIssues: this.algProp,\n puzzleDef: this.puzzleDefProp,\n });\n\n puzzleSetupProp = new PuzzleAlgProp({\n algWithIssues: this.setupProp,\n puzzleDef: this.puzzleDefProp,\n });\n\n visualizationStrategyProp = new VisualizationStrategyProp({\n visualizationRequest: this.visualizationFormatProp,\n puzzleID: this.puzzleIDProp,\n });\n\n // Depth 4\n indexerConstructorProp = new IndexerConstructorProp({\n alg: this.algProp,\n puzzle: this.puzzleIDProp,\n visualizationStrategy: this.visualizationStrategyProp,\n indexerConstructorRequest: this.indexerConstructorRequestProp,\n });\n\n orbitCoordinatesProp = new OrbitCoordinatesProp({\n orbitCoordinatesRequest: this.orbitCoordinatesRequestProp,\n latitudeLimit: this.latitudeLimitProp,\n puzzleID: this.puzzleIDProp,\n strategy: this.visualizationStrategyProp,\n });\n\n setupTransformationProp = new AlgTransformationProp({\n alg: this.puzzleSetupProp,\n def: this.puzzleDefProp,\n });\n\n // Depth 5\n indexerProp = new IndexerProp({\n indexerConstructor: this.indexerConstructorProp,\n algWithIssues: this.puzzleAlgProp,\n def: this.puzzleDefProp,\n });\n\n // Depth 6\n anchoredStartProp = new AnchoredStartProp({\n setupAnchor: this.setupAnchorProp,\n setupTransformation: this.setupTransformationProp,\n indexer: this.indexerProp,\n def: this.puzzleDefProp,\n });\n\n timeRangeProp = new TimeRangeProp({\n indexer: this.indexerProp,\n });\n\n // Depth 7\n detailedTimelineInfoProp: DetailedTimelineInfoProp =\n new DetailedTimelineInfoProp({\n timestampRequest: this.timestampRequestProp,\n timeRange: this.timeRangeProp,\n setupAnchor: this.setupAnchorProp,\n });\n\n // Depth 8\n coarseTimelineInfoProp = new CoarseTimelineInfoProp({\n detailedTimelineInfo: this.detailedTimelineInfoProp,\n playingInfo: this.playingInfoProp,\n });\n\n currentLeavesProp = new CurrentLeavesProp({\n indexer: this.indexerProp,\n detailedTimelineInfo: this.detailedTimelineInfoProp,\n catchUpMove: this.catchUpMoveProp,\n });\n\n // Depth 9\n // TODO: Inline Twisty3D management.\n buttonAppearanceProp = new ButtonAppearanceProp({\n coarseTimelineInfo: this.coarseTimelineInfoProp,\n viewerLink: this.viewerLinkProp,\n });\n\n currentLeavesSimplifiedProp = new CurrentLeavesSimplifiedProp({\n currentMoveInfo: this.currentLeavesProp,\n });\n\n // Depth 10\n currentTransformationProp = new CurrentTransformationProp({\n anchoredStart: this.anchoredStartProp,\n currentLeavesSimplified: this.currentLeavesSimplifiedProp,\n indexer: this.indexerProp,\n def: this.puzzleDefProp,\n });\n\n // Depth 11\n legacyPositionProp = new LegacyPositionProp({\n currentMoveInfo: this.currentLeavesProp,\n transformation: this.currentTransformationProp,\n });\n\n public async twizzleLink(): Promise<string> {\n const url = new URL(\"https://alpha.twizzle.net/edit/\");\n\n const [puzzle, alg, setup, anchor] = await Promise.all([\n this.puzzleIDProp.get(),\n this.algProp.get(),\n this.setupProp.get(),\n this.setupAnchorProp.get(),\n ]);\n\n if (!alg.alg.experimentalIsEmpty()) {\n url.searchParams.set(\"alg\", alg.alg.toString());\n }\n if (!setup.alg.experimentalIsEmpty()) {\n url.searchParams.set(\"setup-alg\", setup.alg.toString());\n }\n if (anchor !== \"start\") {\n url.searchParams.set(\"setup-anchor\", anchor);\n }\n // if (this.experimentalStickering !== \"full\") {\n // url.searchParams.set(\n // \"experimental-stickering\",\n // this.experimentalStickering,\n // );\n if (puzzle !== \"3x3x3\") {\n url.searchParams.set(\"puzzle\", puzzle);\n }\n return url.toString();\n }\n}\n", "import type { Alg } from \"../../alg\";\nimport type { PuzzleDescriptionString } from \"../../puzzle-geometry/PGPuzzles\";\nimport type { ExperimentalStickering } from \"../../twisty\";\nimport type { BackgroundThemeWithAuto } from \"../model/props/viewer/BackgroundProp\";\nimport type { BackViewLayoutWithAuto } from \"../model/props/viewer/BackViewProp\";\nimport type { ControlPanelThemeWithAuto } from \"../model/props/viewer/ControlPanelProp\";\nimport type { HintFaceletStyleWithAuto } from \"../model/props/puzzle/display/HintFaceletProp\";\nimport type { IndexerStrategyName } from \"../model/props/puzzle/state/IndexerConstructorRequestProp\";\nimport type { TimestampRequest } from \"../model/props/timeline/TimestampRequestProp\";\nimport type { ViewerLinkPageWithAuto } from \"../model/props/viewer/ViewerLinkProp\";\nimport type { VisualizationFormatWithAuto } from \"../model/props/viewer/VisualizationProp\";\nimport { TwistyPlayerModel } from \"../model/TwistyPlayerModel\";\nimport type { MillisecondTimestamp } from \"../old/animation/cursor/CursorTypes\";\nimport { ManagedCustomElement } from \"../old/dom/element/ManagedCustomElement\";\nimport type { PuzzleID, SetupToLocation } from \"../old/dom/TwistyPlayerConfig\";\n\nfunction err(propName: string): Error {\n return new Error(\n `Cannot get \\`.${propName}\\` directly from a \\`TwistyPlayer\\`.`,\n );\n}\n\n// prettier-ignore\nexport abstract class TwistyPlayerSettable extends ManagedCustomElement {\n experimentalModel: TwistyPlayerModel = new TwistyPlayerModel();\n\n set alg(newAlg: Alg | string) { this.experimentalModel.algProp.set(newAlg); }\n get alg(): never { throw err(\"alg\"); }\n\n set experimentalSetupAlg(newSetup: Alg | string) { this.experimentalModel.setupProp.set(newSetup); }\n get experimentalSetupAlg(): never { throw err(\"setup\"); }\n\n set experimentalSetupAnchor(anchor: SetupToLocation) { this.experimentalModel.setupAnchorProp.set(anchor); }\n get experimentalSetupAnchor(): never { throw err(\"anchor\"); }\n\n set puzzle(puzzleID: PuzzleID) { this.experimentalModel.puzzleIDRequestProp.set(puzzleID); }\n get puzzle(): never { throw err(\"puzzle\"); }\n\n set experimentalPuzzleDescription(puzzleDescription: PuzzleDescriptionString) { this.experimentalModel.puzzleDescriptionRequestProp.set(puzzleDescription); }\n get experimentalPuzzleDescription(): never { throw err(\"experimentalPuzzleDescription\"); }\n\n set timestamp(timestamp: TimestampRequest) { this.experimentalModel.timestampRequestProp.set(timestamp); }\n get timestamp(): never { throw err(\"timestamp\"); }\n\n set hintFacelets(hintFaceletStyle: HintFaceletStyleWithAuto) { this.experimentalModel.hintFaceletProp.set(hintFaceletStyle); }\n get hintFacelets(): never { throw err(\"hintFacelets\"); }\n\n set experimentalStickering(stickering: ExperimentalStickering) { this.experimentalModel.stickeringProp.set(stickering); }\n get experimentalStickering(): never { throw err(\"stickering\"); }\n\n set backView(backView: BackViewLayoutWithAuto) { this.experimentalModel.backViewProp.set(backView); }\n get backView(): never { throw err(\"backView\"); }\n\n set background(backgroundTheme: BackgroundThemeWithAuto) { this.experimentalModel.backgroundProp.set(backgroundTheme); }\n get background(): never { throw err(\"background\"); }\n\n set controlPanel(newControlPanel: ControlPanelThemeWithAuto) { this.experimentalModel.controlPanelProp.set(newControlPanel); }\n get controlPanel(): never { throw new Error( \"Cannot get `.controlPanel` directly from a `TwistyPlayer`.\"); }\n\n set visualization(visualizationFormat: VisualizationFormatWithAuto) { this.experimentalModel.visualizationFormatProp.set(visualizationFormat); }\n get visualization(): never { throw new Error( \"Cannot get `.visualization` directly from a `TwistyPlayer`.\"); }\n\n set viewerLink(viewerLinkPage: ViewerLinkPageWithAuto) { this.experimentalModel.viewerLinkProp.set(viewerLinkPage); }\n get viewerLink(): never { throw err(\"viewerLink\"); }\n\n set cameraLatitude(latitude: number) { this.experimentalModel.orbitCoordinatesRequestProp.set({ latitude }); }\n get cameraLatitude(): never { throw new Error( \"Cannot get `.cameraLatitude` directly from a `TwistyPlayer`.\"); }\n\n set cameraLongitude(longitude: number) { this.experimentalModel.orbitCoordinatesRequestProp.set({ longitude }); }\n get cameraLongitude(): never { throw new Error( \"Cannot get `.cameraLongitude` directly from a `TwistyPlayer`.\"); }\n\n set cameraDistance(distance: number) { this.experimentalModel.orbitCoordinatesRequestProp.set({ distance }); }\n get cameraDistance(): never { throw new Error( \"Cannot get `.cameraDistance` directly from a `TwistyPlayer`.\"); }\n\n set cameraLatitudeLimit(latitudeLimit: number) { this.experimentalModel.latitudeLimitProp.set(latitudeLimit); }\n get cameraLatitudeLimit(): never { throw new Error( \"Cannot get `.cameraLatitudeLimit` directly from a `TwistyPlayer`.\"); }\n\n set indexer(indexer: IndexerStrategyName) { this.experimentalModel.indexerConstructorRequestProp.set(indexer); }\n get indexer(): never { throw err(\"indexer\"); }\n\n set tempoScale(newTempoScale: number) { this.experimentalModel.tempoScaleProp.set(newTempoScale); }\n get tempoScale(): never { throw err(\"tempoScale\"); }\n\n set experimentalSprite(url: string | URL) { this.experimentalModel.foundationStickerSpriteURL.set(url); }\n get experimentalSprite(): never { throw err(\"experimentalSprite\"); }\n\n set experimentalHintSprite(url: string | URL) { this.experimentalModel.hintStickerSpriteURL.set(url); }\n get experimentalHintSprite(): never { throw err(\"experimentalHintSprite\"); }\n\n experimentalGet = new ExperimentalGetters(this.experimentalModel)\n}\n\nclass ExperimentalGetters {\n constructor(private model: TwistyPlayerModel) {}\n\n async alg(): Promise<Alg> {\n return (await this.model.algProp.get()).alg;\n }\n\n async setupAlg(): Promise<Alg> {\n return (await this.model.setupProp.get()).alg;\n }\n\n puzzleID(): Promise<PuzzleID> {\n return this.model.puzzleIDProp.get();\n }\n\n async timestamp(): Promise<MillisecondTimestamp> {\n return (await this.model.detailedTimelineInfoProp.get()).timestamp;\n }\n}\n", "import type { ExperimentalStickering, PG3D } from \"..\";\nimport { Alg, experimentalAppendMove, Move } from \"../../alg\";\nimport type { PuzzleDescriptionString } from \"../../puzzle-geometry/PGPuzzles\";\nimport type { TwistyAnimationControllerDelegate } from \"../controllers/TwistyAnimationController\";\nimport { TwistyPlayerController } from \"../controllers/TwistyPlayerController\";\nimport type { HintFaceletStyleWithAuto } from \"../model/props/puzzle/display/HintFaceletProp\";\nimport type { BackgroundThemeWithAuto } from \"../model/props/viewer/BackgroundProp\";\nimport type { BackViewLayoutWithAuto } from \"../model/props/viewer/BackViewProp\";\nimport type { ControlPanelThemeWithAuto } from \"../model/props/viewer/ControlPanelProp\";\nimport type { ViewerLinkPageWithAuto } from \"../model/props/viewer/ViewerLinkProp\";\nimport type { VisualizationFormatWithAuto } from \"../model/props/viewer/VisualizationProp\";\nimport type { VisualizationStrategy } from \"../model/props/viewer/VisualizationStrategyProp\";\nimport { ClassListManager } from \"../old/dom/element/ClassListManager\";\nimport { customElementsShim } from \"../old/dom/element/node-custom-element-shims\";\nimport { twistyPlayerCSS } from \"../old/dom/TwistyPlayer.css\";\nimport {\n controlsLocations,\n PuzzleID,\n SetupToLocation,\n} from \"../old/dom/TwistyPlayerConfig\";\nimport { Twisty2DSceneWrapper } from \"./2D/Twisty2DSceneWrapper\";\nimport { Twisty3DSceneWrapper } from \"./3D/Twisty3DSceneWrapper\";\nimport { TwistyButtonsV2 } from \"./control-panel/TwistyButtonsV2\";\nimport { TwistyScrubberV2 } from \"./control-panel/TwistyScrubberV2\";\nimport { downloadURL, getDefaultFilename, screenshot } from \"./screenshot\";\nimport { TwistyPlayerSettable } from \"./TwistyPlayerSettable\";\n\n// TODO: I couldn't figure out how to use use more specific types. Ideally, we'd\n// enforce consistency with the model.\nexport const twistyPlayerAttributeMap = {\n // TODO: We assume each of these can be set using a string or will be automatically converted by JS (e.g. numbers). Can we enforce\n // that with types? Do we need to add a translation mechanism for things we\n // don't want to leave settable as strings?\n // TODO: Enum validation.\n\n // Alg\n \"alg\": \"alg\",\n \"experimental-setup-alg\": \"experimentalSetupAlg\",\n\n // String-based\n \"experimental-setup-anchor\": \"experimentalSetupAnchor\",\n \"puzzle\": \"puzzle\",\n \"experimental-puzzle-description\": \"experimentalPuzzleDescription\",\n \"visualization\": \"visualization\",\n \"hint-facelets\": \"hintFacelets\",\n \"experimental-stickering\": \"experimentalStickering\",\n \"background\": \"background\",\n \"control-panel\": \"controlPanel\",\n \"back-view\": \"backView\",\n // \"indexer\": \"indexer\",\n \"viewer-link\": \"viewerLink\",\n\n // Number-based\n \"camera-latitude\": \"cameraLatitude\",\n \"camera-longitude\": \"cameraLongitude\",\n \"camera-distance\": \"cameraDistance\",\n \"camera-latitude-limit\": \"cameraLatitudeLimit\",\n \"tempo-scale\": \"tempoScale\",\n\n // URL-based\n \"experimental-sprite\": \"experimentalSprite\",\n \"experimental-hint-sprite\": \"experimentalHintSprite\",\n};\n\nexport type TwistyPlayerAttribute = keyof typeof twistyPlayerAttributeMap;\n\nconst configKeys: Record<TwistyPlayerAttribute, true> = Object.fromEntries(\n Object.values(twistyPlayerAttributeMap).map((s) => [s, true]),\n) as any;\n\n// TODO: Find a way to share this def with `attributeMap`.\nexport interface TwistyPlayerConfig {\n // Alg\n alg?: Alg | string;\n experimentalSetupAlg?: Alg | string;\n\n // String-based\n experimentalSetupAnchor?: SetupToLocation; // TODO: \"auto\"\n puzzle?: PuzzleID;\n experimentalPuzzleDescription?: PuzzleDescriptionString;\n visualization?: VisualizationFormatWithAuto;\n hintFacelets?: HintFaceletStyleWithAuto;\n experimentalStickering?: ExperimentalStickering;\n background?: BackViewLayoutWithAuto;\n controlPanel?: ControlPanelThemeWithAuto;\n backView?: BackViewLayoutWithAuto;\n // \"indexer\"?: \"indexer\";\n viewerLink?: ViewerLinkPageWithAuto;\n\n // Number-based\n cameraLatitude?: number;\n cameraLongitude?: number;\n cameraDistance?: number;\n cameraLatitudeLimit?: number;\n tempoScale?: number;\n\n // URL-based\n experimentalSprite?: string | null;\n experimentalHintSprite?: string | null;\n}\n\n/**\n * TwistyPlayer is the heart of `cubing.js`. It can be used to display a puzzle on a web page like this:\n *\n * <script src=\"path/to/cubing/twisty\" type=\"module\"></script>\n * <twisty-player alg=\"R U R'\"></twisty-player>\n *\n * You can also construct it directly in JavaScript:\n *\n * import { TwistyPlayer } from \"cubing/twisty\";\n * const twistyPlayer = new TwistyPlayer({alg: \"R U R'\"});\n * // Once the page has loaded, you can do this:\n * document.body.appendChild(twistyPlayer);\n *\n * See {@link https://js.cubing.net/cubing/} for more examples.\n */\nexport class TwistyPlayer\n extends TwistyPlayerSettable\n implements TwistyAnimationControllerDelegate\n{\n controller: TwistyPlayerController = new TwistyPlayerController(\n this.experimentalModel,\n this,\n );\n\n buttons: TwistyButtonsV2;\n\n experimentalCanvasClickCallback: (...args: any) => void = () => {};\n // #onCanvasClick() {\n\n // }\n\n constructor(config: TwistyPlayerConfig = {}) {\n super();\n\n // TODO: double-check that these are all getting set sync without causing extra work.\n for (const [propName, value] of Object.entries(config)) {\n if (!configKeys[propName as TwistyPlayerAttribute]) {\n console.warn(`Invalid config passed to TwistyPlayer: ${propName}`);\n break;\n }\n (this as any)[propName] = value;\n }\n }\n\n #controlsManager: ClassListManager<ControlPanelThemeWithAuto> =\n new ClassListManager<ControlPanelThemeWithAuto>(\n this,\n \"controls-\",\n ([\"auto\"] as ControlPanelThemeWithAuto[]).concat(\n Object.keys(controlsLocations) as ControlPanelThemeWithAuto[],\n ),\n );\n\n #visualizationWrapperElem = document.createElement(\"div\"); // TODO: Better pattern.\n #errorElem = document.createElement(\"div\"); // TODO: Better pattern.\n #alreadyConnected = false; // TODO: support resetting\n async connectedCallback(): Promise<void> {\n if (this.#alreadyConnected) {\n return;\n }\n this.#alreadyConnected = true;\n this.addCSS(twistyPlayerCSS);\n\n this.addElement(this.#visualizationWrapperElem).classList.add(\n \"visualization-wrapper\",\n );\n this.addElement(this.#errorElem).classList.add(\"error-elem\");\n this.#errorElem.textContent = \"Error\";\n this.experimentalModel.userVisibleErrorTracker.addFreshListener(\n (userVisibleError) => {\n const errorString: string | null = userVisibleError.errors[0] ?? null;\n this.contentWrapper.classList.toggle(\"error\", !!errorString);\n if (errorString) {\n this.#errorElem.textContent = errorString;\n }\n },\n );\n\n const scrubber = new TwistyScrubberV2(this.experimentalModel);\n this.contentWrapper.appendChild(scrubber);\n\n this.buttons = new TwistyButtonsV2(\n this.experimentalModel,\n this.controller,\n this,\n );\n this.contentWrapper.appendChild(this.buttons);\n\n this.experimentalModel.backgroundProp.addFreshListener(\n (backgroundTheme: BackgroundThemeWithAuto) => {\n this.contentWrapper.classList.toggle(\n \"checkered\",\n backgroundTheme !== \"none\",\n );\n },\n );\n\n this.experimentalModel.controlPanelProp.addFreshListener(\n (controlPanel: ControlPanelThemeWithAuto) => {\n this.#controlsManager.setValue(controlPanel);\n },\n );\n\n this.experimentalModel.visualizationStrategyProp.addFreshListener(\n this.#setVisualizationWrapper.bind(this),\n );\n\n this.experimentalModel.puzzleIDProp.addFreshListener(this.flash.bind(this));\n }\n\n flash() {\n this.#visualizationWrapper?.animate([{ opacity: 0.25 }, { opacity: 1 }], {\n duration: 250,\n });\n }\n\n #visualizationWrapper: Twisty2DSceneWrapper | Twisty3DSceneWrapper | null =\n null;\n\n #visualizationStrategy: VisualizationStrategy | null = null;\n #setVisualizationWrapper(strategy: VisualizationStrategy): void {\n if (strategy !== this.#visualizationStrategy) {\n this.#visualizationWrapper?.remove();\n this.#visualizationWrapper?.disconnect();\n let newWrapper: Twisty2DSceneWrapper | Twisty3DSceneWrapper;\n switch (strategy) {\n case \"2D\":\n case \"experimental-2D-LL\":\n newWrapper = new Twisty2DSceneWrapper(\n this.experimentalModel,\n strategy,\n );\n break;\n case \"Cube3D\":\n case \"PG3D\":\n // TODO: Properly wire this up so we can set PG3D for the cube.\n newWrapper = new Twisty3DSceneWrapper(this.experimentalModel);\n break;\n default:\n throw new Error(\"Invalid visualization\");\n }\n this.#visualizationWrapperElem.appendChild(newWrapper);\n this.#visualizationWrapper = newWrapper;\n this.#visualizationStrategy = strategy;\n }\n }\n\n async experimentalCurrentCanvases(): Promise<HTMLCanvasElement[]> {\n this.connectedCallback();\n const wrapper = this.#visualizationWrapper;\n const canvases: HTMLCanvasElement[] = [];\n if (wrapper instanceof Twisty3DSceneWrapper) {\n const vantages = wrapper.experimentalVantages();\n for (const vantage of vantages) {\n canvases.push(await vantage.canvas());\n }\n }\n return canvases;\n }\n\n async experimentalPG3D(): Promise<PG3D | null> {\n this.connectedCallback();\n const wrapper = this.#visualizationWrapper;\n if (wrapper instanceof Twisty3DSceneWrapper) {\n wrapper;\n }\n return null;\n }\n\n jumpToStart(options?: { flash: boolean }): void {\n this.controller.jumpToStart(options);\n }\n\n jumpToEnd(options?: { flash: boolean }): void {\n this.controller.jumpToEnd(options);\n }\n\n play(): void {\n this.controller.togglePlay(true);\n }\n\n pause(): void {\n this.controller.togglePlay(false);\n }\n\n // Inspiration:\n // - https://developer.mozilla.org/en-US/docs/Web/API/Element/toggleAttribute (`force` argument)\n // - https://developer.mozilla.org/en-US/docs/Web/API/DOMTokenList/toggle (`force` argument)\n // We still provide `play()` and `pause()` individually for convenience, though.\n togglePlay(play?: boolean): void {\n this.controller.togglePlay(play);\n }\n\n // TODO: Animate the new move.\n experimentalAddMove(\n flexibleMove: Move | string,\n options: { coalesce?: boolean } = {},\n ): void {\n const move =\n typeof flexibleMove === \"string\" ? new Move(flexibleMove) : flexibleMove;\n (async () => {\n const alg = (await this.experimentalModel.algProp.get()).alg;\n const newAlg = experimentalAppendMove(alg, move, {\n coalesce: options?.coalesce,\n });\n this.experimentalModel.algProp.set(newAlg);\n this.experimentalModel.timestampRequestProp.set(\"end\");\n this.experimentalModel.catchUpMoveProp.set({\n move: move,\n amount: 0,\n });\n })();\n }\n\n static get observedAttributes(): string[] {\n return Object.keys(twistyPlayerAttributeMap);\n }\n\n attributeChangedCallback(\n attributeName: string,\n _oldValue: string,\n newValue: string,\n ): void {\n const setterName =\n twistyPlayerAttributeMap[attributeName as TwistyPlayerAttribute];\n if (!setterName) {\n return;\n }\n\n (this as any)[setterName] = newValue;\n }\n\n // TODO: Make this more ergonomic and flexible.\n // TODO: dimensions.\n async experimentalScreenshot(options?: {\n width: number;\n height: number;\n }): Promise<string> {\n return (await screenshot(this.experimentalModel, options)).dataURL;\n }\n\n // TODO: Make this more ergonomic and flexible.\n // TODO: dimensions.\n async experimentalDownloadScreenshot(filename?: string): Promise<void> {\n if (\n [\"2D\", \"experimental-2D-LL\"].includes(\n await this.experimentalModel.visualizationStrategyProp.get(),\n )\n ) {\n // TODO: This has lots of async issues. It should also go into the screenshot impl file.\n const wrapper2D = this.#visualizationWrapper as Twisty2DSceneWrapper;\n const twisty2DPuzzle = await wrapper2D\n .currentTwisty2DPuzzleWrapper()!\n .twisty2DPuzzle();\n const str = new XMLSerializer().serializeToString(\n twisty2DPuzzle.svg.element,\n );\n const url = URL.createObjectURL(new Blob([str]));\n downloadURL(\n url,\n filename ?? (await getDefaultFilename(this.experimentalModel)),\n \"svg\",\n );\n } else {\n await (await screenshot(this.experimentalModel)).download(filename);\n }\n }\n}\n\ncustomElementsShim.define(\"twisty-player\", TwistyPlayer);\n", "import { CSSSource } from \"../old/dom/element/ManagedCustomElement\";\n\nexport const twistyAlgViewerCSS = new CSSSource(`\n:host {\n display: inline-grid;\n}\n\na:not(:hover) {\n color: inherit;\n text-decoration: none;\n}\n\ntwisty-alg-leaf-elem.twisty-alg-comment {\n color: rgba(0, 0, 0, 0.4);\n}\n\n.wrapper.current-move {\n background: rgba(66, 133, 244, 0.3);\n margin-left: -0.1em;\n margin-right: -0.1em;\n padding-left: 0.1em;\n padding-right: 0.1em;\n border-radius: 0.1em;\n}\n`);\n", "import {\n Alg,\n Commutator,\n Conjugate,\n experimentalDirect,\n ExperimentalIterationDirection,\n Grouping,\n LineComment,\n Move,\n Newline,\n Pause,\n TraversalDownUp,\n Unit,\n} from \"../../alg\";\nimport type { Parsed } from \"../../alg/parse\";\nimport type { AlgWithIssues } from \"../model/props/puzzle/state/AlgProp\";\nimport type { DetailedTimelineInfo } from \"../model/props/timeline/DetailedTimelineInfoProp\";\nimport type { MillisecondTimestamp } from \"../old/animation/cursor/CursorTypes\";\nimport type { CurrentMoveInfo } from \"../old/animation/indexer/AlgIndexer\";\nimport { ManagedCustomElement } from \"../old/dom/element/ManagedCustomElement\";\nimport {\n customElementsShim,\n HTMLElementShim,\n} from \"../old/dom/element/node-custom-element-shims\";\nimport { twistyAlgViewerCSS } from \"./TwistyAlgViewer.css\";\nimport { TwistyPlayer } from \"./TwistyPlayer\";\n\nconst DEFAULT_OFFSET_MS = 250; // TODO: make this a fraction?\n\nclass DataDown {\n earliestMoveIndex: number;\n twistyAlgViewer: TwistyAlgViewer;\n direction: ExperimentalIterationDirection;\n}\n\nclass DataUp {\n moveCount: number;\n element: TwistyAlgWrapperElem | TwistyAlgLeafElem;\n}\n\nclass TwistyAlgLeafElem extends ManagedCustomElement {\n constructor(\n className: string,\n text: string,\n dataDown: DataDown,\n public algOrUnit: Alg | Unit,\n offsetIntoMove: boolean,\n clickable: boolean,\n ) {\n super({ mode: \"open\" });\n this.classList.add(className);\n\n this.addCSS(twistyAlgViewerCSS);\n if (clickable) {\n const anchor = this.contentWrapper.appendChild(\n document.createElement(\"a\"),\n );\n anchor.href = \"#\";\n anchor.textContent = text;\n\n anchor.addEventListener(\"click\", (e) => {\n e.preventDefault();\n dataDown.twistyAlgViewer.jumpToIndex(\n dataDown.earliestMoveIndex,\n offsetIntoMove,\n );\n });\n } else {\n this.contentWrapper.appendChild(\n document.createElement(\"span\"),\n ).textContent = text;\n }\n }\n\n pathToIndex(_index: number): (TwistyAlgWrapperElem | TwistyAlgLeafElem)[] {\n return [];\n }\n\n setCurrentMove(current: boolean) {\n this.contentWrapper.classList.toggle(\"current-move\", current);\n }\n}\n\ncustomElementsShim.define(\"twisty-alg-leaf-elem\", TwistyAlgLeafElem);\n\nclass TwistyAlgWrapperElem extends HTMLElementShim {\n private queue: (Element | Text)[] = [];\n\n constructor(className: string, public algOrUnit: Alg | Unit) {\n super();\n this.classList.add(className);\n }\n\n addString(str: string) {\n this.queue.push(document.createTextNode(str));\n }\n\n addElem(dataUp: DataUp): number {\n this.queue.push(dataUp.element);\n return dataUp.moveCount;\n }\n\n flushQueue(\n direction: ExperimentalIterationDirection = ExperimentalIterationDirection.Forwards,\n ): void {\n for (const node of maybeReverseList(this.queue, direction)) {\n this.append(node);\n }\n this.queue = [];\n }\n\n pathToIndex(_index: number): (TwistyAlgWrapperElem | TwistyAlgLeafElem)[] {\n return [];\n }\n}\n\ncustomElementsShim.define(\"twisty-alg-wrapper-elem\", TwistyAlgWrapperElem);\n\nfunction oppositeDirection(\n direction: ExperimentalIterationDirection,\n): ExperimentalIterationDirection {\n return direction === ExperimentalIterationDirection.Forwards\n ? ExperimentalIterationDirection.Backwards\n : ExperimentalIterationDirection.Forwards;\n}\n\nfunction updateDirectionByAmount(\n currentDirection: ExperimentalIterationDirection,\n amount: number,\n): ExperimentalIterationDirection {\n return amount < 0 ? oppositeDirection(currentDirection) : currentDirection;\n}\n\nfunction maybeReverseList<T>(\n l: T[],\n direction: ExperimentalIterationDirection,\n): T[] {\n if (direction === ExperimentalIterationDirection.Forwards) {\n return l;\n }\n // console.log(\"rev\", Array.from(l).reverse());\n // return Array.from(l).reverse();\n const copy = Array.from(l);\n copy.reverse();\n return copy;\n}\n\nclass AlgToDOMTree extends TraversalDownUp<DataDown, DataUp, DataUp> {\n public traverseAlg(alg: Alg, dataDown: DataDown): DataUp {\n let moveCount = 0;\n const element = new TwistyAlgWrapperElem(\"twisty-alg-alg\", alg); // TODO: pick a better class name.\n let first = true;\n for (const unit of experimentalDirect(alg.units(), dataDown.direction)) {\n if (!first) {\n element.addString(\" \");\n }\n first = false;\n moveCount += element.addElem(\n this.traverseUnit(unit, {\n earliestMoveIndex: dataDown.earliestMoveIndex + moveCount,\n twistyAlgViewer: dataDown.twistyAlgViewer,\n direction: dataDown.direction,\n }),\n );\n }\n element.flushQueue(dataDown.direction);\n return {\n moveCount: moveCount,\n element,\n };\n }\n\n public traverseGrouping(grouping: Grouping, dataDown: DataDown): DataUp {\n const square1Tuple = grouping.experimentalAsSquare1Tuple();\n // if (square1Tuplle) {\n\n // }\n\n const direction = updateDirectionByAmount(\n dataDown.direction,\n grouping.amount,\n );\n let moveCount = 0;\n const element = new TwistyAlgWrapperElem(\"twisty-alg-grouping\", grouping);\n element.addString(\"(\");\n\n if (square1Tuple) {\n moveCount += element.addElem({\n moveCount: 1,\n element: new TwistyAlgLeafElem(\n \"twisty-alg-move\", // TODO: Mark the tuple with a special class?\n square1Tuple[0].amount.toString(),\n dataDown,\n square1Tuple[0],\n true,\n true,\n ),\n });\n element.addString(\", \");\n moveCount += element.addElem({\n moveCount: 1,\n element: new TwistyAlgLeafElem(\n \"twisty-alg-move\", // TODO: Mark the tuple with a special class?\n square1Tuple[1].amount.toString(),\n dataDown,\n square1Tuple[1],\n true,\n true,\n ),\n });\n } else {\n moveCount += element.addElem(\n this.traverseAlg(grouping.alg, {\n earliestMoveIndex: dataDown.earliestMoveIndex + moveCount,\n twistyAlgViewer: dataDown.twistyAlgViewer,\n direction,\n }),\n );\n }\n\n element.addString(\")\" + grouping.experimentalRepetitionSuffix);\n element.flushQueue();\n return {\n moveCount: moveCount * Math.abs(grouping.amount),\n element,\n };\n }\n\n public traverseMove(move: Move, dataDown: DataDown): DataUp {\n const element = new TwistyAlgLeafElem(\n \"twisty-alg-move\",\n move.toString(),\n dataDown,\n move,\n true,\n true,\n );\n dataDown.twistyAlgViewer.highlighter.addMove(\n (move as Parsed<Move>).startCharIndex,\n element,\n );\n return {\n moveCount: 1,\n element,\n };\n }\n\n public traverseCommutator(\n commutator: Commutator,\n dataDown: DataDown,\n ): DataUp {\n let moveCount = 0;\n const element = new TwistyAlgWrapperElem(\n \"twisty-alg-commutator\",\n commutator,\n );\n element.addString(\"[\");\n element.flushQueue();\n const [first, second]: Alg[] = maybeReverseList(\n [commutator.A, commutator.B],\n dataDown.direction,\n );\n moveCount += element.addElem(\n this.traverseAlg(first, {\n earliestMoveIndex: dataDown.earliestMoveIndex + moveCount,\n twistyAlgViewer: dataDown.twistyAlgViewer,\n direction: dataDown.direction,\n }),\n );\n element.addString(\", \");\n moveCount += element.addElem(\n this.traverseAlg(second, {\n earliestMoveIndex: dataDown.earliestMoveIndex + moveCount,\n twistyAlgViewer: dataDown.twistyAlgViewer,\n direction: dataDown.direction,\n }),\n );\n element.flushQueue(dataDown.direction);\n element.addString(\"]\");\n element.flushQueue();\n return {\n moveCount: moveCount * 2,\n element,\n };\n }\n\n public traverseConjugate(conjugate: Conjugate, dataDown: DataDown): DataUp {\n let moveCount = 0;\n const element = new TwistyAlgWrapperElem(\"twisty-alg-conjugate\", conjugate);\n element.addString(\"[\");\n const aLen = element.addElem(\n this.traverseAlg(conjugate.A, {\n earliestMoveIndex: dataDown.earliestMoveIndex + moveCount,\n twistyAlgViewer: dataDown.twistyAlgViewer,\n direction: dataDown.direction,\n }),\n );\n moveCount += aLen;\n element.addString(\": \");\n moveCount += element.addElem(\n this.traverseAlg(conjugate.B, {\n earliestMoveIndex: dataDown.earliestMoveIndex + moveCount,\n twistyAlgViewer: dataDown.twistyAlgViewer,\n direction: dataDown.direction,\n }),\n );\n element.addString(\"]\");\n element.flushQueue();\n return {\n moveCount: moveCount + aLen,\n element,\n };\n }\n\n public traversePause(pause: Pause, dataDown: DataDown): DataUp {\n return {\n moveCount: 1,\n element: new TwistyAlgLeafElem(\n \"twisty-alg-pause\",\n \".\",\n dataDown,\n pause,\n true,\n true,\n ),\n };\n }\n\n public traverseNewline(newline: Newline, _dataDown: DataDown): DataUp {\n const element = new TwistyAlgWrapperElem(\"twisty-alg-newline\", newline);\n element.append(document.createElement(\"br\"));\n return {\n moveCount: 0,\n element,\n };\n }\n\n public traverseLineComment(\n lineComment: LineComment,\n dataDown: DataDown,\n ): DataUp {\n return {\n moveCount: 0,\n element: new TwistyAlgLeafElem(\n \"twisty-alg-line-comment\",\n `//${lineComment.text}`,\n dataDown,\n lineComment,\n false,\n false,\n ),\n };\n }\n}\n\nconst algToDOMTreeInstance = new AlgToDOMTree();\nconst algToDOMTree = algToDOMTreeInstance.traverseAlg.bind(\n algToDOMTreeInstance,\n) as (alg: Alg, dataDown: DataDown) => DataUp;\n\nclass MoveHighlighter {\n moveCharIndexMap: Map<number, TwistyAlgLeafElem> = new Map();\n currentElem: TwistyAlgLeafElem | null = null;\n\n addMove(charIndex: number, elem: TwistyAlgLeafElem): void {\n this.moveCharIndexMap.set(charIndex, elem);\n }\n\n set(move: Parsed<Move> | null): void {\n const newElem = move\n ? this.moveCharIndexMap.get(move.startCharIndex) ?? null\n : null;\n if (this.currentElem === newElem) {\n return;\n }\n this.currentElem?.classList.remove(\"twisty-alg-current-move\");\n this.currentElem?.setCurrentMove(false);\n newElem?.classList.add(\"twisty-alg-current-move\");\n newElem?.setCurrentMove(true);\n this.currentElem = newElem;\n }\n}\n\nexport class TwistyAlgViewer extends HTMLElementShim {\n highlighter: MoveHighlighter = new MoveHighlighter();\n #domTree: TwistyAlgWrapperElem | TwistyAlgLeafElem;\n twistyPlayer: TwistyPlayer | null = null;\n lastClickTimestamp: number | null = null;\n constructor(options?: { twistyPlayer?: TwistyPlayer }) {\n super();\n if (options?.twistyPlayer) {\n this.setTwistyPlayer(options?.twistyPlayer);\n }\n }\n\n protected connectedCallback(): void {\n // nothing to do?\n }\n\n private setAlg(alg: Alg): void {\n this.#domTree = algToDOMTree(alg, {\n earliestMoveIndex: 0,\n twistyAlgViewer: this,\n direction: ExperimentalIterationDirection.Forwards,\n }).element;\n this.textContent = \"\";\n this.appendChild(this.#domTree);\n }\n\n async setTwistyPlayer(twistyPlayer: TwistyPlayer): Promise<void> {\n if (this.twistyPlayer) {\n console.warn(\"twisty-player reassignment is not supported\");\n return;\n }\n this.twistyPlayer = twistyPlayer;\n\n this.twistyPlayer.experimentalModel.algProp.addFreshListener(\n (algWithIssues: AlgWithIssues) => {\n this.setAlg(algWithIssues.alg);\n },\n );\n\n const sourceAlg = (await this.twistyPlayer.experimentalModel.algProp.get())\n .alg;\n // TODO: Use proper architecture instead of a heuristic to ensure we have a parsed alg annotated with char indices.\n const parsedAlg =\n \"startCharIndex\" in (sourceAlg as Partial<Parsed<Alg>>)\n ? sourceAlg\n : Alg.fromString(sourceAlg.toString());\n this.setAlg(parsedAlg);\n\n twistyPlayer.experimentalModel.currentLeavesProp.addFreshListener(\n (currentMoveInfo: CurrentMoveInfo) => {\n let moveInfo = currentMoveInfo.currentMoves[0];\n moveInfo ??= currentMoveInfo.movesStarting[0];\n moveInfo ??= currentMoveInfo.movesFinishing[0];\n if (!moveInfo) {\n this.highlighter.set(null);\n } else {\n const mainCurrentMove = moveInfo.move; // TODO\n this.highlighter.set(mainCurrentMove as Parsed<Move>);\n }\n },\n );\n\n twistyPlayer.experimentalModel.detailedTimelineInfoProp.addFreshListener(\n (detailedTimelineInfo: DetailedTimelineInfo) => {\n if (detailedTimelineInfo.timestamp !== this.lastClickTimestamp) {\n this.lastClickTimestamp = null;\n }\n },\n );\n }\n\n async jumpToIndex(index: number, offsetIntoMove: boolean): Promise<void> {\n // TODO: Fix async issues.\n const twistyPlayer = this.twistyPlayer;\n if (twistyPlayer) {\n twistyPlayer.pause();\n const timestampPromise = (async (): Promise<MillisecondTimestamp> => {\n const indexer = await twistyPlayer.experimentalModel.indexerProp.get();\n const offset = offsetIntoMove ? DEFAULT_OFFSET_MS : 0;\n return (indexer.indexToMoveStartTimestamp(index) ?? -offset) + offset;\n })();\n twistyPlayer.experimentalModel.timestampRequestProp.set(\n await timestampPromise, // TODO\n );\n if (this.lastClickTimestamp === (await timestampPromise)) {\n twistyPlayer.play();\n this.lastClickTimestamp = null;\n } else {\n this.lastClickTimestamp = await timestampPromise;\n }\n }\n }\n\n protected async attributeChangedCallback(\n attributeName: string,\n _oldValue: string,\n newValue: string,\n ): Promise<void> {\n if (attributeName === \"for\") {\n const elem = document.getElementById(newValue);\n if (!elem) {\n console.warn(\"for= elem does not exist\");\n return;\n }\n await customElements.whenDefined(\"twisty-player\");\n if (!(elem instanceof TwistyPlayer)) {\n console.warn(\"for= elem is not a twisty-player\");\n return;\n }\n this.setTwistyPlayer(elem);\n }\n }\n\n static get observedAttributes(): string[] {\n return [\"for\"];\n }\n}\n\ncustomElementsShim.define(\"twisty-alg-viewer\", TwistyAlgViewer);\n", "import {\n Alg,\n Commutator,\n Conjugate,\n Grouping,\n LineComment,\n Move,\n Newline,\n Pause,\n TraversalDownUp,\n} from \"../../../alg\";\nimport type { Parsed } from \"../../../alg/parse\";\nimport type { AnimatedLeafUnit } from \"../../old/animation/indexer/simultaneous-moves/simul-moves\";\n\nexport type AnimatedLeafUnitInfo = {\n leaf: Parsed<AnimatedLeafUnit>;\n idx: number;\n};\nexport type OrderedLeafTokens = AnimatedLeafUnitInfo[];\n\ninterface DataUp {\n tokens: OrderedLeafTokens;\n numLeavesInside: number;\n}\n\ninterface DataDown {\n numMovesSofar: number;\n}\n\nclass LeafTokens extends TraversalDownUp<DataDown, DataUp> {\n public traverseAlg(alg: Alg, dataDown: DataDown): DataUp {\n const unitArrays: OrderedLeafTokens[] = [];\n let numMovesInside = 0;\n for (const unit of alg.units()) {\n const dataUp = this.traverseUnit(unit, {\n numMovesSofar: dataDown.numMovesSofar + numMovesInside,\n });\n unitArrays.push(dataUp.tokens);\n numMovesInside += dataUp.numLeavesInside;\n }\n return {\n tokens: Array.prototype.concat(...unitArrays),\n numLeavesInside: numMovesInside,\n };\n }\n\n public traverseGrouping(grouping: Grouping, dataDown: DataDown): DataUp {\n const dataUp = this.traverseAlg(grouping.alg, dataDown);\n return {\n tokens: dataUp.tokens,\n numLeavesInside: dataUp.numLeavesInside * grouping.amount,\n };\n }\n\n public traverseMove(move: Move, dataDown: DataDown): DataUp {\n return {\n tokens: [{ leaf: move as Parsed<Move>, idx: dataDown.numMovesSofar }],\n numLeavesInside: 1,\n }; // TODO: What if not parsed?\n }\n\n public traverseCommutator(\n commutator: Commutator,\n dataDown: DataDown,\n ): DataUp {\n const dataUpA = this.traverseAlg(commutator.A, dataDown);\n const dataUpB = this.traverseAlg(commutator.B, {\n numMovesSofar: dataDown.numMovesSofar + dataUpA.numLeavesInside,\n });\n return {\n tokens: dataUpA.tokens.concat(dataUpB.tokens),\n numLeavesInside: dataUpA.numLeavesInside * 2 + dataUpB.numLeavesInside,\n };\n }\n\n public traverseConjugate(conjugate: Conjugate, dataDown: DataDown): DataUp {\n const dataUpA = this.traverseAlg(conjugate.A, dataDown);\n const dataUpB = this.traverseAlg(conjugate.B, {\n numMovesSofar: dataDown.numMovesSofar + dataUpA.numLeavesInside,\n });\n return {\n tokens: dataUpA.tokens.concat(dataUpB.tokens),\n numLeavesInside:\n dataUpA.numLeavesInside * 2 + dataUpB.numLeavesInside * 2,\n };\n }\n\n public traversePause(pause: Pause, dataDown: DataDown): DataUp {\n return {\n tokens: [{ leaf: pause as Parsed<Pause>, idx: dataDown.numMovesSofar }],\n numLeavesInside: 1,\n }; // TODO: What if not parsed?\n }\n\n public traverseNewline(_newline: Newline, _dataDown: DataDown): DataUp {\n return {\n tokens: [],\n numLeavesInside: 0,\n };\n }\n\n public traverseLineComment(\n _comment: LineComment,\n _dataDown: DataDown,\n ): DataUp {\n return {\n tokens: [],\n numLeavesInside: 0,\n };\n }\n}\n\nconst leafTokensInstance = new LeafTokens();\nexport const leafTokens = leafTokensInstance.traverseAlg.bind(\n leafTokensInstance,\n) as (alg: Parsed<Alg>, dataDown: DataDown) => DataUp;\n", "// TODO: Move this?\n\nimport type { Alg } from \"../../../alg\";\nimport type { Parsed } from \"../../../alg/parse\";\nimport {\n AlgWithIssues,\n algWithIssuesFromString,\n} from \"../../model/props/puzzle/state/AlgProp\";\nimport {\n SimpleTwistyPropSource,\n TwistyPropDerived,\n TwistyPropSource,\n} from \"../../model/props/TwistyProp\";\nimport {\n AnimatedLeafUnitInfo,\n leafTokens,\n OrderedLeafTokens,\n} from \"./LeafTokens\";\n\nexport class TwistyAlgEditorValueProp extends SimpleTwistyPropSource<string> {\n getDefaultValue(): string {\n return \"\";\n }\n}\n\ninterface AlgEditorAlgWithIssuesPropInput {\n value: string;\n}\nclass AlgEditorAlgWithIssuesProp extends TwistyPropDerived<\n AlgEditorAlgWithIssuesPropInput,\n AlgWithIssues\n> {\n derive(input: AlgEditorAlgWithIssuesPropInput): AlgWithIssues {\n return algWithIssuesFromString(input.value);\n }\n\n // TODO: canReuse needs to take the source string into account.\n}\n\ninterface SelectionInfoPropInput {\n selectionStart: number;\n selectionEnd: number;\n}\ninterface SelectionInfo extends SelectionInfoPropInput {\n endChangedMostRecently: boolean;\n}\nexport class TwistyAlgEditorSelectionProp extends TwistyPropSource<\n SelectionInfo,\n SelectionInfoPropInput\n> {\n getDefaultValue() {\n return {\n selectionStart: 0,\n selectionEnd: 0,\n endChangedMostRecently: false,\n };\n }\n\n async derive(\n input: SelectionInfoPropInput,\n oldValue: Promise<SelectionInfo>,\n ): Promise<SelectionInfo> {\n const { selectionStart, selectionEnd } = input;\n const lastResult = await oldValue;\n const endChangedMostRecently =\n input.selectionStart === lastResult.selectionStart &&\n input.selectionEnd !== (await oldValue).selectionEnd;\n return {\n selectionStart,\n selectionEnd,\n endChangedMostRecently,\n };\n }\n}\n\ninterface TargetCharPropInputs {\n selectionInfo: SelectionInfo;\n}\n\nexport class TargetCharProp extends TwistyPropDerived<\n TargetCharPropInputs,\n number\n> {\n derive(inputs: TargetCharPropInputs) {\n return inputs.selectionInfo.endChangedMostRecently\n ? inputs.selectionInfo.selectionEnd\n : inputs.selectionInfo.selectionStart;\n }\n}\n\ninterface LeafTokensPropInputs {\n algWithIssues: AlgWithIssues;\n}\nclass LeafTokensProp extends TwistyPropDerived<\n LeafTokensPropInputs,\n OrderedLeafTokens\n> {\n derive(inputs: LeafTokensPropInputs): OrderedLeafTokens {\n return leafTokens(inputs.algWithIssues.alg as Parsed<Alg>, {\n numMovesSofar: 0,\n }).tokens;\n }\n}\n\ninterface LeafToHighlightPropInputs {\n targetChar: number;\n leafTokens: OrderedLeafTokens;\n}\ntype HighlightWhere = \"before\" | \"start\" | \"inside\" | \"end\" | \"after\";\nexport interface HighlightInfo {\n leafInfo: AnimatedLeafUnitInfo;\n where: HighlightWhere;\n}\nclass LeafToHighlightProp extends TwistyPropDerived<\n LeafToHighlightPropInputs,\n HighlightInfo | null\n> {\n derive(inputs: LeafToHighlightPropInputs): HighlightInfo | null {\n function withWhere(\n leafInfo: AnimatedLeafUnitInfo | null,\n ): HighlightInfo | null {\n if (leafInfo === null) {\n return null;\n }\n let where: HighlightWhere;\n if (inputs.targetChar < leafInfo.leaf.startCharIndex) {\n where = \"before\";\n } else if (inputs.targetChar === leafInfo.leaf.startCharIndex) {\n where = \"start\";\n } else if (inputs.targetChar < leafInfo.leaf.endCharIndex) {\n where = \"inside\";\n } else if (inputs.targetChar === leafInfo.leaf.endCharIndex) {\n where = \"end\";\n } else {\n where = \"after\";\n }\n return {\n leafInfo,\n where,\n };\n }\n\n let lastLeafInfo: AnimatedLeafUnitInfo | null = null;\n // TODO: binary search\n for (const leafInfo of inputs.leafTokens) {\n if (\n inputs.targetChar < leafInfo.leaf.startCharIndex &&\n lastLeafInfo !== null\n ) {\n return withWhere(lastLeafInfo);\n }\n if (inputs.targetChar <= leafInfo.leaf.endCharIndex) {\n return withWhere(leafInfo);\n }\n lastLeafInfo = leafInfo;\n }\n\n return withWhere(lastLeafInfo);\n }\n}\n\nexport class TwistyAlgEditorModel {\n valueProp = new TwistyAlgEditorValueProp();\n selectionProp = new TwistyAlgEditorSelectionProp();\n targetCharProp = new TargetCharProp({ selectionInfo: this.selectionProp });\n\n algEditorAlgWithIssues = new AlgEditorAlgWithIssuesProp({\n value: this.valueProp,\n });\n\n leafTokensProp = new LeafTokensProp({\n algWithIssues: this.algEditorAlgWithIssues,\n });\n\n leafToHighlight = new LeafToHighlightProp({\n leafTokens: this.leafTokensProp,\n targetChar: this.targetCharProp,\n });\n}\n", "import { CSSSource } from \"../../old/dom/element/ManagedCustomElement\";\n\nexport const twistyAlgEditorCSS = new CSSSource(`\n:host {\n width: 384px;\n display: grid;\n}\n\n.wrapper {\n /*overflow: hidden;\n resize: horizontal;*/\n\n background: var(--background, none);\n display: grid;\n}\n\ntextarea, .carbon-copy {\n grid-area: 1 / 1 / 2 / 2;\n\n width: 100%;\n font-family: sans-serif;\n line-height: 1.2em;\n\n font-size: var(--font-size, inherit);\n font-family: var(--font-family, sans-serif);\n\n box-sizing: border-box;\n\n padding: var(--padding, 0.5em);\n /* Prevent horizontal growth. */\n overflow-x: hidden;\n}\n\ntextarea {\n resize: none;\n background: none;\n z-index: 2;\n overflow: hidden;\n border: 1px solid var(--border-color, rgba(0, 0, 0, 0.25));\n}\n\n.carbon-copy {\n white-space: pre-wrap;\n word-wrap: break-word;\n color: transparent;\n user-select: none;\n pointer-events: none;\n\n z-index: 1;\n}\n\n.carbon-copy .highlight {\n background: var(--highlight-color, rgba(255, 128, 0, 0.5));\n padding: 0.1em 0.2em;\n margin: -0.1em -0.2em;\n border-radius: 0.2em;\n}\n\n.wrapper.issue-warning textarea,\n.wrapper.valid-for-puzzle-warning textarea {\n outline: none;\n border: 1px solid rgba(200, 200, 0, 0.5);\n background: rgba(255, 255, 0, 0.1);\n}\n\n.wrapper.issue-error textarea,\n.wrapper.valid-for-puzzle-error textarea {\n outline: none;\n border: 1px solid red;\n background: rgba(255, 0, 0, 0.1);\n}\n`);\n", "/**\n * Warning: the current implementation of <twisty-alg-editor> is *not good*,\n * but it is *good enough*. The important parts is that:\n *\n * - The editor can be used in apps without much effort.\n * - The editor handles alg validation and move highlighting *okay* when not\n * connected to a `<twisty-player>`.\n * - The editor stays in sync if it's connected to a `<twisty-player>`.\n *\n * The current implementation still has some race conditions and edge cases. A\n * proper rewrite with a better model would be very welcome.\n */\n\nimport type { ExperimentalParsed } from \"../../../alg\";\nimport { Alg, Move, Pause } from \"../../../alg\";\nimport type { Parsed } from \"../../../alg/parse\";\nimport type {\n AlgProp,\n AlgWithIssues,\n} from \"../../model/props/puzzle/state/AlgProp\";\nimport type { CurrentLeavesSimplified } from \"../../model/props/puzzle/state/CurrentLeavesSimplified\";\nimport { ClassListManager } from \"../../old/dom/element/ClassListManager\";\nimport { ManagedCustomElement } from \"../../old/dom/element/ManagedCustomElement\";\nimport { customElementsShim } from \"../../old/dom/element/node-custom-element-shims\";\nimport { TwistyPlayer } from \"../TwistyPlayer\";\nimport { HighlightInfo, TwistyAlgEditorModel } from \"./model\";\nimport { twistyAlgEditorCSS } from \"./TwistyAlgEditor.css\";\n\nconst ATTRIBUTE_FOR_TWISTY_PLAYER = \"for-twisty-player\";\nconst ATTRIBUTE_PLACEHOLDER = \"placeholder\";\nconst ATTRIBUTE_TWISTY_PLAYER_PROP = \"twisty-player-prop\";\n\ntype TwistyPlayerAlgProp = \"algProp\" | \"setupProp\";\n\nexport class TwistyAlgEditor extends ManagedCustomElement {\n model = new TwistyAlgEditorModel();\n\n // #alg: Alg = new Alg();\n #textarea: HTMLTextAreaElement = document.createElement(\"textarea\");\n #carbonCopy: HTMLDivElement = document.createElement(\"div\");\n #carbonCopyPrefix: HTMLSpanElement = document.createElement(\"span\");\n #carbonCopyHighlight: HTMLSpanElement = document.createElement(\"span\");\n #carbonCopySuffix: HTMLSpanElement = document.createElement(\"span\");\n\n // #textareaClassListManager: ClassListManager<\"none\" | \"warning\" | \"error\"> =\n // new ClassListManager(this, \"issue-\", [\"none\", \"warning\", \"error\"]);\n\n #textareaClassListValidForPuzzleManager: ClassListManager<\n \"none\" | \"warning\" | \"error\"\n > = new ClassListManager(this, \"valid-for-puzzle-\", [\n \"none\",\n \"warning\",\n \"error\",\n ]);\n\n #twistyPlayer: TwistyPlayer | null = null;\n #twistyPlayerProp: TwistyPlayerAlgProp;\n get #algProp(): AlgProp | null {\n if (this.#twistyPlayer === null) {\n return null;\n } else {\n return this.#twistyPlayer.experimentalModel[this.#twistyPlayerProp];\n }\n }\n\n constructor(options?: {\n twistyPlayer?: TwistyPlayer;\n twistyPlayerProp?: TwistyPlayerAlgProp;\n }) {\n super();\n this.#carbonCopy.classList.add(\"carbon-copy\");\n this.addElement(this.#carbonCopy);\n this.#textarea.rows = 1;\n this.addElement(this.#textarea);\n this.#carbonCopyPrefix.classList.add(\"prefix\");\n this.#carbonCopy.appendChild(this.#carbonCopyPrefix);\n this.#carbonCopyHighlight.classList.add(\"highlight\");\n this.#carbonCopy.appendChild(this.#carbonCopyHighlight);\n this.#carbonCopySuffix.classList.add(\"suffix\");\n this.#carbonCopy.appendChild(this.#carbonCopySuffix);\n\n this.#textarea.placeholder = \"Alg\";\n // Prevent iOS from defaulting to smart quotes.\n this.#textarea.setAttribute(\"spellcheck\", \"false\");\n\n this.addCSS(twistyAlgEditorCSS);\n\n // TODO: What set of events should we register? `change`? `keydown`?\n this.#textarea.addEventListener(\"input\", () => {\n this.#onInputHasFired = true;\n this.onInput();\n });\n this.#textarea.addEventListener(\"blur\", () => this.onBlur());\n document.addEventListener(\"selectionchange\", () =>\n this.onSelectionChange(),\n );\n\n if (options?.twistyPlayer) {\n this.twistyPlayer = options.twistyPlayer;\n }\n this.#twistyPlayerProp = options?.twistyPlayerProp ?? \"algProp\";\n\n if (options?.twistyPlayerProp === \"algProp\") {\n this.model.leafToHighlight.addFreshListener(\n (highlightInfo: HighlightInfo | null) => {\n if (highlightInfo) {\n this.highlightLeaf(highlightInfo.leafInfo.leaf);\n }\n },\n );\n }\n }\n\n // TODO\n set algString(s: string) {\n this.#textarea.value = s;\n this.onInput();\n }\n\n // TODO: remove?\n get algString(): string {\n return this.#textarea.value;\n }\n\n // To we need a getter?\n set placeholder(placeholderText: string) {\n this.#textarea.placeholder = placeholderText;\n }\n\n #onInputHasFired = false;\n onInput(): void {\n this.#carbonCopyHighlight.hidden = true;\n this.highlightLeaf(null);\n\n // TODO: This is a hack so that the you don't get a warning when the cursor\n // is after the space while typing `R U`. It would be nice to have something\n // cursor-aware that can also ignore whitespace warnings (or other syntax\n // errors due to normal input) adjacent to the cursor when it's in the\n // middle, but this is suffuciently useful for now.\n const endTrimmed = this.#textarea.value.trimEnd();\n this.model.valueProp.set(endTrimmed);\n this.#algProp?.set(endTrimmed);\n }\n\n async onSelectionChange(): Promise<void> {\n if (\n document.activeElement !== this ||\n this.shadow.activeElement !== this.#textarea\n ) {\n return;\n }\n if (this.#twistyPlayerProp !== \"algProp\") {\n return;\n }\n\n const { selectionStart, selectionEnd } = this.#textarea;\n this.model.selectionProp.set({\n selectionStart,\n selectionEnd,\n });\n }\n\n async onBlur(): Promise<void> {\n // TODO: Figure out how not to make the cursor jump.\n // const parsed = Alg.fromString(this.algString);\n // this.algString = parsed.toString();\n // const [currentLeavesSimplified, indexer] = await Promise.all([\n // this.#twistyPlayer!.model.currentLeavesSimplifiedProp.get(),\n // this.#twistyPlayer!.model.indexerProp.get(),\n // ]);\n // const leaf = indexer.getAnimLeaf(currentLeavesSimplified.stateIndex);\n // this.highlightLeaf(leaf as Parsed<Move | Pause> | null);\n }\n\n setAlgIssueClassForPuzzle(issues: \"none\" | \"warning\" | \"error\") {\n this.#textareaClassListValidForPuzzleManager.setValue(issues);\n }\n\n // `white-space: pre;` mostly matches the formatting of the `<textarea>`, *except* when we end with a newline.\n // So we add an space to ensure that there is a character on the final line (that is very unlikely to trigger extra line wrapping).\n #padSuffix(s: string): string {\n return s.endsWith(\"\\n\") ? s + \" \" : s;\n }\n\n #highlightedLeaf: ExperimentalParsed<Move | Pause> | null = null;\n // TODO: support a primary highlighted move and secondary ones.\n highlightLeaf(leaf: ExperimentalParsed<Move | Pause> | null): void {\n if (this.#twistyPlayerProp !== \"algProp\") {\n return;\n }\n if (leaf === null) {\n this.#carbonCopyPrefix.textContent = \"\";\n this.#carbonCopyHighlight.textContent = \"\";\n this.#carbonCopySuffix.textContent = this.#padSuffix(\n this.#textarea.value,\n );\n return;\n }\n if (leaf === this.#highlightedLeaf) {\n return;\n }\n this.#highlightedLeaf = leaf;\n this.#carbonCopyPrefix.textContent = this.#textarea.value.slice(\n 0,\n leaf.startCharIndex,\n );\n this.#carbonCopyHighlight.textContent = this.#textarea.value.slice(\n leaf.startCharIndex,\n leaf.endCharIndex,\n );\n this.#carbonCopySuffix.textContent = this.#padSuffix(\n this.#textarea.value.slice(leaf.endCharIndex),\n );\n this.#carbonCopyHighlight.hidden = false;\n }\n\n get twistyPlayer(): TwistyPlayer | null {\n return this.#twistyPlayer;\n }\n\n // TODO: spread out this impl over private methods instead of self-listeners.\n set twistyPlayer(twistyPlayer: TwistyPlayer | null) {\n if (this.#twistyPlayer) {\n // TODO: support reassigment/clearing\n console.warn(\"twisty-player reassignment/clearing is not supported\");\n return;\n }\n this.#twistyPlayer = twistyPlayer;\n if (!twistyPlayer) {\n return;\n }\n (async () => {\n this.algString = this.#algProp\n ? (await this.#algProp.get()).alg.toString()\n : \"\";\n })();\n\n if (this.#twistyPlayerProp === \"algProp\") {\n // this.model.leafToHighlight.addFreshListener(\n // this.highlightLeaf.bind(this),\n // );\n\n // TODO: listen to puzzle prop?\n this.#twistyPlayer?.experimentalModel.puzzleAlgProp.addFreshListener(\n (algWithIssues: AlgWithIssues) => {\n // console.log(JSON.stringify(algWithIssues));\n if (algWithIssues.issues.errors.length === 0) {\n this.setAlgIssueClassForPuzzle(\n // TODO: Allow trailing spaces.\n algWithIssues.issues.warnings.length === 0 ? \"none\" : \"warning\",\n );\n const newAlg = algWithIssues.alg;\n const oldAlg = Alg.fromString(this.algString);\n if (!newAlg.isIdentical(oldAlg)) {\n this.algString = newAlg.toString();\n this.onInput();\n } else {\n // this.model.algInputProp.set(oldAlg);\n }\n } else {\n this.setAlgIssueClassForPuzzle(\"error\");\n }\n },\n );\n\n this.model.leafToHighlight.addFreshListener(\n async (highlightInfo: HighlightInfo | null) => {\n if (highlightInfo === null) {\n return;\n }\n // TODO: This indexer can be out of date!\n const [indexer, timestampRequest] = await Promise.all([\n await twistyPlayer.experimentalModel.indexerProp.get(),\n await twistyPlayer.experimentalModel.timestampRequestProp.get(),\n ]);\n if (\n timestampRequest === \"opposite-anchor\" &&\n !this.#onInputHasFired\n ) {\n return;\n }\n const moveStartTimestamp = indexer.indexToMoveStartTimestamp(\n highlightInfo.leafInfo.idx,\n );\n const duration = indexer.moveDuration(highlightInfo.leafInfo.idx);\n\n let newTimestamp: number;\n switch (highlightInfo.where) {\n case \"before\":\n newTimestamp = moveStartTimestamp;\n break;\n case \"start\":\n case \"inside\":\n newTimestamp = moveStartTimestamp + duration / 4;\n break;\n case \"end\":\n case \"after\":\n newTimestamp = moveStartTimestamp + duration;\n break;\n default:\n console.log(\"invalid where\");\n throw new Error(\"Invalid where!\");\n }\n twistyPlayer.experimentalModel.timestampRequestProp.set(newTimestamp);\n },\n );\n\n twistyPlayer.experimentalModel.currentLeavesSimplifiedProp.addFreshListener(\n async (currentLeavesSimplified: CurrentLeavesSimplified) => {\n const indexer =\n await twistyPlayer.experimentalModel.indexerProp.get();\n const leaf = indexer.getAnimLeaf(currentLeavesSimplified.stateIndex);\n this.highlightLeaf(leaf as Parsed<Move | Pause> | null);\n },\n );\n }\n }\n\n protected attributeChangedCallback(\n attributeName: string,\n _oldValue: string,\n newValue: string,\n ): void {\n switch (attributeName) {\n case ATTRIBUTE_FOR_TWISTY_PLAYER: {\n const elem = document.getElementById(newValue);\n if (!elem) {\n console.warn(`${ATTRIBUTE_FOR_TWISTY_PLAYER}= elem does not exist`);\n return;\n }\n if (!(elem instanceof TwistyPlayer)) {\n // TODO: avoid assuming single instance of lib?\n console.warn(`${ATTRIBUTE_FOR_TWISTY_PLAYER}=is not a twisty-player`);\n return;\n }\n this.twistyPlayer = elem;\n return;\n }\n case ATTRIBUTE_PLACEHOLDER:\n this.placeholder = newValue;\n return;\n case ATTRIBUTE_TWISTY_PLAYER_PROP:\n if (this.#twistyPlayer) {\n console.log(\"cannot set prop\");\n throw new Error(\"cannot set prop after twisty player\");\n }\n this.#twistyPlayerProp = newValue as TwistyPlayerAlgProp;\n return;\n }\n }\n\n static get observedAttributes(): string[] {\n return [\n ATTRIBUTE_FOR_TWISTY_PLAYER,\n ATTRIBUTE_PLACEHOLDER,\n ATTRIBUTE_TWISTY_PLAYER_PROP,\n ];\n }\n}\n\ncustomElementsShim.define(\"twisty-alg-editor\", TwistyAlgEditor);\n", "import { Vector3 } from \"three\";\nimport { Alg, experimentalAppendMove, Move } from \"../../../alg\";\nimport type { KPuzzleDefinition, Transformation } from \"../../../kpuzzle\";\nimport { countMoves } from \"../../../notation\"; // TODO\nimport type { StickerDat } from \"../../../puzzle-geometry\";\nimport { puzzles } from \"../../../puzzles\";\nimport type { PuzzleLoader } from \"../../../puzzles/PuzzleLoader\";\nimport type { PuzzleAppearance } from \"../../../puzzles/stickerings/appearance\";\nimport { Cube3D } from \"../../views/3D/puzzles/Cube3D\";\nimport { PG3D, PG3DOptions } from \"../../views/3D/puzzles/PG3D\";\nimport type { Twisty3DPuzzle } from \"../../views/3D/puzzles/Twisty3DPuzzle\";\nimport { Twisty3DScene } from \"../../views/3D/Twisty3DScene\";\nimport { AlgCursor, IndexerConstructor } from \"../animation/cursor/AlgCursor\";\nimport { SimpleAlgIndexer } from \"../animation/indexer/SimpleAlgIndexer\";\nimport { SimultaneousMoveIndexer } from \"../animation/indexer/simultaneous-moves/SimultaneousMoveIndexer\";\nimport { TreeAlgIndexer } from \"../animation/indexer/tree/TreeAlgIndexer\";\nimport {\n Timeline,\n TimelineAction,\n TimelineActionEvent,\n TimestampLocationType,\n} from \"../animation/Timeline\";\nimport { TwistyControlButtonPanel } from \"./controls/buttons\";\nimport type { TwistyControlElement } from \"./controls/TwistyControlElement\";\nimport { TwistyScrubber } from \"./controls/TwistyScrubber\";\nimport { ClassListManager } from \"./element/ClassListManager\";\nimport { ManagedCustomElement } from \"./element/ManagedCustomElement\";\nimport { customElementsShim } from \"./element/node-custom-element-shims\";\nimport { twistyPlayerCSS } from \"./TwistyPlayer.css\";\nimport {\n BackgroundTheme,\n CameraLatitudeLimits,\n ControlsLocation,\n defaultCameraOrbitCoordinates,\n ExperimentalStickering,\n HintFaceletStyle,\n PuzzleID,\n pyraminxLookAt,\n SetupToLocation,\n TwistyPlayerConfig,\n TwistyPlayerInitialConfig,\n ViewerLinkPage,\n VisualizationFormat,\n} from \"./TwistyPlayerConfig\";\nimport { Twisty2DSVG, Twisty2DSVGOptions } from \"./viewers/Twisty2DSVG\";\nimport { Twisty3DCanvas } from \"./viewers/Twisty3DCanvas\";\nimport type {\n OrbitCoordinates,\n TwistyOrbitControls,\n} from \"./viewers/TwistyOrbitControls\";\nimport type { TwistyViewerElement } from \"./viewers/TwistyViewerElement\";\nimport {\n BackViewLayout,\n TwistyViewerWrapper,\n} from \"./viewers/TwistyViewerWrapper\";\n\nexport interface LegacyExperimentalPG3DViewConfig {\n def: KPuzzleDefinition;\n stickerDat: StickerDat;\n experimentalPolarVantages?: boolean;\n showFoundation?: boolean;\n hintStickers?: boolean;\n hintStickerHeightScale?: number;\n}\n\nfunction is3DVisualization(visualizationFormat: VisualizationFormat): boolean {\n return [\"3D\", \"PG3D\"].includes(visualizationFormat);\n}\n\ninterface PendingPuzzleUpdate {\n cancelled: boolean;\n}\n\nconst indexerMap = {\n simple: SimpleAlgIndexer,\n tree: TreeAlgIndexer,\n simultaneous: SimultaneousMoveIndexer,\n};\n\nexport class TwistyPlayerV1 extends ManagedCustomElement {\n #config: TwistyPlayerConfig;\n\n timeline: Timeline;\n cursor: AlgCursor | null;\n scene: Twisty3DScene | null = null;\n twisty3D: Twisty3DPuzzle | null = null;\n\n #connected = false;\n #legacyExperimentalPG3DViewConfig: LegacyExperimentalPG3DViewConfig | null =\n null;\n\n /** @deprecated */\n public legacyExperimentalPG3D: PG3D | null = null;\n #experimentalStartStateOverride: Transformation | null = null;\n\n viewerElems: TwistyViewerElement[] = []; // TODO: can we represent the intermediate state better?\n controlElems: TwistyControlElement[] = []; // TODO: can we represent the intermediate state better?\n\n #hackyPendingFinalMoveCoalesce = false;\n\n #viewerWrapper: TwistyViewerWrapper;\n public legacyExperimentalCoalesceModFunc: (move: Move) => number = (\n _move: Move,\n ): number => 0;\n\n #controlsClassListManager: ClassListManager<ControlsLocation> =\n new ClassListManager(this, \"controls-\", [\"none\", \"bottom-row\"]);\n\n #experimentalInvalidInitialAlgCallback: (alg: Alg) => void;\n #initialized = false;\n\n // TODO: support config from DOM.\n constructor(\n initialConfig: TwistyPlayerInitialConfig = {},\n legacyExperimentalPG3DViewConfig: LegacyExperimentalPG3DViewConfig | null = null,\n experimentalInvalidInitialAlgCallback: (alg: Alg) => void = () => {\n // stub\n },\n ) {\n super();\n this.addCSS(twistyPlayerCSS);\n this.#config = new TwistyPlayerConfig(this, initialConfig);\n this.#experimentalInvalidInitialAlgCallback =\n experimentalInvalidInitialAlgCallback;\n\n this.timeline = new Timeline();\n this.timeline.addActionListener(this);\n\n // We also do this in connectedCallback, but for now we also do it here so\n // that there is some visual change even if the rest of construction or\n // initialization fails.\n this.contentWrapper.classList.add(\"checkered\");\n\n this.#legacyExperimentalPG3DViewConfig = legacyExperimentalPG3DViewConfig;\n }\n\n set alg(newAlg: Alg | string) {\n // TODO: do validation for other algs as well.\n if (typeof newAlg === \"string\") {\n newAlg = Alg.fromString(newAlg);\n }\n this.#config.attributes[\"alg\"].setValue(newAlg);\n this.cursor?.setAlg(newAlg, this.#indexerConstructor()); // TODO: can we ensure the cursor already exists?\n this.#setCursorStartState();\n\n this.dispatchEvent(\n new CustomEvent(\"experimental-alg-update\", { detail: { alg: this.alg } }),\n );\n }\n\n get alg(): Alg {\n return this.#config.attributes[\"alg\"].value;\n }\n\n /** @deprecated */\n set experimentalSetupAlg(newAlg: Alg | string) {\n // TODO: do validation for other algs as well.\n if (typeof newAlg === \"string\") {\n console.warn(\n \"`experimentalSetupAlg` for a `TwistyPlayer` was set using a string. It should be set using a `Sequence`!\",\n );\n newAlg = new Alg(newAlg as unknown as string);\n }\n this.#config.attributes[\"experimental-setup-alg\"].setValue(newAlg);\n this.#setCursorStartState();\n }\n\n /** @deprecated */\n get experimentalSetupAlg(): Alg {\n return this.#config.attributes[\"experimental-setup-alg\"].value;\n }\n\n #setCursorStartState(): void {\n if (this.cursor) {\n this.cursor.setStartState(\n this.#experimentalStartStateOverride ??\n this.cursor.algToState(this.#cursorStartAlg()),\n ); // TODO\n }\n }\n\n #cursorStartAlg(): Alg {\n let startAlg = this.experimentalSetupAlg;\n if (this.experimentalSetupAnchor === \"end\") {\n startAlg = startAlg.concat(this.alg.invert());\n }\n return startAlg; // TODO\n }\n\n /** @deprecated */\n set experimentalSetupAnchor(setupToLocation: SetupToLocation) {\n this.#config.attributes[\"experimental-setup-anchor\"].setValue(\n setupToLocation,\n );\n this.#setCursorStartState();\n }\n\n /** @deprecated */\n get experimentalSetupAnchor(): SetupToLocation {\n return this.#config.attributes[\"experimental-setup-anchor\"].value;\n }\n\n set puzzle(puzzle: PuzzleID) {\n if (this.#config.attributes[\"puzzle\"].setValue(puzzle)) {\n this.updatePuzzleDOM();\n }\n }\n\n get puzzle(): PuzzleID {\n return this.#config.attributes[\"puzzle\"].value;\n }\n\n set visualization(visualization: VisualizationFormat) {\n if (this.#config.attributes[\"visualization\"].setValue(visualization)) {\n this.updatePuzzleDOM();\n }\n }\n\n get visualization(): VisualizationFormat {\n return this.#config.attributes[\"visualization\"].value;\n }\n\n set hintFacelets(hintFacelets: HintFaceletStyle) {\n // TODO: implement this for PG3D.\n if (this.#config.attributes[\"hint-facelets\"].setValue(hintFacelets)) {\n if (this.twisty3D instanceof Cube3D) {\n this.twisty3D.experimentalUpdateOptions({ hintFacelets });\n }\n }\n }\n\n get hintFacelets(): HintFaceletStyle {\n return this.#config.attributes[\"hint-facelets\"].value;\n }\n\n // TODO: Implement for PG3D\n /** @deprecated */\n set experimentalStickering(experimentalStickering: ExperimentalStickering) {\n if (\n this.#config.attributes[\"experimental-stickering\"].setValue(\n experimentalStickering,\n )\n ) {\n const twisty3D = this.twisty3D;\n if (twisty3D instanceof Cube3D) {\n twisty3D.experimentalUpdateOptions({\n experimentalStickering,\n });\n }\n if (twisty3D instanceof PG3D) {\n (async () => {\n const appearance = await this.#getPG3DAppearance();\n twisty3D.experimentalSetAppearance(appearance!); // TODO\n })();\n }\n if (this.viewerElems[0] instanceof Twisty2DSVG) {\n this.viewerElems[0].experimentalSetStickering(\n this.experimentalStickering,\n );\n }\n }\n }\n\n // TODO: Implement for PG3D\n /** @deprecated */\n get experimentalStickering(): ExperimentalStickering {\n return this.#config.attributes[\"experimental-stickering\"].value;\n }\n\n set background(background: BackgroundTheme) {\n if (this.#config.attributes[\"background\"].setValue(background)) {\n this.contentWrapper.classList.toggle(\n \"checkered\",\n background === \"checkered\",\n );\n }\n }\n\n get background(): BackgroundTheme {\n return this.#config.attributes[\"background\"].value;\n }\n\n set controlPanel(controlPanel: ControlsLocation) {\n this.#config.attributes[\"control-panel\"].setValue(controlPanel);\n this.#controlsClassListManager.setValue(controlPanel);\n }\n\n get controlPanel(): ControlsLocation {\n return this.#config.attributes[\"control-panel\"].value;\n }\n\n /** @deprecated use `controlPanel */\n set controls(controls: ControlsLocation) {\n this.controlPanel = controls;\n }\n\n /** @deprecated use `controlPanel */\n get controls(): ControlsLocation {\n return this.controlPanel;\n }\n\n set backView(backView: BackViewLayout) {\n this.#config.attributes[\"back-view\"].setValue(backView);\n if (backView !== \"none\" && this.viewerElems.length === 1) {\n this.#createBackViewer();\n }\n if (backView === \"none\" && this.viewerElems.length > 1) {\n this.#removeBackViewerElem();\n }\n if (this.#viewerWrapper && this.#viewerWrapper.setBackView(backView)) {\n for (const viewer of this.viewerElems as Twisty3DCanvas[]) {\n viewer.makeInvisibleUntilRender(); // TODO: can we do this more elegantly?\n }\n }\n }\n\n get backView(): BackViewLayout {\n return this.#config.attributes[\"back-view\"].value;\n }\n\n #orbitControls(): TwistyOrbitControls | null {\n if (\n ![\"3D\", \"PG3D\"].includes(this.#config.attributes[\"visualization\"].value)\n ) {\n return null;\n }\n return (this.viewerElems[0] as Twisty3DCanvas)?.orbitControls ?? null;\n }\n\n #backOrbitControls(): TwistyOrbitControls | null {\n if (\n ![\"3D\", \"PG3D\"].includes(this.#config.attributes[\"visualization\"].value)\n ) {\n return null;\n }\n return (this.viewerElems[1] as Twisty3DCanvas)?.orbitControls ?? null;\n }\n\n set experimentalCameraLatitude(latitude: number | null) {\n this.#config.attributes[\"experimental-camera-latitude\"].setValue(latitude);\n const orbitControls = this.#orbitControls();\n if (orbitControls && latitude !== null) {\n orbitControls.latitude = latitude;\n this.viewerElems[0].scheduleRender();\n this.viewerElems[1]?.scheduleRender();\n }\n }\n\n get experimentalCameraLatitude(): number | null {\n if (\n this.#config.attributes[\"experimental-camera-latitude\"].value !== null\n ) {\n return this.#config.attributes[\"experimental-camera-latitude\"].value;\n }\n return this.#orbitControls()?.latitude ?? null;\n }\n\n set experimentalCameraLongitude(longitude: number | null) {\n this.#config.attributes[\"experimental-camera-longitude\"].setValue(\n longitude,\n );\n const orbitControls = this.#orbitControls();\n if (orbitControls && longitude !== null) {\n orbitControls.longitude = longitude;\n this.viewerElems[0].scheduleRender();\n this.viewerElems[1]?.scheduleRender();\n }\n }\n\n get experimentalCameraLongitude(): number | null {\n if (\n this.#config.attributes[\"experimental-camera-longitude\"].value !== null\n ) {\n return this.#config.attributes[\"experimental-camera-longitude\"].value;\n }\n return this.#orbitControls()?.longitude ?? null;\n }\n\n set experimentalCameraLatitudeLimits(latitudeLimits: CameraLatitudeLimits) {\n this.#config.attributes[\"experimental-camera-latitude-limits\"].setValue(\n latitudeLimits,\n );\n const orbitControls = this.#orbitControls();\n console.log({ orbitControls });\n if (orbitControls) {\n orbitControls.experimentalLatitudeLimits = latitudeLimits;\n }\n const backOrbitControls = this.#backOrbitControls(); // TODO: propagate through direct orbit controls as source of truth.\n if (backOrbitControls) {\n backOrbitControls.experimentalLatitudeLimits = latitudeLimits;\n }\n }\n\n get experimentalCameraLatitudeLimits(): CameraLatitudeLimits {\n // TODO: sync with orbit controls\n return this.#config.attributes[\"experimental-camera-latitude-limits\"].value;\n }\n\n set viewerLink(viewerLinkPage: ViewerLinkPage) {\n this.#config.attributes[\"viewer-link\"].setValue(viewerLinkPage);\n const maybePanel = this.controlElems[1] as\n | TwistyControlButtonPanel\n | undefined;\n if (maybePanel?.setViewerLink) {\n maybePanel.setViewerLink(viewerLinkPage);\n }\n }\n\n get viewerLink(): ViewerLinkPage {\n return this.#config.attributes[\"viewer-link\"].value;\n }\n\n /** @deprecated */\n experimentalSetCameraOrbitCoordinates(coords: OrbitCoordinates): void {\n this.experimentalCameraLatitude = coords.latitude;\n this.experimentalCameraLongitude = coords.longitude;\n const orbitControls = this.#orbitControls();\n if (orbitControls) {\n orbitControls.distance = coords.distance;\n }\n }\n\n /** @deprecated */\n experimentalDerivedCameraOrbitCoordinates(): OrbitCoordinates {\n const defaultCoordinatesForPuzzle = defaultCameraOrbitCoordinates(\n this.puzzle,\n this.twisty3D instanceof PG3D ? \"PG3D\" : \"Cube3D\",\n );\n\n return {\n latitude:\n this.experimentalCameraLatitude ?? defaultCoordinatesForPuzzle.latitude,\n longitude:\n this.experimentalCameraLongitude ??\n defaultCoordinatesForPuzzle.longitude,\n distance: defaultCoordinatesForPuzzle.distance, // TODO\n };\n }\n\n #lookAt(): Vector3 {\n switch (this.puzzle) {\n case \"pyraminx\":\n case \"master_tetraminx\":\n return pyraminxLookAt;\n default:\n return new Vector3(0, 0, 0);\n }\n }\n\n static get observedAttributes(): string[] {\n return TwistyPlayerConfig.observedAttributes;\n }\n\n attributeChangedCallback(\n attributeName: string,\n oldValue: string,\n newValue: string,\n ): void {\n this.#config.attributeChangedCallback(attributeName, oldValue, newValue);\n }\n\n experimentalSetStartStateOverride(state: Transformation | null): void {\n this.#experimentalStartStateOverride = state;\n this.#setCursorStartState();\n }\n\n #cursorIndexerName: \"simple\" | \"tree\" | \"simultaneous\" = \"tree\";\n /** @deprecated */\n public experimentalSetCursorIndexer(\n cursorName: \"simple\" | \"tree\" | \"simultaneous\",\n ): void {\n if (this.#cursorIndexerName === cursorName) {\n // TODO: This is a hacky optimization.\n return;\n }\n this.#cursorIndexerName = cursorName;\n this.cursor?.experimentalSetIndexer(this.#indexerConstructor());\n }\n\n #indexerConstructor(): IndexerConstructor {\n return indexerMap[this.#cursorIndexerName];\n }\n\n // TODO: It seems this called after the `attributeChangedCallback`s for initial values. Can we rely on this?\n protected connectedCallback(): void {\n this.contentWrapper.classList.toggle(\n \"checkered\",\n this.background === \"checkered\",\n );\n\n // TODO: specify exactly when back views are possible.\n // TODO: Are there any SVGs where we'd want a separate back view?\n const setBackView: boolean =\n this.backView && is3DVisualization(this.visualization);\n const backView: BackViewLayout = setBackView ? this.backView : \"none\";\n this.#viewerWrapper = new TwistyViewerWrapper({\n backView,\n });\n this.addElement(this.#viewerWrapper);\n\n const scrubber = new TwistyScrubber(this.timeline);\n const controlButtonGrid = new TwistyControlButtonPanel(this.timeline, {\n fullscreenElement: this,\n viewerLinkCallback: this.visitTwizzleLink.bind(this),\n viewerLink: this.viewerLink,\n });\n\n this.controlElems = [scrubber, controlButtonGrid];\n\n this.#controlsClassListManager.setValue(this.controlPanel);\n\n this.addElement(this.controlElems[0]);\n this.addElement(this.controlElems[1]);\n\n this.#connected = true;\n this.updatePuzzleDOM(true).then(() => {\n if (!this.#initialized) {\n this.#initialized = true;\n // TODO: warn if `initialized` listener is registered after initialized?\n this.dispatchEvent(new CustomEvent(\"initialized\"));\n }\n });\n }\n\n get initialized(): boolean {\n return this.#initialized;\n }\n\n public twizzleLink(): string {\n const url = new URL(\"https://alpha.twizzle.net/edit/\");\n if (!this.alg.experimentalIsEmpty()) {\n url.searchParams.set(\"alg\", this.alg.toString());\n }\n if (!this.experimentalSetupAlg.experimentalIsEmpty()) {\n url.searchParams.set(\n \"experimental-setup-alg\",\n this.experimentalSetupAlg.toString(),\n );\n }\n if (this.experimentalSetupAnchor !== \"start\") {\n url.searchParams.set(\n \"experimental-setup-anchor\",\n this.experimentalSetupAnchor,\n );\n }\n if (this.experimentalStickering !== \"full\") {\n url.searchParams.set(\n \"experimental-stickering\",\n this.experimentalStickering,\n );\n }\n if (this.puzzle !== \"3x3x3\") {\n url.searchParams.set(\"puzzle\", this.puzzle);\n }\n return url.toString();\n }\n\n public visitTwizzleLink(): void {\n const a = document.createElement(\"a\");\n a.href = this.twizzleLink();\n a.target = \"_blank\";\n a.click();\n }\n\n #pendingPuzzleUpdates: PendingPuzzleUpdate[] = [];\n #renderMode: \"2D\" | \"3D\" | null = null;\n\n // Idempotent\n #clearRenderMode(): void {\n switch (this.#renderMode) {\n case \"3D\":\n this.scene = null;\n this.twisty3D = null;\n this.legacyExperimentalPG3D = null;\n this.viewerElems = [];\n this.#viewerWrapper.clear();\n break;\n case \"2D\":\n this.viewerElems = [];\n this.#viewerWrapper.clear();\n break;\n }\n this.#renderMode = null;\n }\n\n #setRenderMode2D(): void {\n if (this.#renderMode === \"2D\") {\n return;\n }\n this.#clearRenderMode();\n this.#renderMode = \"2D\";\n }\n\n #setTwisty2DSVG(twisty2DSVG: Twisty2DSVG): void {\n this.#setRenderMode2D();\n\n this.#viewerWrapper.clear();\n this.#viewerWrapper.addElement(twisty2DSVG);\n this.viewerElems.push(twisty2DSVG);\n }\n\n #setRenderMode3D(): void {\n if (this.#renderMode === \"3D\") {\n return;\n }\n this.#clearRenderMode();\n\n this.scene = new Twisty3DScene();\n const mainViewer = new Twisty3DCanvas(this.scene, {\n orbitCoordinates: this.experimentalDerivedCameraOrbitCoordinates(),\n });\n mainViewer.orbitControls.experimentalLatitudeLimits =\n this.experimentalCameraLatitudeLimits;\n this.viewerElems.push(mainViewer);\n this.#viewerWrapper.addElement(mainViewer);\n\n if (this.backView !== \"none\") {\n this.#createBackViewer();\n }\n this.#renderMode = \"3D\";\n }\n\n #setTwisty3D(twisty3D: Twisty3DPuzzle): void {\n if (this.twisty3D) {\n this.scene!.removeTwisty3DPuzzle(this.twisty3D);\n if (this.twisty3D instanceof PG3D) {\n this.twisty3D.dispose();\n }\n this.twisty3D = null;\n }\n this.twisty3D = twisty3D;\n this.scene!.addTwisty3DPuzzle(twisty3D);\n const orbitControls = this.#orbitControls();\n if (orbitControls) {\n orbitControls.lookAt(this.#lookAt());\n }\n }\n\n #setCursor(cursor: AlgCursor): void {\n const oldCursor = this.cursor;\n this.cursor = cursor;\n try {\n this.cursor.setAlg(this.alg, this.#indexerConstructor());\n this.#setCursorStartState();\n } catch (e) {\n this.cursor.setAlg(new Alg(), this.#indexerConstructor());\n this.cursor.setStartState(this.cursor.algToState(new Alg()));\n this.#experimentalInvalidInitialAlgCallback(this.alg);\n }\n this.#setCursorStartState();\n this.timeline.addCursor(cursor);\n if (oldCursor) {\n this.timeline.removeCursor(oldCursor);\n this.timeline.removeTimestampListener(oldCursor);\n }\n this.experimentalSetCursorIndexer(this.#cursorIndexerName);\n }\n\n async updatePuzzleDOM(initial = false): Promise<void> {\n if (!this.#connected) {\n return;\n }\n\n let puzzleLoader: PuzzleLoader;\n if (this.puzzle === \"custom\") {\n puzzleLoader = {\n id: \"custom\",\n fullName: \"Custom (PG3D)\",\n def: () => Promise.resolve(this.#legacyExperimentalPG3DViewConfig!.def),\n svg: () => {\n throw \"unimplemented\";\n },\n };\n } else {\n puzzleLoader = puzzles[this.puzzle];\n }\n\n for (const pendingPuzzleUpdate of this.#pendingPuzzleUpdates) {\n pendingPuzzleUpdate.cancelled = true;\n }\n this.#pendingPuzzleUpdates = [];\n const pendingPuzzleUpdate: PendingPuzzleUpdate = { cancelled: false };\n this.#pendingPuzzleUpdates.push(pendingPuzzleUpdate);\n\n const def: KPuzzleDefinition = await puzzleLoader.def();\n if (pendingPuzzleUpdate.cancelled) {\n return;\n }\n\n let cursor: AlgCursor;\n try {\n cursor = new AlgCursor(\n this.timeline,\n def,\n this.alg,\n this.#cursorStartAlg(),\n this.#indexerConstructor(),\n ); // TODO: validate more directly if the alg is okay for the puzzle.\n this.#setCursor(cursor);\n } catch (e) {\n if (initial) {\n // TODO: also take into account setup alg.\n this.#experimentalInvalidInitialAlgCallback(this.alg);\n }\n cursor = new AlgCursor(\n this.timeline,\n def,\n new Alg(),\n new Alg(),\n this.#indexerConstructor(),\n );\n this.#setCursor(cursor);\n }\n if (\n initial &&\n this.experimentalSetupAlg.experimentalIsEmpty() &&\n this.experimentalSetupAnchor !== \"end\"\n ) {\n this.timeline.jumpToEnd();\n }\n switch (this.visualization) {\n case \"2D\":\n case \"experimental-2D-LL\":\n {\n const options: Twisty2DSVGOptions = {};\n if (this.experimentalStickering) {\n options.experimentalStickering = this.experimentalStickering;\n }\n\n this.#setRenderMode2D();\n const svgPromiseFn =\n this.visualization === \"2D\"\n ? puzzleLoader.svg\n : puzzleLoader.llSVG ?? puzzleLoader.svg;\n const mainViewer = new Twisty2DSVG(\n cursor,\n def,\n await svgPromiseFn(),\n options,\n puzzleLoader,\n );\n if (!pendingPuzzleUpdate.cancelled) {\n this.#setTwisty2DSVG(mainViewer);\n }\n }\n break;\n case \"3D\":\n case \"PG3D\":\n {\n this.#setRenderMode3D();\n const scene = this.scene!;\n\n let twisty3D: Twisty3DPuzzle;\n if (this.visualization === \"3D\" && this.puzzle === \"3x3x3\") {\n twisty3D = new Cube3D(\n def,\n cursor,\n scene.scheduleRender.bind(scene),\n {\n hintFacelets: this.hintFacelets,\n experimentalStickering: this.experimentalStickering,\n },\n );\n } else {\n let def: KPuzzleDefinition;\n let stickerDat: StickerDat;\n const pgGetter = puzzleLoader.pg;\n if (this.puzzle === \"custom\") {\n def = this.#legacyExperimentalPG3DViewConfig!.def;\n stickerDat = this.#legacyExperimentalPG3DViewConfig!.stickerDat;\n } else if (pgGetter) {\n const pg = await pgGetter();\n if (pendingPuzzleUpdate.cancelled) {\n return;\n }\n def = pg.writekpuzzle(true); // TODO\n stickerDat = pg.get3d();\n } else {\n throw \"Unimplemented!\";\n }\n const options: PG3DOptions = {};\n\n const heightMap: Record<string, number> = {\n megaminx: 1.5,\n pyraminx: 1.75,\n };\n const hintStickerHeightScale =\n this.#legacyExperimentalPG3DViewConfig?.hintStickerHeightScale ??\n heightMap[this.puzzle] ??\n 1;\n const pg3d = new PG3D(\n cursor,\n scene.scheduleRender.bind(scene),\n def,\n stickerDat,\n this.#legacyExperimentalPG3DViewConfig?.showFoundation ?? true,\n this.#legacyExperimentalPG3DViewConfig?.hintStickers ??\n this.hintFacelets === \"floating\",\n hintStickerHeightScale,\n options,\n );\n (async () => {\n const appearance = await this.#getPG3DAppearance();\n if (appearance) {\n pg3d.experimentalSetAppearance(appearance);\n }\n })();\n this.legacyExperimentalPG3D = pg3d;\n twisty3D = pg3d;\n }\n this.#setTwisty3D(twisty3D);\n }\n break;\n }\n }\n\n async #getPG3DAppearance(): Promise<PuzzleAppearance | null> {\n const puzzleLoader = puzzles[this.puzzle];\n if (puzzleLoader?.appearance) {\n return puzzleLoader.appearance(this.experimentalStickering ?? \"full\");\n }\n return null;\n }\n\n #createBackViewer(): void {\n if (!is3DVisualization(this.visualization)) {\n throw new Error(\"Back viewer requires a 3D visualization\");\n }\n\n const backViewer = new Twisty3DCanvas(this.scene!, {\n orbitCoordinates: this.experimentalDerivedCameraOrbitCoordinates(),\n negateCameraPosition: true,\n });\n backViewer.orbitControls.experimentalLatitudeLimits =\n this.experimentalCameraLatitudeLimits;\n this.viewerElems.push(backViewer);\n (this.viewerElems[0] as Twisty3DCanvas).setMirror(backViewer);\n this.#viewerWrapper.addElement(backViewer);\n }\n\n #removeBackViewerElem(): void {\n // TODO: Validate visualization.\n if (this.viewerElems.length !== 2) {\n throw new Error(\"Tried to remove non-existent back view!\");\n }\n this.#viewerWrapper.removeElement(this.viewerElems.pop()!);\n }\n\n async setCustomPuzzleGeometry(\n legacyExperimentalPG3DViewConfig: LegacyExperimentalPG3DViewConfig,\n ): Promise<void> {\n this.puzzle = \"custom\";\n this.#legacyExperimentalPG3DViewConfig = legacyExperimentalPG3DViewConfig;\n await this.updatePuzzleDOM();\n }\n\n // TODO: Handle playing the new move vs. just modying the alg.\n // Note: setting `coalesce`\n experimentalAddMove(\n move: Move,\n coalesce = false,\n coalesceDelayed = false,\n ): void {\n if (this.#hackyPendingFinalMoveCoalesce) {\n this.#hackyCoalescePending();\n }\n const oldNumMoves = countMoves(this.alg); // TODO\n const newAlg = experimentalAppendMove(this.alg, move, {\n coalesce: coalesce && !coalesceDelayed,\n mod: this.legacyExperimentalCoalesceModFunc(move),\n });\n // const newAlg = experimentalAppendBlockMove(\n // this.alg,\n // move,\n // coalesce && !coalesceDelayed,\n // this.legacyExperimentalCoalesceModFunc(move),\n // );\n if (coalesce && coalesceDelayed) {\n this.#hackyPendingFinalMoveCoalesce = true;\n }\n\n this.alg = newAlg;\n // TODO\n if (oldNumMoves <= countMoves(newAlg)) {\n this.timeline.experimentalJumpToLastMove();\n } else {\n this.timeline.jumpToEnd();\n }\n this.timeline.play();\n }\n\n onTimelineAction(actionEvent: TimelineActionEvent): void {\n if (\n actionEvent.action === TimelineAction.Pausing &&\n actionEvent.locationType === TimestampLocationType.EndOfTimeline &&\n this.#hackyPendingFinalMoveCoalesce\n ) {\n this.#hackyCoalescePending();\n this.timeline.jumpToEnd();\n }\n }\n\n #hackyCoalescePending(): void {\n const units = Array.from(this.alg.units());\n const length = units.length;\n const pending = this.#hackyPendingFinalMoveCoalesce;\n this.#hackyPendingFinalMoveCoalesce = false;\n if (pending && length > 1 && units[length - 1].is(Move)) {\n const finalMove = units[length - 1] as Move;\n const newAlg = experimentalAppendMove(\n new Alg(units.slice(0, length - 1)),\n finalMove,\n {\n coalesce: true,\n mod: this.legacyExperimentalCoalesceModFunc(finalMove),\n },\n );\n this.alg = newAlg;\n }\n }\n\n fullscreen(): void {\n this.requestFullscreen();\n }\n}\n\ncustomElementsShim.define(\"twisty-player-v1\", TwistyPlayerV1);\n", "/* eslint-disable no-case-declarations */\n// TODO: private vs. public properties/methods.\n// TODO: optional construtor arguments for DOM elements\n// TODO: figure out what can be moved into a worker using OffscreenCanvas https://developers.google.com/web/updates/2018/08/offscreen-canvas\n\n/* eslint-disable @typescript-eslint/no-empty-interface */\n\n// start of imports\nimport { Alg, Move, Pause } from \"../../../../alg\";\nimport {\n KPuzzle,\n KPuzzleDefinition,\n Transformation,\n} from \"../../../../kpuzzle\";\nimport { KPuzzleWrapper } from \"../../../views/3D/puzzles/KPuzzleWrapper\";\nimport type { AlgIndexer } from \"../indexer/AlgIndexer\";\nimport { TreeAlgIndexer } from \"../indexer/tree/TreeAlgIndexer\";\nimport type { Timeline, TimelineTimestampListener } from \"../Timeline\";\nimport {\n Direction,\n directionScalar,\n MillisecondTimestamp,\n PuzzlePosition,\n} from \"./CursorTypes\";\n// end of imports\n\n// Model\n\nexport interface PositionListener {\n onPositionChange(position: PuzzlePosition): void;\n}\n\nexport interface PositionDispatcher {\n addPositionListener(positionListener: PositionListener): void;\n}\n\nexport interface TimeRange {\n start: MillisecondTimestamp;\n end: MillisecondTimestamp;\n}\n\nexport type IndexerConstructor = new (\n puzzle: KPuzzleWrapper,\n alg: Alg,\n) => AlgIndexer<KPuzzleWrapper>;\n\nexport class AlgCursor\n implements TimelineTimestampListener, PositionDispatcher\n{\n private indexer: AlgIndexer<KPuzzleWrapper>;\n private positionListeners: Set<PositionListener> = new Set(); // TODO: accessor instead of direct access\n private ksolvePuzzle: KPuzzleWrapper;\n private startState: Transformation;\n private indexerConstructor: IndexerConstructor = TreeAlgIndexer;\n constructor(\n private timeline: Timeline,\n private def: KPuzzleDefinition,\n private alg: Alg,\n startStateAlg?: Alg, // TODO: accept actual start state\n indexerConstructor?: IndexerConstructor,\n ) {\n this.ksolvePuzzle = new KPuzzleWrapper(def);\n if (indexerConstructor) {\n this.indexerConstructor = indexerConstructor;\n }\n this.instantiateIndexer(alg);\n this.startState = startStateAlg\n ? this.algToState(startStateAlg)\n : this.ksolvePuzzle.startState();\n timeline.addTimestampListener(this);\n }\n\n setStartState(startState: Transformation): void {\n this.startState = startState;\n this.dispatchPositionForTimestamp(this.timeline.timestamp);\n }\n\n /** @deprecated */\n public experimentalSetIndexer(indexerConstructor: IndexerConstructor): void {\n this.indexerConstructor = indexerConstructor;\n this.instantiateIndexer(this.alg);\n this.timeline.onCursorChange(this);\n this.dispatchPositionForTimestamp(this.timeline.timestamp);\n }\n\n private instantiateIndexer(alg: Alg): void {\n this.indexer = new this.indexerConstructor(this.ksolvePuzzle, alg);\n }\n\n /** @deprecated */\n algToState(s: Alg): Transformation {\n const kpuzzle = new KPuzzle(this.def);\n kpuzzle.applyAlg(s);\n return this.ksolvePuzzle.combine(this.def.startPieces, kpuzzle.state);\n }\n\n timeRange(): TimeRange {\n return {\n start: 0,\n end: this.indexer.algDuration(),\n };\n }\n\n /** @deprecated */\n experimentalTimestampForStartOfLastMove(): MillisecondTimestamp {\n const numMoves = this.indexer.numAnimatedLeaves();\n if (numMoves > 0) {\n return this.indexer.indexToMoveStartTimestamp(numMoves - 1);\n }\n return 0;\n }\n\n addPositionListener(positionListener: PositionListener): void {\n this.positionListeners.add(positionListener);\n this.dispatchPositionForTimestamp(this.timeline.timestamp, [\n positionListener,\n ]); // TODO: should this be a separate dispatch, or should the listener manually ask for the position?\n }\n\n removePositionListener(positionListener: PositionListener): void {\n this.positionListeners.delete(positionListener);\n }\n\n onTimelineTimestampChange(timestamp: MillisecondTimestamp): void {\n this.dispatchPositionForTimestamp(timestamp);\n }\n\n private dispatchPositionForTimestamp(\n timestamp: MillisecondTimestamp,\n listeners: PositionListener[] | Set<PositionListener> = this\n .positionListeners,\n ): void {\n let position: PuzzlePosition;\n if (this.indexer.timestampToPosition) {\n position = this.indexer.timestampToPosition(timestamp, this.startState);\n } else {\n const idx = this.indexer.timestampToIndex(timestamp);\n const state = this.indexer.stateAtIndex(\n idx,\n this.startState,\n ) as Transformation; // TODO\n position = {\n state,\n movesInProgress: [],\n };\n\n if (this.indexer.numAnimatedLeaves() > 0) {\n const move = this.indexer.getAnimLeaf(idx)?.as(Move);\n if (!move) {\n return; // TODO\n }\n const fraction =\n (timestamp - this.indexer.indexToMoveStartTimestamp(idx)) /\n this.indexer.moveDuration(idx);\n if (fraction === 1) {\n // TODO: push this into the indexer\n position.state = this.ksolvePuzzle.combine(\n state,\n this.ksolvePuzzle.stateFromMove(move),\n ) as Transformation;\n } else if (fraction > 0) {\n if (move) {\n position.movesInProgress.push({\n move,\n direction: Direction.Forwards,\n fraction,\n });\n }\n }\n }\n }\n\n for (const listener of listeners) {\n listener.onPositionChange(position);\n }\n }\n\n onTimeRangeChange(_timeRange: TimeRange): void {\n // nothing to do\n }\n\n setAlg(alg: Alg, indexerConstructor?: IndexerConstructor): void {\n indexerConstructor ??= this.indexerConstructor;\n if (\n alg.isIdentical(this.alg) &&\n this.indexerConstructor === indexerConstructor\n ) {\n // TODO: this is a hacky optimization.\n return;\n }\n this.indexerConstructor = indexerConstructor;\n this.alg = alg;\n this.instantiateIndexer(alg);\n this.timeline.onCursorChange(this);\n this.dispatchPositionForTimestamp(this.timeline.timestamp);\n // TODO: Handle state change.\n }\n\n moveBoundary(\n timestamp: MillisecondTimestamp,\n direction: Direction.Backwards | Direction.Forwards,\n ): MillisecondTimestamp | null {\n if (this.indexer.numAnimatedLeaves() === 0) {\n return null;\n }\n // TODO: define semantics of indexing edge cases and remove this hack.\n const offsetHack = directionScalar(direction) * 0.001;\n const idx = this.indexer.timestampToIndex(timestamp + offsetHack);\n const moveStart = this.indexer.indexToMoveStartTimestamp(idx);\n\n if (direction === Direction.Backwards) {\n return timestamp >= moveStart ? moveStart : null;\n } else {\n const moveEnd = moveStart + this.indexer.moveDuration(idx);\n return timestamp <= moveEnd ? moveEnd : null;\n }\n }\n\n setPuzzle(\n def: KPuzzleDefinition,\n alg: Alg = this.alg,\n startStateAlg?: Alg,\n ): void {\n this.ksolvePuzzle = new KPuzzleWrapper(def);\n this.def = def;\n this.indexer = new this.indexerConstructor(this.ksolvePuzzle, alg);\n if (alg !== this.alg) {\n this.timeline.onCursorChange(this);\n }\n this.setStartState(\n startStateAlg\n ? this.algToState(startStateAlg)\n : this.ksolvePuzzle.startState(),\n );\n this.alg = alg;\n }\n\n /** @deprecated */\n experimentalTimestampFromIndex(index: number): MillisecondTimestamp {\n return this.indexer.indexToMoveStartTimestamp(index);\n }\n\n /** @deprecated */\n experimentalIndexFromTimestamp(timestamp: MillisecondTimestamp): number {\n return this.indexer.timestampToIndex(timestamp);\n }\n\n /** @deprecated */\n experimentalLeafAtIndex(index: number): Move | Pause | null {\n return this.indexer.getAnimLeaf(index);\n }\n}\n", "import { Alg, Move } from \"../../../../../alg\";\nimport type {\n PuzzleWrapper,\n State,\n} from \"../../../../views/3D/puzzles/KPuzzleWrapper\";\nimport {\n Direction,\n Duration,\n PuzzlePosition,\n Timestamp,\n} from \"../../cursor/CursorTypes\";\nimport type { AlgIndexer } from \"../AlgIndexer\";\nimport { AnimatedLeafUnit, AnimLeafWithRange, simulMoves } from \"./simul-moves\";\n\nconst demos: Record<string, AnimLeafWithRange[]> = {\n \"y' y' U' E D R2 r2 F2 B2 U E D' R2 L2' z2 S2 U U D D S2 F2' B2\": [\n { animLeaf: new Move(\"y\", -1), start: 0, end: 1000 },\n { animLeaf: new Move(\"y\", -1), start: 1000, end: 2000 },\n { animLeaf: new Move(\"U\", -1), start: 1000, end: 1600 },\n { animLeaf: new Move(\"E\", 1), start: 1200, end: 1800 },\n { animLeaf: new Move(\"D\"), start: 1400, end: 2000 },\n { animLeaf: new Move(\"R\", 2), start: 2000, end: 3500 },\n { animLeaf: new Move(\"r\", 2), start: 2000, end: 3500 },\n { animLeaf: new Move(\"F\", 2), start: 3500, end: 4200 },\n { animLeaf: new Move(\"B\", 2), start: 3800, end: 4500 },\n { animLeaf: new Move(\"U\", 1), start: 4500, end: 5500 },\n { animLeaf: new Move(\"E\", 1), start: 4500, end: 5500 },\n { animLeaf: new Move(\"D\", -1), start: 4500, end: 5500 },\n { animLeaf: new Move(\"R\", 2), start: 5500, end: 6500 },\n { animLeaf: new Move(\"L\", -2), start: 5500, end: 6500 },\n { animLeaf: new Move(\"z\", 2), start: 5500, end: 6500 },\n { animLeaf: new Move(\"S\", 2), start: 6500, end: 7500 },\n { animLeaf: new Move(\"U\"), start: 7500, end: 8000 },\n { animLeaf: new Move(\"U\"), start: 8000, end: 8500 },\n { animLeaf: new Move(\"D\"), start: 7750, end: 8250 },\n { animLeaf: new Move(\"D\"), start: 8250, end: 8750 },\n { animLeaf: new Move(\"S\", 2), start: 8750, end: 9250 },\n { animLeaf: new Move(\"F\", -2), start: 8750, end: 10000 },\n { animLeaf: new Move(\"B\", 2), start: 8750, end: 10000 },\n ],\n \"M' R' U' D' M R\": [\n { animLeaf: new Move(\"M\", -1), start: 0, end: 1000 },\n { animLeaf: new Move(\"R\", -1), start: 0, end: 1000 },\n { animLeaf: new Move(\"U\", -1), start: 1000, end: 2000 },\n { animLeaf: new Move(\"D\", -1), start: 1000, end: 2000 },\n { animLeaf: new Move(\"M\"), start: 2000, end: 3000 },\n { animLeaf: new Move(\"R\"), start: 2000, end: 3000 },\n ],\n \"U' E' r E r2' E r U E\": [\n { animLeaf: new Move(\"U\", -1), start: 0, end: 1000 },\n { animLeaf: new Move(\"E\", -1), start: 0, end: 1000 },\n { animLeaf: new Move(\"r\"), start: 1000, end: 2500 },\n { animLeaf: new Move(\"E\"), start: 2500, end: 3500 },\n { animLeaf: new Move(\"r\", -2), start: 3500, end: 5000 },\n { animLeaf: new Move(\"E\"), start: 5000, end: 6000 },\n { animLeaf: new Move(\"r\"), start: 6000, end: 7000 },\n { animLeaf: new Move(\"U\"), start: 7000, end: 8000 },\n { animLeaf: new Move(\"E\"), start: 7000, end: 8000 },\n ],\n};\n\nexport class SimultaneousMoveIndexer<P extends PuzzleWrapper>\n implements AlgIndexer<P>\n{\n private animLeaves: AnimLeafWithRange[];\n // TODO: Allow custom `durationFn`.\n\n constructor(private puzzle: P, alg: Alg) {\n this.animLeaves = demos[alg.toString()] ?? simulMoves(alg);\n // TODO: Avoid assuming all base moves are block moves.\n }\n\n public getAnimLeaf(index: number): AnimatedLeafUnit | null {\n return (\n this.animLeaves[Math.min(index, this.animLeaves.length - 1)]?.animLeaf ??\n null\n );\n }\n\n private getAnimLeafWithRange(index: number): AnimLeafWithRange {\n return this.animLeaves[Math.min(index, this.animLeaves.length - 1)];\n }\n\n public indexToMoveStartTimestamp(index: number): Timestamp {\n let start = 0;\n if (this.animLeaves.length > 0) {\n start =\n this.animLeaves[Math.min(index, this.animLeaves.length - 1)].start;\n }\n return start;\n }\n\n public timestampToIndex(timestamp: Timestamp): number {\n let i = 0;\n for (i = 0; i < this.animLeaves.length; i++) {\n if (this.animLeaves[i].start >= timestamp) {\n return Math.max(0, i - 1);\n }\n }\n return Math.max(0, i - 1);\n }\n\n public timestampToPosition(\n timestamp: Timestamp,\n startTransformation?: State<P>,\n ): PuzzlePosition {\n const position: PuzzlePosition = {\n state: startTransformation ?? (this.puzzle.identity() as any),\n movesInProgress: [],\n };\n for (const leafWithRange of this.animLeaves) {\n if (leafWithRange.end <= timestamp) {\n const move = leafWithRange.animLeaf.as(Move);\n if (move !== null) {\n position.state = this.puzzle.combine(\n position.state,\n this.puzzle.stateFromMove(move),\n ) as any;\n }\n } else if (\n leafWithRange.start < timestamp &&\n timestamp < leafWithRange.end\n ) {\n const move = leafWithRange.animLeaf.as(Move);\n if (move !== null) {\n position.movesInProgress.push({\n move: move,\n direction: Direction.Forwards,\n fraction:\n (timestamp - leafWithRange.start) /\n (leafWithRange.end - leafWithRange.start),\n });\n }\n } else if (timestamp < leafWithRange.start) {\n continue;\n }\n }\n return position;\n }\n\n public stateAtIndex(index: number, startTransformation?: State<P>): State<P> {\n let state = startTransformation ?? this.puzzle.startState();\n for (let i = 0; i < this.animLeaves.length && i < index; i++) {\n const leafWithRange = this.animLeaves[i];\n const move = leafWithRange.animLeaf.as(Move);\n if (move !== null) {\n state = this.puzzle.combine(state, this.puzzle.stateFromMove(move));\n }\n }\n return state;\n }\n\n public transformAtIndex(index: number): State<P> {\n let state = this.puzzle.identity();\n for (const leafWithRange of this.animLeaves.slice(0, index)) {\n const move = leafWithRange.animLeaf.as(Move);\n if (move !== null) {\n state = this.puzzle.combine(state, this.puzzle.stateFromMove(move));\n }\n }\n return state;\n }\n\n public algDuration(): Duration {\n let max = 0;\n for (const leafWithRange of this.animLeaves) {\n max = Math.max(max, leafWithRange.end);\n }\n return max;\n }\n\n public numAnimatedLeaves(): number {\n // TODO: Cache internally once performance matters.\n return this.animLeaves.length;\n }\n\n public moveDuration(index: number): number {\n const move = this.getAnimLeafWithRange(index);\n return move.end - move.start;\n }\n}\n", "import { RenderScheduler } from \"./RenderScheduler\";\nimport type { AlgCursor, TimeRange } from \"./cursor/AlgCursor\";\nimport {\n BoundaryType,\n Direction,\n directionScalar,\n MillisecondTimestamp,\n} from \"./cursor/CursorTypes\";\n\n// YouTube keeps playing on jump, but it also stays frozen while the cursor is\n// down. So I think it would be good for this to be false, but only if we\n// implement a \"start jumping\" event that pauses until \"finish jumping\" while\n// the scrubber is active.\nconst PAUSE_ON_JUMP = true;\n\n// TODO: We use symbols to avoid exposing `number` values. Is this performant enough? Should/can we use symbols?\nexport enum TimelineAction {\n StartingToPlay = \"StartingToPlay\", // TODO playing backwards.\n Pausing = \"Pausing\",\n Jumping = \"Jumping\",\n}\n\n// TODO: We use symbols to avoid exposing `number` values. Is this performant enough? Should/can we use symbols?\nexport enum TimestampLocationType {\n StartOfTimeline = \"Start\",\n EndOfTimeline = \"End\",\n StartOfMove = \"StartOfMove\",\n EndOfMove = \"EndOfMove\",\n MiddleOfMove = \"MiddleOfMove\",\n BetweenMoves = \"BetweenMoves\",\n}\n\nexport interface TimelineActionEvent {\n action: TimelineAction;\n locationType: TimestampLocationType;\n}\n\n// This should be used by classes that (directly or indirectly) update puzzle\n// state based on a timestamp. It fires every time the timestamp is changed for\n// a new render (e.g. 60 times a second during animation), and only fires if the\n// timestamp has changed since the last call. This means you can use it as a\n// reliable callback telling you when to schedule a new render.\nexport interface TimelineTimestampListener {\n onTimelineTimestampChange(timestamp: MillisecondTimestamp): void;\n onTimeRangeChange(timeRange: TimeRange): void;\n}\n\n// This should be used by classes that (directly or indirectly) update UI (e.g.\n// pause/play buttons).\n//\n// Note: the action events of a `Timeline` are not necessarily coordinated with\n// the timestamp events, since timestamp events are tied to animation frames.\n// For example, if you receive a \"pausing\" event, the final frame may already\n// have been drawn, or may be drawn in the near future.\nexport interface TimelineActionListener {\n onTimelineAction(actionEvent: TimelineActionEvent): void;\n}\n\nexport interface TimelineTimestampDispatcher {\n addTimestampListener(timestampListener: TimelineTimestampListener): void;\n}\n\nexport interface TimelineActionDispatcher {\n addActionListener(actionListener: TimelineActionListener): void;\n}\n\n// `performance.now()` is rounded for security concerns, so it's usually not\n// accurate to the millisecond. So we round it, which lets us work with whole ms\n// everywhere.\nfunction getNow(): MillisecondTimestamp {\n return Math.round(performance.now());\n}\n\nexport class Timeline\n implements TimelineTimestampDispatcher, TimelineActionDispatcher\n{\n animating: boolean = false;\n tempoScale: number = 1;\n private cursors: Set<AlgCursor> = new Set();\n private timestampListeners: Set<TimelineTimestampListener> = new Set();\n private actionListeners: Set<TimelineActionListener> = new Set();\n timestamp: number = 0;\n lastAnimFrameNow: DOMHighResTimeStamp = 0;\n lastAnimFrameTimestamp: MillisecondTimestamp;\n private scheduler: RenderScheduler;\n\n direction: Direction.Backwards | Direction.Forwards = Direction.Forwards; // TODO: handle pausing here?\n\n boundaryType: BoundaryType = BoundaryType.EntireTimeline;\n cachedNextBoundary: MillisecondTimestamp;\n\n constructor() {\n const animFrame = (_now: MillisecondTimestamp): void => {\n if (this.animating) {\n const now = getNow(); // TODO: See if we can use the rAF value without monotonicity issues.;\n this.timestamp =\n this.timestamp +\n this.tempoScale *\n directionScalar(this.direction) *\n (now - this.lastAnimFrameNow);\n this.lastAnimFrameNow = now;\n\n const atOrPastBoundary =\n this.direction === Direction.Backwards\n ? this.timestamp <= this.cachedNextBoundary\n : this.timestamp >= this.cachedNextBoundary;\n if (atOrPastBoundary) {\n this.timestamp = this.cachedNextBoundary;\n if (this.animating) {\n this.animating = false;\n this.dispatchAction(TimelineAction.Pausing);\n }\n }\n }\n\n if (this.timestamp !== this.lastAnimFrameTimestamp) {\n this.dispatchTimestamp();\n this.lastAnimFrameTimestamp = this.timestamp;\n }\n\n if (this.animating) {\n this.scheduler.requestAnimFrame();\n }\n };\n this.scheduler = new RenderScheduler(animFrame);\n }\n\n public addCursor(cursor: AlgCursor): void {\n this.cursors.add(cursor);\n this.dispatchTimeRange();\n }\n\n removeCursor(cursor: AlgCursor): void {\n this.cursors.delete(cursor);\n this.clampTimestampToRange();\n this.dispatchTimeRange();\n }\n\n // TODO: test\n private clampTimestampToRange(): void {\n const timeRange = this.timeRange();\n if (this.timestamp < timeRange.start) {\n this.setTimestamp(timeRange.start);\n }\n if (this.timestamp > timeRange.end) {\n this.setTimestamp(timeRange.end);\n }\n }\n\n // In the future, this might do some calculations or caching.\n public onCursorChange(_cursor: AlgCursor): void {\n if (this.timestamp > this.maxTimestamp()) {\n this.timestamp = this.maxTimestamp();\n }\n this.dispatchTimeRange();\n }\n\n timeRange(): TimeRange {\n let start = 0;\n let end = 0;\n for (const cursor of this.cursors) {\n const cursorTimeRange = cursor.timeRange();\n start = Math.min(start, cursorTimeRange.start);\n end = Math.max(end, cursorTimeRange.end);\n }\n\n return { start, end };\n }\n\n minTimestamp(): number {\n // TODO: Calculate and cache this value every time there's a new cursor.\n return this.timeRange().start;\n }\n\n maxTimestamp(): number {\n // TODO: Calculate and cache this value every time there's a new cursor.\n return this.timeRange().end;\n }\n\n private dispatchTimeRange(): void {\n const timeRange = this.timeRange();\n for (const listener of this.cursors) {\n // TODO: dedup in case the timestamp hasn't changed sine last time.\n listener.onTimeRangeChange(timeRange);\n }\n // TODO: Combine loops without extra memory?\n for (const listener of this.timestampListeners) {\n // TODO: dedup in case the timestamp hasn't changed sine last time.\n listener.onTimeRangeChange(timeRange);\n }\n }\n\n private dispatchTimestamp(): void {\n for (const listener of this.cursors) {\n // TODO: dedup in case the timestamp hasn't changed sine last time.\n listener.onTimelineTimestampChange(this.timestamp);\n }\n // TODO: Combine loops without extra memory?\n for (const listener of this.timestampListeners) {\n // TODO: dedup in case the timestamp hasn't changed sine last time.\n listener.onTimelineTimestampChange(this.timestamp);\n }\n }\n\n addTimestampListener(timestampListener: TimelineTimestampListener): void {\n this.timestampListeners.add(timestampListener);\n }\n\n removeTimestampListener(timestampListener: TimelineTimestampListener): void {\n this.timestampListeners.delete(timestampListener);\n }\n\n addActionListener(actionListener: TimelineActionListener): void {\n this.actionListeners.add(actionListener);\n }\n\n removeActionListener(actionListener: TimelineActionListener): void {\n this.actionListeners.delete(actionListener);\n }\n\n play(): void {\n this.experimentalPlay(Direction.Forwards, BoundaryType.EntireTimeline);\n }\n\n experimentalPlay(\n direction: Direction.Backwards | Direction.Forwards,\n boundaryType: BoundaryType = BoundaryType.EntireTimeline,\n ): void {\n this.direction = direction;\n this.boundaryType = boundaryType;\n const nextBoundary = this.nextBoundary(\n this.timestamp,\n direction,\n this.boundaryType,\n );\n if (nextBoundary === null) {\n return; // Nowhere to end, so we don't animate.\n }\n this.cachedNextBoundary = nextBoundary;\n if (!this.animating) {\n this.animating = true;\n this.lastAnimFrameNow = getNow();\n this.dispatchAction(TimelineAction.StartingToPlay);\n this.scheduler.requestAnimFrame();\n }\n }\n\n // Non-inclusive\n private nextBoundary(\n timestamp: MillisecondTimestamp,\n direction: Direction.Backwards | Direction.Forwards,\n boundaryType: BoundaryType = BoundaryType.EntireTimeline,\n ): MillisecondTimestamp | null {\n switch (boundaryType) {\n case BoundaryType.EntireTimeline: {\n switch (direction) {\n case Direction.Backwards:\n return timestamp <= this.minTimestamp()\n ? null\n : this.minTimestamp();\n case Direction.Forwards:\n return timestamp >= this.maxTimestamp()\n ? null\n : this.maxTimestamp();\n default:\n throw new Error(\"invalid direction\");\n }\n }\n case BoundaryType.Move: {\n let result: null | MillisecondTimestamp = null;\n for (const cursor of this.cursors) {\n const boundaryTimestamp = cursor.moveBoundary(timestamp, direction);\n if (boundaryTimestamp !== null) {\n switch (direction) {\n case Direction.Backwards: {\n result = Math.min(\n result ?? boundaryTimestamp,\n boundaryTimestamp,\n );\n break;\n }\n case Direction.Forwards: {\n result = Math.max(\n result ?? boundaryTimestamp,\n boundaryTimestamp,\n );\n break;\n }\n default:\n throw new Error(\"invalid direction\");\n }\n }\n }\n return result;\n }\n default:\n throw new Error(\"invalid boundary type\");\n }\n }\n\n // One more render may be dispatched after this.\n pause(): void {\n // TODO: error if already paused?\n if (this.animating) {\n this.animating = false;\n this.dispatchAction(TimelineAction.Pausing);\n this.scheduler.requestAnimFrame();\n }\n }\n\n playPause(): void {\n if (this.animating) {\n this.pause();\n } else {\n if (this.timestamp >= this.maxTimestamp()) {\n this.timestamp = 0;\n }\n this.experimentalPlay(Direction.Forwards, BoundaryType.EntireTimeline);\n }\n }\n\n setTimestamp(timestamp: MillisecondTimestamp): void {\n const oldTimestamp = this.timestamp;\n this.timestamp = timestamp;\n this.lastAnimFrameNow = getNow();\n\n if (oldTimestamp !== timestamp) {\n this.dispatchAction(TimelineAction.Jumping);\n this.scheduler.requestAnimFrame();\n }\n\n if (PAUSE_ON_JUMP) {\n this.animating = false;\n this.dispatchAction(TimelineAction.Pausing);\n }\n }\n\n jumpToStart(): void {\n this.setTimestamp(this.minTimestamp());\n }\n\n jumpToEnd(): void {\n this.setTimestamp(this.maxTimestamp());\n }\n\n /** @deprecated */\n experimentalJumpToLastMove(): void {\n let max: MillisecondTimestamp = 0;\n for (const cursor of this.cursors) {\n max = Math.max(\n max,\n cursor.experimentalTimestampForStartOfLastMove() ?? 0,\n );\n }\n this.setTimestamp(max);\n }\n\n private dispatchAction(event: TimelineAction): void {\n let locationType = TimestampLocationType.MiddleOfMove; // TODO\n switch (this.timestamp) {\n // TODO\n case this.minTimestamp():\n locationType = TimestampLocationType.StartOfTimeline;\n break;\n case this.maxTimestamp():\n locationType = TimestampLocationType.EndOfTimeline;\n break;\n }\n\n const actionEvent: TimelineActionEvent = {\n action: event,\n locationType,\n };\n for (const listener of this.actionListeners) {\n listener.onTimelineAction(actionEvent);\n }\n }\n}\n", "import type { TimeRange } from \"../../animation/cursor/AlgCursor\";\nimport {\n BoundaryType,\n Direction,\n MillisecondTimestamp,\n} from \"../../animation/cursor/CursorTypes\";\nimport {\n Timeline,\n TimelineAction,\n TimelineActionEvent,\n TimestampLocationType,\n} from \"../../animation/Timeline\";\nimport { ClassListManager } from \"../element/ClassListManager\";\nimport { ManagedCustomElement } from \"../element/ManagedCustomElement\";\nimport { customElementsShim } from \"../element/node-custom-element-shims\";\nimport type { ViewerLinkPage } from \"../TwistyPlayerConfig\";\nimport { buttonCSS, buttonGridCSS } from \"./buttons.css\";\nimport type { TwistyControlElement } from \"./TwistyControlElement\";\n\ntype TimelineCommand =\n | \"fullscreen\"\n | \"jump-to-start\"\n | \"play-pause\" // TODO: toggle-play?\n // | \"play\"\n // | \"play-backwards\"\n | \"play-step-backwards\"\n | \"play-step\"\n | \"jump-to-end\"\n | \"twizzle-link\";\n\n// TODO: combine this with disabled status and label in a state machine?\ntype ButtonIconName =\n | \"skip-to-start\"\n | \"skip-to-end\"\n | \"step-forward\"\n | \"step-backward\"\n | \"pause\"\n | \"play\"\n | \"enter-fullscreen\"\n | \"exit-fullscreen\"\n | \"twizzle-tw\";\n\nexport class TwistyControlButton\n extends ManagedCustomElement\n implements TwistyControlElement\n{\n private timeline: Timeline;\n private timelineCommand: TimelineCommand;\n private currentIconName: string | null = null;\n protected button: HTMLButtonElement = document.createElement(\"button\");\n private fullscreenElement: Element | null = null;\n private visitTwizzleLinkCallback: (() => void) | null = null;\n constructor(\n timeline?: Timeline,\n timelineCommand?: TimelineCommand,\n options?: {\n fullscreenElement?: Element; // TODO: reflect as an element attribute?\n visitTwizzleLinkCallback?: () => void;\n },\n ) {\n super();\n\n this.fullscreenElement = options?.fullscreenElement ?? null;\n this.visitTwizzleLinkCallback = options?.visitTwizzleLinkCallback ?? null;\n\n if (!timeline) {\n console.warn(\"Must have timeline!\"); // TODO\n }\n this.timeline = timeline!;\n if (!timelineCommand) {\n console.warn(\"Must have timelineCommand!\"); // TODO\n }\n this.timelineCommand = timelineCommand!;\n\n this.addCSS(buttonCSS);\n this.setIcon(this.initialIcon());\n this.setHoverTitle(this.initialHoverTitle());\n this.addElement(this.button);\n this.addEventListener(\"click\", this.onPress.bind(this));\n\n switch (this.timelineCommand) {\n case \"fullscreen\":\n if (!document.fullscreenEnabled) {\n this.button.disabled = true;\n }\n break;\n case \"jump-to-start\":\n case \"play-step-backwards\":\n this.button.disabled = true;\n break;\n }\n\n if (this.timeline) {\n // TODO\n this.timeline.addActionListener(this);\n switch (this.timelineCommand) {\n case \"play-pause\":\n case \"play-step-backwards\":\n case \"play-step\":\n this.timeline.addTimestampListener(this);\n break;\n }\n\n this.autoSetTimelineBasedDisabled();\n }\n }\n\n // TODO: Can we avoid duplicate calculations?\n private autoSetTimelineBasedDisabled(): void {\n switch (this.timelineCommand) {\n case \"jump-to-start\":\n case \"play-pause\":\n case \"play-step-backwards\":\n case \"play-step\":\n case \"jump-to-end\": {\n const timeRange = this.timeline.timeRange();\n if (timeRange.start === timeRange.end) {\n this.button.disabled = true;\n return;\n }\n switch (this.timelineCommand) {\n case \"jump-to-start\":\n case \"play-step-backwards\":\n this.button.disabled =\n this.timeline.timestamp < this.timeline.maxTimestamp();\n break;\n case \"jump-to-end\":\n case \"play-step\":\n this.button.disabled =\n this.timeline.timestamp > this.timeline.minTimestamp();\n break;\n default:\n this.button.disabled = false;\n }\n break;\n }\n }\n }\n\n setIcon(buttonIconName: ButtonIconName): void {\n if (this.currentIconName === buttonIconName) {\n return;\n }\n if (this.currentIconName) {\n this.button.classList.remove(`svg-${this.currentIconName}`);\n }\n this.button.classList.add(`svg-${buttonIconName}`);\n this.currentIconName = buttonIconName;\n }\n\n private initialIcon(): ButtonIconName {\n const map: Record<TimelineCommand, ButtonIconName> = {\n \"jump-to-start\": \"skip-to-start\",\n \"play-pause\": \"play\",\n \"play-step\": \"step-forward\",\n \"play-step-backwards\": \"step-backward\",\n \"jump-to-end\": \"skip-to-end\",\n \"fullscreen\": \"enter-fullscreen\",\n \"twizzle-link\": \"twizzle-tw\",\n };\n return map[this.timelineCommand];\n }\n\n private initialHoverTitle(): string {\n const map: Record<TimelineCommand, string> = {\n \"jump-to-start\": \"Restart\",\n \"play-pause\": \"Play\",\n \"play-step\": \"Step forward\",\n \"play-step-backwards\": \"Step backward\",\n \"jump-to-end\": \"Skip to End\",\n \"fullscreen\": \"Enter fullscreen\",\n \"twizzle-link\": \"View at Twizzle\",\n };\n return map[this.timelineCommand];\n }\n\n private setHoverTitle(title: string): void {\n this.button.title = title;\n }\n\n onPress(): void {\n switch (this.timelineCommand) {\n case \"fullscreen\":\n if (document.fullscreenElement === this.fullscreenElement) {\n document.exitFullscreen();\n // this.setIcon(\"enter-fullscreen\");\n } else {\n this.setIcon(\"exit-fullscreen\");\n this.fullscreenElement!.requestFullscreen().then(() => {\n const onFullscreen = (): void => {\n if (document.fullscreenElement !== this.fullscreenElement) {\n this.setIcon(\"enter-fullscreen\");\n window.removeEventListener(\"fullscreenchange\", onFullscreen);\n }\n };\n window.addEventListener(\"fullscreenchange\", onFullscreen);\n });\n }\n break;\n case \"jump-to-start\":\n this.timeline.setTimestamp(0);\n break;\n case \"jump-to-end\":\n this.timeline.jumpToEnd();\n break;\n case \"play-pause\":\n this.timeline.playPause();\n break;\n case \"play-step\":\n this.timeline.experimentalPlay(Direction.Forwards, BoundaryType.Move);\n break;\n case \"play-step-backwards\":\n this.timeline.experimentalPlay(Direction.Backwards, BoundaryType.Move);\n break;\n case \"twizzle-link\":\n if (this.visitTwizzleLinkCallback) {\n this.visitTwizzleLinkCallback();\n }\n break;\n }\n }\n\n onTimelineAction(actionEvent: TimelineActionEvent): void {\n switch (this.timelineCommand) {\n case \"jump-to-start\":\n // TODO: what if you're already playing?\n this.button.disabled =\n actionEvent.locationType === TimestampLocationType.StartOfTimeline &&\n actionEvent.action !== TimelineAction.StartingToPlay;\n break;\n case \"jump-to-end\":\n this.button.disabled =\n actionEvent.locationType === TimestampLocationType.EndOfTimeline &&\n actionEvent.action !== TimelineAction.StartingToPlay;\n break;\n case \"play-pause\":\n // Always enabled, since we will jump to the start if needed.\n switch (actionEvent.action) {\n case TimelineAction.Pausing:\n this.setIcon(\"play\");\n this.setHoverTitle(\"Play\");\n break;\n case TimelineAction.StartingToPlay:\n this.setIcon(\"pause\");\n this.setHoverTitle(\"Pause\");\n break;\n // TODO: does jumping mean pause?\n }\n break;\n case \"play-step\":\n // TODO: refine this\n this.button.disabled =\n actionEvent.locationType === TimestampLocationType.EndOfTimeline &&\n actionEvent.action !== TimelineAction.StartingToPlay;\n break;\n case \"play-step-backwards\":\n // TODO: refine this\n this.button.disabled =\n actionEvent.locationType === TimestampLocationType.StartOfTimeline &&\n actionEvent.action !== TimelineAction.StartingToPlay;\n break;\n }\n }\n\n onTimelineTimestampChange(_timestamp: MillisecondTimestamp): void {\n // Nothing\n }\n\n onTimeRangeChange(_timeRange: TimeRange): void {\n // TODO\n this.autoSetTimelineBasedDisabled();\n }\n}\n\ncustomElementsShim.define(\"twisty-control-button\", TwistyControlButton);\n\n// <twisty-control-button-grid>\n// Usually a horizontal line.\nexport class TwistyControlButtonPanel\n extends ManagedCustomElement\n implements TwistyControlElement\n{\n #viewerLinkClassListManager: ClassListManager<ViewerLinkPage> =\n new ClassListManager(this, \"viewer-link-\", [\"none\", \"twizzle\"]);\n\n constructor(\n timeline?: Timeline,\n options?: {\n fullscreenElement?: Element;\n viewerLinkCallback?: () => void;\n viewerLink?: ViewerLinkPage;\n },\n ) {\n super();\n this.addCSS(buttonGridCSS);\n\n this.#viewerLinkClassListManager.setValue(options?.viewerLink ?? \"none\");\n\n // this.addElement(new TwistyControlButton(timeline!, fullscreenElement!));\n this.addElement(\n new TwistyControlButton(timeline, \"fullscreen\", {\n fullscreenElement: options?.fullscreenElement,\n }),\n );\n this.addElement(new TwistyControlButton(timeline, \"jump-to-start\"));\n this.addElement(new TwistyControlButton(timeline, \"play-step-backwards\"));\n this.addElement(new TwistyControlButton(timeline, \"play-pause\"));\n this.addElement(new TwistyControlButton(timeline, \"play-step\"));\n this.addElement(new TwistyControlButton(timeline, \"jump-to-end\"));\n this.addElement(\n new TwistyControlButton(timeline, \"twizzle-link\", {\n visitTwizzleLinkCallback: options?.viewerLinkCallback,\n }),\n ).classList.add(\"twizzle-link-button\");\n /*...*/\n }\n\n setViewerLink(viewerLink: ViewerLinkPage): void {\n this.#viewerLinkClassListManager.setValue(viewerLink);\n }\n}\n\ncustomElementsShim.define(\n \"twisty-control-button-panel\",\n TwistyControlButtonPanel,\n);\n", "// <twisty-scrubber>\n\nimport type { TimeRange } from \"../../animation/cursor/AlgCursor\";\nimport type { MillisecondTimestamp } from \"../../animation/cursor/CursorTypes\";\nimport type {\n Timeline,\n TimelineTimestampListener,\n} from \"../../animation/Timeline\";\nimport { ManagedCustomElement } from \"../element/ManagedCustomElement\";\nimport { customElementsShim } from \"../element/node-custom-element-shims\";\nimport type { TwistyControlElement } from \"./TwistyControlElement\";\nimport { twistyScrubberCSS } from \"./TwistyScrubber.css\";\n\n// Usually a horizontal line.\nexport class TwistyScrubber\n extends ManagedCustomElement\n implements TwistyControlElement, TimelineTimestampListener\n{\n private timeline: Timeline;\n range: HTMLInputElement = document.createElement(\"input\"); // type=\"range\"\n constructor(timeline?: Timeline) {\n super();\n this.timeline = timeline!; // TODO\n\n this.addCSS(twistyScrubberCSS);\n\n this.timeline?.addTimestampListener(this); // TODO\n this.range.type = \"range\";\n\n this.range.step = (1).toString();\n this.range.min = this.timeline?.minTimestamp().toString(); // TODO\n this.range.max = this.timeline?.maxTimestamp().toString(); // TODO\n this.range.value = this.timeline?.timestamp.toString(); // TODO\n this.range.addEventListener(\"input\", this.onInput.bind(this));\n\n this.addElement(this.range);\n }\n\n onTimelineTimestampChange(timestamp: MillisecondTimestamp): void {\n this.range.value = timestamp.toString();\n }\n\n onTimeRangeChange(timeRange: TimeRange): void {\n this.range.min = timeRange.start.toString();\n this.range.max = timeRange.end.toString();\n }\n\n private onInput(): void {\n this.timeline.setTimestamp(parseInt(this.range.value, 10));\n }\n}\n\ncustomElementsShim.define(\"twisty-scrubber\", TwistyScrubber);\n", "import {\n combineTransformations,\n KPuzzleDefinition,\n KPuzzleSVGWrapper,\n transformationForMove,\n} from \"../../../../kpuzzle\";\nimport type { PuzzleLoader } from \"../../../../puzzles/PuzzleLoader\";\nimport type { PuzzleAppearance } from \"../../../../puzzles/stickerings/appearance\";\nimport type {\n PositionDispatcher,\n PositionListener,\n} from \"../../animation/cursor/AlgCursor\";\nimport { Direction, PuzzlePosition } from \"../../animation/cursor/CursorTypes\";\nimport { RenderScheduler } from \"../../animation/RenderScheduler\";\nimport { ManagedCustomElement } from \"../element/ManagedCustomElement\";\nimport { customElementsShim } from \"../element/node-custom-element-shims\";\nimport type { ExperimentalStickering } from \"../TwistyPlayerConfig\";\nimport { twisty2DSVGCSS } from \"./Twisty2DSVGView.css\";\nimport type { TwistyViewerElement } from \"./TwistyViewerElement\";\n\nexport interface Twisty2DSVGOptions {\n experimentalStickering?: ExperimentalStickering;\n}\n\n// <twisty-2d-svg>\nexport class Twisty2DSVG\n extends ManagedCustomElement\n implements TwistyViewerElement, PositionListener\n{\n private definition: KPuzzleDefinition;\n private svg: KPuzzleSVGWrapper;\n private scheduler = new RenderScheduler(this.render.bind(this));\n #cachedPosition: PuzzlePosition | null = null; // TODO: pull when needed.\n constructor(\n cursor?: PositionDispatcher,\n def?: KPuzzleDefinition,\n private svgSource?: string,\n private options?: Twisty2DSVGOptions,\n private puzzleLoader?: PuzzleLoader,\n ) {\n super();\n this.addCSS(twisty2DSVGCSS);\n\n this.definition = def!;\n this.resetSVG(); // TODO\n cursor?.addPositionListener(this); // TODO\n\n if (this.options?.experimentalStickering) {\n this.experimentalSetStickering(this.options.experimentalStickering);\n }\n }\n\n onPositionChange(position: PuzzlePosition): void {\n if (position.movesInProgress.length > 0) {\n const move = position.movesInProgress[0].move;\n\n const def = this.definition;\n let partialMove = move;\n if (position.movesInProgress[0].direction === Direction.Backwards) {\n partialMove = move.invert();\n }\n const newState = combineTransformations(\n def,\n position.state,\n transformationForMove(def, partialMove),\n );\n // TODO: move to render()\n this.svg.draw(\n this.definition,\n position.state,\n newState,\n position.movesInProgress[0].fraction,\n );\n } else {\n this.svg.draw(this.definition, position.state);\n this.#cachedPosition = position;\n }\n }\n\n scheduleRender(): void {\n this.scheduler.requestAnimFrame();\n }\n\n experimentalSetStickering(stickering: ExperimentalStickering): void {\n (async () => {\n if (!this.puzzleLoader?.appearance) {\n return;\n }\n const appearance = await this.puzzleLoader.appearance(stickering);\n this.resetSVG(appearance);\n })();\n }\n\n // TODO: do this without constructing a new SVG.\n private resetSVG(appearance?: PuzzleAppearance): void {\n if (this.svg) {\n this.removeElement(this.svg.element);\n }\n if (!this.definition) {\n return; // TODO\n }\n this.svg = new KPuzzleSVGWrapper(\n this.definition,\n this.svgSource!,\n appearance,\n ); // TODO\n this.addElement(this.svg.element);\n if (this.#cachedPosition) {\n this.onPositionChange(this.#cachedPosition);\n }\n }\n\n private render(): void {\n /*...*/\n }\n}\n\ncustomElementsShim.define(\"twisty-2d-svg\", Twisty2DSVG);\n", "import { CSSSource } from \"./element/ManagedCustomElement\";\n\nexport const twistyAlgViewerCSS = new CSSSource(`\n:host {\n display: inline-grid;\n}\n\na:not(:hover) {\n color: inherit;\n text-decoration: none;\n}\n\ntwisty-alg-leaf-elem.twisty-alg-comment {\n color: rgba(0, 0, 0, 0.4);\n}\n\n.wrapper.current-move {\n background: rgba(66, 133, 244, 0.3);\n margin-left: -0.1em;\n margin-right: -0.1em;\n padding-left: 0.1em;\n padding-right: 0.1em;\n border-radius: 0.1em;\n}\n`);\n", "import {\n Alg,\n Commutator,\n Conjugate,\n experimentalDirect,\n ExperimentalIterationDirection,\n Grouping,\n LineComment,\n Move,\n Newline,\n Pause,\n TraversalDownUp,\n Unit,\n} from \"../../../alg\";\nimport type { Parsed } from \"../../../alg/parse\";\nimport { puzzles } from \"../../../puzzles\";\nimport { TwistyPlayerV1 } from \"../..\";\nimport { KPuzzleWrapper } from \"../../views/3D/puzzles/KPuzzleWrapper\";\nimport type { TimeRange } from \"../animation/cursor/AlgCursor\";\nimport type { MillisecondTimestamp } from \"../animation/cursor/CursorTypes\";\nimport { TreeAlgIndexer } from \"../animation/indexer/tree/TreeAlgIndexer\";\nimport { ManagedCustomElement } from \"./element/ManagedCustomElement\";\nimport {\n customElementsShim,\n HTMLElementShim,\n} from \"./element/node-custom-element-shims\";\nimport { twistyAlgViewerCSS } from \"./TwistyAlgViewerV1.css\";\n\nconst DEFAULT_OFFSET_MS = 250; // TODO: make this a fraction?\n\nclass DataDown {\n earliestMoveIndex: number;\n twistyAlgViewer: TwistyAlgViewerV1;\n direction: ExperimentalIterationDirection;\n}\n\nclass DataUp {\n moveCount: number;\n element: TwistyAlgWrapperElemV1 | TwistyAlgLeafElemV1;\n}\n\nclass TwistyAlgLeafElemV1 extends ManagedCustomElement {\n constructor(\n className: string,\n text: string,\n dataDown: DataDown,\n public algOrUnit: Alg | Unit,\n offsetIntoMove: boolean,\n clickable: boolean,\n ) {\n super({ mode: \"open\" });\n this.classList.add(className);\n\n this.addCSS(twistyAlgViewerCSS);\n if (clickable) {\n const anchor = this.contentWrapper.appendChild(\n document.createElement(\"a\"),\n );\n anchor.href = \"#\";\n anchor.textContent = text;\n\n anchor.addEventListener(\"click\", (e) => {\n e.preventDefault();\n dataDown.twistyAlgViewer.jumpToIndex(\n dataDown.earliestMoveIndex,\n offsetIntoMove,\n );\n });\n } else {\n this.contentWrapper.appendChild(\n document.createElement(\"span\"),\n ).textContent = text;\n }\n }\n\n pathToIndex(\n _index: number,\n ): (TwistyAlgWrapperElemV1 | TwistyAlgLeafElemV1)[] {\n return [];\n }\n\n setCurrentMove(current: boolean) {\n this.contentWrapper.classList.toggle(\"current-move\", current);\n }\n}\n\ncustomElementsShim.define(\"twisty-alg-leaf-elem-v1\", TwistyAlgLeafElemV1);\n\nclass TwistyAlgWrapperElemV1 extends HTMLElementShim {\n private queue: (Element | Text)[] = [];\n\n constructor(className: string, public algOrUnit: Alg | Unit) {\n super();\n this.classList.add(className);\n }\n\n addString(str: string) {\n this.queue.push(document.createTextNode(str));\n }\n\n addElem(dataUp: DataUp): number {\n this.queue.push(dataUp.element);\n return dataUp.moveCount;\n }\n\n flushQueue(\n direction: ExperimentalIterationDirection = ExperimentalIterationDirection.Forwards,\n ): void {\n for (const node of maybeReverseList(this.queue, direction)) {\n this.append(node);\n }\n this.queue = [];\n }\n\n pathToIndex(\n _index: number,\n ): (TwistyAlgWrapperElemV1 | TwistyAlgLeafElemV1)[] {\n return [];\n }\n}\n\ncustomElementsShim.define(\"twisty-alg-wrapper-elem-v1\", TwistyAlgWrapperElemV1);\n\nfunction oppositeDirection(\n direction: ExperimentalIterationDirection,\n): ExperimentalIterationDirection {\n return direction === ExperimentalIterationDirection.Forwards\n ? ExperimentalIterationDirection.Backwards\n : ExperimentalIterationDirection.Forwards;\n}\n\nfunction updateDirectionByAmount(\n currentDirection: ExperimentalIterationDirection,\n amount: number,\n): ExperimentalIterationDirection {\n return amount < 0 ? oppositeDirection(currentDirection) : currentDirection;\n}\n\nfunction maybeReverseList<T>(\n l: T[],\n direction: ExperimentalIterationDirection,\n): T[] {\n if (direction === ExperimentalIterationDirection.Forwards) {\n return l;\n }\n // console.log(\"rev\", Array.from(l).reverse());\n // return Array.from(l).reverse();\n const copy = Array.from(l);\n copy.reverse();\n return copy;\n}\n\nclass AlgToDOMTree extends TraversalDownUp<DataDown, DataUp, DataUp> {\n public traverseAlg(alg: Alg, dataDown: DataDown): DataUp {\n let moveCount = 0;\n const element = new TwistyAlgWrapperElemV1(\"twisty-alg-alg\", alg); // TODO: pick a better class name.\n let first = true;\n for (const unit of experimentalDirect(alg.units(), dataDown.direction)) {\n if (!first) {\n element.addString(\" \");\n }\n first = false;\n moveCount += element.addElem(\n this.traverseUnit(unit, {\n earliestMoveIndex: dataDown.earliestMoveIndex + moveCount,\n twistyAlgViewer: dataDown.twistyAlgViewer,\n direction: dataDown.direction,\n }),\n );\n }\n element.flushQueue(dataDown.direction);\n return {\n moveCount: moveCount,\n element,\n };\n }\n\n public traverseGrouping(grouping: Grouping, dataDown: DataDown): DataUp {\n const square1Tuple = grouping.experimentalAsSquare1Tuple();\n // if (square1Tuplle) {\n\n // }\n\n const direction = updateDirectionByAmount(\n dataDown.direction,\n grouping.amount,\n );\n let moveCount = 0;\n const element = new TwistyAlgWrapperElemV1(\"twisty-alg-grouping\", grouping);\n element.addString(\"(\");\n\n if (square1Tuple) {\n moveCount += element.addElem({\n moveCount: 1,\n element: new TwistyAlgLeafElemV1(\n \"twisty-alg-move\", // TODO: Mark the tuple with a special class?\n square1Tuple[0].amount.toString(),\n dataDown,\n square1Tuple[0],\n true,\n true,\n ),\n });\n element.addString(\", \");\n moveCount += element.addElem({\n moveCount: 1,\n element: new TwistyAlgLeafElemV1(\n \"twisty-alg-move\", // TODO: Mark the tuple with a special class?\n square1Tuple[1].amount.toString(),\n dataDown,\n square1Tuple[1],\n true,\n true,\n ),\n });\n } else {\n moveCount += element.addElem(\n this.traverseAlg(grouping.alg, {\n earliestMoveIndex: dataDown.earliestMoveIndex + moveCount,\n twistyAlgViewer: dataDown.twistyAlgViewer,\n direction,\n }),\n );\n }\n\n element.addString(\")\" + grouping.experimentalRepetitionSuffix);\n element.flushQueue();\n return {\n moveCount: moveCount * Math.abs(grouping.amount),\n element,\n };\n }\n\n public traverseMove(move: Move, dataDown: DataDown): DataUp {\n const element = new TwistyAlgLeafElemV1(\n \"twisty-alg-move\",\n move.toString(),\n dataDown,\n move,\n true,\n true,\n );\n dataDown.twistyAlgViewer.highlighter.addMove(\n (move as Parsed<Move>).startCharIndex,\n element,\n );\n return {\n moveCount: 1,\n element,\n };\n }\n\n public traverseCommutator(\n commutator: Commutator,\n dataDown: DataDown,\n ): DataUp {\n let moveCount = 0;\n const element = new TwistyAlgWrapperElemV1(\n \"twisty-alg-commutator\",\n commutator,\n );\n element.addString(\"[\");\n element.flushQueue();\n const [first, second]: Alg[] = maybeReverseList(\n [commutator.A, commutator.B],\n dataDown.direction,\n );\n moveCount += element.addElem(\n this.traverseAlg(first, {\n earliestMoveIndex: dataDown.earliestMoveIndex + moveCount,\n twistyAlgViewer: dataDown.twistyAlgViewer,\n direction: dataDown.direction,\n }),\n );\n element.addString(\", \");\n moveCount += element.addElem(\n this.traverseAlg(second, {\n earliestMoveIndex: dataDown.earliestMoveIndex + moveCount,\n twistyAlgViewer: dataDown.twistyAlgViewer,\n direction: dataDown.direction,\n }),\n );\n element.flushQueue(dataDown.direction);\n element.addString(\"]\");\n element.flushQueue();\n return {\n moveCount: moveCount * 2,\n element,\n };\n }\n\n public traverseConjugate(conjugate: Conjugate, dataDown: DataDown): DataUp {\n let moveCount = 0;\n const element = new TwistyAlgWrapperElemV1(\n \"twisty-alg-conjugate\",\n conjugate,\n );\n element.addString(\"[\");\n const aLen = element.addElem(\n this.traverseAlg(conjugate.A, {\n earliestMoveIndex: dataDown.earliestMoveIndex + moveCount,\n twistyAlgViewer: dataDown.twistyAlgViewer,\n direction: dataDown.direction,\n }),\n );\n moveCount += aLen;\n element.addString(\": \");\n moveCount += element.addElem(\n this.traverseAlg(conjugate.B, {\n earliestMoveIndex: dataDown.earliestMoveIndex + moveCount,\n twistyAlgViewer: dataDown.twistyAlgViewer,\n direction: dataDown.direction,\n }),\n );\n element.addString(\"]\");\n element.flushQueue();\n return {\n moveCount: moveCount + aLen,\n element,\n };\n }\n\n public traversePause(pause: Pause, dataDown: DataDown): DataUp {\n return {\n moveCount: 1,\n element: new TwistyAlgLeafElemV1(\n \"twisty-alg-pause\",\n \".\",\n dataDown,\n pause,\n true,\n true,\n ),\n };\n }\n\n public traverseNewline(newline: Newline, _dataDown: DataDown): DataUp {\n const element = new TwistyAlgWrapperElemV1(\"twisty-alg-newline\", newline);\n element.append(document.createElement(\"br\"));\n return {\n moveCount: 0,\n element,\n };\n }\n\n public traverseLineComment(\n lineComment: LineComment,\n dataDown: DataDown,\n ): DataUp {\n return {\n moveCount: 0,\n element: new TwistyAlgLeafElemV1(\n \"twisty-alg-line-comment\",\n `//${lineComment.text}`,\n dataDown,\n lineComment,\n false,\n false,\n ),\n };\n }\n}\n\nconst algToDOMTreeInstance = new AlgToDOMTree();\nconst algToDOMTree = algToDOMTreeInstance.traverseAlg.bind(\n algToDOMTreeInstance,\n) as (alg: Alg, dataDown: DataDown) => DataUp;\n\nclass MoveHighlighter {\n moveCharIndexMap: Map<number, TwistyAlgLeafElemV1> = new Map();\n currentElem: TwistyAlgLeafElemV1 | null = null;\n\n addMove(charIndex: number, elem: TwistyAlgLeafElemV1): void {\n this.moveCharIndexMap.set(charIndex, elem);\n }\n\n set(move: Parsed<Move> | null): void {\n const newElem = move\n ? this.moveCharIndexMap.get(move.startCharIndex) ?? null\n : null;\n if (this.currentElem === newElem) {\n return;\n }\n this.currentElem?.classList.remove(\"twisty-alg-current-move\");\n this.currentElem?.setCurrentMove(false);\n newElem?.classList.add(\"twisty-alg-current-move\");\n newElem?.setCurrentMove(true);\n this.currentElem = newElem;\n }\n}\n\nexport class TwistyAlgViewerV1 extends HTMLElementShim {\n highlighter: MoveHighlighter = new MoveHighlighter();\n #domTree: TwistyAlgWrapperElemV1 | TwistyAlgLeafElemV1;\n twistyPlayer: TwistyPlayerV1 | null = null;\n lastClickTimestamp: number | null = null;\n constructor(options?: { twistyPlayer?: TwistyPlayerV1 }) {\n super();\n if (options?.twistyPlayer) {\n this.setTwistyPlayer(options?.twistyPlayer);\n }\n }\n\n protected connectedCallback(): void {\n // nothing to do?\n }\n\n private setAlg(alg: Alg): void {\n this.#domTree = algToDOMTree(alg, {\n earliestMoveIndex: 0,\n twistyAlgViewer: this,\n direction: ExperimentalIterationDirection.Forwards,\n }).element;\n this.textContent = \"\";\n this.appendChild(this.#domTree);\n }\n\n setTwistyPlayer(twistyPlayer: TwistyPlayerV1): void {\n if (this.twistyPlayer) {\n console.warn(\"twisty-player reassignment is not supported\");\n return;\n }\n this.twistyPlayer = twistyPlayer;\n\n this.twistyPlayer.addEventListener(\n \"experimental-alg-update\",\n (e: CustomEvent<{ alg: Alg }>) => {\n this.setAlg(e.detail.alg);\n },\n );\n\n const sourceAlg = this.twistyPlayer.alg;\n // TODO: Use proper architecture instead of a heuristic to ensure we have a parsed alg annotated with char indices.\n const parsedAlg =\n \"charIndex\" in (sourceAlg as Partial<Parsed<Alg>>)\n ? sourceAlg\n : Alg.fromString(sourceAlg.toString());\n this.setAlg(parsedAlg);\n (async () => {\n const wrapper = new KPuzzleWrapper(\n await puzzles[twistyPlayer.puzzle].def(),\n );\n const indexer = new TreeAlgIndexer(wrapper, parsedAlg);\n twistyPlayer.timeline.addTimestampListener({\n onTimelineTimestampChange: (timestamp: MillisecondTimestamp): void => {\n // TODO: improve perf, e.g. only get notified when the move index changes.\n this.highlighter.set(\n indexer.getAnimLeaf(\n indexer.timestampToIndex(timestamp),\n ) as Parsed<Move> | null,\n );\n },\n onTimeRangeChange(_timeRange: TimeRange): void {},\n });\n })();\n twistyPlayer.timeline.addTimestampListener({\n onTimelineTimestampChange: (timestamp: MillisecondTimestamp) => {\n if (timestamp !== this.lastClickTimestamp) {\n this.lastClickTimestamp = null;\n }\n const index =\n this.twistyPlayer?.cursor?.experimentalIndexFromTimestamp(\n timestamp,\n ) ?? null;\n if (index !== null) {\n // console.log(index);\n // console.log(this.#domTree.pathToIndex(index));\n }\n },\n onTimeRangeChange: (_timeRange: TimeRange) => {\n // TODO\n },\n });\n }\n\n jumpToIndex(index: number, offsetIntoMove: boolean): void {\n if (this.twistyPlayer && this.twistyPlayer.cursor) {\n const offset = offsetIntoMove ? DEFAULT_OFFSET_MS : 0;\n const timestamp =\n (this.twistyPlayer.cursor.experimentalTimestampFromIndex(index) ??\n -offset) + offset;\n this.twistyPlayer?.timeline.setTimestamp(timestamp);\n if (this.lastClickTimestamp === timestamp) {\n this.twistyPlayer.timeline.play();\n this.lastClickTimestamp = null;\n } else {\n this.lastClickTimestamp = timestamp;\n }\n }\n }\n\n protected attributeChangedCallback(\n attributeName: string,\n _oldValue: string,\n newValue: string,\n ): void {\n if (attributeName === \"for\") {\n const elem = document.getElementById(newValue);\n if (!elem) {\n console.warn(\"for= elem does not exist\");\n return;\n }\n if (!(elem instanceof TwistyPlayerV1)) {\n console.warn(\"for= elem is not a twisty-player\");\n return;\n }\n this.setTwistyPlayer(elem);\n }\n }\n\n static get observedAttributes(): string[] {\n return [\"for\"];\n }\n}\n\ncustomElementsShim.define(\"twisty-alg-viewer-v1\", TwistyAlgViewerV1);\n"],
5
- "mappings": "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",
3
+ "sources": ["../../../src/cubing/twisty/controllers/AnimationTypes.ts", "../../../src/cubing/twisty/controllers/RenderScheduler.ts", "../../../src/cubing/twisty/model/helpers.ts", "../../../src/cubing/twisty/controllers/TwistyAnimationController.ts", "../../../src/cubing/twisty/controllers/TwistyPlayerController.ts", "../../../src/cubing/twisty/model/props/viewer/ControlPanelProp.ts", "../../../src/cubing/twisty/views/ClassListManager.ts", "../../../src/cubing/twisty/views/node-custom-element-shims.ts", "../../../src/cubing/twisty/views/ManagedCustomElement.ts", "../../../src/cubing/twisty/views/TwistyPlayer.css.ts", "../../../src/cubing/twisty/heavy-code-imports/3d.ts", "../../../src/cubing/twisty/views/TwistyViewerWrapper.css.ts", "../../../src/cubing/twisty/views/2D/Twisty2DPuzzle.css.ts", "../../../src/cubing/twisty/views/2D/Twisty2DPuzzle.ts", "../../../src/cubing/twisty/views/2D/Twisty2DPuzzleWrapper.ts", "../../../src/cubing/twisty/views/2D/Twisty2DSceneWrapper.ts", "../../../src/cubing/twisty/views/3D/Twisty3DSceneWrapper.ts", "../../../src/cubing/twisty/views/3D/Twisty3DPuzzleWrapper.ts", "../../../src/cubing/vendor/three/examples/jsm/libs/stats.modified.module.ts", "../../../src/cubing/twisty/views/canvas.ts", "../../../src/cubing/twisty/views/3D/Twisty3DVantage.css.ts", "../../../src/cubing/twisty/views/3D/DragTracker.ts", "../../../src/cubing/twisty/views/3D/RendererPool.ts", "../../../src/cubing/twisty/views/3D/TwistyOrbitControls.ts", "../../../src/cubing/twisty/views/3D/Twisty3DVantage.ts", "../../../src/cubing/twisty/views/control-panel/TwistyButtonsV2.css.ts", "../../../src/cubing/twisty/views/document.ts", "../../../src/cubing/twisty/views/control-panel/webkit-fullscreen.ts", "../../../src/cubing/twisty/model/props/viewer/ButtonAppearanceProp.ts", "../../../src/cubing/twisty/views/control-panel/TwistyButtonsV2.ts", "../../../src/cubing/twisty/views/control-panel/TwistyScrubber.css.ts", "../../../src/cubing/twisty/views/control-panel/TwistyScrubberV2.ts", "../../../src/cubing/twisty/views/screenshot.ts", "../../../src/cubing/twisty/model/props/puzzle/state/AlgProp.ts", "../../../src/cubing/twisty/model/props/viewer/BackgroundProp.ts", "../../../src/cubing/twisty/model/props/viewer/BackViewProp.ts", "../../../src/cubing/twisty/model/props/puzzle/state/IndexerConstructorRequestProp.ts", "../../../src/cubing/twisty/model/props/viewer/LatitudeLimit.ts", "../../../src/cubing/twisty/model/props/viewer/OrbitCoordinatesRequestProp.ts", "../../../src/cubing/twisty/model/props/timeline/PlayingInfoProp.ts", "../../../src/cubing/twisty/model/props/puzzle/structure/PuzzleDescriptionProp.ts", "../../../src/cubing/twisty/model/props/puzzle/structure/PuzzleIDRequestProp.ts", "../../../src/cubing/twisty/model/props/puzzle/structure/PuzzleLoaderProp.ts", "../../../src/cubing/twisty/model/props/puzzle/state/SetupAnchorProp.ts", "../../../src/cubing/twisty/model/props/timeline/TempoScaleProp.ts", "../../../src/cubing/twisty/model/props/timeline/TimestampRequestProp.ts", "../../../src/cubing/twisty/model/props/general/URLProp.ts", "../../../src/cubing/twisty/model/props/viewer/ViewerLinkProp.ts", "../../../src/cubing/twisty/model/props/viewer/VisualizationProp.ts", "../../../src/cubing/twisty/model/props/viewer/OrbitCoordinatesProp.ts", "../../../src/cubing/twisty/model/props/puzzle/structure/PuzzleIDProp.ts", "../../../src/cubing/twisty/model/props/puzzle/display/SpriteProp.ts", "../../../src/cubing/twisty/model/props/viewer/VisualizationStrategyProp.ts", "../../../src/cubing/twisty/controllers/indexer/AlgDuration.ts", "../../../src/cubing/twisty/controllers/indexer/SimpleAlgIndexer.ts", "../../../src/cubing/twisty/controllers/indexer/simultaneous-moves/simul-moves.ts", "../../../src/cubing/twisty/controllers/indexer/simultaneous-moves/SimultaneousMoveIndexerV2.ts", "../../../src/cubing/twisty/controllers/indexer/tree/chunkAlgs.ts", "../../../src/cubing/twisty/controllers/indexer/tree/AlgWalker.ts", "../../../src/cubing/twisty/controllers/indexer/tree/TreeAlgIndexer.ts", "../../../src/cubing/twisty/model/props/puzzle/state/IndexerConstructorProp.ts", "../../../src/cubing/twisty/model/props/puzzle/state/PuzzleAlgProp.ts", "../../../src/cubing/twisty/views/3D/puzzles/KPuzzleWrapper.ts", "../../../src/cubing/twisty/model/props/puzzle/state/AlgTransformationProp.ts", "../../../src/cubing/twisty/model/props/puzzle/state/IndexerProp.ts", "../../../src/cubing/twisty/model/props/puzzle/state/AnchoredStartProp.ts", "../../../src/cubing/twisty/model/props/viewer/TimeRangeProp.ts", "../../../src/cubing/twisty/model/props/timeline/DetailedTimelineInfoProp.ts", "../../../src/cubing/twisty/model/props/timeline/CoarseTimelineInfoProp.ts", "../../../src/cubing/twisty/model/props/puzzle/state/CurrentLeavesProp.ts", "../../../src/cubing/twisty/model/props/puzzle/state/CurrentLeavesSimplified.ts", "../../../src/cubing/twisty/model/props/puzzle/state/CurrentTransformationProp.ts", "../../../src/cubing/twisty/model/props/puzzle/state/LegacyPositionProp.ts", "../../../src/cubing/twisty/model/props/puzzle/structure/PuzzleDefProp.ts", "../../../src/cubing/twisty/model/UserVisibleErrorTracker.ts", "../../../src/cubing/twisty/model/props/puzzle/state/CatchUpMoveProp.ts", "../../../src/cubing/twisty/model/props/puzzle/state/NaiveMoveCountProp.ts", "../../../src/cubing/twisty/model/props/puzzle/state/MovePressInputProp.ts", "../../../src/cubing/twisty/model/props/puzzle/display/FoundationDisplayProp.ts", "../../../src/cubing/twisty/model/TwistyPlayerModel.ts", "../../../src/cubing/twisty/views/TwistyPlayerSettable.ts", "../../../src/cubing/twisty/views/TwistyPlayer.ts", "../../../src/cubing/twisty/views/TwistyAlgViewer.css.ts", "../../../src/cubing/twisty/views/TwistyAlgViewer.ts", "../../../src/cubing/twisty/views/TwistyAlgEditor/LeafTokens.ts", "../../../src/cubing/twisty/views/TwistyAlgEditor/model.ts", "../../../src/cubing/twisty/views/TwistyAlgEditor/TwistyAlgEditor.css.ts", "../../../src/cubing/twisty/views/TwistyAlgEditor/TwistyAlgEditor.ts"],
4
+ "sourcesContent": ["import type { Move } from \"../../alg\";\nimport type { Transformation as KPuzzleState } from \"../../kpuzzle\";\n\nexport type MillisecondTimestamp = number;\n\n// TODO: unify duration/timstamp types\nexport type Duration = MillisecondTimestamp; // Duration in milliseconds\n// TODO: Extend `number`, introduce MoveSequenceTimestamp vs. EpochTimestamp,\n// force Duration to be a difference.\nexport type Timestamp = MillisecondTimestamp; // Duration since a particular epoch.\n\nexport type Fraction = number; // Value from 0 to 1.\n\n// 1, 0, -1 are used as scalars for `directionScalar` below.\nexport enum Direction {\n Forwards = 1,\n Paused = 0,\n Backwards = -1,\n}\n\nexport function directionScalar(direction: Direction): MillisecondTimestamp {\n return direction;\n}\n\nexport interface MoveInProgress {\n move: Move;\n direction: Direction;\n fraction: number;\n}\n\nexport type PuzzlePosition = {\n state: KPuzzleState;\n movesInProgress: MoveInProgress[];\n};\n\nexport enum BoundaryType {\n Move = \"move\",\n EntireTimeline = \"entire-timeline\",\n}\n\nexport interface TimeRange {\n start: MillisecondTimestamp;\n end: MillisecondTimestamp;\n}\n\n// export type DurationForAmount = (amount: number) => Duration;\n\nexport interface PositionListener {\n onPositionChange(position: PuzzlePosition): void;\n}\n", "// Debounces `requestAnimationFrame()`.\nexport class RenderScheduler {\n private animFrameID: number | null = null;\n private animFrame = this.animFrameWrapper.bind(this);\n constructor(private callback: (timestamp: DOMHighResTimeStamp) => void) {}\n requestAnimFrame(): void {\n if (!this.animFrameID) {\n this.animFrameID = requestAnimationFrame(this.animFrame);\n }\n }\n\n cancelAnimFrame(): void {\n if (this.animFrameID) {\n cancelAnimationFrame(this.animFrameID);\n this.animFrameID = 0;\n }\n }\n\n private animFrameWrapper(timestamp: DOMHighResTimeStamp): void {\n this.animFrameID = 0;\n this.callback(timestamp);\n }\n}\n\n// An interface for classes to use to expose their scheduling.\nexport interface Schedulable {\n scheduleRender(): void;\n}\n", "export function arrayEquals<T>(a: readonly T[], b: readonly T[]): boolean {\n if (a === b) {\n return true;\n }\n if (a.length !== b.length) {\n return false;\n }\n for (let i = 0; i < a.length; i++) {\n if (a[i] !== b[i]) {\n return false;\n }\n }\n return true;\n}\n\nexport function arrayEqualsCompare<T>(\n a: readonly T[],\n b: readonly T[],\n compare: (a: T, b: T) => boolean,\n): boolean {\n if (a === b) {\n return true;\n }\n if (a.length !== b.length) {\n return false;\n }\n for (let i = 0; i < a.length; i++) {\n if (!compare(a[i], b[i])) {\n return false;\n }\n }\n return true;\n}\n\n// Assumes `offset > 0`. Will produce invalid values if not!\n// We don't check for that, since this can be a hot path.\nexport function mod(v: number, m: number, offset = 0): number {\n return (((v % m) + m + offset) % m) - offset;\n}\n\nexport function modIntoRange(\n v: number,\n rangeMin: number,\n rangeMax: number,\n): number {\n return mod(v - rangeMin, rangeMax - rangeMin) + rangeMin;\n}\n", "import {\n BoundaryType,\n Direction,\n directionScalar,\n MillisecondTimestamp,\n TimeRange,\n} from \"./AnimationTypes\";\nimport { RenderScheduler } from \"./RenderScheduler\";\nimport type {\n PlayingInfo,\n SimpleDirection,\n} from \"../model/props/timeline/PlayingInfoProp\";\nimport type { TwistyPlayerModel } from \"../model/TwistyPlayerModel\";\nimport { StaleDropper } from \"../model/PromiseFreshener\";\nimport type { CurrentMoveInfo } from \"./indexer/AlgIndexer\";\nimport type { TimestampRequest } from \"../model/props/timeline/TimestampRequestProp\";\nimport { modIntoRange } from \"../model/helpers\";\nimport type { CatchUpMove } from \"../model/props/puzzle/state/CatchUpMoveProp\";\n\n// TODO: Figure out a better way for the controller to instruct the player.\nexport interface TwistyAnimationControllerDelegate {\n flash(): void;\n}\n\n// We use a separate helper to separate the anim frame callbacks (and their cancellations).\n// TODO: fold this into the main controller\nclass CatchUpHelper {\n catchingUp: boolean = false;\n pendingFrame = false;\n\n constructor(private model: TwistyPlayerModel) {}\n\n private scheduler: RenderScheduler = new RenderScheduler(\n this.animFrame.bind(this),\n );\n\n start(): void {\n if (!this.catchingUp) {\n this.lastTimestamp = performance.now();\n }\n this.catchingUp = true;\n this.pendingFrame = true;\n this.scheduler.requestAnimFrame();\n }\n\n stop(): void {\n this.catchingUp = false;\n this.scheduler.cancelAnimFrame();\n }\n\n catchUpMs = 500;\n lastTimestamp = 0;\n animFrame(timestamp: MillisecondTimestamp): void {\n this.scheduler.requestAnimFrame();\n const delta = (timestamp - this.lastTimestamp) / this.catchUpMs;\n this.lastTimestamp = timestamp;\n\n this.model.catchUpMoveProp.set(\n (async () => {\n const previousCatchUpMove = await this.model.catchUpMoveProp.get();\n if (previousCatchUpMove.move === null) {\n return previousCatchUpMove;\n }\n\n const amount = previousCatchUpMove.amount + delta; // TODO: use tempo scale?\n if (amount >= 1) {\n this.pendingFrame = true;\n this.stop();\n this.model.timestampRequestProp.set(\"end\");\n return {\n move: null,\n amount: 0,\n };\n }\n this.pendingFrame = false;\n return {\n move: previousCatchUpMove.move,\n amount: amount,\n };\n })(),\n );\n }\n}\n\n// This controls the logic for animation, so that the main controller can focus on the right API abstractions.\nexport class TwistyAnimationController {\n // TODO: #private?\n private playing: boolean = false;\n private direction: Direction = Direction.Forwards;\n\n private catchUpHelper: CatchUpHelper;\n\n private model: TwistyPlayerModel;\n\n private lastDatestamp: MillisecondTimestamp = 0;\n private lastTimestampPromise: Promise<MillisecondTimestamp>;\n\n private scheduler: RenderScheduler = new RenderScheduler(\n this.animFrame.bind(this),\n );\n\n constructor(\n model: TwistyPlayerModel,\n private delegate: TwistyAnimationControllerDelegate,\n ) {\n this.model = model;\n this.lastTimestampPromise = this.#effectiveTimestampMilliseconds();\n\n this.model.playingInfoProp.addFreshListener(this.onPlayingProp.bind(this)); // TODO\n\n this.catchUpHelper = new CatchUpHelper(this.model);\n this.model.catchUpMoveProp.addFreshListener(\n this.onCatchUpMoveProp.bind(this),\n ); // TODO\n }\n\n // TODO: Do we need this?\n async onPlayingProp(playingInfo: PlayingInfo): Promise<void> {\n if (playingInfo.playing !== this.playing) {\n playingInfo.playing ? this.play(playingInfo) : this.pause();\n }\n }\n\n // TODO: Do we need this?\n async onCatchUpMoveProp(catchUpMove: CatchUpMove): Promise<void> {\n const catchingUp = catchUpMove.move !== null;\n if (catchingUp !== this.catchUpHelper.catchingUp) {\n catchingUp ? this.catchUpHelper.start() : this.catchUpHelper.stop();\n }\n this.scheduler.requestAnimFrame();\n }\n\n async #effectiveTimestampMilliseconds(): Promise<MillisecondTimestamp> {\n return (await this.model.detailedTimelineInfoProp.get()).timestamp;\n }\n\n // TODO: Return the animation we've switched to.\n jumpToStart(options?: { flash: boolean }): void {\n this.model.timestampRequestProp.set(\"start\");\n this.pause();\n if (options?.flash) {\n this.delegate.flash();\n }\n }\n\n // TODO: Return the animation we've switched to.\n jumpToEnd(options?: { flash: boolean }): void {\n this.model.timestampRequestProp.set(\"end\");\n this.pause();\n if (options?.flash) {\n this.delegate.flash();\n }\n }\n\n // TODO: Return the playing info we've switched to.\n playPause(): void {\n if (this.playing) {\n this.pause();\n } else {\n this.play(); // TODO: Resume direction and looping behaviour?\n }\n }\n\n // TODO: bundle playing direction, and boundary into `toggle`.\n async play(options?: {\n direction?: SimpleDirection;\n untilBoundary?: BoundaryType;\n autoSkipToOtherEndIfStartingAtBoundary?: boolean; // TODO What's a good short name that doesn't imply a more general looping concept?\n loop?: boolean;\n }): Promise<void> {\n // TODO: We might need to cache all playing info?\n // Or maybe we don't have to worry about short-circuiting, since this is idempotent?\n // if (this.playing) {\n // return;\n // }\n\n const direction = options?.direction ?? Direction.Forwards;\n\n const coarseTimelineInfo = await this.model.coarseTimelineInfoProp.get(); // TODO: Why do we need to read this if we don't use it?\n if (options?.autoSkipToOtherEndIfStartingAtBoundary ?? true) {\n if (direction === Direction.Forwards && coarseTimelineInfo.atEnd) {\n this.model.timestampRequestProp.set(\"start\");\n this.delegate.flash();\n }\n if (direction === Direction.Backwards && coarseTimelineInfo.atStart) {\n this.model.timestampRequestProp.set(\"end\");\n this.delegate.flash();\n }\n }\n this.model.playingInfoProp.set({\n playing: true,\n direction,\n untilBoundary: options?.untilBoundary ?? BoundaryType.EntireTimeline,\n loop: options?.loop ?? false,\n });\n\n this.playing = true;\n this.lastDatestamp = performance.now(); // TODO: Take from event.\n this.lastTimestampPromise = this.#effectiveTimestampMilliseconds();\n\n // TODO: Save timestamp from model?\n this.scheduler.requestAnimFrame();\n }\n\n pause(): void {\n this.playing = false;\n this.scheduler.cancelAnimFrame();\n this.model.playingInfoProp.set({\n playing: false,\n untilBoundary: BoundaryType.EntireTimeline,\n });\n }\n\n #animFrameEffectiveTimestampStaleDropper: StaleDropper<\n [PlayingInfo, MillisecondTimestamp, TimeRange, number, CurrentMoveInfo]\n > = new StaleDropper<\n [PlayingInfo, MillisecondTimestamp, TimeRange, number, CurrentMoveInfo]\n >();\n\n async animFrame(frameDatestamp: MillisecondTimestamp): Promise<void> {\n if (this.playing) {\n this.scheduler.requestAnimFrame();\n }\n\n const lastDatestamp = this.lastDatestamp;\n const freshenerResult =\n await this.#animFrameEffectiveTimestampStaleDropper.queue(\n Promise.all([\n this.model.playingInfoProp.get(),\n this.lastTimestampPromise,\n this.model.timeRangeProp.get(),\n this.model.tempoScaleProp.get(),\n this.model.currentLeavesProp.get(),\n ]),\n );\n\n const [playingInfo, lastTimestamp, timeRange, tempoScale, currentMoveInfo] =\n freshenerResult;\n\n // TODO: Get this without wasting time on the others?\n if (!playingInfo.playing) {\n this.playing = false;\n // TODO: Ideally we'd cancel the anim frame from the top of this method.\n // But `this.scheduler.cancelAnimFrame();` might accidentally cancel a\n // legit freshly scheduled frame. We should modify `RenderScheduler` to\n // either have individually cancellable requests, or to have something\n // like a \"default\" anim frame re-request that can be canceled separately.\n //\n // Note that we can't wait until here to call\n // `this.scheduler.requestAnimFrame();`, because that would slow down the\n // frame rate.\n return;\n }\n\n let end = currentMoveInfo.earliestEnd; // timeRange.end\n if (\n currentMoveInfo.currentMoves.length === 0 ||\n playingInfo.untilBoundary === BoundaryType.EntireTimeline\n ) {\n end = timeRange.end;\n }\n\n let start = currentMoveInfo.latestStart; // timeRange.end\n if (\n currentMoveInfo.currentMoves.length === 0 ||\n playingInfo.untilBoundary === BoundaryType.EntireTimeline\n ) {\n start = timeRange.start;\n }\n // const start = currentMoveInfo.latestStart; // timeRange.start // TODO\n\n let delta =\n (frameDatestamp - lastDatestamp) *\n directionScalar(this.direction) *\n tempoScale;\n delta = Math.max(delta, 1); // TODO: This guards against the timestamp going in the wrong direction by accident. Can we avoid it?\n delta *= playingInfo.direction;\n let newTimestamp = lastTimestamp + delta; // TODO: Pre-emptively clamp.\n let newSmartTimestampRequest: Exclude<TimestampRequest, number> | null =\n null;\n\n if (newTimestamp >= end) {\n if (playingInfo.loop) {\n newTimestamp = modIntoRange(\n newTimestamp,\n timeRange.start,\n timeRange.end,\n );\n } else {\n if (newTimestamp === timeRange.end) {\n newSmartTimestampRequest = \"end\";\n } else {\n newTimestamp = end;\n }\n this.playing = false;\n this.model.playingInfoProp.set({\n playing: false,\n });\n }\n } else if (newTimestamp <= start) {\n if (playingInfo.loop) {\n newTimestamp = modIntoRange(\n newTimestamp,\n timeRange.start,\n timeRange.end,\n );\n } else {\n if (newTimestamp === timeRange.start) {\n newSmartTimestampRequest = \"start\";\n } else {\n newTimestamp = start;\n }\n this.playing = false;\n this.model.playingInfoProp.set({\n playing: false,\n });\n }\n }\n this.lastDatestamp = frameDatestamp;\n this.lastTimestampPromise = Promise.resolve(newTimestamp); // TODO: Save this earlier? / Do we need to worry about the effecitve timestamp disagreeing?\n this.model.timestampRequestProp.set(\n newSmartTimestampRequest ?? newTimestamp,\n );\n }\n}\n", "import type { TwistyPlayerModel } from \"../model/TwistyPlayerModel\";\nimport {\n TwistyAnimationController,\n TwistyAnimationControllerDelegate,\n} from \"./TwistyAnimationController\";\n\nexport class TwistyPlayerController {\n animationController: TwistyAnimationController;\n\n constructor(\n private model: TwistyPlayerModel,\n delegate: TwistyAnimationControllerDelegate,\n ) {\n this.animationController = new TwistyAnimationController(model, delegate);\n }\n\n jumpToStart(options?: { flash: boolean }): void {\n this.animationController.jumpToStart(options);\n }\n\n jumpToEnd(options?: { flash: boolean }): void {\n this.animationController.jumpToEnd(options);\n }\n\n togglePlay(play?: boolean) {\n if (typeof play === \"undefined\") {\n this.animationController.playPause();\n }\n play ? this.animationController.play() : this.animationController.pause();\n }\n\n public async visitTwizzleLink(): Promise<void> {\n const a = document.createElement(\"a\");\n a.href = await this.model.twizzleLink();\n a.target = \"_blank\";\n a.click();\n }\n}\n", "import { SimpleTwistyPropSource } from \"../TwistyProp\";\n\nexport const controlsLocations = {\n \"bottom-row\": true, // default\n \"none\": true,\n};\nexport type ControlsLocation = keyof typeof controlsLocations;\nexport type ControlPanelThemeWithAuto = ControlsLocation | \"auto\";\n\nexport class ControlPanelProp extends SimpleTwistyPropSource<ControlPanelThemeWithAuto> {\n getDefaultValue(): ControlPanelThemeWithAuto {\n return \"auto\";\n }\n}\n", "import type { ManagedCustomElement } from \"./ManagedCustomElement\";\n\nexport class ClassListManager<SuffixType extends string> {\n #currentClassName: string | null = null;\n // The prefix should ideally end in a dash.\n constructor(\n private elem: ManagedCustomElement,\n private prefix: string,\n private validSuffixes: SuffixType[],\n ) {}\n\n // Does nothing if there was no value.\n clearValue(): void {\n if (this.#currentClassName) {\n this.elem.contentWrapper.classList.remove(this.#currentClassName);\n }\n this.#currentClassName = null; // TODO: add test for this behaviour.\n }\n\n // Returns if the value changed\n setValue(suffix: SuffixType): boolean {\n if (!this.validSuffixes.includes(suffix)) {\n throw new Error(`Invalid suffix: ${suffix}`);\n }\n const newClassName = `${this.prefix}${suffix}`;\n const changed = this.#currentClassName !== newClassName;\n if (changed) {\n this.clearValue();\n this.elem.contentWrapper.classList.add(newClassName);\n this.#currentClassName = newClassName;\n }\n return changed;\n }\n}\n", "// Workarounds for `node`.\n// TODO: figure out how to remove this.\n\n// This stub does not need to be callable, just constructable to satisfy the `node` loader.\nclass HTMLElementStub {}\n\nlet HTMLElementShim: typeof HTMLElement;\nif (globalThis.HTMLElement) {\n HTMLElementShim = HTMLElement;\n} else {\n HTMLElementShim = HTMLElementStub as any;\n}\n\nexport { HTMLElementShim };\n\nclass CustomElementsStub {\n define(): void {\n // nothing\n }\n}\n\nlet customElementsShim: typeof customElements;\n\nif (globalThis.customElements) {\n customElementsShim = customElements;\n} else {\n customElementsShim = new CustomElementsStub() as any;\n}\n\nexport { customElementsShim };\n", "import {\n HTMLElementShim,\n customElementsShim,\n} from \"./node-custom-element-shims\";\n\nexport class CSSSource {\n constructor(private sourceText: string) {\n // TODO: Replace with adopted style sheets some day if we can.\n // const blob = new Blob([sourceText], {\n // type: \"text/utf8\",\n // });\n // this.url = URL.createObjectURL(blob);\n }\n\n getAsString(): string {\n return this.sourceText;\n }\n}\n\n// - Wrapped element\n// - Shadow root\n// - Content wrapper\nexport class ManagedCustomElement extends HTMLElementShim {\n public readonly shadow: ShadowRoot; // TODO: hide this\n public readonly contentWrapper: HTMLDivElement; // TODO: can we get rid of this wrapper?\n\n #cssSourceMap: Map<CSSSource, HTMLStyleElement> = new Map();\n constructor(options?: { mode: \"open\" | \"closed\" }) {\n super();\n this.shadow = this.attachShadow({ mode: options?.mode ?? \"closed\" });\n\n this.contentWrapper = document.createElement(\"div\");\n this.contentWrapper.classList.add(\"wrapper\");\n this.shadow.appendChild(this.contentWrapper);\n }\n\n // Add the source, if not already added.\n public addCSS(cssSource: CSSSource): void {\n if (this.#cssSourceMap.get(cssSource)) {\n return;\n }\n\n const cssElem: HTMLStyleElement = document.createElement(\"style\");\n cssElem.textContent = cssSource.getAsString();\n\n this.#cssSourceMap.set(cssSource, cssElem);\n this.shadow.appendChild(cssElem);\n }\n\n // Remove the source, if it's currently added.\n public removeCSS(cssSource: CSSSource): void {\n const cssElem = this.#cssSourceMap.get(cssSource);\n if (!cssElem) {\n return;\n }\n this.shadow.removeChild(cssElem);\n this.#cssSourceMap.delete(cssSource);\n }\n\n public addElement<T extends Node>(element: T): T {\n return this.contentWrapper.appendChild(element);\n }\n\n public prependElement<T extends Node>(element: T): void {\n this.contentWrapper.prepend(element);\n }\n\n public removeElement<T extends Node>(element: T): T {\n return this.contentWrapper.removeChild(element);\n }\n}\n\ncustomElementsShim.define(\n \"twisty-managed-custom-element\",\n ManagedCustomElement,\n);\n", "import { CSSSource } from \"./ManagedCustomElement\";\n\n// TODO: figure out why `:host(twisty-player):fullscreen { background-color: white }` doesn't work.\nexport const twistyPlayerCSS = new CSSSource(`\n:host {\n width: 384px;\n height: 256px;\n display: grid;\n\n -webkit-user-select: none;\n user-select: none;\n}\n\n.wrapper {\n display: grid;\n overflow: hidden;\n grid-template-rows: 7fr 1em 1fr;\n}\n\n.wrapper > * {\n width: inherit;\n height: inherit;\n overflow: hidden;\n}\n\n.wrapper.controls-none {\n grid-template-rows: 7fr;\n}\n\n.wrapper.controls-none twisty-scrubber,\n.wrapper.controls-none twisty-control-button-panel ,\n.wrapper.controls-none twisty-scrubber-v2,\n.wrapper.controls-none twisty-buttons-v2 {\n display: none;\n}\n\ntwisty-scrubber {\n background: rgba(196, 196, 196, 0.5);\n}\n\n.wrapper.checkered {\n background-color: #EAEAEA;\n background-image: linear-gradient(45deg, #DDD 25%, transparent 25%, transparent 75%, #DDD 75%, #DDD),\n linear-gradient(45deg, #DDD 25%, transparent 25%, transparent 75%, #DDD 75%, #DDD);\n background-size: 32px 32px;\n background-position: 0 0, 16px 16px;\n}\n\n.visualization-wrapper > * {\n width: 100%;\n height: 100%;\n}\n\n.error-elem {\n width: 100%;\n height: 100%;\n display: none;\n place-content: center;\n font-family: sans-serif;\n box-shadow: inset 0 0 2em rgb(255, 0, 0);\n color: red;\n text-shadow: 0 0 0.2em white;\n background: rgba(255, 255, 255, 0.25);\n}\n\n.wrapper.error .visualization-wrapper {\n display: none;\n}\n\n.wrapper.error .error-elem {\n display: grid;\n}\n`);\n", "import { from } from \"../../vendor/p-lazy/p-lazy\";\n\n// TODO can we remove the cached proxy?\n\n// In theory we can, but we've run into situations where imports are not properly cached.\nlet cachedConstructorProxy: Promise<\n typeof import(\"./dynamic-entries/3d\")\n> | null = null;\n\nexport async function proxy3D(): Promise<\n typeof import(\"./dynamic-entries/3d\")\n> {\n return (cachedConstructorProxy ??= import(\"./dynamic-entries/3d\"));\n}\n\nexport const THREEJS: Promise<typeof import(\"three\")> = from(\n async () => (await proxy3D()).T3I,\n);\n", "import { CSSSource } from \"./ManagedCustomElement\";\n\nexport const twistyViewerWrapperCSS = new CSSSource(`\n:host {\n width: 384px;\n height: 256px;\n display: grid;\n}\n\n.wrapper {\n width: 100%;\n height: 100%;\n display: grid;\n overflow: hidden;\n}\n\n.wrapper > * {\n width: 100%;\n height: 100%;\n overflow: hidden;\n}\n\n.wrapper.back-view-side-by-side {\n grid-template-columns: 1fr 1fr;\n}\n\n.wrapper.back-view-top-right {\n grid-template-columns: 3fr 1fr;\n grid-template-rows: 1fr 3fr;\n}\n\n.wrapper.back-view-top-right > :nth-child(1) {\n grid-row: 1 / 3;\n grid-column: 1 / 3;\n}\n\n.wrapper.back-view-top-right > :nth-child(2) {\n grid-row: 1 / 2;\n grid-column: 2 / 3;\n}\n`);\n", "import { CSSSource } from \"../ManagedCustomElement\";\n\n// TODO: Can we do this without so much nesting, and styling all the nested elems?\nexport const twisty2DSVGCSS = new CSSSource(`\n:host {\n width: 384px;\n height: 256px;\n display: grid;\n}\n\n.wrapper {\n width: 100%;\n height: 100%;\n display: grid;\n overflow: hidden;\n}\n\n.svg-wrapper,\ntwisty-2d-svg,\nsvg {\n width: 100%;\n height: 100%;\n display: grid;\n min-height: 0;\n}\n`);\n", "import {\n combineTransformations,\n KPuzzleDefinition,\n KPuzzleSVGWrapper,\n transformationForMove,\n} from \"../../../kpuzzle\";\nimport type { PuzzleLoader } from \"../../../puzzles/PuzzleLoader\";\nimport type { PuzzleAppearance } from \"../../../puzzles/stickerings/appearance\";\nimport {\n Direction,\n PositionListener,\n PuzzlePosition,\n} from \"../../controllers/AnimationTypes\";\nimport { RenderScheduler } from \"../../controllers/RenderScheduler\";\nimport { ManagedCustomElement } from \"../ManagedCustomElement\";\nimport { customElementsShim } from \"../node-custom-element-shims\";\nimport type { TwistyPlayerModel } from \"../../model/TwistyPlayerModel\";\nimport { FreshListenerManager } from \"../../model/props/TwistyProp\";\nimport { twisty2DSVGCSS } from \"./Twisty2DPuzzle.css\";\nimport type { ExperimentalStickering, PuzzleID } from \"../..\";\n\nexport interface Twisty2DPuzzleOptions {\n experimentalStickering?: ExperimentalStickering;\n}\n\n// <twisty-2d-svg>\nexport class Twisty2DPuzzle\n extends ManagedCustomElement\n implements PositionListener\n{\n private definition: KPuzzleDefinition;\n public svg: KPuzzleSVGWrapper;\n private scheduler = new RenderScheduler(this.render.bind(this));\n #cachedPosition: PuzzlePosition | null = null; // TODO: pull when needed.\n constructor(\n private model?: TwistyPlayerModel,\n def?: KPuzzleDefinition,\n private svgSource?: string,\n private options?: Twisty2DPuzzleOptions,\n private puzzleLoader?: PuzzleLoader,\n ) {\n super();\n this.addCSS(twisty2DSVGCSS);\n\n this.definition = def!;\n this.resetSVG(); // TODO: do this in `connectedCallback()`?\n\n this.#freshListenerManager.addListener(\n this.model!.puzzleIDProp,\n (puzzleID: PuzzleID) => {\n if (puzzleLoader?.id !== puzzleID) {\n this.disconnect();\n }\n },\n );\n\n this.#freshListenerManager.addListener(\n this.model!.legacyPositionProp,\n this.onPositionChange.bind(this),\n );\n\n if (this.options?.experimentalStickering) {\n this.experimentalSetStickering(this.options.experimentalStickering);\n }\n }\n\n #freshListenerManager = new FreshListenerManager();\n disconnect(): void {\n this.#freshListenerManager.disconnect();\n }\n\n onPositionChange(position: PuzzlePosition): void {\n try {\n if (position.movesInProgress.length > 0) {\n const move = position.movesInProgress[0].move;\n\n const def = this.definition;\n let partialMove = move;\n if (position.movesInProgress[0].direction === Direction.Backwards) {\n partialMove = move.invert();\n }\n const newState = combineTransformations(\n def,\n position.state,\n transformationForMove(def, partialMove),\n );\n // TODO: move to render()\n this.svg.draw(\n this.definition,\n position.state,\n newState,\n position.movesInProgress[0].fraction,\n );\n } else {\n this.svg.draw(this.definition, position.state);\n this.#cachedPosition = position;\n }\n } catch (e) {\n console.warn(\n \"Bad position (this doesn't necessarily mean something is wrong). Pre-emptively disconnecting:\",\n this.puzzleLoader?.id,\n e,\n );\n this.disconnect();\n }\n }\n\n scheduleRender(): void {\n this.scheduler.requestAnimFrame();\n }\n\n experimentalSetStickering(stickering: ExperimentalStickering): void {\n (async () => {\n if (!this.puzzleLoader?.appearance) {\n return;\n }\n const appearance = await this.puzzleLoader.appearance(stickering);\n this.resetSVG(appearance);\n })();\n }\n\n // TODO: do this without constructing a new SVG.\n private resetSVG(appearance?: PuzzleAppearance): void {\n if (this.svg) {\n this.removeElement(this.svg.element);\n }\n if (!this.definition) {\n return; // TODO\n }\n this.svg = new KPuzzleSVGWrapper(\n this.definition,\n this.svgSource!,\n appearance,\n ); // TODO\n this.addElement(this.svg.element);\n if (this.#cachedPosition) {\n this.onPositionChange(this.#cachedPosition);\n }\n }\n\n private render(): void {\n /*...*/\n }\n}\n\ncustomElementsShim.define(\"twisty-2d-puzzle\", Twisty2DPuzzle);\n", "import type { PuzzleLoader } from \"../../../puzzles\";\nimport type { ExperimentalStickering } from \"../../../twisty\";\nimport type { TwistyPlayerModel } from \"../../model/TwistyPlayerModel\";\nimport { FreshListenerManager } from \"../../model/props/TwistyProp\";\nimport type { Schedulable } from \"../../controllers/RenderScheduler\";\nimport { Twisty2DPuzzle } from \"./Twisty2DPuzzle\";\n\nexport class Twisty2DPuzzleWrapper implements Schedulable {\n constructor(\n private model: TwistyPlayerModel,\n public schedulable: Schedulable,\n private puzzleLoader: PuzzleLoader,\n private effectiveVisualization: \"2D\" | \"experimental-2D-LL\",\n ) {\n this.twisty2DPuzzle(); // Start constructing.\n\n this.#freshListenerManager.addListener(\n this.model.stickeringProp,\n async (stickering: ExperimentalStickering) => {\n (await this.twisty2DPuzzle()).experimentalSetStickering(stickering);\n },\n );\n }\n\n #freshListenerManager = new FreshListenerManager();\n disconnect(): void {\n this.#freshListenerManager.disconnect();\n }\n\n // TODO: Hook this up nicely.\n scheduleRender(): void {\n // Nothing\n }\n\n #cachedTwisty2DPuzzle: Promise<Twisty2DPuzzle> | null = null;\n // TODO: Stale dropper?\n async twisty2DPuzzle(): Promise<Twisty2DPuzzle> {\n return (this.#cachedTwisty2DPuzzle ??= (async () => {\n const svgPromise =\n this.effectiveVisualization === \"experimental-2D-LL\"\n ? this.puzzleLoader.llSVG!()\n : this.puzzleLoader.svg();\n return new Twisty2DPuzzle(\n this.model,\n await this.puzzleLoader.def(),\n await svgPromise,\n {},\n this.puzzleLoader,\n );\n })());\n }\n}\n", "import type { Scene as ThreeScene } from \"three\";\nimport type { PuzzleLoader } from \"../../../puzzles\";\nimport { THREEJS } from \"../../heavy-code-imports/3d\";\nimport type { TwistyPlayerModel } from \"../../model/TwistyPlayerModel\";\nimport { FreshListenerManager } from \"../../model/props/TwistyProp\";\nimport type { Schedulable } from \"../../controllers/RenderScheduler\";\nimport { ManagedCustomElement } from \"../ManagedCustomElement\";\nimport { customElementsShim } from \"../node-custom-element-shims\";\nimport { twistyViewerWrapperCSS } from \"../TwistyViewerWrapper.css\";\nimport { Twisty2DPuzzleWrapper } from \"./Twisty2DPuzzleWrapper\";\n\nexport class Twisty2DSceneWrapper\n extends ManagedCustomElement\n implements Schedulable\n{\n #freshListenerManager = new FreshListenerManager();\n disconnect(): void {\n this.#freshListenerManager.disconnect();\n }\n\n constructor(\n public model?: TwistyPlayerModel,\n private effectiveVisualization?: \"2D\" | \"experimental-2D-LL\",\n ) {\n super();\n }\n\n async connectedCallback(): Promise<void> {\n this.addCSS(twistyViewerWrapperCSS);\n if (this.model) {\n this.#freshListenerManager.addListener(\n this.model.puzzleLoaderProp,\n this.onPuzzleLoader.bind(this),\n );\n }\n }\n\n #cachedScene: Promise<ThreeScene> | null;\n async scene(): Promise<ThreeScene> {\n return (this.#cachedScene ??= (async () => new (await THREEJS).Scene())());\n }\n\n scheduleRender(): void {\n this.#currentTwisty2DPuzzleWrapper?.scheduleRender();\n }\n\n #currentTwisty2DPuzzleWrapper: Twisty2DPuzzleWrapper | null = null;\n currentTwisty2DPuzzleWrapper(): Twisty2DPuzzleWrapper | null {\n return this.#currentTwisty2DPuzzleWrapper;\n }\n\n // #oldTwisty3DPuzzleWrappers: Twisty3DPuzzleWrapper[] = []; // TODO: Animate these out.\n async setCurrentTwisty2DPuzzleWrapper(\n twisty2DPuzzleWrapper: Twisty2DPuzzleWrapper,\n ): Promise<void> {\n const old = this.#currentTwisty2DPuzzleWrapper;\n this.#currentTwisty2DPuzzleWrapper = twisty2DPuzzleWrapper;\n old?.disconnect(); // TODO: Disconnect properly.\n const twisty2DPuzzlePromise = twisty2DPuzzleWrapper.twisty2DPuzzle();\n this.contentWrapper.textContent = \"\"; // Clear existing ones.\n this.addElement(await twisty2DPuzzlePromise);\n }\n\n async onPuzzleLoader(puzzleLoader: PuzzleLoader): Promise<void> {\n this.#currentTwisty2DPuzzleWrapper?.disconnect();\n const twisty2DPuzzleWrapper = new Twisty2DPuzzleWrapper(\n this.model!,\n this,\n puzzleLoader,\n this.effectiveVisualization!,\n );\n\n this.setCurrentTwisty2DPuzzleWrapper(twisty2DPuzzleWrapper);\n }\n}\n\ncustomElementsShim.define(\"twisty-2d-scene-wrapper\", Twisty2DSceneWrapper);\n", "import { PerspectiveCamera, Scene as ThreeScene, Vector2 } from \"three\";\nimport type { PuzzleLoader } from \"../../../puzzles\";\nimport { THREEJS } from \"../../heavy-code-imports/3d\";\nimport { StaleDropper } from \"../../model/PromiseFreshener\";\nimport { FreshListenerManager } from \"../../model/props/TwistyProp\";\nimport type {\n BackViewLayout,\n BackViewLayoutWithAuto,\n} from \"../../model/props/viewer/BackViewProp\";\nimport type { VisualizationStrategy } from \"../../model/props/viewer/VisualizationStrategyProp\";\nimport type { TwistyPlayerModel } from \"../../model/TwistyPlayerModel\";\nimport type { Schedulable } from \"../../controllers/RenderScheduler\";\nimport { ClassListManager } from \"../ClassListManager\";\nimport { ManagedCustomElement } from \"../ManagedCustomElement\";\nimport { customElementsShim } from \"../node-custom-element-shims\";\nimport { twistyViewerWrapperCSS } from \"../TwistyViewerWrapper.css\";\nimport type { PressInfo } from \"./DragTracker\";\nimport { Twisty3DPuzzleWrapper } from \"./Twisty3DPuzzleWrapper\";\nimport { Twisty3DVantage } from \"./Twisty3DVantage\";\n\nexport class Twisty3DSceneWrapper\n extends ManagedCustomElement\n implements Schedulable\n{\n #backViewClassListManager: ClassListManager<BackViewLayoutWithAuto> =\n new ClassListManager(this, \"back-view-\", [\n \"auto\",\n \"none\",\n \"side-by-side\",\n \"top-right\",\n ]);\n\n #freshListenerManager = new FreshListenerManager();\n disconnect(): void {\n this.#freshListenerManager.disconnect();\n }\n\n constructor(public model?: TwistyPlayerModel) {\n super();\n }\n\n async connectedCallback(): Promise<void> {\n this.addCSS(twistyViewerWrapperCSS);\n const vantage = new Twisty3DVantage(this.model, this);\n this.addVantage(vantage);\n if (this.model) {\n this.#freshListenerManager.addMultiListener(\n [this.model.puzzleLoaderProp, this.model.visualizationStrategyProp],\n this.onPuzzle.bind(this),\n );\n this.#freshListenerManager.addListener(\n this.model.backViewProp,\n this.onBackView.bind(this),\n );\n }\n this.scheduleRender();\n }\n\n #backViewVantage: Twisty3DVantage | null = null;\n setBackView(backView: BackViewLayout): void {\n const shouldHaveBackView = [\"side-by-side\", \"top-right\"].includes(backView);\n const hasBackView = this.#backViewVantage !== null;\n\n this.#backViewClassListManager.setValue(backView);\n if (shouldHaveBackView) {\n if (!hasBackView) {\n this.#backViewVantage = new Twisty3DVantage(this.model, this, {\n backView: true,\n });\n this.addVantage(this.#backViewVantage);\n this.scheduleRender();\n }\n } else {\n if (this.#backViewVantage) {\n this.removeVantage(this.#backViewVantage);\n this.#backViewVantage = null;\n }\n }\n }\n\n onBackView(backView: BackViewLayout): void {\n this.setBackView(backView);\n }\n\n async onPress(\n e: CustomEvent<{\n pressInfo: PressInfo;\n cameraPromise: Promise<PerspectiveCamera>;\n }>,\n ): Promise<void> {\n const twisty3DPuzzleWrapper = this.#currentTwisty3DPuzzleWrapper;\n if (!twisty3DPuzzleWrapper) {\n console.info(\"no wrapper; skipping scene wrapper press!\");\n return;\n }\n\n const raycasterPromise = (async () => {\n const [camera, three] = await Promise.all([\n e.detail.cameraPromise,\n THREEJS,\n ]);\n\n const raycaster = new three.Raycaster();\n const mouse = new Vector2(\n e.detail.pressInfo.normalizedX,\n e.detail.pressInfo.normalizedY,\n );\n raycaster.setFromCamera(mouse, camera);\n return raycaster;\n })();\n\n twisty3DPuzzleWrapper.raycastMove(raycasterPromise, {\n invert: !e.detail.pressInfo.rightClick,\n depth: e.detail.pressInfo.keys.ctrlOrMetaKey\n ? \"rotation\"\n : e.detail.pressInfo.keys.shiftKey\n ? \"secondSlice\"\n : \"none\",\n });\n }\n\n #cachedScene: Promise<ThreeScene> | null;\n async scene(): Promise<ThreeScene> {\n return (this.#cachedScene ??= (async () => new (await THREEJS).Scene())());\n }\n\n #vantages: Set<Twisty3DVantage> = new Set();\n addVantage(vantage: Twisty3DVantage) {\n vantage.addEventListener(\"press\", this.onPress.bind(this));\n this.#vantages.add(vantage);\n this.contentWrapper.appendChild(vantage);\n }\n\n removeVantage(vantage: Twisty3DVantage) {\n this.#vantages.delete(vantage);\n vantage.remove();\n vantage.disconnect();\n this.#currentTwisty3DPuzzleWrapper?.disconnect();\n }\n\n experimentalVantages(): Iterable<Twisty3DVantage> {\n return this.#vantages.values();\n }\n\n scheduleRender(): void {\n for (const vantage of this.#vantages) {\n vantage.scheduleRender();\n }\n }\n\n #currentTwisty3DPuzzleWrapper: Twisty3DPuzzleWrapper | null = null;\n // #oldTwisty3DPuzzleWrappers: Twisty3DPuzzleWrapper[] = []; // TODO: Animate these out.\n async setCurrentTwisty3DPuzzleWrapper(\n scene: ThreeScene,\n twisty3DPuzzleWrapper: Twisty3DPuzzleWrapper,\n ): Promise<void> {\n const old = this.#currentTwisty3DPuzzleWrapper;\n this.#currentTwisty3DPuzzleWrapper = twisty3DPuzzleWrapper;\n old?.disconnect();\n scene.add(await twisty3DPuzzleWrapper.twisty3DPuzzle());\n if (old) {\n // We wait for the new puzzle to be in place before removing the old one.\n scene.remove(await old.twisty3DPuzzle());\n }\n }\n\n #twisty3DStaleDropper: StaleDropper<[ThreeScene, Twisty3DPuzzleWrapper]> =\n new StaleDropper<[ThreeScene, Twisty3DPuzzleWrapper]>();\n\n async onPuzzle(\n inputs: [\n puzzleLoader: PuzzleLoader,\n visualizationStrategy: VisualizationStrategy,\n ],\n ): Promise<void> {\n this.#currentTwisty3DPuzzleWrapper?.disconnect();\n const [scene, twisty3DPuzzleWrapper] =\n await this.#twisty3DStaleDropper.queue(\n Promise.all([\n this.scene(),\n new Twisty3DPuzzleWrapper(this.model!, this, inputs[0], inputs[1]), // TODO\n ]),\n );\n\n this.setCurrentTwisty3DPuzzleWrapper(scene, twisty3DPuzzleWrapper);\n }\n}\n\ncustomElementsShim.define(\"twisty-3d-scene-wrapper\", Twisty3DSceneWrapper);\n", "import type { Raycaster, Texture as ThreeTexture } from \"three\";\nimport { experimentalCubeAppearance, PuzzleLoader } from \"../../../puzzles\";\nimport type { ExperimentalStickering } from \"../../../twisty\";\nimport { proxy3D } from \"../../heavy-code-imports/3d\";\nimport { Cube3D, PG3D } from \"../../heavy-code-imports/dynamic-entries/3d\";\nimport type { FoundationDisplay } from \"../../model/props/puzzle/display/FoundationDisplayProp\";\nimport type { HintFaceletStyleWithAuto } from \"../../model/props/puzzle/display/HintFaceletProp\";\nimport { FreshListenerManager } from \"../../model/props/TwistyProp\";\nimport type { VisualizationStrategy } from \"../../model/props/viewer/VisualizationStrategyProp\";\nimport type { TwistyPlayerModel } from \"../../model/TwistyPlayerModel\";\nimport type { PuzzlePosition } from \"../../controllers/AnimationTypes\";\nimport type { Schedulable } from \"../../controllers/RenderScheduler\";\nimport type { Twisty3DPuzzle } from \"./puzzles/Twisty3DPuzzle\";\n\nexport class Twisty3DPuzzleWrapper implements Schedulable {\n constructor(\n private model: TwistyPlayerModel,\n public schedulable: Schedulable,\n private puzzleLoader: PuzzleLoader,\n private visualizationStrategy: VisualizationStrategy,\n ) {\n this.twisty3DPuzzle(); // Start constructing.\n\n // TODO: Hook up listeners before loading the heavy code in the async constructor, so we get any intermediate updates?\n // Repro: Switch to 40x40x40 a fraction of a second before animation finishes. When it's loaded the itmeline is at the end, but the 40x40x40 is rendered with an earlier position.\n\n this.#freshListenerManager.addListener(\n this.model.puzzleLoaderProp,\n (puzzleLoader: PuzzleLoader) => {\n if (this.puzzleLoader.id !== puzzleLoader.id) {\n this.disconnect();\n }\n },\n );\n this.#freshListenerManager.addListener(\n this.model.legacyPositionProp,\n async (position: PuzzlePosition) => {\n try {\n (await this.twisty3DPuzzle()).onPositionChange(position);\n this.scheduleRender();\n } catch (e) {\n // TODO\n // console.warn(\n // \"Bad position (this doesn't necessarily mean something is wrong). Pre-emptively disconnecting:\",\n // this.puzzleLoader.id,\n // e,\n // );\n this.disconnect();\n }\n },\n );\n\n this.#freshListenerManager.addListener(\n this.model.hintFaceletProp,\n async (hintFaceletStyle: HintFaceletStyleWithAuto) => {\n (\n (await this.twisty3DPuzzle()) as Cube3D | PG3D\n ).experimentalUpdateOptions({\n hintFacelets:\n hintFaceletStyle === \"auto\" ? \"floating\" : hintFaceletStyle,\n });\n this.scheduleRender();\n },\n );\n this.#freshListenerManager.addListener(\n this.model.foundationDisplayProp,\n async (foundationDisplay: FoundationDisplay) => {\n (\n (await this.twisty3DPuzzle()) as Cube3D | PG3D\n ).experimentalUpdateOptions({\n showFoundation: foundationDisplay !== \"none\",\n });\n this.scheduleRender();\n },\n );\n this.#freshListenerManager.addListener(\n this.model.stickeringProp,\n async (stickering: ExperimentalStickering) => {\n if (\"setStickering\" in (await this.twisty3DPuzzle())) {\n ((await this.twisty3DPuzzle()) as Cube3D).setStickering(stickering);\n this.scheduleRender();\n } else {\n if (\n [\n \"experimental-global-custom-1\",\n \"experimental-global-custom-2\",\n ].includes(stickering)\n ) {\n const [twisty3D] = await Promise.all([this.twisty3DPuzzle()]);\n (twisty3D as PG3D).experimentalSetAppearance(\n await experimentalCubeAppearance(this.puzzleLoader, stickering),\n );\n this.scheduleRender();\n return;\n }\n\n // TODO: create a prop to handle this.\n if (\"appearance\" in this.puzzleLoader) {\n const [twisty3D, appearancePromise] = await Promise.all([\n this.twisty3DPuzzle(),\n this.puzzleLoader.appearance!(stickering ?? \"full\"),\n ]);\n (twisty3D as PG3D).experimentalSetAppearance(appearancePromise);\n this.scheduleRender();\n }\n }\n },\n );\n\n this.#freshListenerManager.addMultiListener(\n [this.model.foundationStickerSprite, this.model.hintStickerSprite],\n async (\n inputs: [\n foundationSprite: ThreeTexture | null,\n hintSprite: ThreeTexture | null,\n ],\n ) => {\n if (\"experimentalUpdateTexture\" in (await this.twisty3DPuzzle())) {\n ((await this.twisty3DPuzzle()) as PG3D).experimentalUpdateTexture(\n true,\n ...inputs,\n );\n this.scheduleRender();\n }\n },\n );\n }\n\n #freshListenerManager = new FreshListenerManager();\n disconnect(): void {\n this.#freshListenerManager.disconnect();\n }\n\n scheduleRender(): void {\n this.schedulable.scheduleRender();\n }\n\n #cachedTwisty3DPuzzle: Promise<Twisty3DPuzzle> | null = null;\n async twisty3DPuzzle(): Promise<Twisty3DPuzzle> {\n return (this.#cachedTwisty3DPuzzle ??= (async () => {\n const proxyPromise = proxy3D();\n if (\n this.puzzleLoader.id === \"3x3x3\" &&\n this.visualizationStrategy === \"Cube3D\"\n ) {\n // TODO: synchronize\n const [foundationSprite, hintSprite, experimentalStickering] =\n await Promise.all([\n this.model.foundationStickerSprite.get(),\n this.model.hintStickerSprite.get(),\n this.model.stickeringProp.get(),\n ]);\n return (await proxyPromise).cube3DShim({\n foundationSprite,\n hintSprite,\n experimentalStickering,\n });\n } else {\n const [hintFacelets, foundationSprite, hintSprite] = await Promise.all([\n this.model.hintFaceletProp.get(),\n this.model.foundationStickerSprite.get(),\n this.model.hintStickerSprite.get(),\n ]);\n const pg3d = (await proxyPromise).pg3dShim(\n this.puzzleLoader,\n hintFacelets === \"auto\" ? \"floating\" : hintFacelets,\n );\n // TODO: Figure out how to do this in one place using the listener.\n pg3d.then((p) =>\n p.experimentalUpdateTexture(\n true,\n foundationSprite ?? undefined,\n hintSprite ?? undefined,\n ),\n );\n return pg3d;\n }\n })());\n }\n\n async raycastMove(\n raycasterPromise: Promise<Raycaster>,\n transformations: {\n invert: boolean;\n depth?: \"secondSlice\" | \"rotation\" | \"none\";\n },\n ): Promise<void> {\n const puzzle = await this.twisty3DPuzzle();\n // TODO: check this differently.\n if (!(puzzle instanceof PG3D)) {\n console.info(\"not PG3D! skipping raycast\");\n return;\n }\n\n const targets = puzzle.experimentalGetControlTargets(); // TODO: sticker targets\n const [raycaster] = await Promise.all([raycasterPromise]);\n\n const intersects = raycaster.intersectObjects(targets);\n if (intersects.length > 0) {\n const closestMove = puzzle.getClosestMoveToAxis(\n intersects[0].point,\n transformations,\n );\n if (closestMove) {\n this.model.experimentalAddMove(closestMove.move, {\n coalesce: true,\n mod: closestMove.order,\n });\n } else {\n console.info(\"Skipping move!\");\n }\n }\n }\n}\n", "/**\n * @author mrdoob / http://mrdoob.com/\n * ESM conversion by Lucas Garron, 2021-12-21\n */\n\nconst performance:\n | null\n | (Performance & {\n memory?: {\n usedJSHeapSize: number;\n jsHeapSizeLimit: number;\n };\n }) = globalThis.performance;\n\nexport class Stats {\n mode = 0;\n\n dom = document.createElement(\"div\");\n\n constructor() {\n this.dom.style.cssText =\n \"position:fixed;top:0;left:0;cursor:pointer;opacity:0.9;z-index:10000\";\n this.dom.addEventListener(\n \"click\",\n (event) => {\n event.preventDefault();\n this.showPanel(++this.mode % this.dom.children.length);\n },\n false,\n );\n\n this.showPanel(0);\n }\n\n addPanel(panel: StatsPanel): StatsPanel {\n this.dom.appendChild(panel.dom);\n return panel;\n }\n\n showPanel(id: number): void {\n for (let i = 0; i < this.dom.children.length; i++) {\n (this.dom.children[i] as HTMLElement).style.display =\n i === id ? \"block\" : \"none\";\n }\n\n this.mode = id;\n }\n\n beginTime = (performance || Date).now();\n prevTime = this.beginTime;\n frames = 0;\n\n fpsPanel = this.addPanel(new StatsPanel(\"FPS\", \"#0ff\", \"#002\"));\n msPanel = this.addPanel(new StatsPanel(\"MS\", \"#0f0\", \"#020\"));\n memPanel = performance?.memory\n ? this.addPanel(new StatsPanel(\"MB\", \"#f08\", \"#201\"))\n : null;\n REVISION = 16;\n\n begin() {\n this.beginTime = (performance || Date).now();\n }\n\n end() {\n this.frames++;\n\n const time = (performance || Date).now();\n\n this.msPanel.update(time - this.beginTime, 200);\n\n if (time >= this.prevTime + 1000) {\n this.fpsPanel.update((this.frames * 1000) / (time - this.prevTime), 100);\n\n this.prevTime = time;\n this.frames = 0;\n\n if (this.memPanel) {\n const memory = performance!.memory!;\n this.memPanel.update(\n memory.usedJSHeapSize / 1048576,\n memory.jsHeapSizeLimit / 1048576,\n );\n }\n }\n\n return time;\n }\n\n update() {\n this.beginTime = this.end();\n }\n}\n\nconst PR = Math.round(globalThis?.window?.devicePixelRatio ?? 1);\n\nconst WIDTH = 80 * PR,\n HEIGHT = 48 * PR,\n TEXT_X = 3 * PR,\n TEXT_Y = 2 * PR,\n GRAPH_X = 3 * PR,\n GRAPH_Y = 15 * PR,\n GRAPH_WIDTH = 74 * PR,\n GRAPH_HEIGHT = 30 * PR;\n\nexport class StatsPanel {\n min = Infinity;\n max = 0;\n dom = document.createElement(\"canvas\");\n context = this.dom.getContext(\"2d\")!;\n constructor(private name: string, private fg: string, private bg: string) {\n this.dom.width = WIDTH;\n this.dom.height = HEIGHT;\n this.dom.style.cssText = \"width:80px;height:48px\";\n\n this.context.font = `bold ${9 * PR}px Helvetica,Arial,sans-serif`;\n this.context.textBaseline = \"top\";\n\n this.context.fillStyle = bg;\n this.context.fillRect(0, 0, WIDTH, HEIGHT);\n\n this.context.fillStyle = fg;\n this.context.fillText(name, TEXT_X, TEXT_Y);\n this.context.fillRect(GRAPH_X, GRAPH_Y, GRAPH_WIDTH, GRAPH_HEIGHT);\n\n this.context.fillStyle = bg;\n this.context.globalAlpha = 0.9;\n this.context.fillRect(GRAPH_X, GRAPH_Y, GRAPH_WIDTH, GRAPH_HEIGHT);\n }\n\n update(value: number, maxValue: number) {\n this.min = Math.min(this.min, value);\n this.max = Math.max(this.max, value);\n\n this.context.fillStyle = this.bg;\n this.context.globalAlpha = 1;\n this.context.fillRect(0, 0, WIDTH, GRAPH_Y);\n this.context.fillStyle = this.fg;\n this.context.fillText(\n Math.round(value) +\n \" \" +\n this.name +\n \" (\" +\n Math.round(this.min) +\n \"-\" +\n Math.round(this.max) +\n \")\",\n TEXT_X,\n TEXT_Y,\n );\n\n this.context.drawImage(\n this.dom,\n GRAPH_X + PR,\n GRAPH_Y,\n GRAPH_WIDTH - PR,\n GRAPH_HEIGHT,\n GRAPH_X,\n GRAPH_Y,\n GRAPH_WIDTH - PR,\n GRAPH_HEIGHT,\n );\n\n this.context.fillRect(\n GRAPH_X + GRAPH_WIDTH - PR,\n GRAPH_Y,\n PR,\n GRAPH_HEIGHT,\n );\n\n this.context.fillStyle = this.bg;\n this.context.globalAlpha = 0.9;\n this.context.fillRect(\n GRAPH_X + GRAPH_WIDTH - PR,\n GRAPH_Y,\n PR,\n Math.round((1 - value / maxValue) * GRAPH_HEIGHT),\n );\n }\n}\n", "let globalPixelRatioOverride: number | null = null;\nexport function setGlobalPixelRatioOverride(override: number | null): void {\n globalPixelRatioOverride = override;\n}\n\n// TODO: Handle if you move across screens?\nexport function pixelRatio(): number {\n return globalPixelRatioOverride ?? (devicePixelRatio || 1);\n}\n", "import { CSSSource } from \"../ManagedCustomElement\";\n\n// The `position` values are a hack for a bug in Safari where the canvas either\n// grows infinitely, or takes up the full `fr` of any encompassing grid (making\n// the contents of that element e.g. over 100% of its height). `contain:\n// content` is a good fix for this, but there is no indication that Safari will\n// support it soon. https://developer.mozilla.org/en-US/docs/Web/CSS/contain\n\nexport const twisty3DVantageCSS = new CSSSource(`\n:host {\n width: 384px;\n height: 256px;\n display: grid;\n}\n\n.wrapper {\n width: 100%;\n height: 100%;\n display: grid;\n overflow: hidden;\n}\n\n/* TODO: This is due to stats hack. Replace with \\`canvas\\`. */\n.wrapper > canvas {\n max-width: 100%;\n max-height: 100%;\n}\n\n.wrapper.invisible {\n opacity: 0;\n}\n`);\n", "// export class Drag() {\n\n// }\n\ninterface DragInfo {\n attachedInfo: Record<any, any>;\n hasMoved: boolean;\n lastClientX: number;\n lastClientY: number;\n lastTimeStamp: number;\n}\n\ntype PointerID = number;\n\nexport interface DragMovementInfo {\n attachedInfo: Record<any, any>;\n movementX: number;\n movementY: number;\n elapsedMs: number;\n}\n\nexport interface UpInfo {\n attachedInfo: Record<any, any>;\n}\n\nexport interface PressInfo {\n normalizedX: number;\n normalizedY: number;\n rightClick: boolean;\n keys: {\n // TODO: group these\n altKey: boolean;\n ctrlOrMetaKey: boolean;\n shiftKey: boolean;\n };\n}\n\n// Chrome can report movements as low as `0.0000152587890625` even if the cursor did not move at all. So we need a treshold insteadl.\nconst MOVEMENT_EPSILON = 0.1; // px\n\nexport class DragTracker extends EventTarget {\n #dragInfoMap: Map<PointerID, DragInfo> = new Map();\n\n constructor(public readonly target: HTMLElement) {\n super();\n target.addEventListener(\"pointerdown\", this.onPointerDown.bind(this));\n // Prevent right-click on desktop (only tested on macOS Chrome/Safari/Firefox) so we can detect right-click moves.\n // TODO: Can we do this selectively, e.g. only on the puzzle? That way we could allow right-click to download the canvas. Unfortunately, it would probably require a sync calculation.\n this.target.addEventListener(\"contextmenu\", (e) => {\n if (e.buttons & 2) {\n e.preventDefault();\n }\n });\n // Prevent touch scrolling (preventing default on `pointermove` doesn't work).\n this.target.addEventListener(\"touchmove\", (e) => e.preventDefault());\n // Prevent zooming on double-tap (iOS).\n // This is because `dblclick` works to zoom in, but does *not* work to zoom out. So the user can get stuck zoomed into the player without a way to zoom out.\n this.target.addEventListener(\"dblclick\", (e) => e.preventDefault());\n }\n\n // This allows us to avoid getting a callback every time the pointer moves over the canvas, until we have a down event.\n // TODO: Ideally we'd also support unregistering when we're certain there are no more active touches. But this means we need to properly handle every way a pointer \"click\" can end, which is tricky across environments (due to e.g. mouse vs. touch vs. stylues, canvas/viewport/window/scroll boundaries, right-click and other ways of losing focus, etc.), so we conservatively leave the listeners on.\n #lazyListenersRegistered: boolean = false;\n #registerLazyListeners(): void {\n if (this.#lazyListenersRegistered) {\n return;\n }\n this.target.addEventListener(\"pointermove\", this.onPointerMove.bind(this)); // TODO: only register this after pointer down.\n this.target.addEventListener(\"pointerup\", this.onPointerUp.bind(this));\n this.#lazyListenersRegistered = true;\n }\n\n #clear(e: PointerEvent): void {\n this.#dragInfoMap.delete(e.pointerId);\n }\n\n // `null`: means: ignore this result (no movement, or not\n #trackDrag(e: PointerEvent): {\n movementInfo: DragMovementInfo | null;\n hasMoved: boolean;\n } {\n // TODO: Find a way to detect if this is an active press, in a way that works cross-platform.\n // if (e.buttons === 0) {\n // return { movementInfo: null, hasMoved: false };\n // }\n const existing = this.#dragInfoMap.get(e.pointerId);\n if (!existing) {\n return { movementInfo: null, hasMoved: false };\n }\n // We would try to use `e.movementX`/`e.movementY`, except Safari:\n // - Does not have those values on i[Pad]OS.\n // - Will always report `0` for these values on macOS.\n // https://bugs.webkit.org/show_bug.cgi?id=220194\n //\n // The following are all insufficiently powerful for detecting the Safari `0` bug:\n // - `\"movementX\" in e`\n // - `e.movementX !== \"undefined\"`\n // - `e.hasOwnProperty(\"movementX\")`\n\n let movementInfo: DragMovementInfo;\n if ((e.movementX ?? 0) !== 0 || (e.movementY ?? 0) !== 0) {\n // We optimistically try to catch sub-pixel movements in Chrome.\n movementInfo = {\n attachedInfo: existing.attachedInfo,\n movementX: e.movementX,\n movementY: e.movementY,\n elapsedMs: e.timeStamp - existing.lastTimeStamp,\n };\n } else {\n movementInfo = {\n attachedInfo: existing.attachedInfo,\n movementX: e.clientX - existing.lastClientX,\n movementY: e.clientY - existing.lastClientY,\n elapsedMs: e.timeStamp - existing.lastTimeStamp,\n };\n }\n existing.lastClientX = e.clientX;\n existing.lastClientY = e.clientY;\n existing.lastTimeStamp = e.timeStamp;\n if (\n Math.abs(movementInfo.movementX) < MOVEMENT_EPSILON &&\n Math.abs(movementInfo.movementY) < MOVEMENT_EPSILON\n ) {\n return { movementInfo: null, hasMoved: existing.hasMoved };\n } else {\n existing.hasMoved = true;\n return { movementInfo, hasMoved: existing.hasMoved };\n }\n }\n\n private onPointerDown(e: PointerEvent) {\n this.#registerLazyListeners();\n const newDragInfo: DragInfo = {\n attachedInfo: {},\n hasMoved: false,\n lastClientX: e.clientX,\n lastClientY: e.clientY,\n lastTimeStamp: e.timeStamp,\n };\n this.#dragInfoMap.set(e.pointerId, newDragInfo);\n this.target.setPointerCapture(e.pointerId);\n }\n\n private onPointerMove(e: PointerEvent) {\n const movementInfo = this.#trackDrag(e).movementInfo;\n if (movementInfo) {\n e.preventDefault();\n this.dispatchEvent(\n new CustomEvent(\"move\", {\n detail: movementInfo,\n }),\n );\n }\n }\n\n private onPointerUp(e: PointerEvent) {\n const trackDragResult = this.#trackDrag(e);\n const existing = this.#dragInfoMap.get(e.pointerId)!; // TODO\n this.#clear(e);\n this.target.releasePointerCapture(e.pointerId); // TODO: unnecessary?\n let event: CustomEvent;\n if (trackDragResult.hasMoved) {\n // TODO: send proper movement/momentum since last move event.\n event = new CustomEvent<UpInfo>(\"up\", {\n detail: { attachedInfo: existing.attachedInfo },\n });\n } else {\n const { altKey, ctrlKey, metaKey, shiftKey } = e;\n event = new CustomEvent<PressInfo>(\"press\", {\n detail: {\n normalizedX: (e.offsetX / this.target.offsetWidth) * 2 - 1,\n normalizedY: 1 - (e.offsetY / this.target.offsetHeight) * 2,\n rightClick: !!(e.button & 2),\n keys: {\n altKey,\n ctrlOrMetaKey: ctrlKey || metaKey,\n shiftKey,\n },\n },\n });\n }\n this.dispatchEvent(event);\n }\n}\n", "// TODO: https://stackoverflow.com/a/40443642\n\n// let shareAllNewRenderers: boolean = false;\n\n// // WARNING: The current shared renderer implementation is not every efficient.\n// // Avoid using for players that are likely to have dimensions approaching 1 megapixel or higher.\n// // TODO: use a dedicated renderer while fullscreen?\n// export function experimentalSetShareAllNewRenderers(share: boolean): void {\n// shareAllNewRenderers = share;\n// }\n\n// const sharedRenderer: WebGLRenderer | null = null;\n\nimport { THREEJS } from \"../../heavy-code-imports/3d\";\nimport type { Camera, Scene, WebGLRenderer } from \"three\";\nimport { pixelRatio } from \"../canvas\";\n\nconst renderers: Promise<WebGLRenderer>[] = [];\n\n// let haveSet = false;\nexport async function renderPooled(\n width: number,\n height: number,\n canvas: HTMLCanvasElement,\n scene: Scene,\n camera: Camera,\n): Promise<void> {\n if (width === 0 || height === 0) {\n return;\n }\n // At most one in the pool for now.\n if (renderers.length === 0) {\n renderers.push(newRenderer());\n }\n const renderer = await renderers[0];\n // TODO: scissoring\n renderer.setSize(width, height); // TODO: is it faster if we cache values and only call this when necessary?\n renderer.render(scene, camera);\n\n // TODO: Should we cache this? Seems to take about 0.0001ms to get.\n const context = canvas.getContext(\"2d\")!;\n context.clearRect(0, 0, canvas.width, canvas.height);\n context.drawImage(renderer.domElement, 0, 0);\n}\n\nexport async function newRenderer(): Promise<WebGLRenderer> {\n const rendererConstructor = (await THREEJS).WebGLRenderer;\n const renderer = new rendererConstructor({\n antialias: true,\n alpha: true,\n });\n renderer.setPixelRatio(pixelRatio());\n return renderer;\n}\n", "import { Spherical, Vector3 } from \"three\";\nimport type { OrbitCoordinates } from \"../../model/props/viewer/OrbitCoordinatesRequestProp\";\nimport type { TwistyPlayerModel } from \"../../model/TwistyPlayerModel\";\nimport { RenderScheduler } from \"../../controllers/RenderScheduler\";\nimport type { DragMovementInfo, DragTracker } from \"./DragTracker\";\nimport { DEGREES_PER_RADIAN } from \"./TAU\";\n\nconst INERTIA_DEFAULT: boolean = true;\n\nconst INERTIA_DURATION_MS = 500;\n// If the first inertial render is this long after the last move, we assume the\n// user has halted the cursor and we consider inertia to have \"timed out\". We\n// never begin animating the inertia.\nconst INERTIA_TIMEOUT_MS = 50;\n\nconst VERTICAL_MOVEMENT_BASE_SCALE = 0.75;\n\n// progress is from 0 to 1.\nfunction momentumScale(progress: number) {\n // This is the exponential curve flipped so that\n // - The slope at progress = 0 is 1 (this corresponds to \"x = 1\" on the normal\n // curve).\n // - The scale exponentially \"decays\" until progress = 1.\n // This means the scale at the end will be about 0.418\n return (Math.exp(1 - progress) - (1 - progress)) / (1 - Math.E) + 1;\n}\n\nclass Inertia {\n private scheduler = new RenderScheduler(this.render.bind(this));\n private lastTimestamp: number;\n constructor(\n private startTimestamp: number,\n private momentumX: number,\n private momentumY: number,\n private callback: (movementX: number, movementY: number) => void,\n ) {\n this.scheduler.requestAnimFrame();\n this.lastTimestamp = startTimestamp;\n }\n\n private render(now: DOMHighResTimeStamp) {\n const progressBefore =\n (this.lastTimestamp - this.startTimestamp) / INERTIA_DURATION_MS;\n const progressAfter = Math.min(\n 1,\n (now - this.startTimestamp) / INERTIA_DURATION_MS,\n );\n\n if (\n progressBefore === 0 &&\n progressAfter > INERTIA_TIMEOUT_MS / INERTIA_DURATION_MS\n ) {\n // The user has already paused for a while. Don't start any inertia.\n return;\n }\n\n const delta = momentumScale(progressAfter) - momentumScale(progressBefore);\n\n // TODO: For now, we only carry horizontal momentum. If this should stay, we\n // can remove the plumbing for the Y dimension.\n this.callback(this.momentumX * delta * 1000, this.momentumY * delta * 1000);\n\n if (progressAfter < 1) {\n this.scheduler.requestAnimFrame();\n }\n this.lastTimestamp = now;\n }\n}\n\nexport function positionToOrbitCoordinates(\n position: Vector3,\n): OrbitCoordinates {\n const spherical = new Spherical();\n spherical.setFromVector3(position);\n return {\n latitude: 90 - spherical.phi * DEGREES_PER_RADIAN,\n longitude: spherical.theta * DEGREES_PER_RADIAN,\n distance: spherical.radius,\n };\n}\n\ninterface TwistyOrbitControlsDragAttachedInfo {\n lastTemperedX: number;\n lastTemperedY: number;\n timestamp: number;\n}\n\n// TODO: change mouse cursor while moving.\nexport class TwistyOrbitControls {\n /** @deprecated */\n experimentalInertia: boolean = INERTIA_DEFAULT;\n private onMovementBound = this.onMovement.bind(this);\n public experimentalHasBeenMoved: boolean = false;\n constructor(\n private model: TwistyPlayerModel,\n private mirror: boolean,\n private canvas: HTMLCanvasElement,\n private dragTracker: DragTracker,\n ) {\n this.dragTracker.addEventListener(\"move\", this.onMove.bind(this));\n this.dragTracker.addEventListener(\"up\", this.onUp.bind(this));\n }\n\n // f is the fraction of the canvas traversed per ms.\n temperMovement(f: number): number {\n // This is scaled to be linear for small values, but to reduce large values\n // by a significant factor.\n return (Math.sign(f) * Math.log(Math.abs(f * 10) + 1)) / 6;\n }\n\n onMove(e: CustomEvent<DragMovementInfo>): void {\n e.detail.attachedInfo ??= {};\n\n const { temperedX, temperedY } = this.onMovement(\n e.detail.movementX,\n e.detail.movementY,\n );\n const attachedInfo = e.detail\n .attachedInfo as TwistyOrbitControlsDragAttachedInfo;\n attachedInfo.lastTemperedX = temperedX * 10;\n attachedInfo.lastTemperedY = temperedY * 10;\n attachedInfo.timestamp = e.timeStamp; // TODO\n }\n\n onMovement(\n movementX: number,\n movementY: number,\n ): {\n temperedX: number;\n temperedY: number;\n } {\n const scale = this.mirror ? -1 : 1;\n\n // TODO: refactor\n const minDim = Math.min(this.canvas.offsetWidth, this.canvas.offsetHeight);\n\n const temperedX = this.temperMovement(movementX / minDim);\n const temperedY = this.temperMovement(\n (movementY / minDim) * VERTICAL_MOVEMENT_BASE_SCALE,\n );\n this.model.orbitCoordinatesRequestProp.set(\n (async () => {\n const prevCoords = await this.model.orbitCoordinatesProp.get();\n\n const newCoords = {\n latitude:\n prevCoords.latitude + 2 * temperedY * DEGREES_PER_RADIAN * scale,\n longitude: prevCoords.longitude - 2 * temperedX * DEGREES_PER_RADIAN,\n };\n return newCoords;\n })(),\n );\n return { temperedX, temperedY };\n }\n\n onUp(e: CustomEvent<DragMovementInfo>): void {\n e.preventDefault();\n if (\n \"lastTemperedX\" in e.detail.attachedInfo &&\n \"lastTemperedY\" in e.detail.attachedInfo &&\n \"timestamp\" in e.detail.attachedInfo &&\n e.timeStamp - e.detail.attachedInfo.timestamp < 60 // TODO\n ) {\n new Inertia(\n e.timeStamp, // TODO\n (\n e.detail.attachedInfo as TwistyOrbitControlsDragAttachedInfo\n ).lastTemperedX,\n (\n e.detail.attachedInfo as TwistyOrbitControlsDragAttachedInfo\n ).lastTemperedY,\n this.onMovementBound,\n ); // TODO: cancel inertia\n }\n }\n}\n", "import type { PerspectiveCamera, WebGLRenderer } from \"three\";\nimport { Stats } from \"../../../vendor/three/examples/jsm/libs/stats.modified.module\";\nimport { THREEJS } from \"../../heavy-code-imports/3d\";\nimport { StaleDropper } from \"../../model/PromiseFreshener\";\nimport type { TwistyPropParent } from \"../../model/props/TwistyProp\";\nimport type { OrbitCoordinates } from \"../../model/props/viewer/OrbitCoordinatesRequestProp\";\nimport type { TwistyPlayerModel } from \"../../model/TwistyPlayerModel\";\nimport { RenderScheduler } from \"../../controllers/RenderScheduler\";\nimport { ManagedCustomElement } from \"../ManagedCustomElement\";\nimport { customElementsShim } from \"../node-custom-element-shims\";\nimport { pixelRatio } from \"../canvas\";\nimport { twisty3DVantageCSS } from \"./Twisty3DVantage.css\";\nimport { DragTracker, PressInfo } from \"./DragTracker\";\nimport { newRenderer, renderPooled } from \"./RendererPool\";\nimport { DEGREES_PER_RADIAN } from \"./TAU\";\nimport type { Twisty3DSceneWrapper } from \"./Twisty3DSceneWrapper\";\nimport { TwistyOrbitControls } from \"./TwistyOrbitControls\";\n\nlet SHOW_STATS = false;\nexport function debugShowRenderStats(enable: boolean): void {\n SHOW_STATS = enable;\n}\n\nexport async function setCameraFromOrbitCoordinates(\n camera: PerspectiveCamera,\n orbitCoordinates: OrbitCoordinates,\n backView: boolean = false,\n): Promise<void> {\n const spherical = new (await THREEJS).Spherical(\n orbitCoordinates.distance,\n (90 - (backView ? -1 : 1) * orbitCoordinates.latitude) / DEGREES_PER_RADIAN,\n ((backView ? 180 : 0) + orbitCoordinates.longitude) / DEGREES_PER_RADIAN,\n );\n spherical.makeSafe();\n camera.position.setFromSpherical(spherical);\n camera.lookAt(0, 0, 0);\n}\n\nlet shareAllNewRenderers: boolean | null = null;\n\n// WARNING: The current shared renderer implementation is not every efficient.\n// Avoid using for players that are likely to have dimensions approaching 1 megapixel or higher.\n// TODO: use a dedicated renderer while fullscreen?\n// - true: Force all new (i.e. constructed in the future) renderers to be shared\n// - false: Force all new (i.e. constructed in the future) renderers to be dedicated\n// - null: Reset to the default heuristics.\nexport function experimentalForceNewRendererSharing(\n share: boolean | null,\n): void {\n shareAllNewRenderers = share;\n}\n\nlet dedicatedRenderersSoFar = 0;\nconst DEFAULT_MAX_DEDICATED_RENDERERS = 2; // This allows for a front view and a back view (or two separate front views).\nfunction shareRenderer(): boolean {\n if (shareAllNewRenderers !== null) {\n if (!shareAllNewRenderers) {\n dedicatedRenderersSoFar++;\n }\n return shareAllNewRenderers;\n }\n if (dedicatedRenderersSoFar < DEFAULT_MAX_DEDICATED_RENDERERS) {\n dedicatedRenderersSoFar++;\n return false;\n } else {\n return true;\n }\n}\n\nexport class Twisty3DVantage extends ManagedCustomElement {\n scene: Twisty3DSceneWrapper | null = null;\n\n stats: Stats | null = null;\n\n private rendererIsShared: boolean = shareRenderer();\n\n constructor(\n private model?: TwistyPlayerModel,\n scene?: Twisty3DSceneWrapper,\n private options?: { backView?: boolean },\n ) {\n super();\n this.scene = scene ?? null;\n\n if (SHOW_STATS) {\n this.stats = new Stats();\n this.stats.dom.style.position = \"absolute\";\n this.contentWrapper.appendChild(this.stats.dom);\n }\n }\n\n async connectedCallback(): Promise<void> {\n this.addCSS(twisty3DVantageCSS);\n this.addElement((await this.canvasInfo()).canvas);\n\n this.#onResize();\n const observer = new ResizeObserver(this.#onResize.bind(this));\n observer.observe(this.contentWrapper);\n this.orbitControls(); // TODO\n this.#setupBasicPresses();\n\n this.scheduleRender();\n }\n\n async #setupBasicPresses(): Promise<void> {\n const dragTracker = await this.#dragTracker();\n dragTracker.addEventListener(\"press\", async (e: CustomEvent<PressInfo>) => {\n const movePressInput = await this.model!.movePressInputProp.get();\n if (movePressInput !== \"basic\") {\n return;\n }\n this.dispatchEvent(\n new CustomEvent(\"press\", {\n detail: {\n pressInfo: e.detail,\n cameraPromise: this.camera(),\n },\n }),\n );\n });\n }\n\n #onResizeStaleDropper = new StaleDropper<PerspectiveCamera>();\n\n async clearCanvas(): Promise<void> {\n if (this.rendererIsShared) {\n const canvasInfo = await this.canvasInfo();\n canvasInfo.context.clearRect(\n 0,\n 0,\n canvasInfo.canvas.width,\n canvasInfo.canvas.height,\n );\n } else {\n const renderer = await this.renderer();\n const context = renderer.getContext();\n context.clear(context.COLOR_BUFFER_BIT);\n }\n }\n\n // TODO: Why doesn't this work for the top-right back view height?\n #width: number = 0;\n #height: number = 0;\n async #onResize(): Promise<void> {\n const camera = await this.#onResizeStaleDropper.queue(this.camera());\n\n const w = this.contentWrapper.clientWidth;\n const h = this.contentWrapper.clientHeight;\n this.#width = w;\n this.#height = h;\n const off = 0;\n let yoff = 0;\n let excess = 0;\n if (h > w) {\n excess = h - w;\n yoff = -Math.floor(0.5 * excess);\n }\n camera.aspect = w / h;\n camera.setViewOffset(w, h - excess, off, yoff, w, h);\n camera.updateProjectionMatrix(); // TODO\n\n this.clearCanvas();\n if (this.rendererIsShared) {\n const canvasInfo = await this.canvasInfo();\n\n canvasInfo.canvas.width = w * pixelRatio();\n canvasInfo.canvas.height = h * pixelRatio();\n canvasInfo.canvas.style.width = w.toString();\n canvasInfo.canvas.style.height = w.toString();\n } else {\n const renderer = await this.renderer();\n renderer.setSize(w, h, true);\n }\n\n this.scheduleRender();\n }\n\n #cachedRenderer: Promise<WebGLRenderer> | null = null;\n async renderer(): Promise<WebGLRenderer> {\n if (this.rendererIsShared) {\n throw new Error(\"renderer expected to be shared.\");\n }\n return (this.#cachedRenderer ??= newRenderer());\n }\n\n #cachedCanvas: Promise<{\n canvas: HTMLCanvasElement;\n context: CanvasRenderingContext2D;\n }> | null = null;\n async canvasInfo(): Promise<{\n canvas: HTMLCanvasElement;\n context: CanvasRenderingContext2D;\n }> {\n return (this.#cachedCanvas ??= (async () => {\n let canvas: HTMLCanvasElement;\n if (this.rendererIsShared) {\n canvas = this.addElement(document.createElement(\"canvas\"));\n } else {\n const renderer = await this.renderer();\n canvas = this.addElement(renderer.domElement);\n }\n const context = canvas.getContext(\"2d\")!;\n return { canvas, context };\n })());\n }\n\n #cachedDragTracker: Promise<DragTracker> | null = null;\n async #dragTracker(): Promise<DragTracker> {\n return (this.#cachedDragTracker ??= (async () => {\n return new DragTracker((await this.canvasInfo()).canvas);\n })());\n }\n\n #cachedCamera: Promise<PerspectiveCamera> | null = null;\n async camera(): Promise<PerspectiveCamera> {\n return (this.#cachedCamera ??= (async () => {\n const camera = new (await THREEJS).PerspectiveCamera(\n 20,\n 1, // We rely on the resize logic to handle this.\n 0.1,\n 20,\n );\n camera.position.copy(\n new (await THREEJS).Vector3(2, 4, 4).multiplyScalar(\n this.options?.backView ? -1 : 1,\n ),\n );\n camera.lookAt(0, 0, 0);\n // TODO: `TwistyOrbitControls` breaks isolateion\n return camera;\n })());\n }\n\n #cachedOrbitControls: Promise<TwistyOrbitControls> | null = null;\n async orbitControls(): Promise<TwistyOrbitControls> {\n return (this.#cachedOrbitControls ??= (async () => {\n const orbitControls = new TwistyOrbitControls(\n this.model!,\n !!this.options?.backView,\n (await this.canvasInfo()).canvas,\n await this.#dragTracker(),\n );\n\n if (this.model) {\n this.addListener(\n this.model.orbitCoordinatesProp,\n async (orbitCoordinates: OrbitCoordinates) => {\n const camera = await this.camera();\n setCameraFromOrbitCoordinates(\n camera,\n orbitCoordinates,\n this.options?.backView,\n );\n // TODO: Wrap in StaleDropper?\n\n this.scheduleRender();\n },\n );\n }\n\n return orbitControls;\n })());\n }\n\n addListener<T>(\n prop: TwistyPropParent<T>,\n listener: (value: T) => void,\n ): void {\n prop.addFreshListener(listener);\n this.#disconnectionFunctions.push(() => {\n prop.removeFreshListener(listener);\n // disconnected = true; // TODO\n });\n }\n\n #disconnectionFunctions: (() => void)[] = [];\n disconnect(): void {\n for (const fn of this.#disconnectionFunctions) {\n fn();\n }\n this.#disconnectionFunctions = []; // TODO: Encapsulate this.\n }\n\n async render(): Promise<void> {\n if (!this.scene) {\n throw new Error(\"Attempted to render without a scene\");\n }\n\n this.stats?.begin();\n\n const [scene, camera, canvas] = await Promise.all([\n this.scene.scene(),\n this.camera(),\n this.canvasInfo(),\n ]);\n if (this.rendererIsShared) {\n renderPooled(this.#width, this.#height, canvas.canvas, scene, camera);\n } else {\n (await this.renderer()).render(scene, camera);\n }\n\n this.stats?.end();\n }\n\n #scheduler = new RenderScheduler(this.render.bind(this));\n scheduleRender(): void {\n // console.log(\"scheduling\", this);\n this.#scheduler.requestAnimFrame();\n }\n}\n\ncustomElementsShim.define(\"twisty-3d-vantage\", Twisty3DVantage);\n", "import { CSSSource } from \"../ManagedCustomElement\";\n\nexport const buttonGridCSS = new CSSSource(`\n:host {\n width: 384px;\n height: 24px;\n display: grid;\n}\n\n.wrapper {\n width: 100%;\n height: 100%;\n display: grid;\n overflow: hidden;\n backdrop-filter: blur(4px);\n -webkit-backdrop-filter: blur(4px);\n}\n\n.wrapper {\n grid-auto-flow: column;\n}\n\n.viewer-link-none .twizzle-link-button {\n display: none;\n}\n\n.wrapper twisty-button-v2,\n.wrapper twisty-control-button {\n width: inherit;\n height: inherit;\n}\n`);\n\nexport const buttonCSS = new CSSSource(`\n:host:not([hidden]) {\n display: grid;\n}\n\n:host {\n width: 48px;\n height: 24px;\n}\n\n.wrapper {\n width: 100%;\n height: 100%;\n}\n\nbutton {\n width: 100%;\n height: 100%;\n border: none;\n \n background-position: center;\n background-repeat: no-repeat;\n background-size: contain;\n\n background-color: rgba(196, 196, 196, 0.75);\n}\n\nbutton:enabled {\n background-color: rgba(196, 196, 196, 0.75)\n}\n\nbutton:disabled {\n background-color: rgba(0, 0, 0, 0.4);\n opacity: 0.25;\n pointer-events: none;\n}\n\nbutton:enabled:hover {\n background-color: rgba(255, 255, 255, 0.75);\n box-shadow: 0 0 1em rgba(0, 0, 0, 0.25);\n cursor: pointer;\n}\n\n/* TODO: fullscreen icons have too much padding?? */\n.svg-skip-to-start button,\nbutton.svg-skip-to-start {\n background-image: url(\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIzNTg0IiBoZWlnaHQ9IjM1ODQiIHZpZXdCb3g9IjAgMCAzNTg0IDM1ODQiPjxwYXRoIGQ9Ik0yNjQzIDEwMzdxMTktMTkgMzItMTN0MTMgMzJ2MTQ3MnEwIDI2LTEzIDMydC0zMi0xM2wtNzEwLTcxMHEtOS05LTEzLTE5djcxMHEwIDI2LTEzIDMydC0zMi0xM2wtNzEwLTcxMHEtOS05LTEzLTE5djY3OHEwIDI2LTE5IDQ1dC00NSAxOUg5NjBxLTI2IDAtNDUtMTl0LTE5LTQ1VjEwODhxMC0yNiAxOS00NXQ0NS0xOWgxMjhxMjYgMCA0NSAxOXQxOSA0NXY2NzhxNC0xMSAxMy0xOWw3MTAtNzEwcTE5LTE5IDMyLTEzdDEzIDMydjcxMHE0LTExIDEzLTE5eiIvPjwvc3ZnPg==\");\n}\n\n.svg-skip-to-end button,\nbutton.svg-skip-to-end {\n background-image: url(\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIzNTg0IiBoZWlnaHQ9IjM1ODQiIHZpZXdCb3g9IjAgMCAzNTg0IDM1ODQiPjxwYXRoIGQ9Ik05NDEgMjU0N3EtMTkgMTktMzIgMTN0LTEzLTMyVjEwNTZxMC0yNiAxMy0zMnQzMiAxM2w3MTAgNzEwcTggOCAxMyAxOXYtNzEwcTAtMjYgMTMtMzJ0MzIgMTNsNzEwIDcxMHE4IDggMTMgMTl2LTY3OHEwLTI2IDE5LTQ1dDQ1LTE5aDEyOHEyNiAwIDQ1IDE5dDE5IDQ1djE0MDhxMCAyNi0xOSA0NXQtNDUgMTloLTEyOHEtMjYgMC00NS0xOXQtMTktNDV2LTY3OHEtNSAxMC0xMyAxOWwtNzEwIDcxMHEtMTkgMTktMzIgMTN0LTEzLTMydi03MTBxLTUgMTAtMTMgMTl6Ii8+PC9zdmc+\");\n}\n\n.svg-step-forward button,\nbutton.svg-step-forward {\n background-image: url(\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIzNTg0IiBoZWlnaHQ9IjM1ODQiIHZpZXdCb3g9IjAgMCAzNTg0IDM1ODQiPjxwYXRoIGQ9Ik0yNjg4IDE1NjhxMCAyNi0xOSA0NWwtNTEyIDUxMnEtMTkgMTktNDUgMTl0LTQ1LTE5cS0xOS0xOS0xOS00NXYtMjU2aC0yMjRxLTk4IDAtMTc1LjUgNnQtMTU0IDIxLjVxLTc2LjUgMTUuNS0xMzMgNDIuNXQtMTA1LjUgNjkuNXEtNDkgNDIuNS04MCAxMDF0LTQ4LjUgMTM4LjVxLTE3LjUgODAtMTcuNSAxODEgMCA1NSA1IDEyMyAwIDYgMi41IDIzLjV0Mi41IDI2LjVxMCAxNS04LjUgMjV0LTIzLjUgMTBxLTE2IDAtMjgtMTctNy05LTEzLTIydC0xMy41LTMwcS03LjUtMTctMTAuNS0yNC0xMjctMjg1LTEyNy00NTEgMC0xOTkgNTMtMzMzIDE2Mi00MDMgODc1LTQwM2gyMjR2LTI1NnEwLTI2IDE5LTQ1dDQ1LTE5cTI2IDAgNDUgMTlsNTEyIDUxMnExOSAxOSAxOSA0NXoiLz48L3N2Zz4=\");\n}\n\n.svg-step-backward button,\nbutton.svg-step-backward {\n background-image: url(\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIzNTg0IiBoZWlnaHQ9IjM1ODQiIHZpZXdCb3g9IjAgMCAzNTg0IDM1ODQiPjxwYXRoIGQ9Ik0yNjg4IDIwNDhxMCAxNjYtMTI3IDQ1MS0zIDctMTAuNSAyNHQtMTMuNSAzMHEtNiAxMy0xMyAyMi0xMiAxNy0yOCAxNy0xNSAwLTIzLjUtMTB0LTguNS0yNXEwLTkgMi41LTI2LjV0Mi41LTIzLjVxNS02OCA1LTEyMyAwLTEwMS0xNy41LTE4MXQtNDguNS0xMzguNXEtMzEtNTguNS04MC0xMDF0LTEwNS41LTY5LjVxLTU2LjUtMjctMTMzLTQyLjV0LTE1NC0yMS41cS03Ny41LTYtMTc1LjUtNmgtMjI0djI1NnEwIDI2LTE5IDQ1dC00NSAxOXEtMjYgMC00NS0xOWwtNTEyLTUxMnEtMTktMTktMTktNDV0MTktNDVsNTEyLTUxMnExOS0xOSA0NS0xOXQ0NSAxOXExOSAxOSAxOSA0NXYyNTZoMjI0cTcxMyAwIDg3NSA0MDMgNTMgMTM0IDUzIDMzM3oiLz48L3N2Zz4=\");\n}\n\n.svg-pause button,\nbutton.svg-pause {\n background-image: url(\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIzNTg0IiBoZWlnaHQ9IjM1ODQiIHZpZXdCb3g9IjAgMCAzNTg0IDM1ODQiPjxwYXRoIGQ9Ik0yNTYwIDEwODh2MTQwOHEwIDI2LTE5IDQ1dC00NSAxOWgtNTEycS0yNiAwLTQ1LTE5dC0xOS00NVYxMDg4cTAtMjYgMTktNDV0NDUtMTloNTEycTI2IDAgNDUgMTl0MTkgNDV6bS04OTYgMHYxNDA4cTAgMjYtMTkgNDV0LTQ1IDE5aC01MTJxLTI2IDAtNDUtMTl0LTE5LTQ1VjEwODhxMC0yNiAxOS00NXQ0NS0xOWg1MTJxMjYgMCA0NSAxOXQxOSA0NXoiLz48L3N2Zz4=\");\n}\n\n.svg-play button,\nbutton.svg-play {\n background-image: url(\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIzNTg0IiBoZWlnaHQ9IjM1ODQiIHZpZXdCb3g9IjAgMCAzNTg0IDM1ODQiPjxwYXRoIGQ9Ik0yNDcyLjUgMTgyM2wtMTMyOCA3MzhxLTIzIDEzLTM5LjUgM3QtMTYuNS0zNlYxMDU2cTAtMjYgMTYuNS0zNnQzOS41IDNsMTMyOCA3MzhxMjMgMTMgMjMgMzF0LTIzIDMxeiIvPjwvc3ZnPg==\");\n}\n\n.svg-enter-fullscreen button,\nbutton.svg-enter-fullscreen {\n background-image: url(\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGhlaWdodD0iMjgiIHZpZXdCb3g9IjAgMCAyOCAyOCIgd2lkdGg9IjI4Ij48cGF0aCBkPSJNMiAyaDI0djI0SDJ6IiBmaWxsPSJub25lIi8+PHBhdGggZD0iTTkgMTZIN3Y1aDV2LTJIOXYtM3ptLTItNGgyVjloM1Y3SDd2NXptMTIgN2gtM3YyaDV2LTVoLTJ2M3pNMTYgN3YyaDN2M2gyVjdoLTV6Ii8+PC9zdmc+\");\n}\n\n.svg-exit-fullscreen button,\nbutton.svg-exit-fullscreen {\n background-image: url(\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGhlaWdodD0iMjgiIHZpZXdCb3g9IjAgMCAyOCAyOCIgd2lkdGg9IjI4Ij48cGF0aCBkPSJNMiAyaDI0djI0SDJ6IiBmaWxsPSJub25lIi8+PHBhdGggZD0iTTcgMThoM3YzaDJ2LTVIN3Yyem0zLThIN3YyaDVWN2gtMnYzem02IDExaDJ2LTNoM3YtMmgtNXY1em0yLTExVjdoLTJ2NWg1di0yaC0zeiIvPjwvc3ZnPg==\");\n}\n\n.svg-twizzle-tw button,\nbutton.svg-twizzle-tw {\n background-image: url(\"data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iODY0IiBoZWlnaHQ9IjYwMCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cGF0aCBkPSJNMzk3LjU4MSAxNTEuMTh2NTcuMDg0aC04OS43MDN2MjQwLjM1MmgtNjYuOTU1VjIwOC4yNjRIMTUxLjIydi01Ny4wODNoMjQ2LjM2MXptNTQuMzEgNzEuNjc3bDcuNTEyIDMzLjY5MmMyLjcxOCAxMi4xNiA1LjU4IDI0LjY4IDguNTg0IDM3LjU1NWEyMTgwLjc3NSAyMTgwLjc3NSAwIDAwOS40NDIgMzguODQzIDEyNjYuMyAxMjY2LjMgMCAwMDEwLjA4NiAzNy41NTVjMy43Mi0xMi41OSA3LjM2OC0yNS40NjYgMTAuOTQ1LTM4LjYyOCAzLjU3Ni0xMy4xNjIgNy4wMS0yNi4xMSAxMC4zLTM4Ljg0M2w1Ljc2OS0yMi40NTZjMS4yNDgtNC44ODcgMi40NzItOS43MDUgMy42NzQtMTQuNDU1IDMuMDA0LTExLjg3NSA1LjY1MS0yMi45NjIgNy45NC0zMy4yNjNoNDYuMzU0bDIuMzg0IDEwLjU2M2EyMDAwLjc3IDIwMDAuNzcgMCAwMDMuOTM1IDE2LjgyOGw2LjcxMSAyNy43MWMxLjIxMyA0Ljk1NiAyLjQ1IDkuOTggMy43MDkgMTUuMDczYTMxMTkuNzc3IDMxMTkuNzc3IDAgMDA5Ljg3MSAzOC44NDMgMTI0OS4yMjcgMTI0OS4yMjcgMCAwMDEwLjczIDM4LjYyOCAxOTA3LjYwNSAxOTA3LjYwNSAwIDAwMTAuMzAxLTM3LjU1NSAxMzk3Ljk0IDEzOTcuOTQgMCAwMDkuNjU3LTM4Ljg0M2w0LjQtMTkuMDQ2Yy43MTUtMy4xMyAxLjQyMS02LjIzNiAyLjExOC05LjMyMWw5LjU3Ny00Mi44OGg2Ni41MjZhMjk4OC43MTggMjk4OC43MTggMCAwMS0xOS41MjkgNjYuMzExbC01LjcyOCAxOC40ODJhMzIzNy40NiAzMjM3LjQ2IDAgMDEtMTQuMDE1IDQzLjc1MmMtNi40MzggMTkuNi0xMi43MzMgMzcuNjk4LTE4Ljg4NSA1NC4yOTRsLTMuMzA2IDguODI1Yy00Ljg4NCAxMi44OTgtOS40MzMgMjQuMjYzLTEzLjY0NyAzNC4wOTVoLTQ5Ljc4N2E4NDE3LjI4OSA4NDE3LjI4OSAwIDAxLTIxLjAzMS02NC44MDkgMTI4OC42ODYgMTI4OC42ODYgMCAwMS0xOC44ODUtNjQuODEgMTk3Mi40NDQgMTk3Mi40NDQgMCAwMS0xOC4yNCA2NC44MSAyNTc5LjQxMiAyNTc5LjQxMiAwIDAxLTIwLjM4OCA2NC44MWgtNDkuNzg3Yy00LjY4Mi0xMC45MjYtOS43Mi0yMy43NDMtMTUuMTEtMzguNDUxbC0xLjYyOS00LjQ3Yy01LjI1OC0xNC41MjEtMTAuNjgtMzAuMTkyLTE2LjI2Ni00Ny4wMTRsLTIuNDA0LTcuMjhjLTYuNDM4LTE5LjYtMTMuMDItNDAuMzQ0LTE5Ljc0My02Mi4yMzRhMjk4OC43MDcgMjk4OC43MDcgMCAwMS0xOS41MjktNjYuMzExaDY3LjM4NXoiIGZpbGw9IiM0Mjg1RjQiIGZpbGwtcnVsZT0ibm9uemVybyIvPjwvc3ZnPg==\");\n}\n`);\n\n// Sized against full-screen dimensions.\n// button.svg-twizzle-tw {\n// background-image: url(\"data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNzc3IiBoZWlnaHQ9IjUxMyIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cGF0aCBkPSJNMzU0LjU4MSAxMDcuMTh2NTcuMDg0aC04OS43MDN2MjQwLjM1MmgtNjYuOTU1VjE2NC4yNjRIMTA4LjIydi01Ny4wODNoMjQ2LjM2MXptNTQuMzEgNzEuNjc3bDcuNTEyIDMzLjY5MmMyLjcxOCAxMi4xNiA1LjU4IDI0LjY4IDguNTg0IDM3LjU1NWEyMTgwLjc3NSAyMTgwLjc3NSAwIDAwOS40NDIgMzguODQzIDEyNjYuMyAxMjY2LjMgMCAwMDEwLjA4NiAzNy41NTVjMy43Mi0xMi41OSA3LjM2OC0yNS40NjYgMTAuOTQ1LTM4LjYyOCAzLjU3Ni0xMy4xNjIgNy4wMS0yNi4xMSAxMC4zLTM4Ljg0M2w1Ljc2OS0yMi40NTZjMS4yNDgtNC44ODcgMi40NzItOS43MDUgMy42NzQtMTQuNDU1IDMuMDA0LTExLjg3NSA1LjY1MS0yMi45NjIgNy45NC0zMy4yNjNoNDYuMzU0bDIuMzg0IDEwLjU2M2EyMDAwLjc3IDIwMDAuNzcgMCAwMDMuOTM1IDE2LjgyOGw2LjcxMSAyNy43MWMxLjIxMyA0Ljk1NiAyLjQ1IDkuOTggMy43MDkgMTUuMDczYTMxMTkuNzc3IDMxMTkuNzc3IDAgMDA5Ljg3MSAzOC44NDMgMTI0OS4yMjcgMTI0OS4yMjcgMCAwMDEwLjczIDM4LjYyOCAxOTA3LjYwNSAxOTA3LjYwNSAwIDAwMTAuMzAxLTM3LjU1NSAxMzk3Ljk0IDEzOTcuOTQgMCAwMDkuNjU3LTM4Ljg0M2w0LjQtMTkuMDQ2Yy43MTUtMy4xMyAxLjQyMS02LjIzNiAyLjExOC05LjMyMWw5LjU3Ny00Mi44OGg2Ni41MjZhMjk4OC43MTggMjk4OC43MTggMCAwMS0xOS41MjkgNjYuMzExbC01LjcyOCAxOC40ODJhMzIzNy40NiAzMjM3LjQ2IDAgMDEtMTQuMDE1IDQzLjc1MmMtNi40MzggMTkuNi0xMi43MzMgMzcuNjk4LTE4Ljg4NSA1NC4yOTRsLTMuMzA2IDguODI1Yy00Ljg4NCAxMi44OTgtOS40MzMgMjQuMjYzLTEzLjY0NyAzNC4wOTVoLTQ5Ljc4N2E4NDE3LjI4OSA4NDE3LjI4OSAwIDAxLTIxLjAzMS02NC44MDkgMTI4OC42ODYgMTI4OC42ODYgMCAwMS0xOC44ODUtNjQuODEgMTk3Mi40NDQgMTk3Mi40NDQgMCAwMS0xOC4yNCA2NC44MSAyNTc5LjQxMiAyNTc5LjQxMiAwIDAxLTIwLjM4OCA2NC44MWgtNDkuNzg3Yy00LjY4Mi0xMC45MjYtOS43Mi0yMy43NDMtMTUuMTEtMzguNDUxbC0xLjYyOS00LjQ3Yy01LjI1OC0xNC41MjEtMTAuNjgtMzAuMTkyLTE2LjI2Ni00Ny4wMTRsLTIuNDA0LTcuMjhjLTYuNDM4LTE5LjYtMTMuMDItNDAuMzQ0LTE5Ljc0My02Mi4yMzRhMjk4OC43MDcgMjk4OC43MDcgMCAwMS0xOS41MjktNjYuMzExaDY3LjM4NXoiIGZpbGw9IiM0Mjg1RjQiIGZpbGwtcnVsZT0ibm9uemVybyIvPjwvc3ZnPg==\");\n// }\n", "// Use like this:\n// const enabled = globalSafeDocument?.fullscreenEnabled;\nexport const globalSafeDocument: Document | null =\n typeof document === \"undefined\" ? null : document;\n", "// Ponyfills for prefixing in Safari.\n\nimport { globalSafeDocument } from \"../document\";\n\ndeclare global {\n interface Document {\n webkitFullscreenEnabled?: boolean;\n webkitExitFullscreen?: () => Promise<void>;\n webkitFullscreenElement?: Element | null;\n }\n\n interface Element {\n webkitRequestFullscreen: () => Promise<void>;\n }\n}\n\n// TODO: Can `webkitFullscreenEnabled` change after it's cached at page load?\nexport const fullscreenEnabled: boolean =\n globalSafeDocument?.fullscreenEnabled ||\n !!globalSafeDocument?.webkitFullscreenEnabled;\n\nexport function documentExitFullscreen(): Promise<void> {\n if (document.exitFullscreen) {\n return document.exitFullscreen();\n } else {\n return document.webkitExitFullscreen!(); // YOLO\n }\n}\n\nexport function documentFullscreenElement(): Element | null {\n if (document.fullscreenElement) {\n return document.fullscreenElement;\n } else {\n return document.webkitFullscreenElement ?? null;\n }\n}\n\nexport function requestFullscreen(element: Element): Promise<void> {\n if (element.requestFullscreen) {\n return element.requestFullscreen();\n } else {\n return element.webkitRequestFullscreen();\n }\n}\n", "import type { ButtonCommand } from \"../../../views/control-panel/TwistyButtonsV2\";\nimport { fullscreenEnabled } from \"../../../views/control-panel/webkit-fullscreen\";\nimport type { ViewerLinkPageWithAuto } from \"./ViewerLinkProp\";\nimport type { CoarseTimelineInfo as CoarseTimelineInfo } from \"../timeline/CoarseTimelineInfoProp\";\nimport { TwistyPropDerived } from \"../TwistyProp\";\n\nexport const buttonIcons = [\n \"skip-to-start\",\n \"skip-to-end\",\n \"step-forward\",\n \"step-backward\",\n \"pause\",\n \"play\",\n \"enter-fullscreen\",\n \"exit-fullscreen\",\n \"twizzle-tw\",\n];\nexport type ButtonIcon = typeof buttonIcons[number];\n\ninterface ButtonAppearance {\n enabled: boolean;\n icon: ButtonIcon;\n title: string;\n hidden?: boolean;\n}\nexport type ButtonAppearances = Record<ButtonCommand, ButtonAppearance>;\n\n// TODO: reduce inputs to avoid unnecessary updates.\ninterface ButtonAppearancePropInputs {\n coarseTimelineInfo: CoarseTimelineInfo;\n viewerLink: ViewerLinkPageWithAuto;\n}\n\nexport class ButtonAppearanceProp extends TwistyPropDerived<\n ButtonAppearancePropInputs,\n ButtonAppearances\n> {\n // TODO: This still seems to fire twice for play/pause?\n derive(inputs: ButtonAppearancePropInputs): ButtonAppearances {\n const buttonAppearances = {\n \"fullscreen\": {\n // TODO: Cache?// TODO: Cache?\n enabled: fullscreenEnabled,\n icon:\n // TODO: Check against the expected element?\n // TODO: This will *not* update when we enter/leave fullscreen. We need to work more closely with the controller.\n document.fullscreenElement === null\n ? \"enter-fullscreen\"\n : \"exit-fullscreen\",\n title: \"Enter fullscreen\",\n },\n \"jump-to-start\": {\n enabled: !inputs.coarseTimelineInfo.atStart,\n icon: \"skip-to-start\",\n title: \"Restart\",\n },\n \"play-step-backwards\": {\n enabled: !inputs.coarseTimelineInfo.atStart,\n icon: \"step-backward\",\n title: \"Step backward\",\n },\n \"play-pause\": {\n enabled: true,\n icon: inputs.coarseTimelineInfo.playing ? \"pause\" : \"play\",\n title: inputs.coarseTimelineInfo.playing ? \"Pause\" : \"Play\",\n },\n \"play-step\": {\n enabled: !inputs.coarseTimelineInfo.atEnd,\n icon: \"step-forward\",\n title: \"Step forward\",\n },\n \"jump-to-end\": {\n enabled: !inputs.coarseTimelineInfo.atEnd,\n icon: \"skip-to-end\",\n title: \"Skip to End\",\n },\n \"twizzle-link\": {\n enabled: true,\n icon: \"twizzle-tw\",\n title: \"View at Twizzle\",\n hidden: inputs.viewerLink === \"none\",\n },\n };\n return buttonAppearances;\n }\n}\n", "import { BoundaryType, Direction } from \"../../controllers/AnimationTypes\";\nimport { buttonCSS, buttonGridCSS } from \"./TwistyButtonsV2.css\";\nimport { ClassListManager } from \"../ClassListManager\";\nimport { ManagedCustomElement } from \"../ManagedCustomElement\";\nimport { customElementsShim } from \"../node-custom-element-shims\";\nimport {\n ButtonAppearances,\n ButtonIcon,\n buttonIcons,\n} from \"../../model/props/viewer/ButtonAppearanceProp\";\nimport type { TwistyPlayerModel } from \"../../model/TwistyPlayerModel\";\nimport type { TwistyPlayerController } from \"../../controllers/TwistyPlayerController\";\nimport {\n documentExitFullscreen,\n documentFullscreenElement,\n requestFullscreen,\n} from \"./webkit-fullscreen\";\n\nconst buttonCommands = {\n \"fullscreen\": true,\n \"jump-to-start\": true,\n \"play-step-backwards\": true,\n \"play-pause\": true,\n \"play-step\": true,\n \"jump-to-end\": true,\n \"twizzle-link\": true,\n};\n\nexport type ButtonCommand = keyof typeof buttonCommands;\n\nexport class TwistyButtonsV2 extends ManagedCustomElement {\n buttons: Record<ButtonCommand, TwistyButtonV2> | null = null;\n\n // TODO: Privacy\n constructor(\n public model?: TwistyPlayerModel,\n public controller?: TwistyPlayerController,\n private fullscreenElement?: HTMLElement,\n ) {\n super();\n }\n\n connectedCallback(): void {\n this.addCSS(buttonGridCSS);\n const buttons: Partial<Record<ButtonCommand, TwistyButtonV2>> = {};\n for (const command in buttonCommands) {\n const button = new TwistyButtonV2();\n buttons[command as ButtonCommand] = button;\n // Why does this still fire with the `disabled` attribute?\n button.addEventListener(\"click\", () =>\n this.#onCommand(command as ButtonCommand),\n );\n this.addElement(button);\n }\n this.buttons = buttons as Record<ButtonCommand, TwistyButtonV2>;\n\n this.model?.buttonAppearanceProp.addFreshListener(this.update.bind(this));\n }\n\n #onCommand(command: ButtonCommand) {\n switch (command) {\n case \"fullscreen\":\n this.onFullscreenButton();\n break;\n case \"jump-to-start\":\n this.controller?.jumpToStart({ flash: true });\n break;\n case \"play-step-backwards\":\n this.controller?.animationController.play({\n direction: Direction.Backwards,\n untilBoundary: BoundaryType.Move,\n });\n break;\n case \"play-pause\":\n this.controller?.togglePlay();\n break;\n case \"play-step\":\n this.controller?.animationController.play({\n direction: Direction.Forwards,\n untilBoundary: BoundaryType.Move,\n });\n break;\n case \"jump-to-end\":\n this.controller?.jumpToEnd({ flash: true });\n break;\n case \"twizzle-link\":\n this.controller?.visitTwizzleLink();\n break;\n default:\n throw new Error(\"Missing command\");\n }\n }\n\n // TODO: Should we have a prop, or a way to query if we're fullscreen?\n // https://developer.mozilla.org/en-US/docs/Web/API/Element/requestFullScreen\n async onFullscreenButton(): Promise<void> {\n if (!this.fullscreenElement) {\n throw new Error(\"Attempted to go fullscreen without an element.\");\n }\n\n if (documentFullscreenElement() === this.fullscreenElement) {\n documentExitFullscreen();\n } else {\n // TODO: Propagate button info to `ButtonAppearanceProp`.\n this.buttons?.fullscreen.setIcon(\"exit-fullscreen\");\n\n requestFullscreen(this.fullscreenElement);\n\n const onFullscreen = (): void => {\n if (documentFullscreenElement() !== this.fullscreenElement) {\n this.buttons?.fullscreen.setIcon(\"enter-fullscreen\");\n window.removeEventListener(\"fullscreenchange\", onFullscreen);\n }\n };\n window.addEventListener(\"fullscreenchange\", onFullscreen);\n }\n }\n\n async update(buttonAppearances: ButtonAppearances): Promise<void> {\n // TODO: Check that we have every command?\n for (const command in buttonCommands) {\n // TODO: Why doesn't `command` have the type `ButtonCommand`?\n const button = this.buttons![command as ButtonCommand];\n // TODO: track individual changes?\n const info = buttonAppearances[command as ButtonCommand];\n button.button.disabled = !info.enabled;\n button.button.title = info.title;\n button.setIcon(info.icon);\n button.hidden = !!info.hidden;\n // button.textContent = info.icon;\n }\n }\n}\n\ncustomElementsShim.define(\"twisty-buttons-v2\", TwistyButtonsV2);\n\nclass TwistyButtonV2 extends ManagedCustomElement {\n button: HTMLButtonElement = document.createElement(\"button\"); // TODO: async?\n\n connectedCallback() {\n this.addCSS(buttonCSS);\n this.addElement(this.button);\n }\n\n #iconManager: ClassListManager<ButtonIcon> = new ClassListManager(\n this,\n \"svg-\",\n buttonIcons,\n );\n\n setIcon(iconName: ButtonIcon): void {\n this.#iconManager.setValue(iconName);\n }\n}\n\ncustomElementsShim.define(\"twisty-button-v2\", TwistyButtonV2);\n", "import { CSSSource } from \"../ManagedCustomElement\";\n\nexport const twistyScrubberCSS = new CSSSource(`\n:host {\n width: 384px;\n height: 16px;\n display: grid;\n}\n\n.wrapper {\n width: 100%;\n height: 100%;\n display: grid;\n overflow: hidden;\n backdrop-filter: blur(4px);\n -webkit-backdrop-filter: blur(4px);\n}\n\ninput {\n margin: 0; width: 100%;\n}\n\ninput {\n background: none;\n}\n\n::-moz-range-track {\n background: rgba(0, 0, 0, 0.25);\n height: 50%;\n border: 1px solid rgba(0, 0, 0, 0.1);\n}\n\n::-webkit-slider-runnable-track {\n background: rgba(0, 0, 0, 0.05);\n}\n\n::-moz-range-progress {\n background: #3273F6;\n height: 50%;\n border: 1px solid rgba(0, 0, 0, 0.1);\n}\n\n::-ms-fill-lower {\n background: #3273F6;\n height: 50%;\n border: 1px solid rgba(0, 0, 0, 0.1);\n}\n`);\n", "import { twistyScrubberCSS } from \"./TwistyScrubber.css\";\nimport { ManagedCustomElement } from \"../ManagedCustomElement\";\nimport { customElementsShim } from \"../node-custom-element-shims\";\nimport type { DetailedTimelineInfo } from \"../../model/props/timeline/DetailedTimelineInfoProp\";\nimport type { TwistyPlayerModel } from \"../../model/TwistyPlayerModel\";\nimport { globalSafeDocument } from \"../document\";\n\nconst SLOW_DOWN_SCRUBBING = false;\n\nlet isMouseDown = false;\n\nglobalSafeDocument?.addEventListener(\n \"mousedown\",\n function (event) {\n if (event.which) isMouseDown = true;\n },\n true,\n);\n\nglobalSafeDocument?.addEventListener(\n \"mouseup\",\n function (event) {\n if (event.which) isMouseDown = false;\n },\n true,\n);\n\n// var x = 0;\nlet y = 0;\nlet clickNum = 0;\n\nglobalSafeDocument?.addEventListener(\n \"mousedown\",\n () => {\n clickNum++;\n },\n false,\n);\n\nglobalSafeDocument?.addEventListener(\"mousemove\", onMouseUpdate, false);\nglobalSafeDocument?.addEventListener(\"mouseenter\", onMouseUpdate, false);\n\nfunction onMouseUpdate(e: MouseEvent) {\n // x = e.pageX;\n y = e.pageY;\n // console.log(x, y);\n}\n\nconst lastVal = 0;\nlet lastPreval = 0;\nlet scaling: boolean = false;\nlet currentClickNum = 0;\n\n// Values are integers.\nexport class TwistyScrubberV2 extends ManagedCustomElement {\n constructor(public model?: TwistyPlayerModel) {\n super();\n }\n\n async onDetailedTimelineInfo(\n detailedTimelineInfo: DetailedTimelineInfo,\n ): Promise<void> {\n // TODO: is this efficient enough?\n const inputElem = await this.inputElem();\n inputElem.min = detailedTimelineInfo.timeRange.start.toString();\n inputElem.max = detailedTimelineInfo.timeRange.end.toString();\n inputElem.value = detailedTimelineInfo.timestamp.toString();\n }\n\n async connectedCallback(): Promise<void> {\n this.addCSS(twistyScrubberCSS);\n this.addElement(await this.inputElem());\n }\n\n #inputElem: Promise<HTMLInputElement> | null = null;\n async inputElem(): Promise<HTMLInputElement> {\n // console.log(\"inputElem\", this.#inputElem);\n return (this.#inputElem ??= (async () => {\n const elem = document.createElement(\"input\");\n elem.type = \"range\";\n\n // console.log(\"1\");\n this.model?.detailedTimelineInfoProp.addFreshListener(\n this.onDetailedTimelineInfo.bind(this),\n );\n // console.log(\"3\");\n elem.addEventListener(\"input\", this.onInput.bind(this));\n\n return elem;\n })());\n }\n\n async onInput(e: Event): Promise<void> {\n if (scaling) {\n return; // TODO\n }\n const inputElem = await this.inputElem();\n await this.slowDown(e, inputElem); // TODO\n\n const value = parseInt(inputElem.value);\n // console.log(\"on input\", value);\n this.model?.playingInfoProp.set({ playing: false });\n this.model?.timestampRequestProp.set(value);\n }\n\n async slowDown(e: Event, inputElem: HTMLInputElement): Promise<void> {\n if (!SLOW_DOWN_SCRUBBING) {\n return; // TODO\n }\n\n if (isMouseDown) {\n const rect = inputElem.getBoundingClientRect();\n const sliderY = rect.top + rect.height / 2;\n console.log(sliderY, e, y, isMouseDown);\n\n const yDist = Math.abs(sliderY - y);\n let scale = 1;\n if (yDist > 64) {\n scale = Math.max(Math.pow(2, -(yDist - 64) / 64), 1 / 32);\n }\n const preVal = parseInt(inputElem.value);\n console.log(\"cl\", currentClickNum, clickNum, preVal);\n if (currentClickNum === clickNum) {\n const delta = (preVal - lastPreval) * scale;\n console.log(\"delta\", delta, yDist);\n scaling = true;\n let newVal = preVal;\n newVal =\n lastVal +\n delta * scale +\n (preVal - lastVal) *\n Math.min(1, Math.pow(1 / 2, (yDist * yDist) / 64));\n inputElem.value = newVal.toString();\n console.log(scale);\n scaling = false;\n this.contentWrapper.style.opacity = scale.toString();\n } else {\n currentClickNum = clickNum;\n }\n lastPreval = preVal;\n }\n }\n}\n\ncustomElementsShim.define(\"twisty-scrubber-v2\", TwistyScrubberV2);\n", "import { PerspectiveCamera, WebGLRenderer } from \"three\";\nimport { THREEJS } from \"../heavy-code-imports/3d\";\nimport type { TwistyPlayerModel } from \"../model/TwistyPlayerModel\";\nimport { Twisty3DPuzzleWrapper } from \"./3D/Twisty3DPuzzleWrapper\";\nimport { setCameraFromOrbitCoordinates } from \"./3D/Twisty3DVantage\";\n\nexport interface TwistyPlayerScreenshot {\n dataURL: string;\n download: (filename?: string) => Promise<void>;\n}\n\n// TODO: cache\nlet cachedCamera: PerspectiveCamera | null = null;\nexport async function screenshot(\n model: TwistyPlayerModel,\n options?: { width: number; height: number },\n): Promise<TwistyPlayerScreenshot> {\n // TODO: improve async caching\n\n const width = options?.width ?? 2048;\n const height = options?.height ?? 2048;\n const aspectRatio = width / height;\n const camera = (cachedCamera ??= await (async () => {\n return new (await THREEJS).PerspectiveCamera(20, aspectRatio, 0.1, 20);\n })());\n\n const scene = new (await THREEJS).Scene();\n\n const twisty3DWrapper = new Twisty3DPuzzleWrapper(\n model,\n { scheduleRender: () => {} },\n await model.puzzleLoaderProp.get(),\n await model.visualizationStrategyProp.get(),\n );\n\n // TODO: Pass the stickering to the constructor so we don't have to wait..\n await model.stickeringProp.get();\n await new Promise((resolve) => setTimeout(resolve, 1000));\n\n // TODO: Find a more robust way to do this.\n await model.legacyPositionProp.get(); // Force the 3D puzzle listeners for the state to fire.\n\n scene.add(await twisty3DWrapper.twisty3DPuzzle());\n\n const orbitCoordinates = await model.orbitCoordinatesProp.get();\n await setCameraFromOrbitCoordinates(camera, orbitCoordinates);\n\n const renderer = new WebGLRenderer({\n antialias: true,\n alpha: true,\n });\n renderer.setSize(width, height);\n\n renderer.render(scene, camera);\n const dataURL = renderer.domElement.toDataURL();\n\n const defaultFilename = await getDefaultFilename(model);\n\n return {\n dataURL,\n download: async (filename?: string) => {\n downloadURL(dataURL, filename ?? defaultFilename);\n },\n };\n}\n\nexport async function getDefaultFilename(\n model: TwistyPlayerModel,\n): Promise<string> {\n const [puzzleID, algWithIssues] = await Promise.all([\n model.puzzleIDProp.get(),\n model.algProp.get(),\n ]);\n return `[${puzzleID}]${\n algWithIssues.alg.experimentalNumUnits() === 0\n ? \"\"\n : \" \" + algWithIssues.alg.toString()\n }`;\n}\n\nexport function downloadURL(\n url: string,\n name: string,\n extension: string = \"png\",\n): void {\n const a = document.createElement(\"a\");\n a.href = url;\n a.download = `${name}.${extension}`;\n a.click();\n}\n", "import { Alg } from \"../../../../../alg\";\nimport { arrayEquals } from \"../../../helpers\";\nimport { TwistyPropSource } from \"../../TwistyProp\";\n\nexport class AlgIssues {\n // TODO: (string | Error)[]\n\n readonly warnings: readonly string[];\n readonly errors: readonly string[];\n\n constructor(issues?: { warnings?: string[]; errors?: string[] }) {\n // TODO: clone inputs?\n this.warnings = Object.freeze(issues?.warnings ?? []);\n this.errors = Object.freeze(issues?.errors ?? []);\n Object.freeze(this);\n }\n\n add(issues?: { warnings?: string[]; errors?: string[] }) {\n return new AlgIssues({\n warnings: this.warnings.concat(issues?.warnings ?? []),\n errors: this.errors.concat(issues?.errors ?? []),\n });\n }\n\n /** @deprecated */\n log() {\n if (this.errors.length > 0) {\n console.error(`\uD83D\uDEA8 ${this.errors[0]}`);\n } else if (this.warnings.length > 0) {\n console.warn(`\u26A0\uFE0F ${this.warnings[0]}`);\n } else {\n console.info(\"\uD83D\uDE0E No issues!\");\n }\n }\n}\n\nexport interface AlgWithIssues {\n alg: Alg;\n issues: AlgIssues;\n}\n\nexport function algWithIssuesFromString(s: string): AlgWithIssues {\n try {\n const alg = Alg.fromString(s); // TODO: is this safe?\n const warnings = [];\n if (alg.toString() !== s) {\n // TODO: Push this check into the parser and return semantic info (so they can be e.g. highlighted).\n warnings.push(`Alg is non-canonical!`);\n }\n return {\n alg,\n issues: new AlgIssues({ warnings }),\n };\n } catch (e) {\n return {\n alg: new Alg(),\n issues: new AlgIssues({\n errors: [`Malformed alg: ${(e as Error).toString()}`],\n }),\n };\n }\n}\n\nfunction algWithIssuesEquals(a1: AlgWithIssues, a2: AlgWithIssues): boolean {\n return (\n a1.alg.isIdentical(a2.alg) &&\n arrayEquals(a1.issues.warnings, a2.issues.warnings) &&\n arrayEquals(a1.issues.errors, a2.issues.errors)\n );\n}\n\nexport class AlgProp extends TwistyPropSource<AlgWithIssues, Alg | string> {\n getDefaultValue(): AlgWithIssues {\n return { alg: new Alg(), issues: new AlgIssues() };\n }\n\n canReuseValue(v1: AlgWithIssues, v2: AlgWithIssues) {\n return algWithIssuesEquals(v1, v2);\n }\n\n async derive(newAlg: Alg | string): Promise<AlgWithIssues> {\n if (typeof newAlg === \"string\") {\n return algWithIssuesFromString(newAlg);\n } else {\n return {\n alg: newAlg,\n issues: new AlgIssues(),\n };\n }\n }\n}\n", "import { SimpleTwistyPropSource } from \"../TwistyProp\";\n\nexport const backgroundThemes = {\n checkered: true, // default\n none: true,\n};\nexport type BackgroundTheme = keyof typeof backgroundThemes;\n\nexport type BackgroundThemeWithAuto = BackgroundTheme | \"auto\";\n\nexport class BackgroundProp extends SimpleTwistyPropSource<BackgroundThemeWithAuto> {\n getDefaultValue(): BackgroundThemeWithAuto {\n return \"auto\";\n }\n}\n", "import { SimpleTwistyPropSource } from \"../TwistyProp\";\n\nexport const backViewLayouts = {\n \"none\": true, // default\n \"side-by-side\": true,\n \"top-right\": true,\n};\nexport type BackViewLayout = keyof typeof backViewLayouts;\n\nexport type BackViewLayoutWithAuto = BackViewLayout | \"auto\";\n\nexport class BackViewProp extends SimpleTwistyPropSource<BackViewLayoutWithAuto> {\n getDefaultValue(): BackViewLayoutWithAuto {\n return \"auto\";\n }\n}\n", "import { SimpleTwistyPropSource } from \"../../TwistyProp\";\n\nexport const indexerStrategyNames = {\n auto: true,\n simple: true,\n tree: true,\n simultaneous: true,\n};\nexport type IndexerStrategyName = keyof typeof indexerStrategyNames;\n\nexport class IndexerConstructorRequestProp extends SimpleTwistyPropSource<IndexerStrategyName> {\n getDefaultValue(): IndexerStrategyName {\n return \"auto\";\n }\n}\n", "import { SimpleTwistyPropSource } from \"../TwistyProp\";\nimport type { CoordinateDegrees } from \"./OrbitCoordinatesRequestProp\";\n\n// Similar to https://alg.cubing.net/\nconst DEFAULT_LATITUDE_LIMIT = 35;\n\nexport class LatitudeLimitProp extends SimpleTwistyPropSource<CoordinateDegrees> {\n getDefaultValue(): CoordinateDegrees {\n return DEFAULT_LATITUDE_LIMIT;\n }\n}\n", "import { mod } from \"../../helpers\";\nimport { TwistyPropSource } from \"../TwistyProp\";\n\nexport type CoordinateDegrees = number;\n\nexport interface OrbitCoordinates {\n latitude: CoordinateDegrees;\n longitude: CoordinateDegrees;\n distance: number;\n}\n\nexport function orbitCoordinatesEqual(\n c1: OrbitCoordinates,\n c2: OrbitCoordinates,\n): boolean {\n return (\n c1.latitude === c2.latitude &&\n c1.longitude === c2.longitude &&\n c1.distance === c2.distance\n );\n}\n\n// TOOD: Check if freezing affects perf.\n// const DEFAULT_COORDINATES = Object.freeze({\n// latitude: 35,\n// longitude: 30,\n// distance: 6,\n// });\n\nexport type OrbitCoordinatesRequest = Partial<OrbitCoordinates> | \"auto\";\n\n// TODO: Put the \"auto\" calculations in a separate place.\nexport class OrbitCoordinatesRequestProp extends TwistyPropSource<\n OrbitCoordinatesRequest,\n Partial<OrbitCoordinates> | \"auto\"\n> {\n getDefaultValue(): OrbitCoordinatesRequest {\n return \"auto\";\n }\n\n canReuseValue(v1: OrbitCoordinates, v2: OrbitCoordinates) {\n return v1 === v2 || orbitCoordinatesEqual(v1, v2);\n }\n\n async derive(\n newCoordinates: Partial<OrbitCoordinates> | \"auto\",\n oldValuePromise: Promise<OrbitCoordinatesRequest>,\n ): Promise<OrbitCoordinatesRequest> {\n if (newCoordinates === \"auto\") {\n return \"auto\";\n }\n\n let oldValue = await oldValuePromise;\n if (oldValue === \"auto\") {\n oldValue = {};\n }\n\n const newValue: Partial<OrbitCoordinates> = Object.assign({}, oldValue);\n Object.assign(newValue, newCoordinates);\n\n if (typeof newValue.latitude !== \"undefined\") {\n newValue.latitude = Math.min(Math.max(newValue.latitude, -90), 90);\n }\n if (typeof newValue.longitude !== \"undefined\") {\n newValue.longitude = mod(newValue.longitude, 360, 180);\n }\n return newValue;\n }\n}\n", "import { BoundaryType, Direction } from \"../../../controllers/AnimationTypes\";\nimport { TwistyPropSource } from \"../TwistyProp\";\n\nexport type SimpleDirection = Direction.Forwards | Direction.Backwards;\n\nexport interface PlayingInfo {\n playing: boolean;\n direction: SimpleDirection;\n untilBoundary: BoundaryType; // TODO: allows this to be optional in the setter?\n // TODO: Is `loop` responsible to add at this point? Maybe we should wait until we've figured out autoplay?\n // TODO: Combine `loop` into something with BoundaryType?\n loop: boolean;\n}\n\n// TODO: direction,\nexport class PlayingInfoProp extends TwistyPropSource<\n PlayingInfo,\n Partial<PlayingInfo>\n> {\n async getDefaultValue(): Promise<PlayingInfo> {\n return {\n direction: Direction.Forwards,\n playing: false,\n untilBoundary: BoundaryType.EntireTimeline,\n loop: false,\n };\n }\n\n async derive(\n newInfo: Partial<PlayingInfo>,\n oldValuePromise: Promise<PlayingInfo>,\n ): Promise<PlayingInfo> {\n const oldValue = await oldValuePromise;\n\n const newValue: PlayingInfo = Object.assign({}, oldValue);\n Object.assign(newValue, newInfo);\n return newValue;\n }\n\n canReuseValue(v1: PlayingInfo, v2: PlayingInfo) {\n return (\n v1.direction === v2.direction &&\n v1.playing === v2.playing &&\n v1.untilBoundary === v2.untilBoundary &&\n v1.loop === v2.loop\n );\n }\n}\n", "import type { PuzzleDescriptionString } from \"../../../../../puzzle-geometry/PGPuzzles\";\nimport {\n NoValueType,\n NO_VALUE,\n SimpleTwistyPropSource,\n} from \"../../TwistyProp\";\n\nexport class PGPuzzleDescriptionStringProp extends SimpleTwistyPropSource<\n PuzzleDescriptionString | NoValueType\n> {\n getDefaultValue(): PuzzleDescriptionString | NoValueType {\n return NO_VALUE;\n }\n}\n", "import {\n NoValueType,\n NO_VALUE,\n SimpleTwistyPropSource,\n} from \"../../TwistyProp\";\n\nexport const puzzleIDs = {\n \"3x3x3\": true, // default\n \"custom\": true,\n \"2x2x2\": true,\n \"4x4x4\": true,\n \"5x5x5\": true,\n \"6x6x6\": true,\n \"7x7x7\": true,\n \"40x40x40\": true,\n \"megaminx\": true,\n \"pyraminx\": true,\n \"square1\": true,\n \"clock\": true,\n \"skewb\": true,\n \"fto\": true,\n \"gigaminx\": true,\n \"master_tetraminx\": true,\n};\nexport type PuzzleID = keyof typeof puzzleIDs;\n\n// TODO: Ideally we'd use `null` to mean \"no value\", but `null` has a special meaning\n// for `TwistyProp` and might mess with caching.\n// https://github.com/cubing/cubing.js/blob/63b0a55b83963f68410bb117a2e481052a07e086/src/cubing/twisty/model/TwistyProp.ts#L189-L189\nexport class PuzzleIDRequestProp extends SimpleTwistyPropSource<\n PuzzleID | NoValueType\n> {\n getDefaultValue(): PuzzleID | NoValueType {\n return NO_VALUE;\n }\n}\n", "import type { PuzzleDescriptionString } from \"../../../../../puzzle-geometry/PGPuzzles\";\nimport {\n cube3x3x3,\n experimentalCustomPGPuzzleLoader,\n PuzzleLoader,\n puzzles,\n} from \"../../../../../puzzles\";\nimport { NoValueType, NO_VALUE, TwistyPropDerived } from \"../../TwistyProp\";\nimport type { PuzzleID } from \"./PuzzleIDRequestProp\";\n8;\ninterface PuzzleLoaderPropInputs {\n puzzleIDRequest: PuzzleID | NoValueType;\n puzzleDescriptionRequest: PuzzleDescriptionString | NoValueType;\n}\n\nexport class PuzzleLoaderProp extends TwistyPropDerived<\n PuzzleLoaderPropInputs,\n PuzzleLoader\n> {\n derive(inputs: PuzzleLoaderPropInputs): PuzzleLoader {\n if (inputs.puzzleIDRequest && inputs.puzzleIDRequest !== NO_VALUE) {\n const puzzleLoader = puzzles[inputs.puzzleIDRequest];\n if (!puzzleLoader) {\n this.userVisibleErrorTracker!.set({\n errors: [`Invalid puzzle ID: ${inputs.puzzleIDRequest}`],\n });\n }\n return puzzleLoader;\n }\n if (\n inputs.puzzleDescriptionRequest &&\n inputs.puzzleDescriptionRequest !== NO_VALUE\n ) {\n return experimentalCustomPGPuzzleLoader(inputs.puzzleDescriptionRequest);\n }\n return cube3x3x3;\n }\n}\n", "import { SimpleTwistyPropSource } from \"../../TwistyProp\";\n\n// TODO: turn these maps into lists?\nexport const setupToLocations = {\n start: true, // default // TODO: \"beginning\"\n end: true,\n};\nexport type SetupToLocation = keyof typeof setupToLocations;\n\nexport class SetupAnchorProp extends SimpleTwistyPropSource<SetupToLocation> {\n getDefaultValue(): SetupToLocation {\n return \"start\";\n }\n}\n", "import { TwistyPropSource } from \"../TwistyProp\";\n\n// TODO: Pick a better name. `speed` is probably good, although that could mean\n// something else (e.g. shorter, faster moves but still with the same spacing).\nexport class TempoScaleProp extends TwistyPropSource<number, number> {\n getDefaultValue(): number {\n return 1;\n }\n\n derive(v: number): number {\n return v < 0 ? 1 : v;\n }\n}\n", "import type { MillisecondTimestamp } from \"../../../controllers/AnimationTypes\";\nimport { SimpleTwistyPropSource } from \"../TwistyProp\";\n\nconst smartTimestamps = {\n \"start\": true,\n \"end\": true,\n \"anchor\": true,\n \"opposite-anchor\": true,\n};\n\nexport type TimestampRequest =\n | MillisecondTimestamp\n | keyof typeof smartTimestamps;\n\nexport class TimestampRequestProp extends SimpleTwistyPropSource<TimestampRequest> {\n getDefaultValue(): TimestampRequest {\n return \"opposite-anchor\";\n }\n\n // TODO: Support `Promise`\n set(v: TimestampRequest) {\n if (!this.validInput(v)) {\n // TODO: Generalize this to more props. How do we surface this? Throw an error and catch it from sync setters that call into this?\n return;\n }\n super.set(v);\n }\n\n validInput(v: TimestampRequest): boolean {\n if (typeof v === \"number\") {\n return true;\n }\n if (smartTimestamps[v]) {\n return true;\n }\n return false;\n }\n}\n", "import { TwistyPropSource } from \"../TwistyProp\";\n\nexport class URLProp extends TwistyPropSource<URL | null, URL | string | null> {\n getDefaultValue(): URL | null {\n return null;\n }\n\n derive(input: URL | string | null): URL | null {\n if (typeof input === \"string\") {\n return new URL(input, location.href); // TODO\n }\n return input;\n }\n}\n", "import { SimpleTwistyPropSource } from \"../TwistyProp\";\n\nexport const viewerLinkPages = {\n twizzle: true, // default\n none: true,\n};\nexport type ViewerLinkPage = keyof typeof viewerLinkPages;\nexport type ViewerLinkPageWithAuto = ViewerLinkPage | \"auto\";\n\nexport class ViewerLinkProp extends SimpleTwistyPropSource<ViewerLinkPageWithAuto> {\n getDefaultValue(): ViewerLinkPageWithAuto {\n return \"auto\";\n }\n}\n", "import { SimpleTwistyPropSource } from \"../TwistyProp\";\n\n// TODO: turn these maps into lists?\nexport const visualizationFormats = {\n \"3D\": true, // default\n \"2D\": true,\n \"experimental-2D-LL\": true, // TODO\n \"PG3D\": true,\n};\nexport type VisualizationFormat = keyof typeof visualizationFormats;\nexport type VisualizationFormatWithAuto = VisualizationFormat | \"auto\";\n\nexport class VisualizationFormatProp extends SimpleTwistyPropSource<VisualizationFormatWithAuto> {\n getDefaultValue(): VisualizationFormatWithAuto {\n return \"auto\";\n }\n}\n", "import { DEGREES_PER_RADIAN } from \"../../../views/3D/TAU\";\nimport type { PuzzleID } from \"../puzzle/structure/PuzzleIDRequestProp\";\nimport { TwistyPropDerived } from \"../TwistyProp\";\nimport {\n CoordinateDegrees,\n OrbitCoordinates,\n orbitCoordinatesEqual,\n OrbitCoordinatesRequest,\n} from \"./OrbitCoordinatesRequestProp\";\nimport type { VisualizationStrategy } from \"./VisualizationStrategyProp\";\n\ninterface OrbitCoordinatesPropInputs {\n orbitCoordinatesRequest: OrbitCoordinatesRequest;\n latitudeLimit: CoordinateDegrees;\n puzzleID: PuzzleID;\n strategy: VisualizationStrategy;\n}\n\nexport class OrbitCoordinatesProp extends TwistyPropDerived<\n OrbitCoordinatesPropInputs,\n OrbitCoordinates\n> {\n canReuseValue(v1: OrbitCoordinates, v2: OrbitCoordinates) {\n return orbitCoordinatesEqual(v1, v2);\n }\n\n async derive(inputs: OrbitCoordinatesPropInputs): Promise<OrbitCoordinates> {\n if (inputs.orbitCoordinatesRequest === \"auto\") {\n return defaultCameraOrbitCoordinates(inputs.puzzleID, inputs.strategy);\n }\n\n const req: OrbitCoordinates = Object.assign(\n Object.assign(\n {},\n defaultCameraOrbitCoordinates(inputs.puzzleID, inputs.strategy),\n inputs.orbitCoordinatesRequest,\n ),\n );\n\n if (Math.abs(req.latitude) <= inputs.latitudeLimit) {\n return req;\n } else {\n const { latitude, longitude, distance } = req;\n // TODO: Should we re-normalize the request, so we don't depend on normalization in the input?\n return {\n latitude: inputs.latitudeLimit * Math.sign(latitude),\n longitude,\n distance,\n };\n }\n }\n}\n\n// const DEFAULT_CAMERA_Z = 5;\n// // Golden ratio is perfect for FTO and Megaminx.\n// const DEFAULT_CAMERA_Y = DEFAULT_CAMERA_Z * (2 / (1 + Math.sqrt(5)));\nexport const centeredCameraOrbitCoordinates: OrbitCoordinates = {\n latitude: 31.717474411461005,\n longitude: 0,\n distance: 5.877852522924731,\n};\n\n// This is tuned so that the hint facelets for 3x3x3 always fit in the canvas.\nexport const cubeCube3DCameraOrbitCoordinates: OrbitCoordinates = {\n latitude: 35,\n longitude: 30,\n distance: 6,\n};\n\n// This is tuned so that the hint facelets always fit in the canvas.\nexport const cubePG3DCameraOrbitCoordinates: OrbitCoordinates = {\n latitude: 35,\n longitude: 30,\n distance: 6.25,\n};\n\nexport const megaminxCameraOrbitCoordinates: OrbitCoordinates = {\n latitude: Math.atan(1 / 2) * DEGREES_PER_RADIAN,\n longitude: 0,\n distance: 6.7,\n};\n\nexport const pyraminxCameraOrbitCoordinates: OrbitCoordinates = {\n latitude: 26.56505117707799,\n longitude: 0,\n distance: 6,\n};\n\nexport const cornerCameraOrbitCoordinates: OrbitCoordinates = {\n latitude: 35.264389682754654,\n longitude: 45,\n distance: 6.928203230275509,\n};\n\n// TODO\nexport function defaultCameraOrbitCoordinates(\n puzzleID: PuzzleID,\n strategy: VisualizationStrategy,\n): OrbitCoordinates {\n if (puzzleID[1] === \"x\") {\n if (strategy === \"Cube3D\") {\n return cubeCube3DCameraOrbitCoordinates;\n } else {\n return cubePG3DCameraOrbitCoordinates;\n }\n } else {\n switch (puzzleID) {\n case \"megaminx\":\n case \"gigaminx\":\n return megaminxCameraOrbitCoordinates;\n case \"pyraminx\":\n case \"master_tetraminx\":\n return pyraminxCameraOrbitCoordinates;\n case \"skewb\":\n return cubePG3DCameraOrbitCoordinates;\n default:\n return centeredCameraOrbitCoordinates;\n }\n }\n}\n// TODO: templatize\nexport interface ManagedAttribute<K> {\n string: string;\n value: K;\n setString(s: string): boolean;\n setValue(v: K): boolean;\n}\n", "import type { PuzzleLoader } from \"../../../../../puzzles\";\nimport { TwistyPropDerived } from \"../../TwistyProp\";\nimport type { PuzzleID } from \"./PuzzleIDRequestProp\";\n\nexport class PuzzleIDProp extends TwistyPropDerived<\n { puzzleLoader: PuzzleLoader },\n PuzzleID\n> {\n async derive(inputs: { puzzleLoader: PuzzleLoader }): Promise<PuzzleID> {\n return inputs.puzzleLoader.id as PuzzleID;\n }\n}\n", "import type { Texture, TextureLoader } from \"three\";\nimport { THREEJS } from \"../../../../heavy-code-imports/3d\";\nimport { TwistyPropDerived } from \"../../TwistyProp\";\n\nlet cachedLoader: TextureLoader | null = null;\nasync function loader(): Promise<TextureLoader> {\n return (cachedLoader ??= new (await THREEJS).TextureLoader());\n}\n\ntype SpritePropInputs = {\n spriteURL: URL | null;\n};\n\n// TODO: Find a way to make the 3D elements own this, instead of the main `TwistyPlayerModel`.\nexport class SpriteProp extends TwistyPropDerived<\n SpritePropInputs,\n Texture | null\n> {\n async derive(inputs: SpritePropInputs): Promise<Texture | null> {\n const { spriteURL: textureURL } = inputs;\n if (textureURL === null) {\n return null;\n }\n // eslint-disable-next-line no-async-promise-executor\n return new Promise(async (resolve, _reject) => {\n const onLoadingError = (): void => {\n console.warn(\"Could not load sprite:\", textureURL.toString());\n resolve(null);\n };\n // TODO: provide a way to listen for errors?\n try {\n (await loader()).load(\n textureURL.toString(),\n resolve,\n onLoadingError,\n onLoadingError,\n );\n } catch (e) {\n onLoadingError();\n }\n });\n }\n}\n", "import type { VisualizationFormatWithAuto } from \"./VisualizationProp\";\nimport { TwistyPropDerived } from \"../TwistyProp\";\nimport type { PuzzleID } from \"../../..\";\n\ntype VisualizationStrategyPropInputs = {\n visualizationRequest: VisualizationFormatWithAuto;\n puzzleID: PuzzleID;\n};\n\nexport type VisualizationStrategy =\n | \"Cube3D\"\n | \"2D\"\n | \"experimental-2D-LL\"\n | \"PG3D\";\n\nexport class VisualizationStrategyProp extends TwistyPropDerived<\n VisualizationStrategyPropInputs,\n VisualizationStrategy\n> {\n derive(inputs: VisualizationStrategyPropInputs): VisualizationStrategy {\n switch (inputs.puzzleID) {\n case \"clock\":\n case \"square1\":\n return \"2D\";\n case \"3x3x3\":\n switch (inputs.visualizationRequest) {\n case \"auto\":\n case \"3D\":\n return \"Cube3D\";\n default:\n return inputs.visualizationRequest;\n }\n default:\n switch (inputs.visualizationRequest) {\n case \"auto\":\n case \"3D\":\n return \"PG3D\";\n case \"experimental-2D-LL\":\n return \"2D\";\n default:\n return inputs.visualizationRequest;\n }\n }\n }\n}\n", "import {\n Alg,\n Grouping,\n LineComment,\n Commutator,\n Conjugate,\n Move,\n Newline,\n Pause,\n TraversalUp,\n} from \"../../../alg\";\nimport type { Duration } from \"../AnimationTypes\";\n\nexport function constantDurationForAmount(_amount: number): Duration {\n return 1000;\n}\n\nexport function defaultDurationForAmount(amount: number): Duration {\n switch (Math.abs(amount)) {\n case 0:\n return 0;\n case 1:\n return 1000;\n case 2:\n return 1500;\n default:\n return 2000;\n }\n}\n// eslint-disable-next-line no-inner-declarations\nexport function ExperimentalScaledDefaultDurationForAmount(\n scale: number,\n amount: number,\n): Duration {\n switch (Math.abs(amount)) {\n case 0:\n return 0;\n case 1:\n return scale * 1000;\n case 2:\n return scale * 1500;\n default:\n return scale * 2000;\n }\n}\n\nexport class AlgDuration extends TraversalUp<Duration> {\n // TODO: Pass durationForAmount as Down type instead?\n constructor(\n public durationForAmount: (\n amount: number,\n ) => Duration = defaultDurationForAmount,\n ) {\n super();\n }\n\n public traverseAlg(alg: Alg): Duration {\n let total = 0;\n for (const unit of alg.units()) {\n total += this.traverseUnit(unit);\n }\n return total;\n }\n\n public traverseGrouping(grouping: Grouping): Duration {\n return grouping.amount * this.traverseAlg(grouping.alg);\n }\n\n public traverseMove(move: Move): Duration {\n return this.durationForAmount(move.amount);\n }\n\n public traverseCommutator(commutator: Commutator): Duration {\n return (\n 2 * (this.traverseAlg(commutator.A) + this.traverseAlg(commutator.B))\n );\n }\n\n public traverseConjugate(conjugate: Conjugate): Duration {\n return 2 * this.traverseAlg(conjugate.A) + this.traverseAlg(conjugate.B);\n }\n\n public traversePause(_pause: Pause): Duration {\n return this.durationForAmount(1);\n }\n\n public traverseNewline(_newline: Newline): Duration {\n return this.durationForAmount(1);\n }\n\n public traverseLineComment(_comment: LineComment): Duration {\n return this.durationForAmount(0);\n }\n}\n", "import { Alg, Move, TraversalUp } from \"../../../alg\";\nimport { countAnimatedLeaves } from \"../../../notation\";\nimport type {\n PuzzleWrapper,\n State,\n} from \"../../views/3D/puzzles/KPuzzleWrapper\";\nimport type { Duration, Timestamp } from \"../AnimationTypes\";\nimport { AlgDuration, defaultDurationForAmount } from \"./AlgDuration\";\nimport type { AlgIndexer } from \"./AlgIndexer\";\n\nexport class SimpleAlgIndexer<P extends PuzzleWrapper>\n implements AlgIndexer<P>\n{\n private moves: Alg;\n // TODO: Allow custom `durationFn`.\n private durationFn: TraversalUp<Duration> = new AlgDuration(\n defaultDurationForAmount,\n );\n\n constructor(private puzzle: P, alg: Alg) {\n // TODO: Avoid assuming all base moves are block moves.\n this.moves = new Alg(alg.experimentalExpand());\n }\n\n public getAnimLeaf(index: number): Move {\n return Array.from(this.moves.units())[index] as Move; // TODO: perf\n }\n\n public indexToMoveStartTimestamp(index: number): Timestamp {\n const alg = new Alg(Array.from(this.moves.units()).slice(0, index)); // TODO\n return this.durationFn.traverseAlg(alg);\n }\n\n public timestampToIndex(timestamp: Timestamp): number {\n let cumulativeTime = 0;\n let i;\n for (i = 0; i < this.numAnimatedLeaves(); i++) {\n cumulativeTime += this.durationFn.traverseMove(this.getAnimLeaf(i));\n if (cumulativeTime >= timestamp) {\n return i;\n }\n }\n return i;\n }\n\n public stateAtIndex(index: number): State<P> {\n return this.puzzle.combine(\n this.puzzle.startState(),\n this.transformAtIndex(index),\n );\n }\n\n public transformAtIndex(index: number): State<P> {\n let state = this.puzzle.identity();\n for (const move of Array.from(this.moves.units()).slice(0, index)) {\n state = this.puzzle.combine(\n state,\n this.puzzle.stateFromMove(move as Move),\n );\n }\n return state;\n }\n\n public algDuration(): Duration {\n return this.durationFn.traverseAlg(this.moves);\n }\n\n public numAnimatedLeaves(): number {\n // TODO: Cache internally once performance matters.\n return countAnimatedLeaves(this.moves);\n }\n\n public moveDuration(index: number): number {\n return this.durationFn.traverseMove(this.getAnimLeaf(index));\n }\n}\n", "import {\n LineComment,\n Commutator,\n Conjugate,\n Pause,\n TraversalUp,\n Move,\n Alg,\n Grouping,\n Newline,\n} from \"../../../../alg\";\nimport type { MillisecondTimestamp } from \"../../AnimationTypes\";\nimport { defaultDurationForAmount } from \"../AlgDuration\";\n\nexport type AnimatedLeafUnit = Move | Pause;\nexport interface LocalAnimLeavesWithRange {\n animLeafUnit: AnimatedLeafUnit;\n msUntilNext: MillisecondTimestamp;\n duration: MillisecondTimestamp;\n}\n\nexport interface AnimLeafWithRange {\n animLeaf: AnimatedLeafUnit;\n start: MillisecondTimestamp;\n end: MillisecondTimestamp;\n}\n\nconst axisLookup: Record<string, \"x\" | \"y\" | \"z\"> = {\n u: \"y\",\n l: \"x\",\n f: \"z\",\n r: \"x\",\n b: \"z\",\n d: \"y\",\n m: \"x\",\n e: \"y\",\n s: \"z\",\n x: \"x\",\n y: \"y\",\n z: \"z\",\n};\n\nfunction isSameAxis(move1: Move, move2: Move): boolean {\n return (\n axisLookup[move1.family[0].toLowerCase()] ===\n axisLookup[move2.family[0].toLowerCase()]\n );\n}\n\n// TODO: Replace this with an optimized implementation.\n// TODO: Consider `(x U)` and `(U x F)` to be simultaneous.\nexport class LocalSimulMoves extends TraversalUp<LocalAnimLeavesWithRange[]> {\n public traverseAlg(alg: Alg): LocalAnimLeavesWithRange[] {\n const processed: LocalAnimLeavesWithRange[][] = [];\n for (const nestedUnit of alg.units()) {\n processed.push(this.traverseUnit(nestedUnit));\n }\n return Array.prototype.concat(...processed) as LocalAnimLeavesWithRange[];\n }\n\n public traverseGroupingOnce(alg: Alg): LocalAnimLeavesWithRange[] {\n if (alg.experimentalIsEmpty()) {\n return [];\n }\n\n for (const unit of alg.units()) {\n if (!unit.is(Move))\n // TODO: define the type statically on the class?\n return this.traverseAlg(alg);\n }\n\n const moves = Array.from(alg.units()) as Move[];\n let maxSimulDur = defaultDurationForAmount(moves[0].amount);\n for (let i = 0; i < moves.length - 1; i++) {\n for (let j = 1; j < moves.length; j++) {\n if (!isSameAxis(moves[i], moves[j])) {\n return this.traverseAlg(alg);\n }\n }\n maxSimulDur = Math.max(\n maxSimulDur,\n defaultDurationForAmount(moves[i].amount),\n );\n }\n\n const localMovesWithRange: LocalAnimLeavesWithRange[] = moves.map(\n (blockMove): LocalAnimLeavesWithRange => {\n return {\n animLeafUnit: blockMove,\n msUntilNext: 0,\n duration: maxSimulDur,\n };\n },\n );\n localMovesWithRange[localMovesWithRange.length - 1].msUntilNext =\n maxSimulDur;\n return localMovesWithRange;\n }\n\n public traverseGrouping(grouping: Grouping): LocalAnimLeavesWithRange[] {\n const processed: LocalAnimLeavesWithRange[][] = [];\n\n const segmentOnce: Alg =\n grouping.amount > 0 ? grouping.alg : grouping.alg.invert();\n for (let i = 0; i < Math.abs(grouping.amount); i++) {\n processed.push(this.traverseGroupingOnce(segmentOnce));\n }\n return Array.prototype.concat(...processed) as LocalAnimLeavesWithRange[];\n }\n\n public traverseMove(move: Move): LocalAnimLeavesWithRange[] {\n const duration = defaultDurationForAmount(move.amount);\n return [\n {\n animLeafUnit: move,\n msUntilNext: duration,\n duration,\n },\n ];\n }\n\n public traverseCommutator(\n commutator: Commutator,\n ): LocalAnimLeavesWithRange[] {\n const processed: LocalAnimLeavesWithRange[][] = [];\n const segmentsOnce: Alg[] = [\n commutator.A,\n commutator.B,\n commutator.A.invert(),\n commutator.B.invert(),\n ];\n for (const segment of segmentsOnce) {\n processed.push(this.traverseGroupingOnce(segment));\n }\n return Array.prototype.concat(...processed) as LocalAnimLeavesWithRange[];\n }\n\n public traverseConjugate(conjugate: Conjugate): LocalAnimLeavesWithRange[] {\n const processed: LocalAnimLeavesWithRange[][] = [];\n const segmentsOnce: Alg[] = [\n conjugate.A,\n conjugate.B,\n conjugate.A.invert(),\n ];\n for (const segment of segmentsOnce) {\n processed.push(this.traverseGroupingOnce(segment));\n }\n return Array.prototype.concat(...processed) as LocalAnimLeavesWithRange[];\n }\n\n public traversePause(pause: Pause): LocalAnimLeavesWithRange[] {\n const duration = defaultDurationForAmount(1);\n return [\n {\n animLeafUnit: pause,\n msUntilNext: duration, // TODO\n duration,\n },\n ];\n }\n\n public traverseNewline(_newline: Newline): LocalAnimLeavesWithRange[] {\n return [];\n }\n\n public traverseLineComment(\n _comment: LineComment,\n ): LocalAnimLeavesWithRange[] {\n return [];\n }\n}\n\nconst localSimulMovesInstance = new LocalSimulMoves();\n\nconst localSimulMoves = localSimulMovesInstance.traverseAlg.bind(\n localSimulMovesInstance,\n) as (a: Alg) => LocalAnimLeavesWithRange[];\n\nexport function simulMoves(a: Alg): AnimLeafWithRange[] {\n let timestamp = 0;\n const l = localSimulMoves(a).map(\n (localSimulMove: LocalAnimLeavesWithRange): AnimLeafWithRange => {\n const leafWithRange = {\n animLeaf: localSimulMove.animLeafUnit,\n start: timestamp,\n end: timestamp + localSimulMove.duration,\n };\n timestamp += localSimulMove.msUntilNext;\n return leafWithRange;\n },\n );\n return l;\n}\n", "import { Alg, Move } from \"../../../../alg\";\nimport type {\n PuzzleWrapper,\n State,\n} from \"../../../views/3D/puzzles/KPuzzleWrapper\";\nimport {\n Direction,\n Duration,\n PuzzlePosition,\n Timestamp,\n} from \"../../AnimationTypes\";\nimport type { AlgIndexer, CurrentMove, CurrentMoveInfo } from \"../AlgIndexer\";\nimport { AnimatedLeafUnit, AnimLeafWithRange, simulMoves } from \"./simul-moves\";\n\nconst demos: Record<string, AnimLeafWithRange[]> = {\n \"y' y' U' E D R2 r2 F2 B2 U E D' R2 L2' z2 S2 U U D D S2 F2' B2\": [\n { animLeaf: new Move(\"y\", -1), start: 0, end: 1000 },\n { animLeaf: new Move(\"y\", -1), start: 1000, end: 2000 },\n { animLeaf: new Move(\"U\", -1), start: 1000, end: 1600 },\n { animLeaf: new Move(\"E\", 1), start: 1200, end: 1800 },\n { animLeaf: new Move(\"D\"), start: 1400, end: 2000 },\n { animLeaf: new Move(\"R\", 2), start: 2000, end: 3500 },\n { animLeaf: new Move(\"r\", 2), start: 2000, end: 3500 },\n { animLeaf: new Move(\"F\", 2), start: 3500, end: 4200 },\n { animLeaf: new Move(\"B\", 2), start: 3800, end: 4500 },\n { animLeaf: new Move(\"U\", 1), start: 4500, end: 5500 },\n { animLeaf: new Move(\"E\", 1), start: 4500, end: 5500 },\n { animLeaf: new Move(\"D\", -1), start: 4500, end: 5500 },\n { animLeaf: new Move(\"R\", 2), start: 5500, end: 6500 },\n { animLeaf: new Move(\"L\", -2), start: 5500, end: 6500 },\n { animLeaf: new Move(\"z\", 2), start: 5500, end: 6500 },\n { animLeaf: new Move(\"S\", 2), start: 6500, end: 7500 },\n { animLeaf: new Move(\"U\"), start: 7500, end: 8000 },\n { animLeaf: new Move(\"D\"), start: 7750, end: 8250 },\n { animLeaf: new Move(\"U\"), start: 8000, end: 8500 },\n { animLeaf: new Move(\"D\"), start: 8250, end: 8750 },\n { animLeaf: new Move(\"S\", 2), start: 8750, end: 9250 },\n { animLeaf: new Move(\"F\", -2), start: 8750, end: 10000 },\n { animLeaf: new Move(\"B\", 2), start: 8750, end: 10000 },\n ],\n \"M' R' U' D' M R\": [\n { animLeaf: new Move(\"M\", -1), start: 0, end: 1000 },\n { animLeaf: new Move(\"R\", -1), start: 0, end: 1000 },\n { animLeaf: new Move(\"U\", -1), start: 1000, end: 2000 },\n { animLeaf: new Move(\"D\", -1), start: 1000, end: 2000 },\n { animLeaf: new Move(\"M\"), start: 2000, end: 3000 },\n { animLeaf: new Move(\"R\"), start: 2000, end: 3000 },\n ],\n \"U' E' r E r2' E r U E\": [\n { animLeaf: new Move(\"U\", -1), start: 0, end: 1000 },\n { animLeaf: new Move(\"E\", -1), start: 0, end: 1000 },\n { animLeaf: new Move(\"r\"), start: 1000, end: 2500 },\n { animLeaf: new Move(\"E\"), start: 2500, end: 3500 },\n { animLeaf: new Move(\"r\", -2), start: 3500, end: 5000 },\n { animLeaf: new Move(\"E\"), start: 5000, end: 6000 },\n { animLeaf: new Move(\"r\"), start: 6000, end: 7000 },\n { animLeaf: new Move(\"U\"), start: 7000, end: 8000 },\n { animLeaf: new Move(\"E\"), start: 7000, end: 8000 },\n ],\n};\n\nexport class SimultaneousMoveIndexerV2<P extends PuzzleWrapper>\n implements AlgIndexer<P>\n{\n private animLeaves: AnimLeafWithRange[];\n // TODO: Allow custom `durationFn`.\n\n constructor(private puzzle: P, alg: Alg) {\n this.animLeaves = demos[alg.toString()] ?? simulMoves(alg);\n // TODO: Avoid assuming all base moves are block moves.\n }\n\n public getAnimLeaf(index: number): AnimatedLeafUnit | null {\n return (\n this.animLeaves[Math.min(index, this.animLeaves.length - 1)]?.animLeaf ??\n null\n );\n }\n\n private getAnimLeafWithRange(index: number): AnimLeafWithRange {\n return this.animLeaves[Math.min(index, this.animLeaves.length - 1)];\n }\n\n public indexToMoveStartTimestamp(index: number): Timestamp {\n let start = 0;\n if (this.animLeaves.length > 0) {\n start =\n this.animLeaves[Math.min(index, this.animLeaves.length - 1)].start;\n }\n return start;\n }\n\n public timestampToIndex(timestamp: Timestamp): number {\n let i = 0;\n for (i = 0; i < this.animLeaves.length; i++) {\n if (this.animLeaves[i].start >= timestamp) {\n return Math.max(0, i - 1);\n }\n }\n return Math.max(0, i - 1);\n }\n\n public timestampToPosition(\n timestamp: Timestamp,\n startTransformation?: State<P>,\n ): PuzzlePosition {\n const currentMoveInfo = this.currentMoveInfo(timestamp);\n\n let state = startTransformation ?? this.puzzle.identity();\n for (const leafWithRange of this.animLeaves.slice(\n 0,\n currentMoveInfo.stateIndex,\n )) {\n const move = leafWithRange.animLeaf.as(Move);\n if (move !== null) {\n state = this.puzzle.combine(state, this.puzzle.stateFromMove(move));\n }\n }\n\n return {\n state: state as any,\n movesInProgress: currentMoveInfo.currentMoves,\n };\n }\n\n // TODO: Caching\n public currentMoveInfo(timestamp: Timestamp): CurrentMoveInfo {\n // The starting timestamp of the earliest active move.\n let windowEarliestTimestamp = Infinity;\n for (const leafWithRange of this.animLeaves) {\n if (leafWithRange.start <= timestamp && leafWithRange.end >= timestamp) {\n windowEarliestTimestamp = Math.min(\n windowEarliestTimestamp,\n leafWithRange.start,\n );\n } else if (leafWithRange.start > timestamp) {\n break;\n }\n }\n\n const currentMoves: CurrentMove[] = [];\n const movesStarting: CurrentMove[] = [];\n const movesFinishing: CurrentMove[] = [];\n const movesFinished: CurrentMove[] = [];\n let latestStart: number = -Infinity; // TODO: is there a better way to accumulate this?\n let earliestEnd: number = Infinity; // TODO: is there a better way to accumulate this?\n\n let stateIndex: number = 0;\n for (const leafWithRange of this.animLeaves) {\n if (leafWithRange.end <= windowEarliestTimestamp) {\n stateIndex++;\n } else if (leafWithRange.start > timestamp) {\n break;\n } else {\n const move = leafWithRange.animLeaf.as(Move);\n if (move !== null) {\n let fraction =\n (timestamp - leafWithRange.start) /\n (leafWithRange.end - leafWithRange.start);\n let moveFinished = false;\n if (fraction > 1) {\n fraction = 1;\n moveFinished = true;\n }\n const currentMove = {\n move: move,\n direction: Direction.Forwards,\n fraction: fraction,\n startTimestamp: leafWithRange.start,\n endTimestamp: leafWithRange.end,\n };\n switch (fraction) {\n case 0:\n movesStarting.push(currentMove);\n break;\n case 1:\n // Generalize this to avoid reordering commuting moves.\n if (moveFinished) {\n movesFinished.push(currentMove);\n } else {\n movesFinishing.push(currentMove);\n }\n break;\n default:\n currentMoves.push(currentMove);\n latestStart = Math.max(latestStart, leafWithRange.start);\n earliestEnd = Math.min(earliestEnd, leafWithRange.end);\n }\n }\n }\n }\n return {\n stateIndex,\n currentMoves,\n latestStart,\n earliestEnd,\n movesStarting,\n movesFinishing,\n movesFinished,\n };\n }\n\n public stateAtIndex(index: number, startTransformation?: State<P>): State<P> {\n let state = startTransformation ?? this.puzzle.startState();\n for (let i = 0; i < this.animLeaves.length && i < index; i++) {\n const leafWithRange = this.animLeaves[i];\n const move = leafWithRange.animLeaf.as(Move);\n if (move !== null) {\n state = this.puzzle.combine(state, this.puzzle.stateFromMove(move));\n }\n }\n return state;\n }\n\n public transformAtIndex(index: number): State<P> {\n let state = this.puzzle.identity();\n for (const leafWithRange of this.animLeaves.slice(0, index)) {\n const move = leafWithRange.animLeaf.as(Move);\n if (move !== null) {\n state = this.puzzle.combine(state, this.puzzle.stateFromMove(move));\n }\n }\n return state;\n }\n\n public algDuration(): Duration {\n let max = 0;\n for (const leafWithRange of this.animLeaves) {\n max = Math.max(max, leafWithRange.end);\n }\n return max;\n }\n\n public numAnimatedLeaves(): number {\n // TODO: Cache internally once performance matters.\n return this.animLeaves.length;\n }\n\n public moveDuration(index: number): number {\n const move = this.getAnimLeafWithRange(index);\n return move.end - move.start;\n }\n}\n", "import {\n Alg,\n Commutator,\n Conjugate,\n Grouping,\n LineComment,\n Move,\n Newline,\n Pause,\n TraversalUp,\n Unit,\n} from \"../../../../alg\";\nimport { AlgBuilder } from \"../../../../alg\";\n\nconst MIN_CHUNKING_THRESHOLD = 16;\n\nfunction chunkifyAlg(alg: Alg, chunkMaxLength: number): Alg {\n const mainAlgBuilder = new AlgBuilder();\n const chunkAlgBuilder = new AlgBuilder();\n for (const unit of alg.units()) {\n chunkAlgBuilder.push(unit);\n if (chunkAlgBuilder.experimentalNumUnits() >= chunkMaxLength) {\n mainAlgBuilder.push(new Grouping(chunkAlgBuilder.toAlg()));\n chunkAlgBuilder.reset();\n }\n }\n mainAlgBuilder.push(new Grouping(chunkAlgBuilder.toAlg()));\n return mainAlgBuilder.toAlg();\n}\n\nclass ChunkAlgs extends TraversalUp<Alg, Unit> {\n traverseAlg(alg: Alg): Alg {\n const algLength = alg.experimentalNumUnits();\n if (algLength < MIN_CHUNKING_THRESHOLD) {\n return alg;\n }\n return chunkifyAlg(alg, Math.ceil(Math.sqrt(algLength)));\n }\n\n traverseGrouping(grouping: Grouping): Unit {\n return new Grouping(\n this.traverseAlg(grouping.alg),\n grouping.amount, // TODO\n );\n }\n\n traverseMove(move: Move): Unit {\n return move;\n }\n\n traverseCommutator(commutator: Commutator): Unit {\n return new Conjugate(\n this.traverseAlg(commutator.A),\n this.traverseAlg(commutator.B),\n );\n }\n\n traverseConjugate(conjugate: Conjugate): Unit {\n return new Conjugate(\n this.traverseAlg(conjugate.A),\n this.traverseAlg(conjugate.B),\n );\n }\n\n traversePause(pause: Pause): Unit {\n return pause;\n }\n\n traverseNewline(newline: Newline): Unit {\n return newline;\n }\n\n traverseLineComment(comment: LineComment): Unit {\n return comment;\n }\n}\n\nconst chunkAlgsInstance = new ChunkAlgs();\nexport const chunkAlgs = chunkAlgsInstance.traverseAlg.bind(\n chunkAlgsInstance,\n) as (alg: Alg) => Alg;\n", "import {\n Alg,\n Grouping,\n LineComment,\n Commutator,\n Conjugate,\n Move,\n Newline,\n Pause,\n TraversalDownUp,\n TraversalUp,\n Unit,\n} from \"../../../../alg\";\nimport {\n experimentalDirectedGenerator,\n ExperimentalIterationDirection,\n} from \"../../../../alg\";\nimport type {\n PuzzleWrapper,\n State,\n} from \"../../../views/3D/puzzles/KPuzzleWrapper\";\nimport type { Duration } from \"../../AnimationTypes\";\nimport { AlgDuration, defaultDurationForAmount } from \"../AlgDuration\";\n\nexport class AlgPartDecoration<P extends PuzzleWrapper> {\n constructor(\n _puz: PuzzleWrapper,\n public moveCount: number,\n public duration: number,\n public forward: State<P>,\n public backward: State<P>,\n public children: Array<AlgPartDecoration<P>> = [],\n ) {}\n}\nexport class DecoratorConstructor<P extends PuzzleWrapper> extends TraversalUp<\n AlgPartDecoration<P>\n> {\n private identity: State<P>;\n private dummyLeaf: AlgPartDecoration<P>;\n private durationFn: TraversalUp<Duration> = new AlgDuration(\n defaultDurationForAmount,\n );\n\n private cache: { [key: string]: AlgPartDecoration<P> } = {};\n\n constructor(private puz: PuzzleWrapper) {\n super();\n this.identity = puz.identity();\n this.dummyLeaf = new AlgPartDecoration<P>(\n puz,\n 0,\n 0,\n this.identity,\n this.identity,\n [],\n );\n }\n\n public traverseAlg(alg: Alg): AlgPartDecoration<P> {\n let moveCount = 0;\n let duration = 0;\n let state = this.identity;\n const child: Array<AlgPartDecoration<P>> = [];\n for (const unit of alg.units()) {\n const apd = this.traverseUnit(unit);\n moveCount += apd.moveCount;\n duration += apd.duration;\n if (state === this.identity) {\n state = apd.forward;\n } else {\n state = this.puz.combine(state, apd.forward);\n }\n child.push(apd);\n }\n return new AlgPartDecoration<P>(\n this.puz,\n moveCount,\n duration,\n state,\n this.puz.invert(state),\n child,\n );\n }\n\n public traverseGrouping(grouping: Grouping): AlgPartDecoration<P> {\n const dec = this.traverseAlg(grouping.alg);\n return this.mult(dec, grouping.amount, [dec]);\n }\n\n public traverseMove(move: Move): AlgPartDecoration<P> {\n const key = move.toString();\n let r: AlgPartDecoration<P> | undefined = this.cache[key];\n if (r) {\n return r;\n }\n r = new AlgPartDecoration<P>(\n this.puz,\n 1,\n this.durationFn.traverseUnit(move),\n this.puz.stateFromMove(move),\n this.puz.stateFromMove(move.invert()),\n );\n this.cache[key] = r;\n return r;\n }\n\n public traverseCommutator(commutator: Commutator): AlgPartDecoration<P> {\n const decA = this.traverseAlg(commutator.A);\n const decB = this.traverseAlg(commutator.B);\n const AB = this.puz.combine(decA.forward, decB.forward);\n const ApBp = this.puz.combine(decA.backward, decB.backward);\n const ABApBp = this.puz.combine(AB, ApBp);\n const dec = new AlgPartDecoration<P>(\n this.puz,\n 2 * (decA.moveCount + decB.moveCount),\n 2 * (decA.duration + decB.duration),\n ABApBp,\n this.puz.invert(ABApBp),\n [decA, decB],\n );\n return this.mult(dec, 1, [dec, decA, decB]);\n }\n\n public traverseConjugate(conjugate: Conjugate): AlgPartDecoration<P> {\n const decA = this.traverseAlg(conjugate.A);\n const decB = this.traverseAlg(conjugate.B);\n const AB = this.puz.combine(decA.forward, decB.forward);\n const ABAp = this.puz.combine(AB, decA.backward);\n const dec = new AlgPartDecoration<P>(\n this.puz,\n 2 * decA.moveCount + decB.moveCount,\n 2 * decA.duration + decB.duration,\n ABAp,\n this.puz.invert(ABAp),\n [decA, decB],\n );\n return this.mult(dec, 1, [dec, decA, decB]);\n }\n\n public traversePause(pause: Pause): AlgPartDecoration<P> {\n return new AlgPartDecoration<P>(\n this.puz,\n 1,\n this.durationFn.traverseUnit(pause),\n this.identity,\n this.identity,\n );\n }\n\n public traverseNewline(_newline: Newline): AlgPartDecoration<P> {\n return this.dummyLeaf;\n }\n\n public traverseLineComment(_comment: LineComment): AlgPartDecoration<P> {\n return this.dummyLeaf;\n }\n\n private mult(\n apd: AlgPartDecoration<P>,\n n: number,\n child: Array<AlgPartDecoration<P>>,\n ): AlgPartDecoration<P> {\n const absn = Math.abs(n);\n const st = this.puz.multiply(apd.forward, n);\n return new AlgPartDecoration<P>(\n this.puz,\n apd.moveCount * absn,\n apd.duration * absn,\n st,\n this.puz.invert(st),\n child,\n );\n }\n}\nclass WalkerDown<P extends PuzzleWrapper> {\n constructor(public apd: AlgPartDecoration<P>, public back: boolean) {\n /**/\n }\n}\nexport class AlgWalker<P extends PuzzleWrapper> extends TraversalDownUp<\n WalkerDown<P>,\n boolean\n> {\n public move?: Unit;\n public moveDuration: number;\n public back: boolean;\n public st: State<P>;\n public root: WalkerDown<P>;\n public i: number;\n public dur: number;\n private goali: number;\n private goaldur: number;\n constructor(\n public puz: P,\n public algOrUnit: Alg | Unit, // TODO: can we keep these separate?\n public apd: AlgPartDecoration<P>,\n ) {\n super();\n this.i = -1;\n this.dur = -1;\n this.goali = -1;\n this.goaldur = -1;\n this.move = undefined;\n this.back = false;\n this.moveDuration = 0;\n this.st = this.puz.identity();\n this.root = new WalkerDown(this.apd, false);\n }\n\n public moveByIndex(loc: number): boolean {\n if (this.i >= 0 && this.i === loc) {\n return this.move !== undefined;\n }\n return this.dosearch(loc, Infinity);\n }\n\n public moveByDuration(dur: number): boolean {\n if (\n this.dur >= 0 &&\n this.dur < dur &&\n this.dur + this.moveDuration >= dur\n ) {\n return this.move !== undefined;\n }\n return this.dosearch(Infinity, dur);\n }\n\n public dosearch(loc: number, dur: number): boolean {\n this.goali = loc;\n this.goaldur = dur;\n this.i = 0;\n this.dur = 0;\n this.move = undefined;\n this.moveDuration = 0;\n this.back = false;\n this.st = this.puz.identity();\n const r = this.algOrUnit.is(Alg)\n ? this.traverseAlg(this.algOrUnit as Alg, this.root)\n : this.traverseUnit(this.algOrUnit as Unit, this.root); // TODO\n return r;\n }\n\n public traverseAlg(alg: Alg, wd: WalkerDown<P>): boolean {\n if (!this.firstcheck(wd)) {\n return false;\n }\n let i = wd.back ? alg.experimentalNumUnits() - 1 : 0;\n for (const unit of experimentalDirectedGenerator(\n alg.units(),\n wd.back\n ? ExperimentalIterationDirection.Backwards\n : ExperimentalIterationDirection.Forwards,\n )) {\n if (\n this.traverseUnit(unit, new WalkerDown(wd.apd.children[i], wd.back))\n ) {\n return true;\n }\n i += wd.back ? -1 : 1;\n }\n return false;\n }\n\n public traverseGrouping(grouping: Grouping, wd: WalkerDown<P>): boolean {\n if (!this.firstcheck(wd)) {\n return false;\n }\n const back = this.domult(wd, grouping.amount);\n return this.traverseAlg(\n grouping.alg,\n new WalkerDown(wd.apd.children[0], back),\n );\n }\n\n public traverseMove(move: Move, wd: WalkerDown<P>): boolean {\n if (!this.firstcheck(wd)) {\n return false;\n }\n this.move = move;\n this.moveDuration = wd.apd.duration;\n this.back = wd.back;\n return true;\n }\n\n public traverseCommutator(\n commutator: Commutator,\n wd: WalkerDown<P>,\n ): boolean {\n if (!this.firstcheck(wd)) {\n return false;\n }\n const back = this.domult(wd, 1);\n if (back) {\n return (\n this.traverseAlg(\n commutator.B,\n new WalkerDown(wd.apd.children[2], !back),\n ) ||\n this.traverseAlg(\n commutator.A,\n new WalkerDown(wd.apd.children[1], !back),\n ) ||\n this.traverseAlg(\n commutator.B,\n new WalkerDown(wd.apd.children[2], back),\n ) ||\n this.traverseAlg(commutator.A, new WalkerDown(wd.apd.children[1], back))\n );\n } else {\n return (\n this.traverseAlg(\n commutator.A,\n new WalkerDown(wd.apd.children[1], back),\n ) ||\n this.traverseAlg(\n commutator.B,\n new WalkerDown(wd.apd.children[2], back),\n ) ||\n this.traverseAlg(\n commutator.A,\n new WalkerDown(wd.apd.children[1], !back),\n ) ||\n this.traverseAlg(\n commutator.B,\n new WalkerDown(wd.apd.children[2], !back),\n )\n );\n }\n }\n\n public traverseConjugate(conjugate: Conjugate, wd: WalkerDown<P>): boolean {\n if (!this.firstcheck(wd)) {\n return false;\n }\n const back = this.domult(wd, 1);\n if (back) {\n return (\n this.traverseAlg(\n conjugate.A,\n new WalkerDown(wd.apd.children[1], !back),\n ) ||\n this.traverseAlg(\n conjugate.B,\n new WalkerDown(wd.apd.children[2], back),\n ) ||\n this.traverseAlg(conjugate.A, new WalkerDown(wd.apd.children[1], back))\n );\n } else {\n return (\n this.traverseAlg(\n conjugate.A,\n new WalkerDown(wd.apd.children[1], back),\n ) ||\n this.traverseAlg(\n conjugate.B,\n new WalkerDown(wd.apd.children[2], back),\n ) ||\n this.traverseAlg(conjugate.A, new WalkerDown(wd.apd.children[1], !back))\n );\n }\n }\n\n public traversePause(pause: Pause, wd: WalkerDown<P>): boolean {\n if (!this.firstcheck(wd)) {\n return false;\n }\n this.move = pause;\n this.moveDuration = wd.apd.duration;\n this.back = wd.back;\n return true;\n }\n\n public traverseNewline(_newline: Newline, _wd: WalkerDown<P>): boolean {\n return false;\n }\n\n public traverseLineComment(\n _lineComment: LineComment,\n _wd: WalkerDown<P>,\n ): boolean {\n return false;\n }\n\n private firstcheck(wd: WalkerDown<P>): boolean {\n if (\n wd.apd.moveCount + this.i <= this.goali &&\n wd.apd.duration + this.dur < this.goaldur\n ) {\n return this.keepgoing(wd);\n }\n return true;\n }\n\n private domult(wd: WalkerDown<P>, amount: number): boolean {\n let back = wd.back;\n if (amount === 0) {\n // I don't believe this will ever happen\n return back;\n }\n if (amount < 0) {\n back = !back;\n amount = -amount;\n }\n const base = wd.apd.children[0];\n const full = Math.min(\n Math.floor((this.goali - this.i) / base.moveCount),\n Math.ceil((this.goaldur - this.dur) / base.duration - 1),\n );\n if (full > 0) {\n this.keepgoing(new WalkerDown<P>(base, back), full);\n }\n return back;\n }\n\n private keepgoing(wd: WalkerDown<P>, mul: number = 1): boolean {\n this.i += mul * wd.apd.moveCount;\n this.dur += mul * wd.apd.duration;\n if (mul !== 1) {\n if (wd.back) {\n this.st = this.puz.combine(\n this.st,\n this.puz.multiply(wd.apd.backward, mul),\n );\n } else {\n this.st = this.puz.combine(\n this.st,\n this.puz.multiply(wd.apd.forward, mul),\n );\n }\n } else {\n if (wd.back) {\n this.st = this.puz.combine(this.st, wd.apd.backward);\n } else {\n this.st = this.puz.combine(this.st, wd.apd.forward);\n }\n }\n return false;\n }\n}\n", "import type { Alg, Move } from \"../../../../alg\";\nimport type {\n PuzzleWrapper,\n State,\n} from \"../../../views/3D/puzzles/KPuzzleWrapper\";\nimport type { Duration, Timestamp } from \"../../AnimationTypes\";\nimport type { AlgIndexer } from \"../AlgIndexer\";\nimport { chunkAlgs } from \"./chunkAlgs\";\nimport {\n AlgPartDecoration,\n AlgWalker,\n DecoratorConstructor,\n} from \"./AlgWalker\";\n\nexport class TreeAlgIndexer implements AlgIndexer<PuzzleWrapper> {\n private decoration: AlgPartDecoration<PuzzleWrapper>;\n private walker: AlgWalker<PuzzleWrapper>;\n constructor(private puzzle: PuzzleWrapper, alg: Alg) {\n const deccon = new DecoratorConstructor<PuzzleWrapper>(this.puzzle);\n\n const chunkedAlg = chunkAlgs(alg);\n\n this.decoration = deccon.traverseAlg(chunkedAlg);\n this.walker = new AlgWalker<PuzzleWrapper>(\n this.puzzle,\n chunkedAlg,\n this.decoration,\n );\n }\n\n public getAnimLeaf(index: number): Move | null {\n // FIXME need to support Pause\n if (this.walker.moveByIndex(index)) {\n if (!this.walker.move) {\n throw new Error(\"`this.walker.mv` missing\");\n }\n const move = this.walker.move as Move;\n // TODO: this type of negation needs to be in alg\n if (this.walker.back) {\n return move.invert();\n }\n return move;\n }\n return null;\n }\n\n public indexToMoveStartTimestamp(index: number): Timestamp {\n if (this.walker.moveByIndex(index) || this.walker.i === index) {\n return this.walker.dur;\n }\n throw new Error(`Out of algorithm: index ${index}`);\n }\n\n public indexToMovesInProgress(index: number): Timestamp {\n if (this.walker.moveByIndex(index) || this.walker.i === index) {\n return this.walker.dur;\n }\n throw new Error(`Out of algorithm: index ${index}`);\n }\n\n public stateAtIndex(\n index: number,\n startTransformation?: State<PuzzleWrapper>,\n ): State<PuzzleWrapper> {\n this.walker.moveByIndex(index);\n return this.puzzle.combine(\n startTransformation ?? this.puzzle.startState(),\n this.walker.st,\n );\n }\n\n // TransformAtIndex does not reflect the start state; it only reflects\n // the change from the start state to the current move index. If you\n // want the actual state, use stateAtIndex.\n public transformAtIndex(index: number): State<PuzzleWrapper> {\n this.walker.moveByIndex(index);\n return this.walker.st;\n }\n\n public numAnimatedLeaves(): number {\n return this.decoration.moveCount;\n }\n\n public timestampToIndex(timestamp: Timestamp): number {\n this.walker.moveByDuration(timestamp);\n return this.walker.i;\n }\n\n public algDuration(): Duration {\n return this.decoration.duration;\n }\n\n public moveDuration(index: number): number {\n this.walker.moveByIndex(index);\n return this.walker.moveDuration;\n }\n}\n", "import { countMoves } from \"../../../../../notation\";\nimport { SimpleAlgIndexer } from \"../../../../controllers/indexer/SimpleAlgIndexer\";\nimport { SimultaneousMoveIndexerV2 } from \"../../../../controllers/indexer/simultaneous-moves/SimultaneousMoveIndexerV2\";\nimport { TreeAlgIndexer } from \"../../../../controllers/indexer/tree/TreeAlgIndexer\";\nimport type { AlgWithIssues } from \"./AlgProp\";\nimport type { IndexerStrategyName } from \"./IndexerConstructorRequestProp\";\nimport type { VisualizationStrategy } from \"../../viewer/VisualizationStrategyProp\";\nimport { TwistyPropDerived } from \"../../TwistyProp\";\nimport type { PuzzleID } from \"../structure/PuzzleIDRequestProp\";\nimport type { KPuzzleWrapper } from \"../../../../views/3D/puzzles/KPuzzleWrapper\";\nimport type { Alg } from \"../../../../../alg\";\nimport type { AlgIndexer } from \"../../../..\";\n\nexport type IndexerConstructor = new (\n puzzle: KPuzzleWrapper,\n alg: Alg,\n) => AlgIndexer<KPuzzleWrapper>;\n\ninterface IndexerConstructorPropInputs {\n puzzle: PuzzleID;\n alg: AlgWithIssues;\n visualizationStrategy: VisualizationStrategy;\n indexerConstructorRequest: IndexerStrategyName;\n}\n\n// TODO: Also handle PG3D vs. 3D\nexport class IndexerConstructorProp extends TwistyPropDerived<\n IndexerConstructorPropInputs,\n IndexerConstructor\n> {\n derive(inputs: IndexerConstructorPropInputs): IndexerConstructor {\n switch (inputs.indexerConstructorRequest) {\n case \"auto\":\n if (\n countMoves(inputs.alg.alg) < 100 &&\n inputs.puzzle === \"3x3x3\" &&\n inputs.visualizationStrategy === \"Cube3D\"\n ) {\n return SimultaneousMoveIndexerV2;\n } else {\n return TreeAlgIndexer;\n }\n case \"tree\":\n return TreeAlgIndexer;\n case \"simple\":\n return SimpleAlgIndexer;\n case \"simultaneous\":\n return SimultaneousMoveIndexerV2;\n default:\n throw new Error(\"Invalid indexer request!\");\n }\n }\n}\n", "import { Alg } from \"../../../../../alg\";\nimport { KPuzzle, KPuzzleDefinition } from \"../../../../../kpuzzle\";\nimport { AlgIssues, AlgWithIssues } from \"./AlgProp\";\nimport { TwistyPropDerived } from \"../../TwistyProp\";\n\nexport class PuzzleAlgProp extends TwistyPropDerived<\n { algWithIssues: AlgWithIssues; puzzleDef: KPuzzleDefinition },\n AlgWithIssues\n> {\n async derive(inputs: {\n algWithIssues: AlgWithIssues;\n puzzleDef: KPuzzleDefinition;\n }): Promise<AlgWithIssues> {\n try {\n const kpuzzle = new KPuzzle(inputs.puzzleDef);\n kpuzzle.applyAlg(inputs.algWithIssues.alg);\n // Looks like we could apply the alg!\n return inputs.algWithIssues;\n } catch (e) {\n return {\n alg: new Alg(),\n issues: new AlgIssues({\n errors: [`Invalid alg for puzzle: ${(e as Error).toString()}`],\n }),\n };\n }\n }\n}\n", "import type { Move } from \"../../../../alg\";\nimport {\n combineTransformations,\n areStatesEquivalent,\n identityTransformation,\n invertTransformation,\n KPuzzleDefinition,\n transformationForMove,\n Transformation,\n} from \"../../../../kpuzzle\";\nimport { puzzles } from \"../../../../puzzles\";\n\nexport type MoveName = string;\n\nexport interface MoveProgress {\n move: Move;\n fraction: number;\n}\n\n// eslint-disable-next-line @typescript-eslint/no-empty-interface, @typescript-eslint/no-unused-vars\nexport interface State<T extends PuzzleWrapper> {}\n\nexport abstract class PuzzleWrapper {\n public abstract startState(): State<PuzzleWrapper>;\n public abstract invert(state: State<PuzzleWrapper>): State<PuzzleWrapper>;\n public abstract combine(\n s1: State<PuzzleWrapper>,\n s2: State<PuzzleWrapper>,\n ): State<PuzzleWrapper>;\n\n public multiply(\n state: State<PuzzleWrapper>,\n amount: number,\n ): State<PuzzleWrapper> {\n if (amount < 0) {\n return this.invert(this.multiply(state, -amount));\n }\n if (amount === 0) {\n return this.identity();\n }\n while (amount % 2 === 0) {\n amount = amount / 2;\n state = this.combine(state, state);\n }\n let newState = state;\n amount--;\n while (amount > 0) {\n if (amount % 2 === 1) {\n newState = this.combine(newState, state);\n }\n amount = Math.floor(amount / 2);\n if (amount > 0) {\n state = this.combine(state, state);\n }\n }\n return newState;\n }\n\n public abstract stateFromMove(move: Move): State<PuzzleWrapper>;\n public abstract identity(): State<PuzzleWrapper>;\n public abstract equivalent(\n s1: State<PuzzleWrapper>,\n s2: State<PuzzleWrapper>,\n ): boolean;\n}\n\nexport interface KSolvePuzzleState\n extends Transformation,\n State<KPuzzleWrapper> {}\n\nexport class KPuzzleWrapper extends PuzzleWrapper {\n // don't work the underlying kdefinition/multiply so hard\n public static async fromID(id: string): Promise<KPuzzleWrapper> {\n return new KPuzzleWrapper(await puzzles[id].def());\n }\n\n public moveCache: { [key: string]: Transformation } = {};\n constructor(private definition: KPuzzleDefinition) {\n super();\n }\n\n public startState(): KSolvePuzzleState {\n return this.definition.startPieces;\n }\n\n public invert(state: KSolvePuzzleState): KSolvePuzzleState {\n return invertTransformation(this.definition, state);\n }\n\n public combine(\n s1: KSolvePuzzleState,\n s2: KSolvePuzzleState,\n ): KSolvePuzzleState {\n return combineTransformations(this.definition, s1, s2);\n }\n\n public stateFromMove(move: Move): KSolvePuzzleState {\n const key = move.toString();\n if (!this.moveCache[key]) {\n this.moveCache[key] = transformationForMove(this.definition, move);\n }\n return this.moveCache[key];\n }\n\n public identity(): KSolvePuzzleState {\n return identityTransformation(this.definition);\n }\n\n public equivalent(s1: KSolvePuzzleState, s2: KSolvePuzzleState): boolean {\n return areStatesEquivalent(this.definition, s1, s2);\n }\n}\n\nclass QTMCounterState implements State<QTMCounterPuzzle> {\n constructor(public value: number) {}\n}\n\nexport class QTMCounterPuzzle extends PuzzleWrapper {\n public startState(): QTMCounterState {\n return new QTMCounterState(0);\n }\n\n public invert(state: QTMCounterState): QTMCounterState {\n return new QTMCounterState(-state.value);\n }\n\n public combine(s1: QTMCounterState, s2: QTMCounterState): QTMCounterState {\n return new QTMCounterState(s1.value + s2.value);\n }\n\n public stateFromMove(move: Move): QTMCounterState {\n return new QTMCounterState(Math.abs(move.amount));\n }\n\n public identity(): QTMCounterState {\n return new QTMCounterState(0);\n }\n\n public equivalent(s1: QTMCounterState, s2: QTMCounterState): boolean {\n return s1.value === s2.value;\n }\n}\n", "import type { Alg } from \"../../../../../alg\";\nimport type { KPuzzleDefinition, Transformation } from \"../../../../../kpuzzle\";\nimport { KPuzzleWrapper } from \"../../../../views/3D/puzzles/KPuzzleWrapper\";\nimport { TreeAlgIndexer } from \"../../../../controllers/indexer/tree/TreeAlgIndexer\";\nimport type { AlgWithIssues } from \"./AlgProp\";\nimport { TwistyPropDerived } from \"../../TwistyProp\";\n\ntype AlgTransformationPropInputs = {\n alg: AlgWithIssues;\n def: KPuzzleDefinition;\n};\n\nexport class AlgTransformationProp extends TwistyPropDerived<\n AlgTransformationPropInputs,\n Transformation\n> {\n derive(input: AlgTransformationPropInputs): Transformation {\n return this.applyAlg(input.def, input.alg.alg);\n }\n\n applyAlg(def: KPuzzleDefinition, alg: Alg): Transformation {\n const kpuzzleWrapper = new KPuzzleWrapper(def); // TODO: Remove this layer.\n const indexer = new TreeAlgIndexer(kpuzzleWrapper, alg); // TODO: Use a direct efficient traversal in `cubing/kpuzzle` instead of instantiating a whole indexer.\n return indexer.transformAtIndex(\n indexer.numAnimatedLeaves(),\n ) as Transformation;\n }\n}\n", "import type { KPuzzleDefinition } from \"../../../../../kpuzzle\";\nimport { KPuzzleWrapper } from \"../../../../views/3D/puzzles/KPuzzleWrapper\";\nimport type { AlgIndexer } from \"../../../../controllers/indexer/AlgIndexer\";\nimport type { AlgWithIssues } from \"./AlgProp\";\nimport { TwistyPropDerived } from \"../../TwistyProp\";\nimport type { IndexerConstructor } from \"./IndexerConstructorProp\";\n\ntype IndexerPropInputs = {\n indexerConstructor: IndexerConstructor;\n algWithIssues: AlgWithIssues;\n def: KPuzzleDefinition;\n};\nexport class IndexerProp extends TwistyPropDerived<\n IndexerPropInputs,\n AlgIndexer<any>\n> {\n derive(input: IndexerPropInputs): AlgIndexer<any> {\n const kpuzzleWrapper = new KPuzzleWrapper(input.def); // TODO: Remove this layer.\n return new input.indexerConstructor(\n kpuzzleWrapper,\n input.algWithIssues.alg,\n );\n }\n}\n", "import {\n combineTransformations,\n invertTransformation,\n KPuzzleDefinition,\n Transformation,\n} from \"../../../../../kpuzzle\";\nimport type { AlgIndexer } from \"../../../../controllers/indexer/AlgIndexer\";\nimport { TwistyPropDerived } from \"../../TwistyProp\";\nimport type { SetupToLocation } from \"./SetupAnchorProp\";\n\ninterface AnchoredStartPropInputs {\n setupAnchor: SetupToLocation;\n setupTransformation: Transformation;\n indexer: AlgIndexer<any>;\n def: KPuzzleDefinition;\n}\n\nexport class AnchoredStartProp extends TwistyPropDerived<\n AnchoredStartPropInputs,\n Transformation\n> {\n derive(inputs: AnchoredStartPropInputs): Transformation {\n switch (inputs.setupAnchor) {\n case \"start\":\n return inputs.setupTransformation;\n case \"end\": {\n const algTransformation = inputs.indexer.transformAtIndex(\n inputs.indexer.numAnimatedLeaves(),\n ) as Transformation;\n const inverseAlgTransformation = invertTransformation(\n inputs.def,\n algTransformation,\n );\n return combineTransformations(\n inputs.def,\n inputs.setupTransformation,\n inverseAlgTransformation,\n );\n }\n default:\n throw new Error(\"Unimplemented!\");\n }\n }\n}\n", "import type { TimeRange } from \"../../../controllers/AnimationTypes\";\nimport type { AlgIndexer } from \"../../../controllers/indexer/AlgIndexer\";\nimport { TwistyPropDerived } from \"../TwistyProp\";\n\nexport class TimeRangeProp extends TwistyPropDerived<\n { indexer: AlgIndexer<any> },\n TimeRange\n> {\n derive(inputs: { indexer: AlgIndexer<any> }): TimeRange {\n return {\n start: 0,\n end: inputs.indexer.algDuration(),\n };\n }\n}\n", "import type {\n MillisecondTimestamp,\n TimeRange,\n} from \"../../../controllers/AnimationTypes\";\nimport type { TimestampRequest } from \"./TimestampRequestProp\";\nimport { TwistyPropDerived } from \"../TwistyProp\";\nimport type { SetupToLocation } from \"../puzzle/state/SetupAnchorProp\";\n\ninterface DetailedTimelineInfoInputs {\n timestampRequest: TimestampRequest;\n timeRange: TimeRange;\n setupAnchor: SetupToLocation;\n}\n\nexport interface DetailedTimelineInfo {\n timestamp: MillisecondTimestamp;\n timeRange: TimeRange; // TODO: Don't incluede this, and let fresh listeners listen to multiple inputs?\n // Note: `atStart` and `atEnd` can both be true. This is the case with the\n // default (empty) alg, which has a duration of 0 ms.\n atStart: boolean;\n atEnd: boolean;\n}\n\nexport class DetailedTimelineInfoProp extends TwistyPropDerived<\n DetailedTimelineInfoInputs,\n DetailedTimelineInfo\n> {\n derive(inputs: DetailedTimelineInfoInputs): DetailedTimelineInfo {\n let timestamp = this.#requestedTimestampToMilliseconds(inputs);\n let atStart: boolean = false;\n let atEnd: boolean = false;\n if (timestamp >= inputs.timeRange.end) {\n atEnd = true;\n timestamp = Math.min(inputs.timeRange.end, timestamp);\n }\n if (timestamp <= inputs.timeRange.start) {\n atStart = true;\n timestamp = Math.max(inputs.timeRange.start, timestamp);\n }\n return {\n timestamp,\n timeRange: inputs.timeRange,\n atStart,\n atEnd,\n };\n }\n\n #requestedTimestampToMilliseconds(\n inputs: DetailedTimelineInfoInputs,\n ): MillisecondTimestamp {\n switch (inputs.timestampRequest) {\n case \"start\":\n return inputs.timeRange.start;\n case \"end\":\n return inputs.timeRange.end;\n case \"anchor\":\n return inputs.setupAnchor === \"start\"\n ? inputs.timeRange.start\n : inputs.timeRange.end;\n case \"opposite-anchor\":\n return inputs.setupAnchor === \"start\"\n ? inputs.timeRange.end\n : inputs.timeRange.start;\n default:\n return inputs.timestampRequest;\n }\n }\n\n canReuse(v1: DetailedTimelineInfo, v2: DetailedTimelineInfo) {\n return (\n v1.timestamp === v2.timestamp &&\n v1.timeRange.start === v2.timeRange.start &&\n v1.timeRange.end === v2.timeRange.end &&\n v1.atStart === v2.atStart &&\n v1.atEnd === v2.atEnd\n );\n }\n}\n", "import type { ButtonCommand } from \"../../../views/control-panel/TwistyButtonsV2\";\nimport type { PlayingInfo } from \"./PlayingInfoProp\";\nimport type { DetailedTimelineInfo } from \"./DetailedTimelineInfoProp\";\nimport { TwistyPropDerived } from \"../TwistyProp\";\n\ninterface ButtonAppearance {\n enabled: boolean;\n icon: string;\n title: string;\n}\nexport type ButtonAppearances = Record<ButtonCommand, ButtonAppearance>;\n\ninterface CoarseTimelineInfoInputs {\n playingInfo: PlayingInfo;\n detailedTimelineInfo: DetailedTimelineInfo;\n}\n\nexport interface CoarseTimelineInfo {\n playing: boolean;\n atStart: boolean;\n atEnd: boolean;\n}\n\n// This started as a version of `EffectiveTimestamp` without the actual\n// timestamp, to enable easier caching.\nexport class CoarseTimelineInfoProp extends TwistyPropDerived<\n CoarseTimelineInfoInputs,\n CoarseTimelineInfo\n> {\n derive(inputs: CoarseTimelineInfoInputs): CoarseTimelineInfo {\n return {\n playing: inputs.playingInfo.playing,\n atStart: inputs.detailedTimelineInfo.atStart,\n atEnd: inputs.detailedTimelineInfo.atEnd,\n };\n }\n\n canReuseValue(v1: CoarseTimelineInfo, v2: CoarseTimelineInfo): boolean {\n return (\n v1.playing === v2.playing &&\n v1.atStart === v2.atStart &&\n v1.atEnd === v2.atEnd\n );\n }\n}\n", "import { Move } from \"../../../../../alg\";\nimport { Direction } from \"../../../../controllers/AnimationTypes\";\nimport type {\n AlgIndexer,\n CurrentMoveInfo,\n} from \"../../../../controllers/indexer/AlgIndexer\";\nimport type { DetailedTimelineInfo } from \"../../timeline/DetailedTimelineInfoProp\";\nimport { TwistyPropDerived } from \"../../TwistyProp\";\nimport type { CatchUpMove } from \"./CatchUpMoveProp\";\n\ninterface PositionPropInputs {\n indexer: AlgIndexer<any>;\n detailedTimelineInfo: DetailedTimelineInfo;\n catchUpMove: CatchUpMove;\n}\n\n// TODO: Rename \"current\" (implies a single one) to \"active\"?\nexport class CurrentLeavesProp extends TwistyPropDerived<\n PositionPropInputs,\n CurrentMoveInfo\n> {\n derive(inputs: PositionPropInputs): CurrentMoveInfo {\n function addCatchUpMove(currentMoveInfo: CurrentMoveInfo): CurrentMoveInfo {\n if (\n inputs.detailedTimelineInfo.atEnd &&\n inputs.catchUpMove.move !== null\n ) {\n currentMoveInfo.currentMoves.push({\n move: inputs.catchUpMove.move,\n direction: Direction.Backwards,\n fraction: 1 - inputs.catchUpMove.amount,\n startTimestamp: -1, // TODO\n endTimestamp: -1, // TODO\n });\n }\n return currentMoveInfo;\n }\n\n // Copied from AlgCursor\n if (inputs.indexer.currentMoveInfo) {\n return addCatchUpMove(\n inputs.indexer.currentMoveInfo(inputs.detailedTimelineInfo.timestamp),\n );\n } else {\n const idx = inputs.indexer.timestampToIndex(\n inputs.detailedTimelineInfo.timestamp,\n );\n const currentMoveInfo: CurrentMoveInfo = {\n stateIndex: idx,\n currentMoves: [],\n movesFinishing: [],\n movesFinished: [],\n movesStarting: [],\n latestStart: -Infinity,\n earliestEnd: Infinity,\n };\n\n if (inputs.indexer.numAnimatedLeaves() > 0) {\n const move = inputs.indexer.getAnimLeaf(idx)?.as(Move);\n if (!move) {\n return addCatchUpMove(currentMoveInfo);\n }\n const start = inputs.indexer.indexToMoveStartTimestamp(idx);\n const duration = inputs.indexer.moveDuration(idx);\n const fraction =\n (inputs.detailedTimelineInfo.timestamp - start) / duration;\n const end = start + duration;\n const currentMove = {\n move,\n direction: Direction.Forwards,\n fraction,\n startTimestamp: start,\n endTimestamp: end,\n };\n if (fraction === 0) {\n currentMoveInfo.movesStarting.push(currentMove);\n // // TODO: push this into the indexer\n // position.state = combineTransformations(\n // inputs.def,\n // state,\n // transformationForMove(inputs.def, move),\n // ) as Transformation;\n } else if (fraction === 1) {\n currentMoveInfo.movesFinishing.push(currentMove);\n // // TODO: push this into the indexer\n // position.state = combineTransformations(\n // inputs.def,\n // state,\n // transformationForMove(inputs.def, move),\n // ) as Transformation;\n } else {\n // TODO\n currentMoveInfo.currentMoves.push(currentMove);\n currentMoveInfo.latestStart = Math.max(\n currentMoveInfo.latestStart,\n start,\n );\n currentMoveInfo.earliestEnd = Math.min(\n currentMoveInfo.earliestEnd,\n end,\n );\n }\n // }\n // }\n }\n return addCatchUpMove(currentMoveInfo);\n }\n }\n}\n", "import type { Move } from \"../../../../../alg\";\nimport type { CurrentMoveInfo } from \"../../../../controllers/indexer/AlgIndexer\";\nimport { arrayEqualsCompare } from \"../../../helpers\";\nimport { TwistyPropDerived } from \"../../TwistyProp\";\n\ninterface CurrentLeavesSimplifiedPropInputs {\n currentMoveInfo: CurrentMoveInfo;\n}\n\nexport interface CurrentLeavesSimplified {\n stateIndex: number;\n movesFinishing: Move[];\n movesFinished: Move[];\n}\n\n// This started as a version of `CurrentLeaves` without highly timestamp-sensitive info like fractions, to enable easier caching.\nexport class CurrentLeavesSimplifiedProp extends TwistyPropDerived<\n CurrentLeavesSimplifiedPropInputs,\n CurrentLeavesSimplified\n> {\n derive(inputs: CurrentLeavesSimplifiedPropInputs): CurrentLeavesSimplified {\n return {\n stateIndex: inputs.currentMoveInfo.stateIndex,\n movesFinishing: inputs.currentMoveInfo.movesFinishing.map(\n (currentMoveInfo) => currentMoveInfo.move,\n ),\n movesFinished: inputs.currentMoveInfo.movesFinished.map(\n (currentMoveInfo) => currentMoveInfo.move,\n ),\n };\n }\n\n canReuse(v1: CurrentLeavesSimplified, v2: CurrentLeavesSimplified): boolean {\n return (\n v1.stateIndex === v2.stateIndex &&\n arrayEqualsCompare(\n v1.movesFinishing,\n v2.movesFinishing,\n (m1: Move, m2: Move) => m1.isIdentical(m2),\n ) &&\n arrayEqualsCompare(\n v1.movesFinished,\n v2.movesFinished,\n (m1: Move, m2: Move) => m1.isIdentical(m2),\n )\n );\n }\n}\n", "import { KSolvePuzzle } from \"../../../..\";\nimport {\n combineTransformations,\n KPuzzleDefinition,\n Transformation,\n} from \"../../../../../kpuzzle\";\nimport type { AlgIndexer } from \"../../../../controllers/indexer/AlgIndexer\";\nimport type { CurrentLeavesSimplified } from \"./CurrentLeavesSimplified\";\nimport { TwistyPropDerived } from \"../../TwistyProp\";\n\ninterface CurrentTransformationPropInputs {\n anchoredStart: Transformation;\n currentLeavesSimplified: CurrentLeavesSimplified;\n indexer: AlgIndexer<any>;\n def: KPuzzleDefinition;\n}\n\n// TODO: Make this so we don't have to handle the finishing moves?\nexport class CurrentTransformationProp extends TwistyPropDerived<\n CurrentTransformationPropInputs,\n Transformation\n> {\n derive(inputs: CurrentTransformationPropInputs): Transformation {\n let state: Transformation = inputs.indexer.transformAtIndex(\n inputs.currentLeavesSimplified.stateIndex,\n ) as any;\n state = combineTransformations(inputs.def, inputs.anchoredStart, state);\n const ksolvePuzzle = new KSolvePuzzle(inputs.def); // TODO: put this elsewhere.\n // TODO: handle non-commutative finished/finishing/current moves.\n for (const finishingMove of inputs.currentLeavesSimplified.movesFinishing) {\n state = combineTransformations(\n inputs.def,\n state,\n ksolvePuzzle.stateFromMove(finishingMove),\n );\n }\n for (const finishedMove of inputs.currentLeavesSimplified.movesFinished) {\n state = combineTransformations(\n inputs.def,\n state,\n ksolvePuzzle.stateFromMove(finishedMove),\n );\n }\n return state;\n }\n}\n", "import type { Transformation } from \"../../../../../kpuzzle\";\nimport type { PuzzlePosition } from \"../../../../controllers/AnimationTypes\";\nimport type { CurrentMoveInfo } from \"../../../../controllers/indexer/AlgIndexer\";\nimport { TwistyPropDerived } from \"../../TwistyProp\";\n\nexport interface LegacyPositionPropInputs {\n currentMoveInfo: CurrentMoveInfo;\n transformation: Transformation;\n}\n\n// TODO: This exist as a convenience for old `Twisty3D` implementations. Get rid of this.\nexport class LegacyPositionProp extends TwistyPropDerived<\n LegacyPositionPropInputs,\n PuzzlePosition\n> {\n derive(inputs: LegacyPositionPropInputs): PuzzlePosition {\n return {\n state: inputs.transformation,\n movesInProgress: inputs.currentMoveInfo.currentMoves,\n };\n }\n}\n", "import type { KPuzzleDefinition } from \"../../../../../kpuzzle\";\nimport type { PuzzleLoader } from \"../../../../../puzzles\";\nimport { TwistyPropDerived } from \"../../TwistyProp\";\n\nexport class PuzzleDefProp extends TwistyPropDerived<\n { puzzleLoader: PuzzleLoader },\n KPuzzleDefinition\n> {\n async derive(inputs: {\n puzzleLoader: PuzzleLoader;\n }): Promise<KPuzzleDefinition> {\n return inputs.puzzleLoader.def();\n }\n}\n", "import { arrayEquals } from \"./helpers\";\nimport { SimpleTwistyPropSource } from \"./props/TwistyProp\";\n\ninterface UserVisibleError {\n errors: string[];\n}\n\nconst EMPTY_ERRORS = { errors: [] };\n\nexport class UserVisibleErrorTracker extends SimpleTwistyPropSource<UserVisibleError> {\n override getDefaultValue(): UserVisibleError {\n return EMPTY_ERRORS;\n }\n\n reset() {\n this.set(this.getDefaultValue());\n }\n\n canReuseValue(_v1: UserVisibleError, _v2: UserVisibleError): boolean {\n return arrayEquals(_v1.errors, _v2.errors);\n }\n}\n", "import type { Move } from \"../../../../../alg\";\nimport { SimpleTwistyPropSource } from \"../../TwistyProp\";\n\nexport interface CatchUpMove {\n move: Move | null;\n amount: number;\n}\n\nexport class CatchUpMoveProp extends SimpleTwistyPropSource<CatchUpMove> {\n getDefaultValue(): CatchUpMove {\n return { move: null, amount: 0 };\n }\n\n canReuseValue(v1: CatchUpMove, v2: CatchUpMove) {\n return v1.move === v2.move && v1.amount === v2.amount;\n }\n}\n", "import { countMoves } from \"../../../../../notation\";\nimport { TwistyPropDerived } from \"../../TwistyProp\";\nimport type { AlgWithIssues } from \"./AlgProp\";\n\ninterface NaiveMoveCountPropInputs {\n alg: AlgWithIssues;\n}\n\n// TODO: handle metrics\nexport class NaiveMoveCountProp extends TwistyPropDerived<\n NaiveMoveCountPropInputs,\n number | null\n> {\n derive(inputs: NaiveMoveCountPropInputs): number | null {\n if (inputs.alg.issues.errors.length > 0) {\n return null;\n }\n return countMoves(inputs.alg.alg);\n }\n}\n", "import { SimpleTwistyPropSource } from \"../../TwistyProp\";\n\nexport const movePressInputNames = {\n auto: true,\n none: true,\n basic: true,\n};\nexport type MovePressInput = keyof typeof movePressInputNames;\n\nexport class MovePressInputProp extends SimpleTwistyPropSource<MovePressInput> {\n getDefaultValue(): MovePressInput {\n return \"auto\";\n }\n}\n", "import { SimpleTwistyPropSource } from \"../../TwistyProp\";\n\nexport type FoundationDisplay = \"auto\" | \"opaque\" | \"none\";\n\nexport class FoundationDisplayProp extends SimpleTwistyPropSource<FoundationDisplay> {\n getDefaultValue(): FoundationDisplay {\n return \"auto\";\n }\n}\n", "import { AlgProp } from \"./props/puzzle/state/AlgProp\";\nimport { BackgroundProp } from \"./props/viewer/BackgroundProp\";\nimport { BackViewProp } from \"./props/viewer/BackViewProp\";\nimport { ControlPanelProp } from \"./props/viewer/ControlPanelProp\";\nimport { HintFaceletProp } from \"./props/puzzle/display/HintFaceletProp\";\nimport { IndexerConstructorRequestProp } from \"./props/puzzle/state/IndexerConstructorRequestProp\";\nimport { LatitudeLimitProp } from \"./props/viewer/LatitudeLimit\";\nimport { OrbitCoordinatesRequestProp } from \"./props/viewer/OrbitCoordinatesRequestProp\";\nimport { PlayingInfoProp } from \"./props/timeline/PlayingInfoProp\";\nimport { PGPuzzleDescriptionStringProp } from \"./props/puzzle/structure/PuzzleDescriptionProp\";\nimport { PuzzleIDRequestProp } from \"./props/puzzle/structure/PuzzleIDRequestProp\";\nimport { PuzzleLoaderProp } from \"./props/puzzle/structure/PuzzleLoaderProp\";\nimport { SetupAnchorProp } from \"./props/puzzle/state/SetupAnchorProp\";\nimport { StickeringProp } from \"./props/puzzle/display/StickeringProp\";\nimport { TempoScaleProp } from \"./props/timeline/TempoScaleProp\";\nimport { TimestampRequestProp } from \"./props/timeline/TimestampRequestProp\";\nimport { URLProp } from \"./props/general/URLProp\";\nimport { ViewerLinkProp } from \"./props/viewer/ViewerLinkProp\";\nimport { VisualizationFormatProp } from \"./props/viewer/VisualizationProp\";\nimport { OrbitCoordinatesProp } from \"./props/viewer/OrbitCoordinatesProp\";\nimport { PuzzleIDProp } from \"./props/puzzle/structure/PuzzleIDProp\";\nimport { SpriteProp } from \"./props/puzzle/display/SpriteProp\";\nimport { VisualizationStrategyProp } from \"./props/viewer/VisualizationStrategyProp\";\nimport { IndexerConstructorProp } from \"./props/puzzle/state/IndexerConstructorProp\";\nimport { PuzzleAlgProp } from \"./props/puzzle/state/PuzzleAlgProp\";\nimport { AlgTransformationProp } from \"./props/puzzle/state/AlgTransformationProp\";\nimport { IndexerProp } from \"./props/puzzle/state/IndexerProp\";\nimport { AnchoredStartProp } from \"./props/puzzle/state/AnchoredStartProp\";\nimport { TimeRangeProp } from \"./props/viewer/TimeRangeProp\";\nimport { DetailedTimelineInfoProp } from \"./props/timeline/DetailedTimelineInfoProp\";\nimport { CoarseTimelineInfoProp } from \"./props/timeline/CoarseTimelineInfoProp\";\nimport { CurrentLeavesProp } from \"./props/puzzle/state/CurrentLeavesProp\";\nimport { ButtonAppearanceProp } from \"./props/viewer/ButtonAppearanceProp\";\nimport { CurrentLeavesSimplifiedProp } from \"./props/puzzle/state/CurrentLeavesSimplified\";\nimport { CurrentTransformationProp } from \"./props/puzzle/state/CurrentTransformationProp\";\nimport { LegacyPositionProp } from \"./props/puzzle/state/LegacyPositionProp\";\nimport { PuzzleDefProp } from \"./props/puzzle/structure/PuzzleDefProp\";\nimport { UserVisibleErrorTracker } from \"./UserVisibleErrorTracker\";\nimport { CatchUpMoveProp } from \"./props/puzzle/state/CatchUpMoveProp\";\nimport { experimentalAppendMove, Move } from \"../../alg\";\nimport { NaiveMoveCountProp } from \"./props/puzzle/state/NaiveMoveCountProp\";\nimport { MovePressInputProp } from \"./props/puzzle/state/MovePressInputProp\";\nimport { FoundationDisplayProp } from \"./props/puzzle/display/FoundationDisplayProp\";\n\nexport class TwistyPlayerModel {\n // TODO: incorporate error handling into the entire prop graph.\n // TODO: Make this something that can't get confused with normal props?\n userVisibleErrorTracker = new UserVisibleErrorTracker();\n\n // TODO: Redistribute and group props with controllers.\n\n // Depth 0\n algProp = new AlgProp();\n backgroundProp = new BackgroundProp();\n backViewProp = new BackViewProp();\n controlPanelProp = new ControlPanelProp();\n catchUpMoveProp = new CatchUpMoveProp();\n foundationDisplayProp = new FoundationDisplayProp();\n foundationStickerSpriteURL = new URLProp();\n hintFaceletProp = new HintFaceletProp();\n hintStickerSpriteURL = new URLProp();\n indexerConstructorRequestProp = new IndexerConstructorRequestProp();\n latitudeLimitProp = new LatitudeLimitProp();\n movePressInputProp = new MovePressInputProp();\n orbitCoordinatesRequestProp: OrbitCoordinatesRequestProp =\n new OrbitCoordinatesRequestProp();\n playingInfoProp = new PlayingInfoProp();\n puzzleDescriptionRequestProp = new PGPuzzleDescriptionStringProp();\n puzzleIDRequestProp = new PuzzleIDRequestProp();\n setupAnchorProp = new SetupAnchorProp();\n setupProp = new AlgProp();\n stickeringProp = new StickeringProp();\n tempoScaleProp = new TempoScaleProp();\n timestampRequestProp = new TimestampRequestProp();\n viewerLinkProp = new ViewerLinkProp();\n visualizationFormatProp = new VisualizationFormatProp();\n\n // Depth 1\n foundationStickerSprite = new SpriteProp({\n spriteURL: this.foundationStickerSpriteURL,\n });\n\n hintStickerSprite = new SpriteProp({\n spriteURL: this.hintStickerSpriteURL,\n });\n\n puzzleLoaderProp = new PuzzleLoaderProp(\n {\n puzzleIDRequest: this.puzzleIDRequestProp,\n puzzleDescriptionRequest: this.puzzleDescriptionRequestProp,\n },\n this.userVisibleErrorTracker,\n );\n\n // Depth 2\n puzzleDefProp = new PuzzleDefProp({ puzzleLoader: this.puzzleLoaderProp });\n\n puzzleIDProp = new PuzzleIDProp({ puzzleLoader: this.puzzleLoaderProp });\n\n // Depth 3\n\n puzzleAlgProp = new PuzzleAlgProp({\n algWithIssues: this.algProp,\n puzzleDef: this.puzzleDefProp,\n });\n\n puzzleSetupProp = new PuzzleAlgProp({\n algWithIssues: this.setupProp,\n puzzleDef: this.puzzleDefProp,\n });\n\n visualizationStrategyProp = new VisualizationStrategyProp({\n visualizationRequest: this.visualizationFormatProp,\n puzzleID: this.puzzleIDProp,\n });\n\n // Depth 4\n indexerConstructorProp = new IndexerConstructorProp({\n alg: this.algProp,\n puzzle: this.puzzleIDProp,\n visualizationStrategy: this.visualizationStrategyProp,\n indexerConstructorRequest: this.indexerConstructorRequestProp,\n });\n\n moveCountProp = new NaiveMoveCountProp({ alg: this.puzzleAlgProp });\n\n orbitCoordinatesProp = new OrbitCoordinatesProp({\n orbitCoordinatesRequest: this.orbitCoordinatesRequestProp,\n latitudeLimit: this.latitudeLimitProp,\n puzzleID: this.puzzleIDProp,\n strategy: this.visualizationStrategyProp,\n });\n\n setupTransformationProp = new AlgTransformationProp({\n alg: this.puzzleSetupProp,\n def: this.puzzleDefProp,\n });\n\n // Depth 5\n indexerProp = new IndexerProp({\n indexerConstructor: this.indexerConstructorProp,\n algWithIssues: this.puzzleAlgProp,\n def: this.puzzleDefProp,\n });\n\n // Depth 6\n anchoredStartProp = new AnchoredStartProp({\n setupAnchor: this.setupAnchorProp,\n setupTransformation: this.setupTransformationProp,\n indexer: this.indexerProp,\n def: this.puzzleDefProp,\n });\n\n timeRangeProp = new TimeRangeProp({\n indexer: this.indexerProp,\n });\n\n // Depth 7\n detailedTimelineInfoProp: DetailedTimelineInfoProp =\n new DetailedTimelineInfoProp({\n timestampRequest: this.timestampRequestProp,\n timeRange: this.timeRangeProp,\n setupAnchor: this.setupAnchorProp,\n });\n\n // Depth 8\n coarseTimelineInfoProp = new CoarseTimelineInfoProp({\n detailedTimelineInfo: this.detailedTimelineInfoProp,\n playingInfo: this.playingInfoProp,\n });\n\n currentLeavesProp = new CurrentLeavesProp({\n indexer: this.indexerProp,\n detailedTimelineInfo: this.detailedTimelineInfoProp,\n catchUpMove: this.catchUpMoveProp,\n });\n\n // Depth 9\n // TODO: Inline Twisty3D management.\n buttonAppearanceProp = new ButtonAppearanceProp({\n coarseTimelineInfo: this.coarseTimelineInfoProp,\n viewerLink: this.viewerLinkProp,\n });\n\n currentLeavesSimplifiedProp = new CurrentLeavesSimplifiedProp({\n currentMoveInfo: this.currentLeavesProp,\n });\n\n // Depth 10\n currentTransformationProp = new CurrentTransformationProp({\n anchoredStart: this.anchoredStartProp,\n currentLeavesSimplified: this.currentLeavesSimplifiedProp,\n indexer: this.indexerProp,\n def: this.puzzleDefProp,\n });\n\n // Depth 11\n legacyPositionProp = new LegacyPositionProp({\n currentMoveInfo: this.currentLeavesProp,\n transformation: this.currentTransformationProp,\n });\n\n public async twizzleLink(): Promise<string> {\n const url = new URL(\"https://alpha.twizzle.net/edit/\");\n\n const [puzzle, alg, setup, anchor, experimentalStickering] = await Promise.all([\n this.puzzleIDProp.get(),\n this.algProp.get(),\n this.setupProp.get(),\n this.setupAnchorProp.get(),\n this.stickeringProp.get(),\n ]);\n\n if (!alg.alg.experimentalIsEmpty()) {\n url.searchParams.set(\"alg\", alg.alg.toString());\n }\n if (!setup.alg.experimentalIsEmpty()) {\n url.searchParams.set(\"setup-alg\", setup.alg.toString());\n }\n if (anchor !== \"start\") {\n url.searchParams.set(\"setup-anchor\", anchor);\n }\n if (experimentalStickering !== \"full\") {\n url.searchParams.set(\n \"experimental-stickering\",\n experimentalStickering,\n );\n }\n if (puzzle !== \"3x3x3\") {\n url.searchParams.set(\"puzzle\", puzzle);\n }\n return url.toString();\n }\n\n // TODO: Animate the new move.\n experimentalAddMove(\n flexibleMove: Move | string,\n options: { coalesce?: boolean; mod?: number } = {},\n ): void {\n const move =\n typeof flexibleMove === \"string\" ? new Move(flexibleMove) : flexibleMove;\n (async () => {\n const alg = (await this.algProp.get()).alg;\n const newAlg = experimentalAppendMove(alg, move, {\n coalesce: options?.coalesce,\n mod: options?.mod,\n });\n this.algProp.set(newAlg);\n this.timestampRequestProp.set(\"end\");\n this.catchUpMoveProp.set({\n move: move,\n amount: 0,\n });\n })();\n }\n}\n", "import type { Alg } from \"../../alg\";\nimport type { PuzzleDescriptionString } from \"../../puzzle-geometry/PGPuzzles\";\nimport type { ExperimentalStickering, PuzzleID } from \"../../twisty\";\nimport type { BackgroundThemeWithAuto } from \"../model/props/viewer/BackgroundProp\";\nimport type { BackViewLayoutWithAuto } from \"../model/props/viewer/BackViewProp\";\nimport type { ControlPanelThemeWithAuto } from \"../model/props/viewer/ControlPanelProp\";\nimport type { HintFaceletStyleWithAuto } from \"../model/props/puzzle/display/HintFaceletProp\";\nimport type { IndexerStrategyName } from \"../model/props/puzzle/state/IndexerConstructorRequestProp\";\nimport type { TimestampRequest } from \"../model/props/timeline/TimestampRequestProp\";\nimport type { ViewerLinkPageWithAuto } from \"../model/props/viewer/ViewerLinkProp\";\nimport type { VisualizationFormatWithAuto } from \"../model/props/viewer/VisualizationProp\";\nimport { TwistyPlayerModel } from \"../model/TwistyPlayerModel\";\nimport type { MillisecondTimestamp } from \"../controllers/AnimationTypes\";\nimport { ManagedCustomElement } from \"./ManagedCustomElement\";\nimport type { MovePressInput } from \"../model/props/puzzle/state/MovePressInputProp\";\nimport type { SetupToLocation } from \"../model/props/puzzle/state/SetupAnchorProp\";\n\nfunction err(propName: string): Error {\n return new Error(\n `Cannot get \\`.${propName}\\` directly from a \\`TwistyPlayer\\`.`,\n );\n}\n\n// prettier-ignore\nexport abstract class TwistyPlayerSettable extends ManagedCustomElement {\n experimentalModel: TwistyPlayerModel = new TwistyPlayerModel();\n\n set alg(newAlg: Alg | string) { this.experimentalModel.algProp.set(newAlg); }\n get alg(): never { throw err(\"alg\"); }\n\n set experimentalSetupAlg(newSetup: Alg | string) { this.experimentalModel.setupProp.set(newSetup); }\n get experimentalSetupAlg(): never { throw err(\"setup\"); }\n\n set experimentalSetupAnchor(anchor: SetupToLocation) { this.experimentalModel.setupAnchorProp.set(anchor); }\n get experimentalSetupAnchor(): never { throw err(\"anchor\"); }\n\n set puzzle(puzzleID: PuzzleID) { this.experimentalModel.puzzleIDRequestProp.set(puzzleID); }\n get puzzle(): never { throw err(\"puzzle\"); }\n\n set experimentalPuzzleDescription(puzzleDescription: PuzzleDescriptionString) { this.experimentalModel.puzzleDescriptionRequestProp.set(puzzleDescription); }\n get experimentalPuzzleDescription(): never { throw err(\"experimentalPuzzleDescription\"); }\n\n set timestamp(timestamp: TimestampRequest) { this.experimentalModel.timestampRequestProp.set(timestamp); }\n get timestamp(): never { throw err(\"timestamp\"); }\n\n set hintFacelets(hintFaceletStyle: HintFaceletStyleWithAuto) { this.experimentalModel.hintFaceletProp.set(hintFaceletStyle); }\n get hintFacelets(): never { throw err(\"hintFacelets\"); }\n\n set experimentalStickering(stickering: ExperimentalStickering) { this.experimentalModel.stickeringProp.set(stickering); }\n get experimentalStickering(): never { throw err(\"stickering\"); }\n\n set backView(backView: BackViewLayoutWithAuto) { this.experimentalModel.backViewProp.set(backView); }\n get backView(): never { throw err(\"backView\"); }\n\n set background(backgroundTheme: BackgroundThemeWithAuto) { this.experimentalModel.backgroundProp.set(backgroundTheme); }\n get background(): never { throw err(\"background\"); }\n\n set controlPanel(newControlPanel: ControlPanelThemeWithAuto) { this.experimentalModel.controlPanelProp.set(newControlPanel); }\n get controlPanel(): never { throw err(\"controlPanel\"); }\n\n set visualization(visualizationFormat: VisualizationFormatWithAuto) { this.experimentalModel.visualizationFormatProp.set(visualizationFormat); }\n get visualization(): never { throw err(\"visualization\"); }\n\n set viewerLink(viewerLinkPage: ViewerLinkPageWithAuto) { this.experimentalModel.viewerLinkProp.set(viewerLinkPage); }\n get viewerLink(): never { throw err(\"viewerLink\"); }\n\n set experimentalMovePressInput(movePressInput: MovePressInput) { this.experimentalModel.movePressInputProp.set(movePressInput); }\n get experimentalMovePressInput(): never { throw err(\"experimentalMovePressInput\"); }\n\n set cameraLatitude(latitude: number) { this.experimentalModel.orbitCoordinatesRequestProp.set({ latitude }); }\n get cameraLatitude(): never { throw err(\"cameraLatitude\"); }\n\n set cameraLongitude(longitude: number) { this.experimentalModel.orbitCoordinatesRequestProp.set({ longitude }); }\n get cameraLongitude(): never { throw err(\"cameraLongitude\"); }\n\n set cameraDistance(distance: number) { this.experimentalModel.orbitCoordinatesRequestProp.set({ distance }); }\n get cameraDistance(): never { throw err(\"cameraDistance\"); }\n\n set cameraLatitudeLimit(latitudeLimit: number) { this.experimentalModel.latitudeLimitProp.set(latitudeLimit); }\n get cameraLatitudeLimit(): never { throw err(\"cameraLatitudeLimit\"); }\n\n set indexer(indexer: IndexerStrategyName) { this.experimentalModel.indexerConstructorRequestProp.set(indexer); }\n get indexer(): never { throw err(\"indexer\"); }\n\n set tempoScale(newTempoScale: number) { this.experimentalModel.tempoScaleProp.set(newTempoScale); }\n get tempoScale(): never { throw err(\"tempoScale\"); }\n\n set experimentalSprite(url: string | URL) { this.experimentalModel.foundationStickerSpriteURL.set(url); }\n get experimentalSprite(): never { throw err(\"experimentalSprite\"); }\n\n set experimentalHintSprite(url: string | URL) { this.experimentalModel.hintStickerSpriteURL.set(url); }\n get experimentalHintSprite(): never { throw err(\"experimentalHintSprite\"); }\n\n experimentalGet = new ExperimentalGetters(this.experimentalModel)\n}\n\nclass ExperimentalGetters {\n constructor(private model: TwistyPlayerModel) {}\n\n async alg(): Promise<Alg> {\n return (await this.model.algProp.get()).alg;\n }\n\n async setupAlg(): Promise<Alg> {\n return (await this.model.setupProp.get()).alg;\n }\n\n puzzleID(): Promise<PuzzleID> {\n return this.model.puzzleIDProp.get();\n }\n\n async timestamp(): Promise<MillisecondTimestamp> {\n return (await this.model.detailedTimelineInfoProp.get()).timestamp;\n }\n}\n", "import type { ExperimentalStickering, PG3D } from \"..\";\nimport type { Alg, Move } from \"../../alg\";\nimport type { PuzzleDescriptionString } from \"../../puzzle-geometry/PGPuzzles\";\nimport type { TwistyAnimationControllerDelegate } from \"../controllers/TwistyAnimationController\";\nimport { TwistyPlayerController } from \"../controllers/TwistyPlayerController\";\nimport type { HintFaceletStyleWithAuto } from \"../model/props/puzzle/display/HintFaceletProp\";\nimport type { MovePressInput } from \"../model/props/puzzle/state/MovePressInputProp\";\nimport type { SetupToLocation } from \"../model/props/puzzle/state/SetupAnchorProp\";\nimport type { PuzzleID } from \"../model/props/puzzle/structure/PuzzleIDRequestProp\";\nimport type { BackgroundThemeWithAuto } from \"../model/props/viewer/BackgroundProp\";\nimport type { BackViewLayoutWithAuto } from \"../model/props/viewer/BackViewProp\";\nimport {\n ControlPanelThemeWithAuto,\n controlsLocations,\n} from \"../model/props/viewer/ControlPanelProp\";\nimport type { ViewerLinkPageWithAuto } from \"../model/props/viewer/ViewerLinkProp\";\nimport type { VisualizationFormatWithAuto } from \"../model/props/viewer/VisualizationProp\";\nimport type { VisualizationStrategy } from \"../model/props/viewer/VisualizationStrategyProp\";\nimport { ClassListManager } from \"./ClassListManager\";\nimport { customElementsShim } from \"./node-custom-element-shims\";\nimport { twistyPlayerCSS } from \"./TwistyPlayer.css\";\n\nimport { Twisty2DSceneWrapper } from \"./2D/Twisty2DSceneWrapper\";\nimport { Twisty3DSceneWrapper } from \"./3D/Twisty3DSceneWrapper\";\nimport { TwistyButtonsV2 } from \"./control-panel/TwistyButtonsV2\";\nimport { TwistyScrubberV2 } from \"./control-panel/TwistyScrubberV2\";\nimport { downloadURL, getDefaultFilename, screenshot } from \"./screenshot\";\nimport { TwistyPlayerSettable } from \"./TwistyPlayerSettable\";\n\n// TODO: I couldn't figure out how to use use more specific types. Ideally, we'd\n// enforce consistency with the model.\nexport const twistyPlayerAttributeMap = {\n // TODO: We assume each of these can be set using a string or will be automatically converted by JS (e.g. numbers). Can we enforce\n // that with types? Do we need to add a translation mechanism for things we\n // don't want to leave settable as strings?\n // TODO: Enum validation.\n\n // Alg\n \"alg\": \"alg\",\n \"experimental-setup-alg\": \"experimentalSetupAlg\",\n\n // String-based\n \"experimental-setup-anchor\": \"experimentalSetupAnchor\",\n \"puzzle\": \"puzzle\",\n \"experimental-puzzle-description\": \"experimentalPuzzleDescription\",\n \"visualization\": \"visualization\",\n \"hint-facelets\": \"hintFacelets\",\n \"experimental-stickering\": \"experimentalStickering\",\n \"background\": \"background\",\n \"control-panel\": \"controlPanel\",\n \"back-view\": \"backView\",\n // \"indexer\": \"indexer\",\n \"viewer-link\": \"viewerLink\",\n \"experimental-move-press-input\": \"experimentalMovePressInput\",\n\n // Number-based\n \"camera-latitude\": \"cameraLatitude\",\n \"camera-longitude\": \"cameraLongitude\",\n \"camera-distance\": \"cameraDistance\",\n \"camera-latitude-limit\": \"cameraLatitudeLimit\",\n \"tempo-scale\": \"tempoScale\",\n\n // URL-based\n \"experimental-sprite\": \"experimentalSprite\",\n \"experimental-hint-sprite\": \"experimentalHintSprite\",\n};\n\nexport type TwistyPlayerAttribute = keyof typeof twistyPlayerAttributeMap;\n\nconst configKeys: Record<TwistyPlayerAttribute, true> = Object.fromEntries(\n Object.values(twistyPlayerAttributeMap).map((s) => [s, true]),\n) as any;\n\n// TODO: Find a way to share this def with `attributeMap`.\nexport interface TwistyPlayerConfig {\n // Alg\n alg?: Alg | string;\n experimentalSetupAlg?: Alg | string;\n\n // String-based\n experimentalSetupAnchor?: SetupToLocation; // TODO: \"auto\"\n puzzle?: PuzzleID;\n experimentalPuzzleDescription?: PuzzleDescriptionString;\n visualization?: VisualizationFormatWithAuto;\n hintFacelets?: HintFaceletStyleWithAuto;\n experimentalStickering?: ExperimentalStickering;\n background?: BackViewLayoutWithAuto;\n controlPanel?: ControlPanelThemeWithAuto;\n backView?: BackViewLayoutWithAuto;\n // \"indexer\"?: \"indexer\";\n viewerLink?: ViewerLinkPageWithAuto;\n experimentalMovePressInput?: MovePressInput;\n\n // Number-based\n cameraLatitude?: number;\n cameraLongitude?: number;\n cameraDistance?: number;\n cameraLatitudeLimit?: number;\n tempoScale?: number;\n\n // URL-based\n experimentalSprite?: string | null;\n experimentalHintSprite?: string | null;\n}\n\n/**\n * TwistyPlayer is the heart of `cubing.js`. It can be used to display a puzzle on a web page like this:\n *\n * <script src=\"path/to/cubing/twisty\" type=\"module\"></script>\n * <twisty-player alg=\"R U R'\"></twisty-player>\n *\n * You can also construct it directly in JavaScript:\n *\n * import { TwistyPlayer } from \"cubing/twisty\";\n * const twistyPlayer = new TwistyPlayer({alg: \"R U R'\"});\n * // Once the page has loaded, you can do this:\n * document.body.appendChild(twistyPlayer);\n *\n * See {@link https://js.cubing.net/cubing/} for more examples.\n */\nexport class TwistyPlayer\n extends TwistyPlayerSettable\n implements TwistyAnimationControllerDelegate\n{\n controller: TwistyPlayerController = new TwistyPlayerController(\n this.experimentalModel,\n this,\n );\n\n buttons: TwistyButtonsV2;\n\n experimentalCanvasClickCallback: (...args: any) => void = () => {};\n // #onCanvasClick() {\n\n // }\n\n constructor(config: TwistyPlayerConfig = {}) {\n super();\n\n // TODO: double-check that these are all getting set sync without causing extra work.\n for (const [propName, value] of Object.entries(config)) {\n if (!configKeys[propName as TwistyPlayerAttribute]) {\n console.warn(`Invalid config passed to TwistyPlayer: ${propName}`);\n break;\n }\n (this as any)[propName] = value;\n }\n }\n\n #controlsManager: ClassListManager<ControlPanelThemeWithAuto> =\n new ClassListManager<ControlPanelThemeWithAuto>(\n this,\n \"controls-\",\n ([\"auto\"] as ControlPanelThemeWithAuto[]).concat(\n Object.keys(controlsLocations) as ControlPanelThemeWithAuto[],\n ),\n );\n\n #visualizationWrapperElem = document.createElement(\"div\"); // TODO: Better pattern.\n #errorElem = document.createElement(\"div\"); // TODO: Better pattern.\n #alreadyConnected = false; // TODO: support resetting\n async connectedCallback(): Promise<void> {\n if (this.#alreadyConnected) {\n return;\n }\n this.#alreadyConnected = true;\n this.addCSS(twistyPlayerCSS);\n\n this.addElement(this.#visualizationWrapperElem).classList.add(\n \"visualization-wrapper\",\n );\n this.addElement(this.#errorElem).classList.add(\"error-elem\");\n this.#errorElem.textContent = \"Error\";\n this.experimentalModel.userVisibleErrorTracker.addFreshListener(\n (userVisibleError) => {\n const errorString: string | null = userVisibleError.errors[0] ?? null;\n this.contentWrapper.classList.toggle(\"error\", !!errorString);\n if (errorString) {\n this.#errorElem.textContent = errorString;\n }\n },\n );\n\n const scrubber = new TwistyScrubberV2(this.experimentalModel);\n this.contentWrapper.appendChild(scrubber);\n\n this.buttons = new TwistyButtonsV2(\n this.experimentalModel,\n this.controller,\n this,\n );\n this.contentWrapper.appendChild(this.buttons);\n\n this.experimentalModel.backgroundProp.addFreshListener(\n (backgroundTheme: BackgroundThemeWithAuto) => {\n this.contentWrapper.classList.toggle(\n \"checkered\",\n backgroundTheme !== \"none\",\n );\n },\n );\n\n this.experimentalModel.controlPanelProp.addFreshListener(\n (controlPanel: ControlPanelThemeWithAuto) => {\n this.#controlsManager.setValue(controlPanel);\n },\n );\n\n this.experimentalModel.visualizationStrategyProp.addFreshListener(\n this.#setVisualizationWrapper.bind(this),\n );\n\n this.experimentalModel.puzzleIDProp.addFreshListener(this.flash.bind(this));\n }\n\n flash() {\n this.#visualizationWrapper?.animate([{ opacity: 0.25 }, { opacity: 1 }], {\n duration: 250,\n });\n }\n\n #visualizationWrapper: Twisty2DSceneWrapper | Twisty3DSceneWrapper | null =\n null;\n\n #visualizationStrategy: VisualizationStrategy | null = null;\n #setVisualizationWrapper(strategy: VisualizationStrategy): void {\n if (strategy !== this.#visualizationStrategy) {\n this.#visualizationWrapper?.remove();\n this.#visualizationWrapper?.disconnect();\n let newWrapper: Twisty2DSceneWrapper | Twisty3DSceneWrapper;\n switch (strategy) {\n case \"2D\":\n case \"experimental-2D-LL\":\n newWrapper = new Twisty2DSceneWrapper(\n this.experimentalModel,\n strategy,\n );\n break;\n case \"Cube3D\":\n case \"PG3D\":\n // TODO: Properly wire this up so we can set PG3D for the cube.\n newWrapper = new Twisty3DSceneWrapper(this.experimentalModel);\n break;\n default:\n throw new Error(\"Invalid visualization\");\n }\n this.#visualizationWrapperElem.appendChild(newWrapper);\n this.#visualizationWrapper = newWrapper;\n this.#visualizationStrategy = strategy;\n }\n }\n\n async experimentalCurrentCanvases(): Promise<HTMLCanvasElement[]> {\n this.connectedCallback();\n const wrapper = this.#visualizationWrapper;\n const canvases: HTMLCanvasElement[] = [];\n if (wrapper instanceof Twisty3DSceneWrapper) {\n const vantages = wrapper.experimentalVantages();\n for (const vantage of vantages) {\n canvases.push((await vantage.canvasInfo()).canvas);\n }\n }\n return canvases;\n }\n\n async experimentalPG3D(): Promise<PG3D | null> {\n this.connectedCallback();\n const wrapper = this.#visualizationWrapper;\n if (wrapper instanceof Twisty3DSceneWrapper) {\n wrapper;\n }\n return null;\n }\n\n jumpToStart(options?: { flash: boolean }): void {\n this.controller.jumpToStart(options);\n }\n\n jumpToEnd(options?: { flash: boolean }): void {\n this.controller.jumpToEnd(options);\n }\n\n play(): void {\n this.controller.togglePlay(true);\n }\n\n pause(): void {\n this.controller.togglePlay(false);\n }\n\n // Inspiration:\n // - https://developer.mozilla.org/en-US/docs/Web/API/Element/toggleAttribute (`force` argument)\n // - https://developer.mozilla.org/en-US/docs/Web/API/DOMTokenList/toggle (`force` argument)\n // We still provide `play()` and `pause()` individually for convenience, though.\n togglePlay(play?: boolean): void {\n this.controller.togglePlay(play);\n }\n\n // TODO: Animate the new move.\n experimentalAddMove(\n flexibleMove: Move | string,\n options: { coalesce?: boolean } = {},\n ): void {\n this.experimentalModel.experimentalAddMove(flexibleMove, options);\n }\n\n static get observedAttributes(): string[] {\n return Object.keys(twistyPlayerAttributeMap);\n }\n\n attributeChangedCallback(\n attributeName: string,\n _oldValue: string,\n newValue: string,\n ): void {\n const setterName =\n twistyPlayerAttributeMap[attributeName as TwistyPlayerAttribute];\n if (!setterName) {\n return;\n }\n\n (this as any)[setterName] = newValue;\n }\n\n // TODO: Make this more ergonomic and flexible.\n // TODO: dimensions.\n async experimentalScreenshot(options?: {\n width: number;\n height: number;\n }): Promise<string> {\n return (await screenshot(this.experimentalModel, options)).dataURL;\n }\n\n // TODO: Make this more ergonomic and flexible.\n // TODO: dimensions.\n async experimentalDownloadScreenshot(filename?: string): Promise<void> {\n if (\n [\"2D\", \"experimental-2D-LL\"].includes(\n await this.experimentalModel.visualizationStrategyProp.get(),\n )\n ) {\n // TODO: This has lots of async issues. It should also go into the screenshot impl file.\n const wrapper2D = this.#visualizationWrapper as Twisty2DSceneWrapper;\n const twisty2DPuzzle = await wrapper2D\n .currentTwisty2DPuzzleWrapper()!\n .twisty2DPuzzle();\n const str = new XMLSerializer().serializeToString(\n twisty2DPuzzle.svg.element,\n );\n const url = URL.createObjectURL(new Blob([str]));\n downloadURL(\n url,\n filename ?? (await getDefaultFilename(this.experimentalModel)),\n \"svg\",\n );\n } else {\n await (await screenshot(this.experimentalModel)).download(filename);\n }\n }\n}\n\ncustomElementsShim.define(\"twisty-player\", TwistyPlayer);\n", "import { CSSSource } from \"./ManagedCustomElement\";\n\nexport const twistyAlgViewerCSS = new CSSSource(`\n:host {\n display: inline-grid;\n}\n\na:not(:hover) {\n color: inherit;\n text-decoration: none;\n}\n\ntwisty-alg-leaf-elem.twisty-alg-comment {\n color: rgba(0, 0, 0, 0.4);\n}\n\n.wrapper.current-move {\n background: rgba(66, 133, 244, 0.3);\n margin-left: -0.1em;\n margin-right: -0.1em;\n padding-left: 0.1em;\n padding-right: 0.1em;\n border-radius: 0.1em;\n}\n`);\n", "import {\n Alg,\n Commutator,\n Conjugate,\n experimentalDirect,\n ExperimentalIterationDirection,\n Grouping,\n LineComment,\n Move,\n Newline,\n Pause,\n TraversalDownUp,\n Unit,\n} from \"../../alg\";\nimport type { Parsed } from \"../../alg/parse\";\nimport type { AlgWithIssues } from \"../model/props/puzzle/state/AlgProp\";\nimport type { DetailedTimelineInfo } from \"../model/props/timeline/DetailedTimelineInfoProp\";\nimport type { MillisecondTimestamp } from \"../controllers/AnimationTypes\";\nimport type { CurrentMoveInfo } from \"../controllers/indexer/AlgIndexer\";\nimport { ManagedCustomElement } from \"./ManagedCustomElement\";\nimport {\n customElementsShim,\n HTMLElementShim,\n} from \"./node-custom-element-shims\";\nimport { twistyAlgViewerCSS } from \"./TwistyAlgViewer.css\";\nimport { TwistyPlayer } from \"./TwistyPlayer\";\n\nconst DEFAULT_OFFSET_MS = 250; // TODO: make this a fraction?\n\nclass DataDown {\n earliestMoveIndex: number;\n twistyAlgViewer: TwistyAlgViewer;\n direction: ExperimentalIterationDirection;\n}\n\nclass DataUp {\n moveCount: number;\n element: TwistyAlgWrapperElem | TwistyAlgLeafElem;\n}\n\nclass TwistyAlgLeafElem extends ManagedCustomElement {\n constructor(\n className: string,\n text: string,\n dataDown: DataDown,\n public algOrUnit: Alg | Unit,\n offsetIntoMove: boolean,\n clickable: boolean,\n ) {\n super({ mode: \"open\" });\n this.classList.add(className);\n\n this.addCSS(twistyAlgViewerCSS);\n if (clickable) {\n const anchor = this.contentWrapper.appendChild(\n document.createElement(\"a\"),\n );\n anchor.href = \"#\";\n anchor.textContent = text;\n\n anchor.addEventListener(\"click\", (e) => {\n e.preventDefault();\n dataDown.twistyAlgViewer.jumpToIndex(\n dataDown.earliestMoveIndex,\n offsetIntoMove,\n );\n });\n } else {\n this.contentWrapper.appendChild(\n document.createElement(\"span\"),\n ).textContent = text;\n }\n }\n\n pathToIndex(_index: number): (TwistyAlgWrapperElem | TwistyAlgLeafElem)[] {\n return [];\n }\n\n setCurrentMove(current: boolean) {\n this.contentWrapper.classList.toggle(\"current-move\", current);\n }\n}\n\ncustomElementsShim.define(\"twisty-alg-leaf-elem\", TwistyAlgLeafElem);\n\nclass TwistyAlgWrapperElem extends HTMLElementShim {\n private queue: (Element | Text)[] = [];\n\n constructor(className: string, public algOrUnit: Alg | Unit) {\n super();\n this.classList.add(className);\n }\n\n addString(str: string) {\n this.queue.push(document.createTextNode(str));\n }\n\n addElem(dataUp: DataUp): number {\n this.queue.push(dataUp.element);\n return dataUp.moveCount;\n }\n\n flushQueue(\n direction: ExperimentalIterationDirection = ExperimentalIterationDirection.Forwards,\n ): void {\n for (const node of maybeReverseList(this.queue, direction)) {\n this.append(node);\n }\n this.queue = [];\n }\n\n pathToIndex(_index: number): (TwistyAlgWrapperElem | TwistyAlgLeafElem)[] {\n return [];\n }\n}\n\ncustomElementsShim.define(\"twisty-alg-wrapper-elem\", TwistyAlgWrapperElem);\n\nfunction oppositeDirection(\n direction: ExperimentalIterationDirection,\n): ExperimentalIterationDirection {\n return direction === ExperimentalIterationDirection.Forwards\n ? ExperimentalIterationDirection.Backwards\n : ExperimentalIterationDirection.Forwards;\n}\n\nfunction updateDirectionByAmount(\n currentDirection: ExperimentalIterationDirection,\n amount: number,\n): ExperimentalIterationDirection {\n return amount < 0 ? oppositeDirection(currentDirection) : currentDirection;\n}\n\nfunction maybeReverseList<T>(\n l: T[],\n direction: ExperimentalIterationDirection,\n): T[] {\n if (direction === ExperimentalIterationDirection.Forwards) {\n return l;\n }\n // console.log(\"rev\", Array.from(l).reverse());\n // return Array.from(l).reverse();\n const copy = Array.from(l);\n copy.reverse();\n return copy;\n}\n\nclass AlgToDOMTree extends TraversalDownUp<DataDown, DataUp, DataUp> {\n public traverseAlg(alg: Alg, dataDown: DataDown): DataUp {\n let moveCount = 0;\n const element = new TwistyAlgWrapperElem(\"twisty-alg-alg\", alg); // TODO: pick a better class name.\n let first = true;\n for (const unit of experimentalDirect(alg.units(), dataDown.direction)) {\n if (!first) {\n element.addString(\" \");\n }\n first = false;\n moveCount += element.addElem(\n this.traverseUnit(unit, {\n earliestMoveIndex: dataDown.earliestMoveIndex + moveCount,\n twistyAlgViewer: dataDown.twistyAlgViewer,\n direction: dataDown.direction,\n }),\n );\n }\n element.flushQueue(dataDown.direction);\n return {\n moveCount: moveCount,\n element,\n };\n }\n\n public traverseGrouping(grouping: Grouping, dataDown: DataDown): DataUp {\n const square1Tuple = grouping.experimentalAsSquare1Tuple();\n // if (square1Tuplle) {\n\n // }\n\n const direction = updateDirectionByAmount(\n dataDown.direction,\n grouping.amount,\n );\n let moveCount = 0;\n const element = new TwistyAlgWrapperElem(\"twisty-alg-grouping\", grouping);\n element.addString(\"(\");\n\n if (square1Tuple) {\n moveCount += element.addElem({\n moveCount: 1,\n element: new TwistyAlgLeafElem(\n \"twisty-alg-move\", // TODO: Mark the tuple with a special class?\n square1Tuple[0].amount.toString(),\n dataDown,\n square1Tuple[0],\n true,\n true,\n ),\n });\n element.addString(\", \");\n moveCount += element.addElem({\n moveCount: 1,\n element: new TwistyAlgLeafElem(\n \"twisty-alg-move\", // TODO: Mark the tuple with a special class?\n square1Tuple[1].amount.toString(),\n dataDown,\n square1Tuple[1],\n true,\n true,\n ),\n });\n } else {\n moveCount += element.addElem(\n this.traverseAlg(grouping.alg, {\n earliestMoveIndex: dataDown.earliestMoveIndex + moveCount,\n twistyAlgViewer: dataDown.twistyAlgViewer,\n direction,\n }),\n );\n }\n\n element.addString(\")\" + grouping.experimentalRepetitionSuffix);\n element.flushQueue();\n return {\n moveCount: moveCount * Math.abs(grouping.amount),\n element,\n };\n }\n\n public traverseMove(move: Move, dataDown: DataDown): DataUp {\n const element = new TwistyAlgLeafElem(\n \"twisty-alg-move\",\n move.toString(),\n dataDown,\n move,\n true,\n true,\n );\n dataDown.twistyAlgViewer.highlighter.addMove(\n (move as Parsed<Move>).startCharIndex,\n element,\n );\n return {\n moveCount: 1,\n element,\n };\n }\n\n public traverseCommutator(\n commutator: Commutator,\n dataDown: DataDown,\n ): DataUp {\n let moveCount = 0;\n const element = new TwistyAlgWrapperElem(\n \"twisty-alg-commutator\",\n commutator,\n );\n element.addString(\"[\");\n element.flushQueue();\n const [first, second]: Alg[] = maybeReverseList(\n [commutator.A, commutator.B],\n dataDown.direction,\n );\n moveCount += element.addElem(\n this.traverseAlg(first, {\n earliestMoveIndex: dataDown.earliestMoveIndex + moveCount,\n twistyAlgViewer: dataDown.twistyAlgViewer,\n direction: dataDown.direction,\n }),\n );\n element.addString(\", \");\n moveCount += element.addElem(\n this.traverseAlg(second, {\n earliestMoveIndex: dataDown.earliestMoveIndex + moveCount,\n twistyAlgViewer: dataDown.twistyAlgViewer,\n direction: dataDown.direction,\n }),\n );\n element.flushQueue(dataDown.direction);\n element.addString(\"]\");\n element.flushQueue();\n return {\n moveCount: moveCount * 2,\n element,\n };\n }\n\n public traverseConjugate(conjugate: Conjugate, dataDown: DataDown): DataUp {\n let moveCount = 0;\n const element = new TwistyAlgWrapperElem(\"twisty-alg-conjugate\", conjugate);\n element.addString(\"[\");\n const aLen = element.addElem(\n this.traverseAlg(conjugate.A, {\n earliestMoveIndex: dataDown.earliestMoveIndex + moveCount,\n twistyAlgViewer: dataDown.twistyAlgViewer,\n direction: dataDown.direction,\n }),\n );\n moveCount += aLen;\n element.addString(\": \");\n moveCount += element.addElem(\n this.traverseAlg(conjugate.B, {\n earliestMoveIndex: dataDown.earliestMoveIndex + moveCount,\n twistyAlgViewer: dataDown.twistyAlgViewer,\n direction: dataDown.direction,\n }),\n );\n element.addString(\"]\");\n element.flushQueue();\n return {\n moveCount: moveCount + aLen,\n element,\n };\n }\n\n public traversePause(pause: Pause, dataDown: DataDown): DataUp {\n return {\n moveCount: 1,\n element: new TwistyAlgLeafElem(\n \"twisty-alg-pause\",\n \".\",\n dataDown,\n pause,\n true,\n true,\n ),\n };\n }\n\n public traverseNewline(newline: Newline, _dataDown: DataDown): DataUp {\n const element = new TwistyAlgWrapperElem(\"twisty-alg-newline\", newline);\n element.append(document.createElement(\"br\"));\n return {\n moveCount: 0,\n element,\n };\n }\n\n public traverseLineComment(\n lineComment: LineComment,\n dataDown: DataDown,\n ): DataUp {\n return {\n moveCount: 0,\n element: new TwistyAlgLeafElem(\n \"twisty-alg-line-comment\",\n `//${lineComment.text}`,\n dataDown,\n lineComment,\n false,\n false,\n ),\n };\n }\n}\n\nconst algToDOMTreeInstance = new AlgToDOMTree();\nconst algToDOMTree = algToDOMTreeInstance.traverseAlg.bind(\n algToDOMTreeInstance,\n) as (alg: Alg, dataDown: DataDown) => DataUp;\n\nclass MoveHighlighter {\n moveCharIndexMap: Map<number, TwistyAlgLeafElem> = new Map();\n currentElem: TwistyAlgLeafElem | null = null;\n\n addMove(charIndex: number, elem: TwistyAlgLeafElem): void {\n this.moveCharIndexMap.set(charIndex, elem);\n }\n\n set(move: Parsed<Move> | null): void {\n const newElem = move\n ? this.moveCharIndexMap.get(move.startCharIndex) ?? null\n : null;\n if (this.currentElem === newElem) {\n return;\n }\n this.currentElem?.classList.remove(\"twisty-alg-current-move\");\n this.currentElem?.setCurrentMove(false);\n newElem?.classList.add(\"twisty-alg-current-move\");\n newElem?.setCurrentMove(true);\n this.currentElem = newElem;\n }\n}\n\nexport class TwistyAlgViewer extends HTMLElementShim {\n highlighter: MoveHighlighter = new MoveHighlighter();\n #domTree: TwistyAlgWrapperElem | TwistyAlgLeafElem;\n twistyPlayer: TwistyPlayer | null = null;\n lastClickTimestamp: number | null = null;\n constructor(options?: { twistyPlayer?: TwistyPlayer }) {\n super();\n if (options?.twistyPlayer) {\n this.setTwistyPlayer(options?.twistyPlayer);\n }\n }\n\n protected connectedCallback(): void {\n // nothing to do?\n }\n\n private setAlg(alg: Alg): void {\n this.#domTree = algToDOMTree(alg, {\n earliestMoveIndex: 0,\n twistyAlgViewer: this,\n direction: ExperimentalIterationDirection.Forwards,\n }).element;\n this.textContent = \"\";\n this.appendChild(this.#domTree);\n }\n\n async setTwistyPlayer(twistyPlayer: TwistyPlayer): Promise<void> {\n if (this.twistyPlayer) {\n console.warn(\"twisty-player reassignment is not supported\");\n return;\n }\n this.twistyPlayer = twistyPlayer;\n\n this.twistyPlayer.experimentalModel.algProp.addFreshListener(\n (algWithIssues: AlgWithIssues) => {\n this.setAlg(algWithIssues.alg);\n },\n );\n\n const sourceAlg = (await this.twistyPlayer.experimentalModel.algProp.get())\n .alg;\n // TODO: Use proper architecture instead of a heuristic to ensure we have a parsed alg annotated with char indices.\n const parsedAlg =\n \"startCharIndex\" in (sourceAlg as Partial<Parsed<Alg>>)\n ? sourceAlg\n : Alg.fromString(sourceAlg.toString());\n this.setAlg(parsedAlg);\n\n twistyPlayer.experimentalModel.currentLeavesProp.addFreshListener(\n (currentMoveInfo: CurrentMoveInfo) => {\n let moveInfo = currentMoveInfo.currentMoves[0];\n moveInfo ??= currentMoveInfo.movesStarting[0];\n moveInfo ??= currentMoveInfo.movesFinishing[0];\n if (!moveInfo) {\n this.highlighter.set(null);\n } else {\n const mainCurrentMove = moveInfo.move; // TODO\n this.highlighter.set(mainCurrentMove as Parsed<Move>);\n }\n },\n );\n\n twistyPlayer.experimentalModel.detailedTimelineInfoProp.addFreshListener(\n (detailedTimelineInfo: DetailedTimelineInfo) => {\n if (detailedTimelineInfo.timestamp !== this.lastClickTimestamp) {\n this.lastClickTimestamp = null;\n }\n },\n );\n }\n\n async jumpToIndex(index: number, offsetIntoMove: boolean): Promise<void> {\n // TODO: Fix async issues.\n const twistyPlayer = this.twistyPlayer;\n if (twistyPlayer) {\n twistyPlayer.pause();\n const timestampPromise = (async (): Promise<MillisecondTimestamp> => {\n const indexer = await twistyPlayer.experimentalModel.indexerProp.get();\n const offset = offsetIntoMove ? DEFAULT_OFFSET_MS : 0;\n return (indexer.indexToMoveStartTimestamp(index) ?? -offset) + offset;\n })();\n twistyPlayer.experimentalModel.timestampRequestProp.set(\n await timestampPromise, // TODO\n );\n if (this.lastClickTimestamp === (await timestampPromise)) {\n twistyPlayer.play();\n this.lastClickTimestamp = null;\n } else {\n this.lastClickTimestamp = await timestampPromise;\n }\n }\n }\n\n protected async attributeChangedCallback(\n attributeName: string,\n _oldValue: string,\n newValue: string,\n ): Promise<void> {\n if (attributeName === \"for\") {\n const elem = document.getElementById(newValue);\n if (!elem) {\n console.warn(\"for= elem does not exist\");\n return;\n }\n await customElements.whenDefined(\"twisty-player\");\n if (!(elem instanceof TwistyPlayer)) {\n console.warn(\"for= elem is not a twisty-player\");\n return;\n }\n this.setTwistyPlayer(elem);\n }\n }\n\n static get observedAttributes(): string[] {\n return [\"for\"];\n }\n}\n\ncustomElementsShim.define(\"twisty-alg-viewer\", TwistyAlgViewer);\n", "import {\n Alg,\n Commutator,\n Conjugate,\n Grouping,\n LineComment,\n Move,\n Newline,\n Pause,\n TraversalDownUp,\n} from \"../../../alg\";\nimport type { Parsed } from \"../../../alg/parse\";\nimport type { AnimatedLeafUnit } from \"../../controllers/indexer/simultaneous-moves/simul-moves\";\n\nexport type AnimatedLeafUnitInfo = {\n leaf: Parsed<AnimatedLeafUnit>;\n idx: number;\n};\nexport type OrderedLeafTokens = AnimatedLeafUnitInfo[];\n\ninterface DataUp {\n tokens: OrderedLeafTokens;\n numLeavesInside: number;\n}\n\ninterface DataDown {\n numMovesSofar: number;\n}\n\nclass LeafTokens extends TraversalDownUp<DataDown, DataUp> {\n public traverseAlg(alg: Alg, dataDown: DataDown): DataUp {\n const unitArrays: OrderedLeafTokens[] = [];\n let numMovesInside = 0;\n for (const unit of alg.units()) {\n const dataUp = this.traverseUnit(unit, {\n numMovesSofar: dataDown.numMovesSofar + numMovesInside,\n });\n unitArrays.push(dataUp.tokens);\n numMovesInside += dataUp.numLeavesInside;\n }\n return {\n tokens: Array.prototype.concat(...unitArrays),\n numLeavesInside: numMovesInside,\n };\n }\n\n public traverseGrouping(grouping: Grouping, dataDown: DataDown): DataUp {\n const dataUp = this.traverseAlg(grouping.alg, dataDown);\n return {\n tokens: dataUp.tokens,\n numLeavesInside: dataUp.numLeavesInside * grouping.amount,\n };\n }\n\n public traverseMove(move: Move, dataDown: DataDown): DataUp {\n return {\n tokens: [{ leaf: move as Parsed<Move>, idx: dataDown.numMovesSofar }],\n numLeavesInside: 1,\n }; // TODO: What if not parsed?\n }\n\n public traverseCommutator(\n commutator: Commutator,\n dataDown: DataDown,\n ): DataUp {\n const dataUpA = this.traverseAlg(commutator.A, dataDown);\n const dataUpB = this.traverseAlg(commutator.B, {\n numMovesSofar: dataDown.numMovesSofar + dataUpA.numLeavesInside,\n });\n return {\n tokens: dataUpA.tokens.concat(dataUpB.tokens),\n numLeavesInside: dataUpA.numLeavesInside * 2 + dataUpB.numLeavesInside,\n };\n }\n\n public traverseConjugate(conjugate: Conjugate, dataDown: DataDown): DataUp {\n const dataUpA = this.traverseAlg(conjugate.A, dataDown);\n const dataUpB = this.traverseAlg(conjugate.B, {\n numMovesSofar: dataDown.numMovesSofar + dataUpA.numLeavesInside,\n });\n return {\n tokens: dataUpA.tokens.concat(dataUpB.tokens),\n numLeavesInside:\n dataUpA.numLeavesInside * 2 + dataUpB.numLeavesInside * 2,\n };\n }\n\n public traversePause(pause: Pause, dataDown: DataDown): DataUp {\n return {\n tokens: [{ leaf: pause as Parsed<Pause>, idx: dataDown.numMovesSofar }],\n numLeavesInside: 1,\n }; // TODO: What if not parsed?\n }\n\n public traverseNewline(_newline: Newline, _dataDown: DataDown): DataUp {\n return {\n tokens: [],\n numLeavesInside: 0,\n };\n }\n\n public traverseLineComment(\n _comment: LineComment,\n _dataDown: DataDown,\n ): DataUp {\n return {\n tokens: [],\n numLeavesInside: 0,\n };\n }\n}\n\nconst leafTokensInstance = new LeafTokens();\nexport const leafTokens = leafTokensInstance.traverseAlg.bind(\n leafTokensInstance,\n) as (alg: Parsed<Alg>, dataDown: DataDown) => DataUp;\n", "// TODO: Move this?\n\nimport type { Alg } from \"../../../alg\";\nimport type { Parsed } from \"../../../alg/parse\";\nimport {\n AlgWithIssues,\n algWithIssuesFromString,\n} from \"../../model/props/puzzle/state/AlgProp\";\nimport {\n SimpleTwistyPropSource,\n TwistyPropDerived,\n TwistyPropSource,\n} from \"../../model/props/TwistyProp\";\nimport {\n AnimatedLeafUnitInfo,\n leafTokens,\n OrderedLeafTokens,\n} from \"./LeafTokens\";\n\nexport class TwistyAlgEditorValueProp extends SimpleTwistyPropSource<string> {\n getDefaultValue(): string {\n return \"\";\n }\n}\n\ninterface AlgEditorAlgWithIssuesPropInput {\n value: string;\n}\nclass AlgEditorAlgWithIssuesProp extends TwistyPropDerived<\n AlgEditorAlgWithIssuesPropInput,\n AlgWithIssues\n> {\n derive(input: AlgEditorAlgWithIssuesPropInput): AlgWithIssues {\n return algWithIssuesFromString(input.value);\n }\n\n // TODO: canReuse needs to take the source string into account.\n}\n\ninterface SelectionInfoPropInput {\n selectionStart: number;\n selectionEnd: number;\n}\ninterface SelectionInfo extends SelectionInfoPropInput {\n endChangedMostRecently: boolean;\n}\nexport class TwistyAlgEditorSelectionProp extends TwistyPropSource<\n SelectionInfo,\n SelectionInfoPropInput\n> {\n getDefaultValue() {\n return {\n selectionStart: 0,\n selectionEnd: 0,\n endChangedMostRecently: false,\n };\n }\n\n async derive(\n input: SelectionInfoPropInput,\n oldValue: Promise<SelectionInfo>,\n ): Promise<SelectionInfo> {\n const { selectionStart, selectionEnd } = input;\n const lastResult = await oldValue;\n const endChangedMostRecently =\n input.selectionStart === lastResult.selectionStart &&\n input.selectionEnd !== (await oldValue).selectionEnd;\n return {\n selectionStart,\n selectionEnd,\n endChangedMostRecently,\n };\n }\n}\n\ninterface TargetCharPropInputs {\n selectionInfo: SelectionInfo;\n}\n\nexport class TargetCharProp extends TwistyPropDerived<\n TargetCharPropInputs,\n number\n> {\n derive(inputs: TargetCharPropInputs) {\n return inputs.selectionInfo.endChangedMostRecently\n ? inputs.selectionInfo.selectionEnd\n : inputs.selectionInfo.selectionStart;\n }\n}\n\ninterface LeafTokensPropInputs {\n algWithIssues: AlgWithIssues;\n}\nclass LeafTokensProp extends TwistyPropDerived<\n LeafTokensPropInputs,\n OrderedLeafTokens\n> {\n derive(inputs: LeafTokensPropInputs): OrderedLeafTokens {\n return leafTokens(inputs.algWithIssues.alg as Parsed<Alg>, {\n numMovesSofar: 0,\n }).tokens;\n }\n}\n\ninterface LeafToHighlightPropInputs {\n targetChar: number;\n leafTokens: OrderedLeafTokens;\n}\ntype HighlightWhere = \"before\" | \"start\" | \"inside\" | \"end\" | \"after\";\nexport interface HighlightInfo {\n leafInfo: AnimatedLeafUnitInfo;\n where: HighlightWhere;\n}\nclass LeafToHighlightProp extends TwistyPropDerived<\n LeafToHighlightPropInputs,\n HighlightInfo | null\n> {\n derive(inputs: LeafToHighlightPropInputs): HighlightInfo | null {\n function withWhere(\n leafInfo: AnimatedLeafUnitInfo | null,\n ): HighlightInfo | null {\n if (leafInfo === null) {\n return null;\n }\n let where: HighlightWhere;\n if (inputs.targetChar < leafInfo.leaf.startCharIndex) {\n where = \"before\";\n } else if (inputs.targetChar === leafInfo.leaf.startCharIndex) {\n where = \"start\";\n } else if (inputs.targetChar < leafInfo.leaf.endCharIndex) {\n where = \"inside\";\n } else if (inputs.targetChar === leafInfo.leaf.endCharIndex) {\n where = \"end\";\n } else {\n where = \"after\";\n }\n return {\n leafInfo,\n where,\n };\n }\n\n let lastLeafInfo: AnimatedLeafUnitInfo | null = null;\n // TODO: binary search\n for (const leafInfo of inputs.leafTokens) {\n if (\n inputs.targetChar < leafInfo.leaf.startCharIndex &&\n lastLeafInfo !== null\n ) {\n return withWhere(lastLeafInfo);\n }\n if (inputs.targetChar <= leafInfo.leaf.endCharIndex) {\n return withWhere(leafInfo);\n }\n lastLeafInfo = leafInfo;\n }\n\n return withWhere(lastLeafInfo);\n }\n}\n\nexport class TwistyAlgEditorModel {\n valueProp = new TwistyAlgEditorValueProp();\n selectionProp = new TwistyAlgEditorSelectionProp();\n targetCharProp = new TargetCharProp({ selectionInfo: this.selectionProp });\n\n algEditorAlgWithIssues = new AlgEditorAlgWithIssuesProp({\n value: this.valueProp,\n });\n\n leafTokensProp = new LeafTokensProp({\n algWithIssues: this.algEditorAlgWithIssues,\n });\n\n leafToHighlight = new LeafToHighlightProp({\n leafTokens: this.leafTokensProp,\n targetChar: this.targetCharProp,\n });\n}\n", "import { CSSSource } from \"../ManagedCustomElement\";\n\nexport const twistyAlgEditorCSS = new CSSSource(`\n:host {\n width: 384px;\n display: grid;\n}\n\n.wrapper {\n /*overflow: hidden;\n resize: horizontal;*/\n\n background: var(--background, none);\n display: grid;\n}\n\ntextarea, .carbon-copy {\n grid-area: 1 / 1 / 2 / 2;\n\n width: 100%;\n font-family: sans-serif;\n line-height: 1.2em;\n\n font-size: var(--font-size, inherit);\n font-family: var(--font-family, sans-serif);\n\n box-sizing: border-box;\n\n padding: var(--padding, 0.5em);\n /* Prevent horizontal growth. */\n overflow-x: hidden;\n}\n\ntextarea {\n resize: none;\n background: none;\n z-index: 2;\n overflow: hidden;\n border: 1px solid var(--border-color, rgba(0, 0, 0, 0.25));\n}\n\n.carbon-copy {\n white-space: pre-wrap;\n word-wrap: break-word;\n color: transparent;\n user-select: none;\n pointer-events: none;\n\n z-index: 1;\n}\n\n.carbon-copy .highlight {\n background: var(--highlight-color, rgba(255, 128, 0, 0.5));\n padding: 0.1em 0.2em;\n margin: -0.1em -0.2em;\n border-radius: 0.2em;\n}\n\n.wrapper.issue-warning textarea,\n.wrapper.valid-for-puzzle-warning textarea {\n outline: none;\n border: 1px solid rgba(200, 200, 0, 0.5);\n background: rgba(255, 255, 0, 0.1);\n}\n\n.wrapper.issue-error textarea,\n.wrapper.valid-for-puzzle-error textarea {\n outline: none;\n border: 1px solid red;\n background: rgba(255, 0, 0, 0.1);\n}\n`);\n", "/**\n * Warning: the current implementation of <twisty-alg-editor> is *not good*,\n * but it is *good enough*. The important parts is that:\n *\n * - The editor can be used in apps without much effort.\n * - The editor handles alg validation and move highlighting *okay* when not\n * connected to a `<twisty-player>`.\n * - The editor stays in sync if it's connected to a `<twisty-player>`.\n *\n * The current implementation still has some race conditions and edge cases. A\n * proper rewrite with a better model would be very welcome.\n */\n\nimport type { ExperimentalParsed } from \"../../../alg\";\nimport { Alg, Move, Pause } from \"../../../alg\";\nimport type { Parsed } from \"../../../alg/parse\";\nimport type {\n AlgProp,\n AlgWithIssues,\n} from \"../../model/props/puzzle/state/AlgProp\";\nimport type { CurrentLeavesSimplified } from \"../../model/props/puzzle/state/CurrentLeavesSimplified\";\nimport { ClassListManager } from \"../ClassListManager\";\nimport { ManagedCustomElement } from \"../ManagedCustomElement\";\nimport { customElementsShim } from \"../node-custom-element-shims\";\nimport { TwistyPlayer } from \"../TwistyPlayer\";\nimport { HighlightInfo, TwistyAlgEditorModel } from \"./model\";\nimport { twistyAlgEditorCSS } from \"./TwistyAlgEditor.css\";\n\nconst ATTRIBUTE_FOR_TWISTY_PLAYER = \"for-twisty-player\";\nconst ATTRIBUTE_PLACEHOLDER = \"placeholder\";\nconst ATTRIBUTE_TWISTY_PLAYER_PROP = \"twisty-player-prop\";\n\ntype TwistyPlayerAlgProp = \"algProp\" | \"setupProp\";\n\nexport class TwistyAlgEditor extends ManagedCustomElement {\n model = new TwistyAlgEditorModel();\n\n // #alg: Alg = new Alg();\n #textarea: HTMLTextAreaElement = document.createElement(\"textarea\");\n #carbonCopy: HTMLDivElement = document.createElement(\"div\");\n #carbonCopyPrefix: HTMLSpanElement = document.createElement(\"span\");\n #carbonCopyHighlight: HTMLSpanElement = document.createElement(\"span\");\n #carbonCopySuffix: HTMLSpanElement = document.createElement(\"span\");\n\n // #textareaClassListManager: ClassListManager<\"none\" | \"warning\" | \"error\"> =\n // new ClassListManager(this, \"issue-\", [\"none\", \"warning\", \"error\"]);\n\n #textareaClassListValidForPuzzleManager: ClassListManager<\n \"none\" | \"warning\" | \"error\"\n > = new ClassListManager(this, \"valid-for-puzzle-\", [\n \"none\",\n \"warning\",\n \"error\",\n ]);\n\n #twistyPlayer: TwistyPlayer | null = null;\n #twistyPlayerProp: TwistyPlayerAlgProp;\n get #algProp(): AlgProp | null {\n if (this.#twistyPlayer === null) {\n return null;\n } else {\n return this.#twistyPlayer.experimentalModel[this.#twistyPlayerProp];\n }\n }\n\n // Temporary Workaround for Twizzle Explorer\n debugNeverRequestTimestamp: boolean = false;\n\n constructor(options?: {\n twistyPlayer?: TwistyPlayer;\n twistyPlayerProp?: TwistyPlayerAlgProp;\n }) {\n super();\n this.#carbonCopy.classList.add(\"carbon-copy\");\n this.addElement(this.#carbonCopy);\n this.#textarea.rows = 1;\n this.addElement(this.#textarea);\n this.#carbonCopyPrefix.classList.add(\"prefix\");\n this.#carbonCopy.appendChild(this.#carbonCopyPrefix);\n this.#carbonCopyHighlight.classList.add(\"highlight\");\n this.#carbonCopy.appendChild(this.#carbonCopyHighlight);\n this.#carbonCopySuffix.classList.add(\"suffix\");\n this.#carbonCopy.appendChild(this.#carbonCopySuffix);\n\n this.#textarea.placeholder = \"Alg\";\n // Prevent iOS from defaulting to smart quotes.\n this.#textarea.setAttribute(\"spellcheck\", \"false\");\n\n this.addCSS(twistyAlgEditorCSS);\n\n // TODO: What set of events should we register? `change`? `keydown`?\n this.#textarea.addEventListener(\"input\", () => {\n this.#onInputHasFired = true;\n this.onInput();\n });\n this.#textarea.addEventListener(\"blur\", () => this.onBlur());\n document.addEventListener(\"selectionchange\", () =>\n this.onSelectionChange(),\n );\n\n if (options?.twistyPlayer) {\n this.twistyPlayer = options.twistyPlayer;\n }\n this.#twistyPlayerProp = options?.twistyPlayerProp ?? \"algProp\";\n\n if (options?.twistyPlayerProp === \"algProp\") {\n this.model.leafToHighlight.addFreshListener(\n (highlightInfo: HighlightInfo | null) => {\n if (highlightInfo) {\n this.highlightLeaf(highlightInfo.leafInfo.leaf);\n }\n },\n );\n }\n }\n\n // TODO\n set algString(s: string) {\n this.#textarea.value = s;\n this.onInput();\n }\n\n // TODO: remove?\n get algString(): string {\n return this.#textarea.value;\n }\n\n // To we need a getter?\n set placeholder(placeholderText: string) {\n this.#textarea.placeholder = placeholderText;\n }\n\n #onInputHasFired = false;\n onInput(): void {\n this.#carbonCopyHighlight.hidden = true;\n this.highlightLeaf(null);\n\n // TODO: This is a hack so that the you don't get a warning when the cursor\n // is after the space while typing `R U`. It would be nice to have something\n // cursor-aware that can also ignore whitespace warnings (or other syntax\n // errors due to normal input) adjacent to the cursor when it's in the\n // middle, but this is suffuciently useful for now.\n const endTrimmed = this.#textarea.value.trimEnd();\n this.model.valueProp.set(endTrimmed);\n this.#algProp?.set(endTrimmed);\n }\n\n async onSelectionChange(): Promise<void> {\n if (\n document.activeElement !== this ||\n this.shadow.activeElement !== this.#textarea\n ) {\n return;\n }\n if (this.#twistyPlayerProp !== \"algProp\") {\n return;\n }\n\n const { selectionStart, selectionEnd } = this.#textarea;\n this.model.selectionProp.set({\n selectionStart,\n selectionEnd,\n });\n }\n\n async onBlur(): Promise<void> {\n // TODO: Figure out how not to make the cursor jump.\n // const parsed = Alg.fromString(this.algString);\n // this.algString = parsed.toString();\n // const [currentLeavesSimplified, indexer] = await Promise.all([\n // this.#twistyPlayer!.model.currentLeavesSimplifiedProp.get(),\n // this.#twistyPlayer!.model.indexerProp.get(),\n // ]);\n // const leaf = indexer.getAnimLeaf(currentLeavesSimplified.stateIndex);\n // this.highlightLeaf(leaf as Parsed<Move | Pause> | null);\n }\n\n setAlgIssueClassForPuzzle(issues: \"none\" | \"warning\" | \"error\") {\n this.#textareaClassListValidForPuzzleManager.setValue(issues);\n }\n\n // `white-space: pre;` mostly matches the formatting of the `<textarea>`, *except* when we end with a newline.\n // So we add an space to ensure that there is a character on the final line (that is very unlikely to trigger extra line wrapping).\n #padSuffix(s: string): string {\n return s.endsWith(\"\\n\") ? s + \" \" : s;\n }\n\n #highlightedLeaf: ExperimentalParsed<Move | Pause> | null = null;\n // TODO: support a primary highlighted move and secondary ones.\n highlightLeaf(leaf: ExperimentalParsed<Move | Pause> | null): void {\n if (this.#twistyPlayerProp !== \"algProp\") {\n return;\n }\n if (leaf === null) {\n this.#carbonCopyPrefix.textContent = \"\";\n this.#carbonCopyHighlight.textContent = \"\";\n this.#carbonCopySuffix.textContent = this.#padSuffix(\n this.#textarea.value,\n );\n return;\n }\n if (leaf === this.#highlightedLeaf) {\n return;\n }\n this.#highlightedLeaf = leaf;\n this.#carbonCopyPrefix.textContent = this.#textarea.value.slice(\n 0,\n leaf.startCharIndex,\n );\n this.#carbonCopyHighlight.textContent = this.#textarea.value.slice(\n leaf.startCharIndex,\n leaf.endCharIndex,\n );\n this.#carbonCopySuffix.textContent = this.#padSuffix(\n this.#textarea.value.slice(leaf.endCharIndex),\n );\n this.#carbonCopyHighlight.hidden = false;\n }\n\n get twistyPlayer(): TwistyPlayer | null {\n return this.#twistyPlayer;\n }\n\n // TODO: spread out this impl over private methods instead of self-listeners.\n set twistyPlayer(twistyPlayer: TwistyPlayer | null) {\n if (this.#twistyPlayer) {\n // TODO: support reassigment/clearing\n console.warn(\"twisty-player reassignment/clearing is not supported\");\n return;\n }\n this.#twistyPlayer = twistyPlayer;\n if (!twistyPlayer) {\n return;\n }\n (async () => {\n this.algString = this.#algProp\n ? (await this.#algProp.get()).alg.toString()\n : \"\";\n })();\n\n if (this.#twistyPlayerProp === \"algProp\") {\n // this.model.leafToHighlight.addFreshListener(\n // this.highlightLeaf.bind(this),\n // );\n\n // TODO: listen to puzzle prop?\n this.#twistyPlayer?.experimentalModel.puzzleAlgProp.addFreshListener(\n (algWithIssues: AlgWithIssues) => {\n // console.log(JSON.stringify(algWithIssues));\n if (algWithIssues.issues.errors.length === 0) {\n this.setAlgIssueClassForPuzzle(\n // TODO: Allow trailing spaces.\n algWithIssues.issues.warnings.length === 0 ? \"none\" : \"warning\",\n );\n const newAlg = algWithIssues.alg;\n const oldAlg = Alg.fromString(this.algString);\n if (!newAlg.isIdentical(oldAlg)) {\n this.algString = newAlg.toString();\n this.onInput();\n } else {\n // this.model.algInputProp.set(oldAlg);\n }\n } else {\n this.setAlgIssueClassForPuzzle(\"error\");\n }\n },\n );\n\n this.model.leafToHighlight.addFreshListener(\n async (highlightInfo: HighlightInfo | null) => {\n if (highlightInfo === null) {\n return;\n }\n // TODO: This indexer can be out of date!\n const [indexer, timestampRequest] = await Promise.all([\n await twistyPlayer.experimentalModel.indexerProp.get(),\n await twistyPlayer.experimentalModel.timestampRequestProp.get(),\n ]);\n if (\n timestampRequest === \"opposite-anchor\" &&\n !this.#onInputHasFired\n ) {\n return;\n }\n const moveStartTimestamp = indexer.indexToMoveStartTimestamp(\n highlightInfo.leafInfo.idx,\n );\n const duration = indexer.moveDuration(highlightInfo.leafInfo.idx);\n\n let newTimestamp: number;\n switch (highlightInfo.where) {\n case \"before\":\n newTimestamp = moveStartTimestamp;\n break;\n case \"start\":\n case \"inside\":\n newTimestamp = moveStartTimestamp + duration / 4;\n break;\n case \"end\":\n case \"after\":\n newTimestamp = moveStartTimestamp + duration;\n break;\n default:\n console.log(\"invalid where\");\n throw new Error(\"Invalid where!\");\n }\n if (!this.debugNeverRequestTimestamp) {\n twistyPlayer.experimentalModel.timestampRequestProp.set(\n newTimestamp,\n );\n }\n },\n );\n\n twistyPlayer.experimentalModel.currentLeavesSimplifiedProp.addFreshListener(\n async (currentLeavesSimplified: CurrentLeavesSimplified) => {\n const indexer =\n await twistyPlayer.experimentalModel.indexerProp.get();\n const leaf = indexer.getAnimLeaf(currentLeavesSimplified.stateIndex);\n this.highlightLeaf(leaf as Parsed<Move | Pause> | null);\n },\n );\n }\n }\n\n protected attributeChangedCallback(\n attributeName: string,\n _oldValue: string,\n newValue: string,\n ): void {\n switch (attributeName) {\n case ATTRIBUTE_FOR_TWISTY_PLAYER: {\n const elem = document.getElementById(newValue);\n if (!elem) {\n console.warn(`${ATTRIBUTE_FOR_TWISTY_PLAYER}= elem does not exist`);\n return;\n }\n if (!(elem instanceof TwistyPlayer)) {\n // TODO: avoid assuming single instance of lib?\n console.warn(`${ATTRIBUTE_FOR_TWISTY_PLAYER}=is not a twisty-player`);\n return;\n }\n this.twistyPlayer = elem;\n return;\n }\n case ATTRIBUTE_PLACEHOLDER:\n this.placeholder = newValue;\n return;\n case ATTRIBUTE_TWISTY_PLAYER_PROP:\n if (this.#twistyPlayer) {\n console.log(\"cannot set prop\");\n throw new Error(\"cannot set prop after twisty player\");\n }\n this.#twistyPlayerProp = newValue as TwistyPlayerAlgProp;\n return;\n }\n }\n\n static get observedAttributes(): string[] {\n return [\n ATTRIBUTE_FOR_TWISTY_PLAYER,\n ATTRIBUTE_PLACEHOLDER,\n ATTRIBUTE_TWISTY_PLAYER_PROP,\n ];\n }\n}\n\ncustomElementsShim.define(\"twisty-alg-editor\", TwistyAlgEditor);\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }