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,307 @@
1
+ # Copyright 2026 The cuju Authors
2
+ # SPDX-License-Identifier: Apache-2.0
3
+
4
+ """Codes the frames of a recording of version 2, which decode to the bytes of version 1 exactly.
5
+
6
+ The frames section stores every field of every frame as a lane, the values of one field across all
7
+ frames, and lanes of a kind lie together as planes of bytes, the low bytes of every lane and then
8
+ the high bytes. A joint is stored relative to its parent, as the rotation and offset that the
9
+ parent carries it by and a small residual, so most lanes change slowly and the whole file's gzip
10
+ finds them. The coding starts afresh at every keyframe, so any frame decodes from the keyframe
11
+ before it. The layout is in the repository's `docs/rendering.md`, under Recording format.
12
+
13
+ Speed: the coder works on whole lanes with numpy, every joint of every frame at once, and the
14
+ decoder one joint at a time over every frame, so a full match of eleven a side codes in a few
15
+ seconds and decodes in about one.
16
+ """
17
+
18
+ from __future__ import annotations
19
+
20
+ import numpy as np
21
+
22
+ # The steps between keyframes, ten seconds of play.
23
+ KEYFRAME_INTERVAL = 100
24
+ # A rotation component is stored in steps of 1 / UNIT, as version 1 stores it.
25
+ UNIT = 32767
26
+ HEAD_WORDS = 19
27
+ HEAD_BYTES = HEAD_WORDS * 4
28
+ JOINTS = 14
29
+ PARENTS = (-1, 0, 1, 2, 2, 4, 2, 6, 1, 8, 9, 1, 11, 12)
30
+ _CHILDREN = JOINTS - 1
31
+ _PARENT_INDEX = np.array(PARENTS[1:])
32
+ # The kinds of int16 lanes per player, in the order of the section, with the number of each.
33
+ _ROOT_POSITION, _ROOT_ROTATION = 3, 4
34
+ _LOCAL_ROTATION, _LOCAL_OFFSET = 3 * _CHILDREN, 3 * _CHILDREN
35
+ _ROTATION_RESIDUAL, _POSITION_RESIDUAL = 4 * _CHILDREN, 3 * _CHILDREN
36
+ _SIGNS = _CHILDREN
37
+ _CONJUGATE = np.array([-1, -1, -1, 1])
38
+
39
+
40
+ def padded(players: int) -> int:
41
+ """Returns the bytes of each of the three byte runs that close a frame of version 1."""
42
+ return -(-players // 4) * 4
43
+
44
+
45
+ def frame_bytes(players: int) -> int:
46
+ """Returns the bytes of one decoded frame, as version 1 stores it."""
47
+ return HEAD_BYTES + players * JOINTS * 14 + 3 * padded(players)
48
+
49
+
50
+ def section_bytes(players: int, count: int) -> int:
51
+ """Returns the bytes of the frames section of `count` frames of `players` players."""
52
+ short = players * (
53
+ _ROOT_POSITION
54
+ + _ROOT_ROTATION
55
+ + _LOCAL_ROTATION
56
+ + _LOCAL_OFFSET
57
+ + _ROTATION_RESIDUAL
58
+ + _POSITION_RESIDUAL
59
+ )
60
+ return count * (HEAD_BYTES + 2 * short + players * _SIGNS + 3 * padded(players))
61
+
62
+
63
+ def _hamilton(first: np.ndarray, second: np.ndarray) -> np.ndarray:
64
+ """Returns the Hamilton products of quaternions, x, y, z and w along the first axis."""
65
+ x1, y1, z1, w1 = first
66
+ x2, y2, z2, w2 = second
67
+ return np.stack(
68
+ (
69
+ w1 * x2 + x1 * w2 + y1 * z2 - z1 * y2,
70
+ w1 * y2 + y1 * w2 + z1 * x2 - x1 * z2,
71
+ w1 * z2 + z1 * w2 + x1 * y2 - y1 * x2,
72
+ w1 * w2 - x1 * x2 - y1 * y2 - z1 * z2,
73
+ )
74
+ )
75
+
76
+
77
+ def _cross(first: np.ndarray, second: np.ndarray) -> np.ndarray:
78
+ """Returns the cross products of vectors, x, y and z along the first axis."""
79
+ x1, y1, z1 = first
80
+ x2, y2, z2 = second
81
+ return np.stack((y1 * z2 - z1 * y2, z1 * x2 - x1 * z2, x1 * y2 - y1 * x2))
82
+
83
+
84
+ def _isqrt(values: np.ndarray) -> np.ndarray:
85
+ """Returns the integer square roots of non-negative integers below 2**52."""
86
+ root = np.floor(np.sqrt(values.astype(np.float64))).astype(np.int64)
87
+ root -= root * root > values
88
+ root += (root + 1) * (root + 1) <= values
89
+ return root
90
+
91
+
92
+ def _predict_rotation(parent: np.ndarray, local: np.ndarray, sign: np.ndarray) -> np.ndarray:
93
+ """Returns the rotation that `parent` carries the local rotation `local` to.
94
+
95
+ The local rotation gives x, y and z, its w follows from the unit length, negative where `sign`
96
+ is set, and the product rounds half up in steps of 1 / UNIT. Every value is an integer below
97
+ 2**53, so a reader in double precision computes the same. Components lie along the first axis.
98
+ """
99
+ w = _isqrt(np.maximum(UNIT * UNIT - (local * local).sum(0), 0))
100
+ w = np.where(sign != 0, -w, w)
101
+ product = _hamilton(parent, np.concatenate((local, w[None]), 0))
102
+ return (2 * product + UNIT) // (2 * UNIT)
103
+
104
+
105
+ def _predict_position(origin: np.ndarray, parent: np.ndarray, offset: np.ndarray) -> np.ndarray:
106
+ """Returns `origin` plus `offset` turned by the rotation `parent`, rounded half up."""
107
+ axis, w = parent[:3], parent[3:]
108
+ turned = _cross(axis, offset)
109
+ total = offset * (UNIT * UNIT) + 2 * w * turned + 2 * _cross(axis, turned)
110
+ return origin + (2 * total + UNIT * UNIT) // (2 * UNIT * UNIT)
111
+
112
+
113
+ def _difference(values: np.ndarray, interval: int) -> np.ndarray:
114
+ """Returns each value less the one before along the last axis, the keyframes as they are."""
115
+ out = values.copy()
116
+ out[..., 1:] -= values[..., :-1]
117
+ out[..., ::interval] = values[..., ::interval]
118
+ return out
119
+
120
+
121
+ def _sum(values: np.ndarray, interval: int) -> np.ndarray:
122
+ """Undoes `_difference`, summing from each keyframe on."""
123
+ out = values.copy()
124
+ for start in range(0, values.shape[-1], interval):
125
+ part = out[..., start : start + interval]
126
+ np.cumsum(part, axis=-1, out=part)
127
+ return out
128
+
129
+
130
+ def _xor(values: np.ndarray, interval: int) -> np.ndarray:
131
+ """Returns each byte XOR the one before along the last axis, the keyframes as they are."""
132
+ out = values.copy()
133
+ out[..., 1:] ^= values[..., :-1]
134
+ out[..., ::interval] = values[..., ::interval]
135
+ return out
136
+
137
+
138
+ def _unxor(values: np.ndarray, interval: int) -> np.ndarray:
139
+ """Undoes `_xor`, from each keyframe on."""
140
+ out = values.copy()
141
+ for start in range(0, values.shape[-1], interval):
142
+ part = out[..., start : start + interval]
143
+ np.bitwise_xor.accumulate(part, axis=-1, out=part)
144
+ return out
145
+
146
+
147
+ def _steady(values: np.ndarray, interval: int, reach: int) -> np.ndarray:
148
+ """Holds each value at the one before while it moves by at most `reach`, from each keyframe.
149
+
150
+ A held value costs nothing in its lane, and the residual takes up the difference.
151
+ """
152
+ out = np.moveaxis(values, -1, 0).copy()
153
+ for frame in range(1, len(out)):
154
+ if frame % interval:
155
+ near = np.abs(out[frame] - out[frame - 1]) <= reach
156
+ out[frame] = np.where(near, out[frame - 1], out[frame])
157
+ return np.ascontiguousarray(np.moveaxis(out, 0, -1))
158
+
159
+
160
+ def _planes(values: np.ndarray, width: int) -> bytes:
161
+ """Returns lanes `[..., frames]` of signed integers as zigzag planes, the lowest byte first."""
162
+ signed = np.ascontiguousarray(values).astype(f'<i{width}')
163
+ zigzag = ((signed << 1) ^ (signed >> (8 * width - 1))).view(f'<u{width}')
164
+ split = zigzag.reshape(-1).view(np.uint8).reshape(-1, width)
165
+ return b''.join(split[:, plane].tobytes() for plane in range(width))
166
+
167
+
168
+ def _unplanes(data: np.ndarray, width: int) -> np.ndarray:
169
+ """Undoes `_planes` for planes `[width, lanes, frames]`, returning `[lanes, frames]` int64."""
170
+ joined = np.empty((*data.shape[1:], width), np.uint8)
171
+ for plane in range(width):
172
+ joined[..., plane] = data[plane]
173
+ zigzag = joined.view(f'<u{width}')[..., 0]
174
+ signed = (zigzag >> 1).astype(f'<i{width}') ^ -(zigzag & 1).astype(f'<i{width}')
175
+ return signed.astype(np.int64)
176
+
177
+
178
+ def encode(frames: list[bytes], players: int, interval: int = KEYFRAME_INTERVAL) -> bytes:
179
+ """Returns the frames section of version 2 for frames of version 1.
180
+
181
+ Args:
182
+ frames: The frames, each as version 1 stores it.
183
+ players: The number of players.
184
+ interval: The frames from one keyframe to the next.
185
+ """
186
+ count = len(frames)
187
+ size = frame_bytes(players)
188
+ raw = np.frombuffer(b''.join(frames), np.uint8).reshape(count, size)
189
+ nodes_end = HEAD_BYTES + players * JOINTS * 14
190
+ head = raw[:, :HEAD_BYTES].copy().view('<i4').T.astype(np.int64)
191
+ tail = np.ascontiguousarray(raw[:, nodes_end:].T)
192
+ nodes = raw[:, HEAD_BYTES:nodes_end].copy().view('<i2').reshape(count, players, JOINTS, 7)
193
+ # Components, joints, players and frames, so each lane of values is contiguous.
194
+ nodes = np.ascontiguousarray(nodes.transpose(3, 2, 1, 0)).astype(np.int64)
195
+ position, rotation = nodes[:3], nodes[3:]
196
+ parent, child = rotation[:, _PARENT_INDEX], rotation[:, 1:]
197
+ origin, place = position[:, _PARENT_INDEX], position[:, 1:]
198
+ conjugate = parent * _CONJUGATE[:, None, None, None]
199
+ # The local rotation, from the parent's rotation to the child's, in steps of 1 / UNIT.
200
+ local = _hamilton(conjugate, child)
201
+ turn = np.clip(np.rint(local[:3] / UNIT), -UNIT, UNIT).astype(np.int64)
202
+ turn = _steady(turn, interval, 1)
203
+ sign = (local[3] < 0).astype(np.uint8)
204
+ # The offset of the child in the frame of its parent, in the steps of a position.
205
+ unit = conjugate.astype(np.float64)
206
+ unit /= np.maximum(np.sqrt((unit * unit).sum(0)), 1.0)
207
+ gap = (place - origin).astype(np.float64)
208
+ turned = _cross(unit[:3], gap)
209
+ offset = gap + 2 * unit[3:] * turned + 2 * _cross(unit[:3], turned)
210
+ offset = _steady(np.clip(np.rint(offset), -UNIT, UNIT).astype(np.int64), interval, 1)
211
+ rotation_residual = child - _predict_rotation(parent, turn, sign)
212
+ position_residual = place - _predict_position(origin, parent, offset)
213
+
214
+ def lanes(values: np.ndarray) -> np.ndarray:
215
+ # Components, joints, players and frames become joints, components, players and frames.
216
+ return values.transpose(1, 0, 2, 3)
217
+
218
+ parts = [
219
+ _planes(_difference(head, interval), 4),
220
+ _planes(_difference(_difference(position[:, 0], interval), interval), 2),
221
+ _planes(_difference(rotation[:, 0], interval), 2),
222
+ _planes(lanes(_difference(turn, interval)), 2),
223
+ _xor(sign, interval).tobytes(),
224
+ _planes(lanes(_difference(offset, interval)), 2),
225
+ _planes(lanes(rotation_residual), 2),
226
+ _planes(lanes(position_residual), 2),
227
+ _xor(tail, interval).tobytes(),
228
+ ]
229
+ data = b''.join(parts)
230
+ assert len(data) == section_bytes(players, count)
231
+ return data
232
+
233
+
234
+ def decode(
235
+ data: bytes | memoryview,
236
+ players: int,
237
+ count: int,
238
+ interval: int = KEYFRAME_INTERVAL,
239
+ start: int = 0,
240
+ stop: int | None = None,
241
+ ) -> np.ndarray:
242
+ """Returns frames `start` to `stop` of a frames section, as `[frames, frame_bytes]` bytes.
243
+
244
+ Only the frames from the keyframe before `start` decode, so a reader seeks in constant time.
245
+
246
+ Args:
247
+ data: The frames section, at least `section_bytes(players, count)` bytes.
248
+ players: The number of players.
249
+ count: The number of frames of the section.
250
+ interval: The frames from one keyframe to the next.
251
+ start: The first frame to return.
252
+ stop: The frame after the last to return, by default the end.
253
+ """
254
+ stop = count if stop is None else max(0, min(stop, count))
255
+ start = max(0, min(start, stop))
256
+ first = start // interval * interval
257
+ span = stop - first
258
+ if start == stop:
259
+ return np.empty((0, frame_bytes(players)), np.uint8)
260
+ buffer = np.frombuffer(data, np.uint8, section_bytes(players, count))
261
+ at = 0
262
+
263
+ def take(lanes: int, width: int = 2) -> np.ndarray:
264
+ nonlocal at
265
+ size = lanes * count * width
266
+ block = buffer[at : at + size].reshape(width, lanes, count)[:, :, first:stop]
267
+ at += size
268
+ return _unplanes(block, width) if width > 1 else block[0]
269
+
270
+ def short(values: np.ndarray) -> np.ndarray:
271
+ # A sum of differences holds the value up to whole turns of 2**16.
272
+ return values.astype(np.int16).astype(np.int64)
273
+
274
+ head = _sum(take(HEAD_WORDS, 4), interval)
275
+ root_position = short(_sum(_sum(take(3 * players), interval), interval))
276
+ root_rotation = short(_sum(take(4 * players), interval))
277
+ turn = short(_sum(take(_LOCAL_ROTATION * players), interval))
278
+ sign = _unxor(take(_SIGNS * players, 1), interval).reshape(_CHILDREN, players, span)
279
+ offsets = short(_sum(take(_LOCAL_OFFSET * players), interval))
280
+ rotation_residual = take(_ROTATION_RESIDUAL * players).reshape(_CHILDREN, 4, players, span)
281
+ position_residual = take(_POSITION_RESIDUAL * players).reshape(_CHILDREN, 3, players, span)
282
+ tail = _unxor(take(3 * padded(players), 1), interval)
283
+ turn = turn.reshape(_CHILDREN, 3, players, span)
284
+ offsets = offsets.reshape(_CHILDREN, 3, players, span)
285
+
286
+ # Components, joints, players and frames, as the encoder holds them.
287
+ nodes = np.empty((7, JOINTS, players, span), np.int64)
288
+ nodes[:3, 0] = root_position.reshape(3, players, span)
289
+ nodes[3:, 0] = root_rotation.reshape(4, players, span)
290
+ for joint in range(1, JOINTS):
291
+ parent = nodes[:, PARENTS[joint]]
292
+ index = joint - 1
293
+ rotation = _predict_rotation(parent[3:], turn[index], sign[index])
294
+ nodes[3:, joint] = short(rotation + rotation_residual[index])
295
+ position = _predict_position(parent[:3], parent[3:], offsets[index])
296
+ nodes[:3, joint] = short(position + position_residual[index])
297
+ out = np.empty((span, frame_bytes(players)), np.uint8)
298
+ out[:, :HEAD_BYTES] = np.ascontiguousarray(head.T).astype('<i4').view(np.uint8)
299
+ nodes_end = HEAD_BYTES + players * JOINTS * 14
300
+ out[:, HEAD_BYTES:nodes_end] = (
301
+ np.ascontiguousarray(nodes.transpose(3, 2, 1, 0))
302
+ .astype('<i2')
303
+ .reshape(span, -1)
304
+ .view(np.uint8)
305
+ )
306
+ out[:, nodes_end:] = tail.T
307
+ return out[start - first :]
@@ -0,0 +1,121 @@
1
+ # Copyright 2026 The cuju Authors
2
+ # SPDX-License-Identifier: Apache-2.0
3
+
4
+ """The filters of a recorder, which decide at the end of each episode whether to save it.
5
+
6
+ A filter reads the summary of the episode, its score, goals, length, rewards and annotations, so it
7
+ never touches the batch, and the frames of an episode that it drops are discarded unwritten.
8
+ """
9
+
10
+ from __future__ import annotations
11
+
12
+ import math
13
+ import struct
14
+ from collections.abc import Callable
15
+ from typing import Any
16
+
17
+ from cuju.errors import ArgumentError
18
+
19
+ # The names that `keep` takes besides a function.
20
+ KEEP = ('all', 'goals')
21
+
22
+
23
+ class Filter:
24
+ """Decides from the summary of an ended episode whether a recorder saves it.
25
+
26
+ Every condition must hold, the choice or function of `keep`, every `every`-th episode from the
27
+ first, and a return of at least `min_reward`.
28
+ """
29
+
30
+ def __init__(
31
+ self,
32
+ keep: str | Callable[[dict[str, Any]], Any] | None = None,
33
+ every: int = 1,
34
+ min_reward: float | None = None,
35
+ ) -> None:
36
+ """Checks and keeps the conditions.
37
+
38
+ Raises:
39
+ ArgumentError: If `keep` is neither a function nor one of `KEEP`, `every` is not a
40
+ whole number of at least 1, or `min_reward` is not a finite number.
41
+ """
42
+ if keep is None:
43
+ keep = 'all'
44
+ if not callable(keep) and keep not in KEEP:
45
+ raise ArgumentError(f'expected keep as a function or one of {KEEP}, found {keep!r}')
46
+ if isinstance(every, bool) or not isinstance(every, int) or every < 1:
47
+ raise ArgumentError(f'expected every as a whole number of at least 1, found {every!r}')
48
+ if min_reward is not None and (
49
+ isinstance(min_reward, bool)
50
+ or not isinstance(min_reward, int | float)
51
+ or not math.isfinite(min_reward)
52
+ ):
53
+ raise ArgumentError(f'expected min_reward as a finite number, found {min_reward!r}')
54
+ self.keep = keep
55
+ self.every = every
56
+ self.min_reward = min_reward
57
+
58
+ def __call__(self, summary: dict[str, Any]) -> bool:
59
+ """Returns whether to save the episode of `summary`, as `episode_summary` returns it."""
60
+ if summary['episode'] % self.every:
61
+ return False
62
+ if self.min_reward is not None and summary['reward'] < self.min_reward:
63
+ return False
64
+ if self.keep == 'goals':
65
+ return summary['goals'] > 0
66
+ if callable(self.keep):
67
+ return bool(self.keep(summary))
68
+ return True
69
+
70
+
71
+ def step_rewards(batch: Any, environment: int, information: dict[str, Any]) -> list[float]:
72
+ """Returns the reward of each agent of an environment on a step, none when it is not known.
73
+
74
+ The rewards are those that the batch hands its step observers, read without a change, and the
75
+ agents count in the batch's order, those of the left team first.
76
+
77
+ Args:
78
+ batch: The batch.
79
+ environment: The environment.
80
+ information: What the batch handed its observers for the step.
81
+ """
82
+ rewards = information.get('reward')
83
+ if rewards is None:
84
+ return []
85
+ reward = rewards[environment].reshape(-1)
86
+ mask = batch.agent_mask[environment].reshape(-1)
87
+ return [
88
+ float(value) for value, kept in zip(reward.tolist(), mask.tolist(), strict=True) if kept
89
+ ]
90
+
91
+
92
+ def episode_summary(
93
+ episode: int,
94
+ frames: list[bytes],
95
+ rewards: list[float],
96
+ environment: int,
97
+ annotations: list[dict[str, Any]] | None = None,
98
+ ) -> dict[str, Any]:
99
+ """Returns the summary of an episode that a filter reads.
100
+
101
+ Args:
102
+ episode: The number of episodes that the recorder ended before this one.
103
+ frames: The frames of the episode.
104
+ rewards: The return of each agent over the captured steps.
105
+ environment: The environment of the recorder.
106
+ annotations: The annotations of the episode, with long keys.
107
+ """
108
+ last = frames[-1]
109
+ score = list(struct.unpack_from('<2i', last, 8))
110
+ (step,) = struct.unpack_from('<i', last, 0)
111
+ return {
112
+ 'episode': episode,
113
+ 'environment': environment,
114
+ 'score': score,
115
+ 'goals': sum(score),
116
+ 'length': len(frames),
117
+ 'steps': step,
118
+ 'rewards': list(rewards),
119
+ 'reward': sum(rewards),
120
+ 'annotations': list(annotations or ()),
121
+ }