cuju-render 0.1.0__py3-none-any.whl

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 (382) hide show
  1. cuju/render/__init__.py +759 -0
  2. cuju/render/__main__.py +1065 -0
  3. cuju/render/_export/__init__.py +3 -0
  4. cuju/render/_export/feed.py +542 -0
  5. cuju/render/_export/sizes.py +157 -0
  6. cuju/render/_export/video.py +1618 -0
  7. cuju/render/_export/video_jobs.py +408 -0
  8. cuju/render/_format/__init__.py +3 -0
  9. cuju/render/_format/annotations.py +235 -0
  10. cuju/render/_format/codec.py +307 -0
  11. cuju/render/_format/keep.py +121 -0
  12. cuju/render/_format/recording.py +860 -0
  13. cuju/render/_format/writer.py +54 -0
  14. cuju/render/_guide/__init__.py +3 -0
  15. cuju/render/_guide/doctor.py +523 -0
  16. cuju/render/_guide/help.py +62 -0
  17. cuju/render/_guide/tutorial.py +254 -0
  18. cuju/render/_http/__init__.py +3 -0
  19. cuju/render/_http/commands.py +57 -0
  20. cuju/render/_http/headers.py +103 -0
  21. cuju/render/_http/launch.py +500 -0
  22. cuju/render/_http/launchers.py +408 -0
  23. cuju/render/_http/pwa.py +128 -0
  24. cuju/render/_http/server.py +2105 -0
  25. cuju/render/_http/window.py +360 -0
  26. cuju/render/_moments/__init__.py +3 -0
  27. cuju/render/_moments/captions.py +284 -0
  28. cuju/render/_moments/events.py +1123 -0
  29. cuju/render/_moments/search.py +694 -0
  30. cuju/render/_packages/__init__.py +3 -0
  31. cuju/render/_packages/glsl.py +746 -0
  32. cuju/render/_packages/loudness.py +334 -0
  33. cuju/render/_packages/pack.py +1959 -0
  34. cuju/render/_packages/presentation.py +1376 -0
  35. cuju/render/_packages/vocabulary.py +609 -0
  36. cuju/render/_playing/__init__.py +3 -0
  37. cuju/render/_playing/achievements.py +463 -0
  38. cuju/render/_playing/bench.py +609 -0
  39. cuju/render/_playing/challenges.py +1813 -0
  40. cuju/render/_playing/demo.py +323 -0
  41. cuju/render/_playing/draw.py +211 -0
  42. cuju/render/_playing/errors.py +20 -0
  43. cuju/render/_playing/game.py +645 -0
  44. cuju/render/_playing/limits.py +339 -0
  45. cuju/render/_playing/play.py +926 -0
  46. cuju/render/_playing/policy_worker.py +250 -0
  47. cuju/render/_playing/strict.py +810 -0
  48. cuju/render/_registry/__init__.py +3 -0
  49. cuju/render/_registry/clips.py +394 -0
  50. cuju/render/_registry/joints.py +108 -0
  51. cuju/render/_registry/teams.py +2058 -0
  52. cuju/render/_store/__init__.py +3 -0
  53. cuju/render/_store/home.py +70 -0
  54. cuju/render/_store/library.py +604 -0
  55. cuju/render/_store/samples.py +163 -0
  56. cuju/render/_text/__init__.py +3 -0
  57. cuju/render/_text/languages.py +637 -0
  58. cuju/render/_text/messages.py +1396 -0
  59. cuju/render/_tournaments/__init__.py +3 -0
  60. cuju/render/_tournaments/results.py +547 -0
  61. cuju/render/_tournaments/tournament.py +2742 -0
  62. cuju/render/_tournaments/tournament_cli.py +587 -0
  63. cuju/render/_tournaments/tournament_runner.py +1975 -0
  64. cuju/render/_version.py +6 -0
  65. cuju/render/_watch/__init__.py +3 -0
  66. cuju/render/_watch/grid.py +265 -0
  67. cuju/render/_watch/live.py +664 -0
  68. cuju/render/_watch/notebook.py +79 -0
  69. cuju/render/_watch/show.py +171 -0
  70. cuju/render/samples/sample-11v11.cjr +0 -0
  71. cuju/render/samples/sample-5v5.cjr +0 -0
  72. cuju/render/samples/teams/starter/main.py +33 -0
  73. cuju/render/scenarios/benchmark_full_game_11_vs_11_easy.py +46 -0
  74. cuju/render/scenarios/benchmark_full_game_11_vs_11_hard.py +46 -0
  75. cuju/render/scenarios/benchmark_full_game_11_vs_11_medium.py +46 -0
  76. cuju/render/scenarios/benchmark_full_game_5_vs_5_easy.py +34 -0
  77. cuju/render/scenarios/benchmark_full_game_5_vs_5_hard.py +34 -0
  78. cuju/render/scenarios/benchmark_full_game_5_vs_5_medium.py +34 -0
  79. cuju/render/web/assets/adboard_polygon.webp +0 -0
  80. cuju/render/web/assets/adboard_your_ad_here.webp +0 -0
  81. cuju/render/web/assets/animations/kaykit-rig-medium-combatmelee.glb +0 -0
  82. cuju/render/web/assets/animations/kaykit-rig-medium-general.glb +0 -0
  83. cuju/render/web/assets/animations/kaykit-rig-medium-movementadvanced.glb +0 -0
  84. cuju/render/web/assets/animations/kaykit-rig-medium-movementbasic.glb +0 -0
  85. cuju/render/web/assets/animations/kaykit-rig-medium-simulation.glb +0 -0
  86. cuju/render/web/assets/animations/kaykit-rig-medium-special.glb +0 -0
  87. cuju/render/web/assets/ball.glb +0 -0
  88. cuju/render/web/assets/challenges/3_vs_1_with_keeper.mp4 +0 -0
  89. cuju/render/web/assets/challenges/3_vs_1_with_keeper.webp +0 -0
  90. cuju/render/web/assets/challenges/corner.mp4 +0 -0
  91. cuju/render/web/assets/challenges/corner.webp +0 -0
  92. cuju/render/web/assets/challenges/counterattack_easy.mp4 +0 -0
  93. cuju/render/web/assets/challenges/counterattack_easy.webp +0 -0
  94. cuju/render/web/assets/challenges/counterattack_hard.mp4 +0 -0
  95. cuju/render/web/assets/challenges/counterattack_hard.webp +0 -0
  96. cuju/render/web/assets/challenges/empty_goal.mp4 +0 -0
  97. cuju/render/web/assets/challenges/empty_goal.webp +0 -0
  98. cuju/render/web/assets/challenges/empty_goal_close.mp4 +0 -0
  99. cuju/render/web/assets/challenges/empty_goal_close.webp +0 -0
  100. cuju/render/web/assets/challenges/manifest.json +375 -0
  101. cuju/render/web/assets/challenges/one_on_one.mp4 +0 -0
  102. cuju/render/web/assets/challenges/one_on_one.webp +0 -0
  103. cuju/render/web/assets/challenges/one_on_one_hard.mp4 +0 -0
  104. cuju/render/web/assets/challenges/one_on_one_hard.webp +0 -0
  105. cuju/render/web/assets/challenges/pass_and_shoot_with_keeper.mp4 +0 -0
  106. cuju/render/web/assets/challenges/pass_and_shoot_with_keeper.webp +0 -0
  107. cuju/render/web/assets/challenges/run_pass_and_shoot_with_keeper.mp4 +0 -0
  108. cuju/render/web/assets/challenges/run_pass_and_shoot_with_keeper.webp +0 -0
  109. cuju/render/web/assets/challenges/run_to_score.mp4 +0 -0
  110. cuju/render/web/assets/challenges/run_to_score.webp +0 -0
  111. cuju/render/web/assets/challenges/run_to_score_with_keeper.mp4 +0 -0
  112. cuju/render/web/assets/challenges/run_to_score_with_keeper.webp +0 -0
  113. cuju/render/web/assets/challenges/single_goal_versus_lazy.mp4 +0 -0
  114. cuju/render/web/assets/challenges/single_goal_versus_lazy.webp +0 -0
  115. cuju/render/web/assets/crowd.webp +0 -0
  116. cuju/render/web/assets/crowd_normal.webp +0 -0
  117. cuju/render/web/assets/cuju-logo-384.png +0 -0
  118. cuju/render/web/assets/cuju-logo.png +0 -0
  119. cuju/render/web/assets/cuju-logo.svg +46 -0
  120. cuju/render/web/assets/cuju-mark-light.svg +33 -0
  121. cuju/render/web/assets/cuju-mark.svg +33 -0
  122. cuju/render/web/assets/goal.glb +0 -0
  123. cuju/render/web/assets/grass.webp +0 -0
  124. cuju/render/web/assets/hair_black.png +0 -0
  125. cuju/render/web/assets/hair_blonde.png +0 -0
  126. cuju/render/web/assets/hair_brown.png +0 -0
  127. cuju/render/web/assets/hair_darkblonde.png +0 -0
  128. cuju/render/web/assets/hair_long01.glb +0 -0
  129. cuju/render/web/assets/hair_long02.glb +0 -0
  130. cuju/render/web/assets/hair_medium01.glb +0 -0
  131. cuju/render/web/assets/hair_red.png +0 -0
  132. cuju/render/web/assets/hair_short01.glb +0 -0
  133. cuju/render/web/assets/hair_short02.glb +0 -0
  134. cuju/render/web/assets/icons/cuju-192.png +0 -0
  135. cuju/render/web/assets/icons/cuju-512.png +0 -0
  136. cuju/render/web/assets/icons/cuju-maskable-512.png +0 -0
  137. cuju/render/web/assets/kit_goalkeeper.webp +0 -0
  138. cuju/render/web/assets/kit_mask.png +0 -0
  139. cuju/render/web/assets/kit_normal.webp +0 -0
  140. cuju/render/web/assets/manifest.json +601 -0
  141. cuju/render/web/assets/models/kaykit-barbarian.glb +0 -0
  142. cuju/render/web/assets/models/kaykit-barbarian.json +23 -0
  143. cuju/render/web/assets/models/kaykit-knight.glb +0 -0
  144. cuju/render/web/assets/models/kaykit-knight.json +23 -0
  145. cuju/render/web/assets/models/kaykit-mage.glb +0 -0
  146. cuju/render/web/assets/models/kaykit-mage.json +23 -0
  147. cuju/render/web/assets/models/kaykit-mannequin-medium.glb +0 -0
  148. cuju/render/web/assets/models/kaykit-mannequin-medium.json +23 -0
  149. cuju/render/web/assets/models/kaykit-ranger.glb +0 -0
  150. cuju/render/web/assets/models/kaykit-ranger.json +23 -0
  151. cuju/render/web/assets/models/kaykit-rogue-hooded.glb +0 -0
  152. cuju/render/web/assets/models/kaykit-rogue-hooded.json +23 -0
  153. cuju/render/web/assets/models/kaykit-rogue.glb +0 -0
  154. cuju/render/web/assets/models/kaykit-rogue.json +23 -0
  155. cuju/render/web/assets/models/kaykit-skeleton-mage.glb +0 -0
  156. cuju/render/web/assets/models/kaykit-skeleton-mage.json +23 -0
  157. cuju/render/web/assets/models/kaykit-skeleton-minion.glb +0 -0
  158. cuju/render/web/assets/models/kaykit-skeleton-minion.json +23 -0
  159. cuju/render/web/assets/models/kaykit-skeleton-rogue.glb +0 -0
  160. cuju/render/web/assets/models/kaykit-skeleton-rogue.json +23 -0
  161. cuju/render/web/assets/models/kaykit-skeleton-warrior.glb +0 -0
  162. cuju/render/web/assets/models/kaykit-skeleton-warrior.json +23 -0
  163. cuju/render/web/assets/pitch.webp +0 -0
  164. cuju/render/web/assets/pitch_normal.webp +0 -0
  165. cuju/render/web/assets/player.glb +0 -0
  166. cuju/render/web/assets/shoe.webp +0 -0
  167. cuju/render/web/assets/shoe_sole.png +0 -0
  168. cuju/render/web/assets/skin_01.png +0 -0
  169. cuju/render/web/assets/skin_02.png +0 -0
  170. cuju/render/web/assets/skin_03.png +0 -0
  171. cuju/render/web/assets/skin_04.png +0 -0
  172. cuju/render/web/assets/sounds/applause.ogg +0 -0
  173. cuju/render/web/assets/sounds/beach-wave-1.ogg +0 -0
  174. cuju/render/web/assets/sounds/beach-wave-2.ogg +0 -0
  175. cuju/render/web/assets/sounds/beach-wave-3.ogg +0 -0
  176. cuju/render/web/assets/sounds/beach-wave-4.ogg +0 -0
  177. cuju/render/web/assets/sounds/city-horn.ogg +0 -0
  178. cuju/render/web/assets/sounds/city-loop.ogg +0 -0
  179. cuju/render/web/assets/sounds/city-siren.ogg +0 -0
  180. cuju/render/web/assets/sounds/crowd-cheer.ogg +0 -0
  181. cuju/render/web/assets/sounds/crowd-loop.ogg +0 -0
  182. cuju/render/web/assets/sounds/crowd-ooh.ogg +0 -0
  183. cuju/render/web/assets/sounds/gulls.ogg +0 -0
  184. cuju/render/web/assets/sounds/neon-sting.ogg +0 -0
  185. cuju/render/web/assets/sounds/rain-loop.ogg +0 -0
  186. cuju/render/web/assets/sounds/sounds.json +46 -0
  187. cuju/render/web/assets/sounds/space-beep.ogg +0 -0
  188. cuju/render/web/assets/sounds/space-hum.ogg +0 -0
  189. cuju/render/web/assets/sounds/space-radio.ogg +0 -0
  190. cuju/render/web/assets/sounds/whistle-long.ogg +0 -0
  191. cuju/render/web/assets/sounds/whistle-short.ogg +0 -0
  192. cuju/render/web/assets/sounds/wind-loop.ogg +0 -0
  193. cuju/render/web/easy.css +357 -0
  194. cuju/render/web/export.html +23 -0
  195. cuju/render/web/feed.css +262 -0
  196. cuju/render/web/feed.html +28 -0
  197. cuju/render/web/flat.css +120 -0
  198. cuju/render/web/home.css +837 -0
  199. cuju/render/web/index.html +373 -0
  200. cuju/render/web/js/boot.js +50 -0
  201. cuju/render/web/js/broadcast/audio.js +2141 -0
  202. cuju/render/web/js/broadcast/celebrate.js +1238 -0
  203. cuju/render/web/js/broadcast/decisions.js +609 -0
  204. cuju/render/web/js/broadcast/hud.js +352 -0
  205. cuju/render/web/js/broadcast/show.js +3614 -0
  206. cuju/render/web/js/broadcast/transition.js +2231 -0
  207. cuju/render/web/js/broadcast/voices.js +153 -0
  208. cuju/render/web/js/capture.js +101 -0
  209. cuju/render/web/js/core/accessibility.js +90 -0
  210. cuju/render/web/js/core/api.js +429 -0
  211. cuju/render/web/js/core/comfort.js +135 -0
  212. cuju/render/web/js/core/i18n.js +705 -0
  213. cuju/render/web/js/core/icons.js +167 -0
  214. cuju/render/web/js/core/input-settings.js +156 -0
  215. cuju/render/web/js/core/keys.js +277 -0
  216. cuju/render/web/js/core/language-ui.js +125 -0
  217. cuju/render/web/js/core/menu.js +853 -0
  218. cuju/render/web/js/core/names.js +113 -0
  219. cuju/render/web/js/core/page-structure.js +110 -0
  220. cuju/render/web/js/core/scenarios.js +109 -0
  221. cuju/render/web/js/core/spoilers.js +236 -0
  222. cuju/render/web/js/core/typeahead.js +38 -0
  223. cuju/render/web/js/export/dom-picture.js +330 -0
  224. cuju/render/web/js/export/export-host.js +97 -0
  225. cuju/render/web/js/export/feed-dialog.js +191 -0
  226. cuju/render/web/js/export/feed-params.js +266 -0
  227. cuju/render/web/js/export/feed.js +363 -0
  228. cuju/render/web/js/export/mp4-mux.js +295 -0
  229. cuju/render/web/js/export/photo-core.js +313 -0
  230. cuju/render/web/js/export/photo.js +1314 -0
  231. cuju/render/web/js/export/safe-frame.js +59 -0
  232. cuju/render/web/js/export/size-fields.js +103 -0
  233. cuju/render/web/js/export/sizes.js +178 -0
  234. cuju/render/web/js/export/video-boot.js +55 -0
  235. cuju/render/web/js/export/video-browser.js +325 -0
  236. cuju/render/web/js/export/video-export.js +417 -0
  237. cuju/render/web/js/export/video-plan.js +207 -0
  238. cuju/render/web/js/export/video-range.js +185 -0
  239. cuju/render/web/js/export/webm-mux.js +198 -0
  240. cuju/render/web/js/feed-boot.js +151 -0
  241. cuju/render/web/js/feed-frame.js +101 -0
  242. cuju/render/web/js/help/doctor.js +488 -0
  243. cuju/render/web/js/help/firstrun.js +379 -0
  244. cuju/render/web/js/help/help-center.js +438 -0
  245. cuju/render/web/js/help/install-offer.js +164 -0
  246. cuju/render/web/js/help/install-state.js +104 -0
  247. cuju/render/web/js/help/lessons-core.js +207 -0
  248. cuju/render/web/js/help/lessons.js +463 -0
  249. cuju/render/web/js/help/palette.js +584 -0
  250. cuju/render/web/js/help/pwa.js +257 -0
  251. cuju/render/web/js/help/tour-core.js +241 -0
  252. cuju/render/web/js/help/tour.js +461 -0
  253. cuju/render/web/js/main.js +2513 -0
  254. cuju/render/web/js/pages/draw.js +188 -0
  255. cuju/render/web/js/pages/fieldpage.js +530 -0
  256. cuju/render/web/js/pages/home.js +521 -0
  257. cuju/render/web/js/pages/matches.js +779 -0
  258. cuju/render/web/js/pages/moments-ui.js +359 -0
  259. cuju/render/web/js/pages/queue-filters.js +63 -0
  260. cuju/render/web/js/pages/recording-groups.js +80 -0
  261. cuju/render/web/js/pages/recordings.js +1069 -0
  262. cuju/render/web/js/play/bench.js +347 -0
  263. cuju/render/web/js/play/challenges.js +1302 -0
  264. cuju/render/web/js/play/medals.js +127 -0
  265. cuju/render/web/js/play/play.js +1953 -0
  266. cuju/render/web/js/play/teasers.js +196 -0
  267. cuju/render/web/js/play/touch.js +350 -0
  268. cuju/render/web/js/play/tournament-layout.js +487 -0
  269. cuju/render/web/js/play/tournament-results.js +441 -0
  270. cuju/render/web/js/play/tournament-strict.js +560 -0
  271. cuju/render/web/js/play/tournament.js +2585 -0
  272. cuju/render/web/js/players/animate.js +972 -0
  273. cuju/render/web/js/players/clips.js +224 -0
  274. cuju/render/web/js/players/kaykit.js +162 -0
  275. cuju/render/web/js/players/kits.js +676 -0
  276. cuju/render/web/js/players/number-patch.js +82 -0
  277. cuju/render/web/js/players/players.js +2694 -0
  278. cuju/render/web/js/players/recolor.js +893 -0
  279. cuju/render/web/js/players/retarget.js +325 -0
  280. cuju/render/web/js/players/rig-numbers.js +174 -0
  281. cuju/render/web/js/presentation/animator.js +231 -0
  282. cuju/render/web/js/presentation/assign.js +85 -0
  283. cuju/render/web/js/presentation/behaviors.js +440 -0
  284. cuju/render/web/js/presentation/budget.js +209 -0
  285. cuju/render/web/js/presentation/catalog.js +1674 -0
  286. cuju/render/web/js/presentation/clocks.js +72 -0
  287. cuju/render/web/js/presentation/commands.js +301 -0
  288. cuju/render/web/js/presentation/contract.js +240 -0
  289. cuju/render/web/js/presentation/effects.js +904 -0
  290. cuju/render/web/js/presentation/flash.js +605 -0
  291. cuju/render/web/js/presentation/freeze-worklet.js +22 -0
  292. cuju/render/web/js/presentation/glsl.js +464 -0
  293. cuju/render/web/js/presentation/host.js +323 -0
  294. cuju/render/web/js/presentation/index.js +2066 -0
  295. cuju/render/web/js/presentation/loudness-worklet.js +235 -0
  296. cuju/render/web/js/presentation/loudness.js +740 -0
  297. cuju/render/web/js/presentation/moments.js +536 -0
  298. cuju/render/web/js/presentation/post.js +327 -0
  299. cuju/render/web/js/presentation/preview.js +180 -0
  300. cuju/render/web/js/presentation/protocol.js +174 -0
  301. cuju/render/web/js/presentation/reach.js +158 -0
  302. cuju/render/web/js/presentation/rigging.js +130 -0
  303. cuju/render/web/js/presentation/sandbox.js +157 -0
  304. cuju/render/web/js/presentation/shaders.js +235 -0
  305. cuju/render/web/js/presentation/stage.js +402 -0
  306. cuju/render/web/js/presentation/teamaudio.js +722 -0
  307. cuju/render/web/js/presentation/tracks.js +197 -0
  308. cuju/render/web/js/presentation/values.js +81 -0
  309. cuju/render/web/js/recording/annotation-data.js +203 -0
  310. cuju/render/web/js/recording/captions.js +491 -0
  311. cuju/render/web/js/recording/codec.js +185 -0
  312. cuju/render/web/js/recording/decode-worker.js +70 -0
  313. cuju/render/web/js/recording/decode.js +94 -0
  314. cuju/render/web/js/recording/episodes.js +46 -0
  315. cuju/render/web/js/recording/format.js +461 -0
  316. cuju/render/web/js/recording/live.js +348 -0
  317. cuju/render/web/js/recording/moments-query.js +59 -0
  318. cuju/render/web/js/recording/moments.js +149 -0
  319. cuju/render/web/js/recording/pose.js +86 -0
  320. cuju/render/web/js/recording/timeline.js +275 -0
  321. cuju/render/web/js/teams/art.js +50 -0
  322. cuju/render/web/js/teams/clip-editor.js +293 -0
  323. cuju/render/web/js/teams/editor.js +1979 -0
  324. cuju/render/web/js/teams/library.js +344 -0
  325. cuju/render/web/js/teams/painter.js +633 -0
  326. cuju/render/web/js/teams/surprise-ui.js +195 -0
  327. cuju/render/web/js/teams/surprise.js +497 -0
  328. cuju/render/web/js/teams/team-check.js +127 -0
  329. cuju/render/web/js/watch/annotations.js +270 -0
  330. cuju/render/web/js/watch/flat.js +366 -0
  331. cuju/render/web/js/watch/grid.js +436 -0
  332. cuju/render/web/js/watch/pitch2d.js +289 -0
  333. cuju/render/web/js/watch/player-tools.js +192 -0
  334. cuju/render/web/js/watch/presets.js +201 -0
  335. cuju/render/web/js/world/arenas.js +997 -0
  336. cuju/render/web/js/world/ball.js +204 -0
  337. cuju/render/web/js/world/cameras.js +982 -0
  338. cuju/render/web/js/world/crowd.js +376 -0
  339. cuju/render/web/js/world/field.js +227 -0
  340. cuju/render/web/js/world/framing.js +145 -0
  341. cuju/render/web/js/world/occlusion.js +48 -0
  342. cuju/render/web/js/world/pitch.js +703 -0
  343. cuju/render/web/js/world/scene.js +395 -0
  344. cuju/render/web/js/world/sky.js +325 -0
  345. cuju/render/web/js/world/stadium.js +1262 -0
  346. cuju/render/web/js/world/vendor-sky.js +367 -0
  347. cuju/render/web/js/world/weather.js +264 -0
  348. cuju/render/web/languages/en.json +4750 -0
  349. cuju/render/web/lessons.json +137 -0
  350. cuju/render/web/manifest.webmanifest +23 -0
  351. cuju/render/web/style.css +8399 -0
  352. cuju/render/web/sw.js +235 -0
  353. cuju/render/web/vendor/fabric/LICENSE +16 -0
  354. cuju/render/web/vendor/fabric/fabric.min.mjs +1 -0
  355. cuju/render/web/vendor/lucide/LICENSE +43 -0
  356. cuju/render/web/vendor/lucide/icons.js +141 -0
  357. cuju/render/web/vendor/three/LICENSE +21 -0
  358. cuju/render/web/vendor/three/build/three.core.js +60586 -0
  359. cuju/render/web/vendor/three/build/three.module.js +19719 -0
  360. cuju/render/web/vendor/three/examples/jsm/loaders/GLTFLoader.js +4925 -0
  361. cuju/render/web/vendor/three/examples/jsm/postprocessing/EffectComposer.js +365 -0
  362. cuju/render/web/vendor/three/examples/jsm/postprocessing/MaskPass.js +195 -0
  363. cuju/render/web/vendor/three/examples/jsm/postprocessing/OutputPass.js +148 -0
  364. cuju/render/web/vendor/three/examples/jsm/postprocessing/Pass.js +191 -0
  365. cuju/render/web/vendor/three/examples/jsm/postprocessing/RenderPass.js +193 -0
  366. cuju/render/web/vendor/three/examples/jsm/postprocessing/ShaderPass.js +135 -0
  367. cuju/render/web/vendor/three/examples/jsm/postprocessing/UnrealBloomPass.js +541 -0
  368. cuju/render/web/vendor/three/examples/jsm/shaders/CopyShader.js +52 -0
  369. cuju/render/web/vendor/three/examples/jsm/shaders/LuminosityHighPassShader.js +68 -0
  370. cuju/render/web/vendor/three/examples/jsm/shaders/OutputShader.js +103 -0
  371. cuju/render/web/vendor/three/examples/jsm/utils/BufferGeometryUtils.js +1501 -0
  372. cuju/render/web/vendor/three/examples/jsm/utils/SkeletonUtils.js +496 -0
  373. cuju_render-0.1.0.dist-info/METADATA +116 -0
  374. cuju_render-0.1.0.dist-info/RECORD +382 -0
  375. cuju_render-0.1.0.dist-info/WHEEL +4 -0
  376. cuju_render-0.1.0.dist-info/licenses/LICENSE +202 -0
  377. cuju_render-0.1.0.dist-info/licenses/LICENSES/CC-BY-4.0.txt +396 -0
  378. cuju_render-0.1.0.dist-info/licenses/LICENSES/CC0-1.0.txt +127 -0
  379. cuju_render-0.1.0.dist-info/licenses/LICENSES/ISC.txt +16 -0
  380. cuju_render-0.1.0.dist-info/licenses/LICENSES/MIT.txt +24 -0
  381. cuju_render-0.1.0.dist-info/licenses/LICENSES/Unlicense.txt +13 -0
  382. cuju_render-0.1.0.dist-info/licenses/NOTICE +35 -0
@@ -0,0 +1,461 @@
1
+ // Copyright 2026 The cuju Authors
2
+ // SPDX-License-Identifier: Apache-2.0
3
+
4
+ // The guided tour, a card that walks through the pages and points at the real control of each
5
+ // step with a ring around it. The card is a dialog that leaves the page usable, marked with
6
+ // aria-modal false, so menu.js leaves the focus and the Tab key free and a person can try each
7
+ // control while it shows. Next and Back move through the steps, the arrow keys too while
8
+ // the card has the focus, and Esc or Leave the tour closes it, keeping the step for the next start.
9
+ // Try it opens what the control of the step opens, by a click as a person would make it, or
10
+ // moves the focus to a control used by keys and says its keys. The card keeps clear of its
11
+ // target and of every menu, palette, panel or dialog open over the page, and moves as soon as
12
+ // one opens or closes. While one of them is open, Esc closes it first and leaves the tour only
13
+ // the next time. The focus moves to the title of each step and the text is read out. A step that
14
+ // needs a recording or a team offers to add a sample first. Under reduced motion the ring and the
15
+ // card move at once. Scripts reach it as window.cuju.tour.
16
+
17
+ import { NEED_OFFERS, TOUR_KEY, TOUR_STEPS, moveTour, needMet, placeCard, resumeStep, stepAnnouncement, tourState } from './tour-core.js';
18
+ import { POINTER_PANELS } from '../core/comfort.js';
19
+ import { t, tm, tn } from '../core/i18n.js';
20
+ import { icon, reicon, relabel, symbolOnly } from '../core/icons.js';
21
+
22
+ function h(tag, attributes = {}, ...children) {
23
+ const node = document.createElement(tag);
24
+ for (const [key, value] of Object.entries(attributes)) {
25
+ if (key.startsWith('on') && typeof value === 'function') {
26
+ node.addEventListener(key.slice(2), value);
27
+ } else if (value !== null && value !== undefined && value !== false) {
28
+ node.setAttribute(key, value === true ? '' : value);
29
+ }
30
+ }
31
+ node.append(...children.flat().filter((child) => child !== null && child !== undefined));
32
+ return node;
33
+ }
34
+
35
+ function readState() {
36
+ try {
37
+ return tourState(JSON.parse(localStorage.getItem(TOUR_KEY)));
38
+ } catch {
39
+ return tourState(null);
40
+ }
41
+ }
42
+
43
+ // How long after a step shows its target is scrolled back into view when the page moves it.
44
+ const SETTLE_MS = 2000;
45
+
46
+ // Whether a box lies whole inside the window, or fills it when it is larger.
47
+ const inView = (box, view) => (box.top >= 0 || box.height > view.height) && (box.bottom <= view.height || box.height > view.height)
48
+ && (box.left >= 0 || box.width > view.width) && (box.right <= view.width || box.width > view.width);
49
+
50
+ const shown = (node) => !!node && node.isConnected && node.getClientRects().length > 0 && !node.closest('[hidden]');
51
+
52
+ // The elements whose opening or closing moves the card, the parts of POINTER_PANELS that float
53
+ // over the page and the command palette.
54
+ const OVERLAYS = '.dd-panel, #palette, dialog, details, [role="dialog"], [role="alertdialog"], [role="menu"], '
55
+ + '#team-editor, #lineups, .post-card, #victory, #spotlight, [data-prompt]';
56
+
57
+ export class GuidedTour {
58
+ // helpers holds facts(), what the page holds, and ensure(need), which adds the sample a step
59
+ // needs and resolves once it is there.
60
+ constructor(app, helpers) {
61
+ this.app = app;
62
+ this.helpers = helpers;
63
+ this.steps = TOUR_STEPS;
64
+ this.state = readState();
65
+ this.index = -1;
66
+ this.target = null;
67
+ this.token = 0;
68
+ this.title = h('h2', { id: 'tour-title', tabindex: '-1' });
69
+ this.count = h('p', { class: 'tour-count', id: 'tour-count' });
70
+ this.text = h('p', { id: 'tour-text', class: 'tour-text' });
71
+ this.live = h('p', { class: 'sr-only', 'aria-live': 'polite', id: 'tour-live' });
72
+ this.offerText = h('span', {});
73
+ this.offerButton = h('button', { type: 'button', class: 'btn small', onclick: () => this.fillNeed() });
74
+ this.offer = h('div', { class: 'tour-offer', hidden: true }, this.offerText, this.offerButton);
75
+ this.backButton = h('button', { type: 'button', class: 'btn', ...symbolOnly(t('tour.back')), onclick: () => this.back() }, icon('back'));
76
+ this.nextButton = h('button', { type: 'button', class: 'btn primary', ...symbolOnly(t('tour.next')), onclick: () => this.next() }, icon('next'));
77
+ this.tryButton = h('button', { type: 'button', class: 'btn', ...symbolOnly(t('tour.try')), onclick: () => this.tryIt() }, icon('cursor'));
78
+ // The focus on the title reads the title, and the live region reads the count and the
79
+ // text once, so the card names no description that a screen reader would read again.
80
+ this.card = h('div', {
81
+ id: 'tour', class: 'tour', role: 'dialog', 'aria-modal': 'false', 'aria-labelledby': 'tour-title', hidden: true,
82
+ },
83
+ this.count, this.title, this.text, this.offer,
84
+ h('div', { class: 'tour-actions' }, this.backButton, this.nextButton, this.tryButton,
85
+ h('button', { type: 'button', class: 'link small', ...symbolOnly(t('tour.leave')), onclick: () => this.leave() }, icon('close'))),
86
+ h('p', { class: 'muted small tour-keys' }, ...tn('tour.keys')),
87
+ this.live);
88
+ this.ring = h('div', { id: 'tour-ring', class: 'tour-ring', 'aria-hidden': 'true', hidden: true });
89
+ (document.getElementById('app') || document.body).append(this.ring, this.card);
90
+ this.card.addEventListener('keydown', (e) => {
91
+ if (e.target.closest('input, select, textarea')) {
92
+ return;
93
+ }
94
+ if (e.key === 'ArrowRight' && !e.altKey && !e.ctrlKey && !e.metaKey) {
95
+ e.preventDefault();
96
+ this.next();
97
+ } else if (e.key === 'ArrowLeft' && !e.altKey && !e.ctrlKey && !e.metaKey) {
98
+ e.preventDefault();
99
+ this.back();
100
+ }
101
+ });
102
+ // Esc leaves the tour from the card, or from the page when nothing else is open over it,
103
+ // before the keys of the page see it. A menu, the palette or a panel open over the page
104
+ // keeps its Esc, which closes it, so the next Esc leaves the tour.
105
+ window.addEventListener('keydown', (e) => {
106
+ if (e.key !== 'Escape' || !this.isOpen || e.defaultPrevented) {
107
+ return;
108
+ }
109
+ if (this.card.contains(document.activeElement) || !this.otherOpen()) {
110
+ e.preventDefault();
111
+ e.stopImmediatePropagation();
112
+ this.leave();
113
+ }
114
+ }, true);
115
+ this.place = () => this.position();
116
+ window.addEventListener('resize', this.place);
117
+ window.addEventListener('scroll', this.place, true);
118
+ // A menu, the palette or a panel that opens or closes moves the card at once, in the
119
+ // next frame, rather than at the next beat of the timer.
120
+ this.observer = new MutationObserver((records) => {
121
+ if (this.isOpen && !this.frame && records.some((record) => this.overlayChanged(record.target))) {
122
+ this.frame = requestAnimationFrame(() => {
123
+ this.frame = 0;
124
+ this.position();
125
+ });
126
+ }
127
+ });
128
+ }
129
+
130
+ // Whether a change of an element may open or close something over the page.
131
+ overlayChanged(node) {
132
+ return node instanceof Element && node !== this.ring && !this.card.contains(node) && node.matches(OVERLAYS);
133
+ }
134
+
135
+ // The elements open over the page that show, other than the card, as POINTER_PANELS names
136
+ // them, and the command palette.
137
+ openOver() {
138
+ const nodes = [...document.querySelectorAll(POINTER_PANELS), ...document.querySelectorAll('#palette:not([hidden])')];
139
+ return nodes.filter((node) => node !== this.card && !this.card.contains(node) && shown(node));
140
+ }
141
+
142
+ // Whether anything other than the card is open over the page.
143
+ otherOpen() {
144
+ return this.openOver().length > 0;
145
+ }
146
+
147
+ // The boxes of the menus, popovers, panels, dialogs and the palette open over the page, which
148
+ // the card keeps clear of. A button that shows as expanded is left to its panel, the palette
149
+ // counts by its box rather than its scrim, and a layer that covers the whole window counts
150
+ // not at all, since no place of the card could clear it.
151
+ openBoxes(view) {
152
+ const boxes = [];
153
+ for (const found of this.openOver()) {
154
+ const node = found.id === 'palette' ? found.querySelector('.palette-box') : found;
155
+ if (!node || node.matches('button') || node.contains(this.card)) {
156
+ continue;
157
+ }
158
+ const style = getComputedStyle(node);
159
+ if (style.position !== 'fixed' && style.position !== 'absolute' && !node.matches('dialog[open]')) {
160
+ continue;
161
+ }
162
+ const box = node.getBoundingClientRect();
163
+ if (box.width < 1 || box.height < 1 || (box.width >= 0.9 * view.width && box.height >= 0.9 * view.height)) {
164
+ continue;
165
+ }
166
+ boxes.push({ left: box.left, top: box.top, right: box.right, bottom: box.bottom });
167
+ }
168
+ return boxes;
169
+ }
170
+
171
+ get isOpen() {
172
+ return !this.card.hidden;
173
+ }
174
+
175
+ save() {
176
+ try {
177
+ localStorage.setItem(TOUR_KEY, JSON.stringify(this.state));
178
+ } catch {
179
+ // Storage can be unavailable, the tour then resumes within this visit only.
180
+ }
181
+ }
182
+
183
+ // The step a start resumes at, or 0.
184
+ get resumeAt() {
185
+ return resumeStep(this.state, this.steps.length);
186
+ }
187
+
188
+ // Opens the tour at a step, by default where it stopped.
189
+ start(index = this.resumeAt) {
190
+ if (document.pointerLockElement) {
191
+ document.exitPointerLock();
192
+ }
193
+ if (this.app.palette && this.app.palette.isOpen) {
194
+ this.app.palette.close(false);
195
+ }
196
+ this.returnTo = this.returnTo || (document.activeElement !== document.body ? document.activeElement : null);
197
+ return this.show(Math.max(0, Math.min(this.steps.length - 1, Number(index) || 0)));
198
+ }
199
+
200
+ async show(index) {
201
+ const token = ++this.token;
202
+ const step = this.steps[index];
203
+ this.closeTried();
204
+ this.index = index;
205
+ this.state = { step: index, done: false, started: true };
206
+ this.save();
207
+ if (this.app.page !== step.page) {
208
+ this.app.showPage(step.page);
209
+ }
210
+ this.card.hidden = false;
211
+ this.observer.observe(document.getElementById('app') || document.body, {
212
+ subtree: true, attributes: true, attributeFilter: ['class', 'hidden', 'open'],
213
+ });
214
+ this.tryButton.hidden = true;
215
+ this.card.classList.toggle('still', !!this.app.reducedMotion);
216
+ this.ring.classList.toggle('still', !!this.app.reducedMotion);
217
+ this.count.textContent = t('tour.count', { index: index + 1, count: this.steps.length });
218
+ this.title.textContent = step.title;
219
+ // The text shows with its marks, the message tour.step.<id>.text.
220
+ this.text.replaceChildren(tm(`tour.step.${step.id}.text`));
221
+ this.backButton.disabled = index === 0;
222
+ relabel(this.nextButton, index === this.steps.length - 1 ? t('tour.finish') : t('tour.next'));
223
+ reicon(this.nextButton, index === this.steps.length - 1 ? 'check' : 'next');
224
+ this.updateOffer(step);
225
+ this.target = null;
226
+ this.settleUntil = 0;
227
+ this.ring.hidden = true;
228
+ this.position();
229
+ this.title.focus({ preventScroll: true });
230
+ // A page builds its controls after it shows, some only once the server answers, so the
231
+ // target is looked for up to five seconds.
232
+ let found = null;
233
+ for (let i = 0; i < 100 && token === this.token; i++) {
234
+ found = [...document.querySelectorAll(step.target)].find(shown) || null;
235
+ if (found) {
236
+ break;
237
+ }
238
+ await new Promise((resolve) => setTimeout(resolve, 50));
239
+ }
240
+ if (token !== this.token) {
241
+ return this.scriptState();
242
+ }
243
+ this.target = found;
244
+ if (found) {
245
+ found.scrollIntoView({ block: 'center', inline: 'nearest', behavior: 'auto' });
246
+ // A page that is still laying out can push the target down after this scroll, so
247
+ // position scrolls it back into view for a moment.
248
+ this.settleUntil = performance.now() + SETTLE_MS;
249
+ }
250
+ this.tryButton.hidden = !found || !step.tryIt;
251
+ this.live.textContent = stepAnnouncement(step, index, this.steps.length, !!found);
252
+ this.position();
253
+ clearInterval(this.timer);
254
+ this.timer = setInterval(() => this.position(), 250);
255
+ return this.scriptState();
256
+ }
257
+
258
+ updateOffer(step) {
259
+ const facts = this.helpers.facts();
260
+ const missing = !needMet(step, facts);
261
+ this.offer.hidden = !missing;
262
+ if (missing) {
263
+ const offer = NEED_OFFERS[step.needs];
264
+ this.offerText.replaceChildren(tm(`tour.need.${step.needs}.text`), ' ');
265
+ this.offerButton.textContent = offer.label;
266
+ this.offerButton.disabled = false;
267
+ }
268
+ }
269
+
270
+ async fillNeed() {
271
+ const step = this.steps[this.index];
272
+ if (!step || !step.needs) {
273
+ return;
274
+ }
275
+ this.offerButton.disabled = true;
276
+ this.live.textContent = t('tour.adding');
277
+ try {
278
+ await this.helpers.ensure(step.needs);
279
+ } catch (err) {
280
+ this.offerButton.disabled = false;
281
+ this.live.textContent = t('tour.addFailed', { error: err.message });
282
+ return;
283
+ }
284
+ if (this.isOpen && this.steps[this.index] === step) {
285
+ await this.show(this.index);
286
+ }
287
+ }
288
+
289
+ position() {
290
+ if (!this.isOpen) {
291
+ return;
292
+ }
293
+ const view = { width: window.innerWidth, height: window.innerHeight };
294
+ let whole = shown(this.target) ? this.target.getBoundingClientRect() : null;
295
+ if (whole && performance.now() < (this.settleUntil || 0) && !inView(whole, view)) {
296
+ this.target.scrollIntoView({ block: 'center', inline: 'nearest', behavior: 'auto' });
297
+ whole = this.target.getBoundingClientRect();
298
+ }
299
+ // A region taller or wider than the window is ringed where it shows.
300
+ const target = whole && whole.width > 0 ? (() => {
301
+ const left = Math.max(whole.left, 4);
302
+ const top = Math.max(whole.top, 4);
303
+ const right = Math.min(whole.right, view.width - 4);
304
+ const bottom = Math.min(whole.bottom, view.height - 4);
305
+ return right > left && bottom > top
306
+ ? { left, top, right, bottom, width: right - left, height: bottom - top } : null;
307
+ })() : null;
308
+ if (target && target.width > 0) {
309
+ const pad = 4;
310
+ Object.assign(this.ring.style, {
311
+ left: `${Math.round(target.left - pad)}px`, top: `${Math.round(target.top - pad)}px`,
312
+ width: `${Math.round(target.width + 2 * pad)}px`, height: `${Math.round(target.height + 2 * pad)}px`,
313
+ });
314
+ this.ring.hidden = false;
315
+ } else {
316
+ this.ring.hidden = true;
317
+ }
318
+ // The card is measured at its own size, and a docked card is made smaller after.
319
+ this.card.style.maxWidth = '';
320
+ this.card.style.maxHeight = '';
321
+ this.card.style.overflowY = '';
322
+ const box = this.card.getBoundingClientRect();
323
+ const card = { width: box.width || 360, height: box.height || 200 };
324
+ const spot = placeCard(target && target.width > 0 ? {
325
+ left: target.left - 4, top: target.top - 4, right: target.right + 4, bottom: target.bottom + 4,
326
+ } : null, card, view, this.openBoxes(view));
327
+ this.card.style.left = `${spot.left}px`;
328
+ this.card.style.top = `${spot.top}px`;
329
+ if (spot.width < card.width) {
330
+ this.card.style.maxWidth = `${spot.width}px`;
331
+ }
332
+ if (spot.height < card.height) {
333
+ this.card.style.maxHeight = `${spot.height}px`;
334
+ this.card.style.overflowY = 'auto';
335
+ }
336
+ this.card.dataset.side = spot.side;
337
+ }
338
+
339
+ // Try it, as the step names it. Open clicks the control as a person would, so menu.js, the
340
+ // palette and the page open what they open as usual and put the focus where they put it, and
341
+ // leaves an open control open. Focus moves the focus to the control and says its keys.
342
+ tryIt() {
343
+ const step = this.steps[this.index];
344
+ const target = this.target;
345
+ if (!step || !step.tryIt || !shown(target)) {
346
+ return;
347
+ }
348
+ if (step.tryIt === 'open') {
349
+ const open = target.getAttribute('aria-expanded') === 'true'
350
+ || (target.id === 'open-palette' && this.app.palette && this.app.palette.isOpen);
351
+ if (!open) {
352
+ target.focus({ preventScroll: true });
353
+ this.tried = target;
354
+ target.click();
355
+ }
356
+ } else if (step.tryIt === 'focus') {
357
+ target.focus({ preventScroll: true });
358
+ this.live.textContent = t(`tour.try.${step.id}`);
359
+ }
360
+ this.position();
361
+ }
362
+
363
+ // Closes the menu or the palette that Try it opened, when it is still open as the step changes
364
+ // or the tour closes.
365
+ closeTried() {
366
+ const tried = this.tried;
367
+ this.tried = null;
368
+ if (!tried) {
369
+ return;
370
+ }
371
+ if (tried.id === 'open-palette' && this.app.palette && this.app.palette.isOpen) {
372
+ this.app.palette.close(false);
373
+ return;
374
+ }
375
+ for (const menu of Object.values(this.app.menus || {})) {
376
+ if (menu && menu.button === tried && menu.isOpen) {
377
+ menu.close(false);
378
+ }
379
+ }
380
+ }
381
+
382
+ next() {
383
+ if (!this.isOpen) {
384
+ return this.scriptState();
385
+ }
386
+ const moved = moveTour(this.state, 1, this.steps.length);
387
+ if (moved.done) {
388
+ return this.finish();
389
+ }
390
+ return this.show(moved.step);
391
+ }
392
+
393
+ back() {
394
+ if (!this.isOpen || this.index <= 0) {
395
+ return this.scriptState();
396
+ }
397
+ return this.show(this.index - 1);
398
+ }
399
+
400
+ close() {
401
+ this.token++;
402
+ this.settleUntil = 0;
403
+ clearInterval(this.timer);
404
+ this.observer.disconnect();
405
+ cancelAnimationFrame(this.frame);
406
+ this.frame = 0;
407
+ this.closeTried();
408
+ this.card.hidden = true;
409
+ this.ring.hidden = true;
410
+ this.target = null;
411
+ const back = this.returnTo;
412
+ this.returnTo = null;
413
+ if (back && shown(back)) {
414
+ back.focus({ preventScroll: true });
415
+ } else {
416
+ document.getElementById('pages')?.focus({ preventScroll: true });
417
+ }
418
+ }
419
+
420
+ // Leaves the tour midway, which resumes at this step.
421
+ leave() {
422
+ if (!this.isOpen) {
423
+ return this.scriptState();
424
+ }
425
+ this.close();
426
+ this.app.hud?.toast(t('tour.stopped', { index: this.index + 1 }), 'info', 3500);
427
+ return this.scriptState();
428
+ }
429
+
430
+ finish() {
431
+ this.state = { step: 0, done: true, started: false };
432
+ this.save();
433
+ this.close();
434
+ this.app.hud?.toast(t('tour.done'), 'info', 4500);
435
+ return this.scriptState();
436
+ }
437
+
438
+ scriptState() {
439
+ return {
440
+ open: this.isOpen,
441
+ step: this.isOpen ? this.index : null,
442
+ id: this.isOpen ? this.steps[this.index].id : null,
443
+ resumeAt: this.resumeAt,
444
+ done: this.state.done,
445
+ target: this.isOpen ? !!this.target : null,
446
+ steps: this.steps.length,
447
+ };
448
+ }
449
+
450
+ // The functions of window.cuju.tour.
451
+ script() {
452
+ return {
453
+ start: (index) => this.start(index === undefined ? this.resumeAt : index),
454
+ next: () => this.next(),
455
+ back: () => this.back(),
456
+ leave: () => this.leave(),
457
+ state: () => this.scriptState(),
458
+ steps: () => this.steps.map((step) => ({ id: step.id, page: step.page, title: step.title, text: step.text, needs: step.needs || null })),
459
+ };
460
+ }
461
+ }