@nodetool-ai/websocket 0.8.1 → 0.8.2

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 (284) hide show
  1. package/dist/.nodetool-build-stamp +1 -1
  2. package/dist/collection-api.d.ts.map +1 -1
  3. package/dist/collection-api.js +41 -4
  4. package/dist/collection-api.js.map +1 -1
  5. package/dist/error-traces.d.ts +56 -0
  6. package/dist/error-traces.d.ts.map +1 -0
  7. package/dist/error-traces.js +179 -0
  8. package/dist/error-traces.js.map +1 -0
  9. package/dist/fake-runtime.d.ts.map +1 -1
  10. package/dist/fake-runtime.js +40 -3
  11. package/dist/fake-runtime.js.map +1 -1
  12. package/dist/generation-recovery.d.ts.map +1 -1
  13. package/dist/generation-recovery.js +26 -4
  14. package/dist/generation-recovery.js.map +1 -1
  15. package/dist/http-api.d.ts.map +1 -1
  16. package/dist/http-api.js +15 -0
  17. package/dist/http-api.js.map +1 -1
  18. package/dist/index.d.ts +0 -1
  19. package/dist/index.d.ts.map +1 -1
  20. package/dist/index.js +0 -1
  21. package/dist/index.js.map +1 -1
  22. package/dist/interrupted-jobs.d.ts +14 -0
  23. package/dist/interrupted-jobs.d.ts.map +1 -0
  24. package/dist/interrupted-jobs.js +28 -0
  25. package/dist/interrupted-jobs.js.map +1 -0
  26. package/dist/lib/app-debug-service.js +1 -1
  27. package/dist/lib/app-debug-service.js.map +1 -1
  28. package/dist/lib/app-instances-service.d.ts +1284 -0
  29. package/dist/lib/app-instances-service.d.ts.map +1 -0
  30. package/dist/lib/app-instances-service.js +378 -0
  31. package/dist/lib/app-instances-service.js.map +1 -0
  32. package/dist/lib/app-run-cancellation.d.ts +4 -0
  33. package/dist/lib/app-run-cancellation.d.ts.map +1 -0
  34. package/dist/lib/app-run-cancellation.js +28 -0
  35. package/dist/lib/app-run-cancellation.js.map +1 -0
  36. package/dist/lib/applications-service.d.ts +182 -1
  37. package/dist/lib/applications-service.d.ts.map +1 -1
  38. package/dist/lib/applications-service.js +20 -4
  39. package/dist/lib/applications-service.js.map +1 -1
  40. package/dist/lib/asset-paths.d.ts +7 -11
  41. package/dist/lib/asset-paths.d.ts.map +1 -1
  42. package/dist/lib/asset-paths.js +8 -56
  43. package/dist/lib/asset-paths.js.map +1 -1
  44. package/dist/lib/asset-response.d.ts.map +1 -1
  45. package/dist/lib/asset-response.js +2 -1
  46. package/dist/lib/asset-response.js.map +1 -1
  47. package/dist/lib/audio-peaks.d.ts.map +1 -1
  48. package/dist/lib/audio-peaks.js +5 -1
  49. package/dist/lib/audio-peaks.js.map +1 -1
  50. package/dist/lib/bridge.d.ts.map +1 -1
  51. package/dist/lib/bridge.js.map +1 -1
  52. package/dist/lib/document-model-interfaces.d.ts.map +1 -1
  53. package/dist/lib/document-model-interfaces.js +9 -8
  54. package/dist/lib/document-model-interfaces.js.map +1 -1
  55. package/dist/lib/example-apps.d.ts +9 -0
  56. package/dist/lib/example-apps.d.ts.map +1 -1
  57. package/dist/lib/example-apps.js +61 -14
  58. package/dist/lib/example-apps.js.map +1 -1
  59. package/dist/lib/http-tracing.d.ts +12 -0
  60. package/dist/lib/http-tracing.d.ts.map +1 -0
  61. package/dist/lib/http-tracing.js +81 -0
  62. package/dist/lib/http-tracing.js.map +1 -0
  63. package/dist/lib/media.d.ts +1 -6
  64. package/dist/lib/media.d.ts.map +1 -1
  65. package/dist/lib/media.js +8 -44
  66. package/dist/lib/media.js.map +1 -1
  67. package/dist/lib/public-routes.d.ts +7 -0
  68. package/dist/lib/public-routes.d.ts.map +1 -1
  69. package/dist/lib/public-routes.js +14 -0
  70. package/dist/lib/public-routes.js.map +1 -1
  71. package/dist/lib/public-workflow-share.d.ts +20 -0
  72. package/dist/lib/public-workflow-share.d.ts.map +1 -0
  73. package/dist/lib/public-workflow-share.js +45 -0
  74. package/dist/lib/public-workflow-share.js.map +1 -0
  75. package/dist/lib/run-trace-live-delivery.d.ts +25 -0
  76. package/dist/lib/run-trace-live-delivery.d.ts.map +1 -0
  77. package/dist/lib/run-trace-live-delivery.js +91 -0
  78. package/dist/lib/run-trace-live-delivery.js.map +1 -0
  79. package/dist/lib/test-ui-run-routes.d.ts +8 -0
  80. package/dist/lib/test-ui-run-routes.d.ts.map +1 -0
  81. package/dist/lib/test-ui-run-routes.js +42 -0
  82. package/dist/lib/test-ui-run-routes.js.map +1 -0
  83. package/dist/lib/thumbnail.d.ts.map +1 -1
  84. package/dist/lib/thumbnail.js +12 -9
  85. package/dist/lib/thumbnail.js.map +1 -1
  86. package/dist/lib/timeline-bundle.d.ts +148 -16
  87. package/dist/lib/timeline-bundle.d.ts.map +1 -1
  88. package/dist/lib/timeline-bundle.js +12 -0
  89. package/dist/lib/timeline-bundle.js.map +1 -1
  90. package/dist/lib/video-proxy.d.ts.map +1 -1
  91. package/dist/lib/video-proxy.js +3 -2
  92. package/dist/lib/video-proxy.js.map +1 -1
  93. package/dist/lib/workflow-service.d.ts.map +1 -1
  94. package/dist/lib/workflow-service.js +4 -1
  95. package/dist/lib/workflow-service.js.map +1 -1
  96. package/dist/mcp-agent-tools.d.ts.map +1 -1
  97. package/dist/mcp-agent-tools.js +93 -162
  98. package/dist/mcp-agent-tools.js.map +1 -1
  99. package/dist/mcp-client-config.d.ts +64 -0
  100. package/dist/mcp-client-config.d.ts.map +1 -0
  101. package/dist/mcp-client-config.js +353 -0
  102. package/dist/mcp-client-config.js.map +1 -0
  103. package/dist/models-api.d.ts +10 -0
  104. package/dist/models-api.d.ts.map +1 -1
  105. package/dist/models-api.js +23 -0
  106. package/dist/models-api.js.map +1 -1
  107. package/dist/node-registry-setup.d.ts +1 -1
  108. package/dist/node-registry-setup.d.ts.map +1 -1
  109. package/dist/node-registry-setup.js +21 -114
  110. package/dist/node-registry-setup.js.map +1 -1
  111. package/dist/plugins/websocket.d.ts.map +1 -1
  112. package/dist/plugins/websocket.js +20 -57
  113. package/dist/plugins/websocket.js.map +1 -1
  114. package/dist/python-bridge-gate.d.ts +28 -0
  115. package/dist/python-bridge-gate.d.ts.map +1 -0
  116. package/dist/python-bridge-gate.js +36 -0
  117. package/dist/python-bridge-gate.js.map +1 -0
  118. package/dist/routes/app-runs.d.ts +4 -0
  119. package/dist/routes/app-runs.d.ts.map +1 -0
  120. package/dist/routes/app-runs.js +173 -0
  121. package/dist/routes/app-runs.js.map +1 -0
  122. package/dist/routes/js-scripts.d.ts +9 -3
  123. package/dist/routes/js-scripts.d.ts.map +1 -1
  124. package/dist/routes/js-scripts.js +450 -68
  125. package/dist/routes/js-scripts.js.map +1 -1
  126. package/dist/routes/nodes.d.ts.map +1 -1
  127. package/dist/routes/nodes.js +32 -1
  128. package/dist/routes/nodes.js.map +1 -1
  129. package/dist/routes/public-shared-workflows.d.ts +16 -0
  130. package/dist/routes/public-shared-workflows.d.ts.map +1 -0
  131. package/dist/routes/public-shared-workflows.js +55 -0
  132. package/dist/routes/public-shared-workflows.js.map +1 -0
  133. package/dist/routes/run-spans.d.ts +4 -0
  134. package/dist/routes/run-spans.d.ts.map +1 -0
  135. package/dist/routes/run-spans.js +53 -0
  136. package/dist/routes/run-spans.js.map +1 -0
  137. package/dist/routes/timeline-fonts.d.ts +22 -0
  138. package/dist/routes/timeline-fonts.d.ts.map +1 -1
  139. package/dist/routes/timeline-fonts.js +138 -7
  140. package/dist/routes/timeline-fonts.js.map +1 -1
  141. package/dist/screenshot-server.js +4 -5
  142. package/dist/screenshot-server.js.map +1 -1
  143. package/dist/sdk/sdk-model-download-service.d.ts.map +1 -1
  144. package/dist/sdk/sdk-model-download-service.js +5 -2
  145. package/dist/sdk/sdk-model-download-service.js.map +1 -1
  146. package/dist/server.js +86 -19
  147. package/dist/server.js.map +1 -1
  148. package/dist/session/app-run-fold.d.ts +7 -0
  149. package/dist/session/app-run-fold.d.ts.map +1 -0
  150. package/dist/session/app-run-fold.js +45 -0
  151. package/dist/session/app-run-fold.js.map +1 -0
  152. package/dist/session/chat-prompt.d.ts.map +1 -1
  153. package/dist/session/chat-prompt.js +37 -15
  154. package/dist/session/chat-prompt.js.map +1 -1
  155. package/dist/session/chat-turn.d.ts +1 -0
  156. package/dist/session/chat-turn.d.ts.map +1 -1
  157. package/dist/session/chat-turn.js +203 -107
  158. package/dist/session/chat-turn.js.map +1 -1
  159. package/dist/session/commands.d.ts.map +1 -1
  160. package/dist/session/commands.js +6 -0
  161. package/dist/session/commands.js.map +1 -1
  162. package/dist/session/inference.d.ts +5 -0
  163. package/dist/session/inference.d.ts.map +1 -1
  164. package/dist/session/inference.js +80 -9
  165. package/dist/session/inference.js.map +1 -1
  166. package/dist/session/job-execution.d.ts +7 -0
  167. package/dist/session/job-execution.d.ts.map +1 -1
  168. package/dist/session/job-execution.js +297 -7
  169. package/dist/session/job-execution.js.map +1 -1
  170. package/dist/session/model-interfaces.d.ts +2 -1
  171. package/dist/session/model-interfaces.d.ts.map +1 -1
  172. package/dist/session/model-interfaces.js +1 -0
  173. package/dist/session/model-interfaces.js.map +1 -1
  174. package/dist/storage-retention.d.ts +5 -0
  175. package/dist/storage-retention.d.ts.map +1 -1
  176. package/dist/storage-retention.js +22 -1
  177. package/dist/storage-retention.js.map +1 -1
  178. package/dist/test-ui-server.d.ts.map +1 -1
  179. package/dist/test-ui-server.js +21 -3
  180. package/dist/test-ui-server.js.map +1 -1
  181. package/dist/timeline-generation-recovery.d.ts +4 -0
  182. package/dist/timeline-generation-recovery.d.ts.map +1 -0
  183. package/dist/timeline-generation-recovery.js +72 -0
  184. package/dist/timeline-generation-recovery.js.map +1 -0
  185. package/dist/triggers/dispatcher.js +2 -2
  186. package/dist/triggers/dispatcher.js.map +1 -1
  187. package/dist/triggers/stores.js +8 -8
  188. package/dist/triggers/stores.js.map +1 -1
  189. package/dist/triggers/webhook-route.js +2 -2
  190. package/dist/triggers/webhook-route.js.map +1 -1
  191. package/dist/trpc/error-logging.d.ts +10 -0
  192. package/dist/trpc/error-logging.d.ts.map +1 -1
  193. package/dist/trpc/error-logging.js +21 -0
  194. package/dist/trpc/error-logging.js.map +1 -1
  195. package/dist/trpc/router.d.ts +100 -31028
  196. package/dist/trpc/router.d.ts.map +1 -1
  197. package/dist/trpc/router.js +12 -3
  198. package/dist/trpc/router.js.map +1 -1
  199. package/dist/trpc/routers/app-instances.d.ts +2269 -0
  200. package/dist/trpc/routers/app-instances.d.ts.map +1 -0
  201. package/dist/trpc/routers/app-instances.js +52 -0
  202. package/dist/trpc/routers/app-instances.js.map +1 -0
  203. package/dist/trpc/routers/app-runs.d.ts +1092 -0
  204. package/dist/trpc/routers/app-runs.d.ts.map +1 -0
  205. package/dist/trpc/routers/app-runs.js +28 -0
  206. package/dist/trpc/routers/app-runs.js.map +1 -0
  207. package/dist/trpc/routers/applications.d.ts +1095 -0
  208. package/dist/trpc/routers/applications.d.ts.map +1 -1
  209. package/dist/trpc/routers/applications.js +5 -2
  210. package/dist/trpc/routers/applications.js.map +1 -1
  211. package/dist/trpc/routers/assets.d.ts +10 -0
  212. package/dist/trpc/routers/assets.d.ts.map +1 -1
  213. package/dist/trpc/routers/assets.js +4 -0
  214. package/dist/trpc/routers/assets.js.map +1 -1
  215. package/dist/trpc/routers/bug-reports.d.ts +33 -0
  216. package/dist/trpc/routers/bug-reports.d.ts.map +1 -0
  217. package/dist/trpc/routers/bug-reports.js +69 -0
  218. package/dist/trpc/routers/bug-reports.js.map +1 -0
  219. package/dist/trpc/routers/documents.d.ts.map +1 -1
  220. package/dist/trpc/routers/documents.js +8 -2
  221. package/dist/trpc/routers/documents.js.map +1 -1
  222. package/dist/trpc/routers/error-traces.d.ts +132 -0
  223. package/dist/trpc/routers/error-traces.d.ts.map +1 -0
  224. package/dist/trpc/routers/error-traces.js +118 -0
  225. package/dist/trpc/routers/error-traces.js.map +1 -0
  226. package/dist/trpc/routers/extension.d.ts +3 -3
  227. package/dist/trpc/routers/extension.js +6 -6
  228. package/dist/trpc/routers/extension.js.map +1 -1
  229. package/dist/trpc/routers/gameDraftHistory.d.ts +8 -0
  230. package/dist/trpc/routers/gameDraftHistory.d.ts.map +1 -0
  231. package/dist/trpc/routers/gameDraftHistory.js +40 -0
  232. package/dist/trpc/routers/gameDraftHistory.js.map +1 -0
  233. package/dist/trpc/routers/games.d.ts +23691 -4799
  234. package/dist/trpc/routers/games.d.ts.map +1 -1
  235. package/dist/trpc/routers/games.js +301 -83
  236. package/dist/trpc/routers/games.js.map +1 -1
  237. package/dist/trpc/routers/jobs.d.ts +35 -0
  238. package/dist/trpc/routers/jobs.d.ts.map +1 -1
  239. package/dist/trpc/routers/jobs.js +84 -1
  240. package/dist/trpc/routers/jobs.js.map +1 -1
  241. package/dist/trpc/routers/mcp-config.d.ts +3 -1
  242. package/dist/trpc/routers/mcp-config.d.ts.map +1 -1
  243. package/dist/trpc/routers/mcp-config.js +46 -208
  244. package/dist/trpc/routers/mcp-config.js.map +1 -1
  245. package/dist/trpc/routers/models.d.ts +130 -0
  246. package/dist/trpc/routers/models.d.ts.map +1 -1
  247. package/dist/trpc/routers/models.js +99 -31
  248. package/dist/trpc/routers/models.js.map +1 -1
  249. package/dist/trpc/routers/runs.d.ts +472 -0
  250. package/dist/trpc/routers/runs.d.ts.map +1 -0
  251. package/dist/trpc/routers/runs.js +40 -0
  252. package/dist/trpc/routers/runs.js.map +1 -0
  253. package/dist/trpc/routers/settings.d.ts +3 -0
  254. package/dist/trpc/routers/settings.d.ts.map +1 -1
  255. package/dist/trpc/routers/settings.js +2 -0
  256. package/dist/trpc/routers/settings.js.map +1 -1
  257. package/dist/trpc/routers/sketch.d.ts +14 -0
  258. package/dist/trpc/routers/sketch.d.ts.map +1 -1
  259. package/dist/trpc/routers/storyboards.d.ts +732 -0
  260. package/dist/trpc/routers/storyboards.d.ts.map +1 -1
  261. package/dist/trpc/routers/timeline.d.ts +632 -63
  262. package/dist/trpc/routers/timeline.d.ts.map +1 -1
  263. package/dist/trpc/routers/timeline.js +178 -2
  264. package/dist/trpc/routers/timeline.js.map +1 -1
  265. package/dist/trpc/routers/worker.d.ts +10 -9
  266. package/dist/trpc/routers/worker.d.ts.map +1 -1
  267. package/dist/trpc/routers/worker.js +3 -2
  268. package/dist/trpc/routers/worker.js.map +1 -1
  269. package/dist/trpc/routers/workflows.d.ts +56 -3
  270. package/dist/trpc/routers/workflows.d.ts.map +1 -1
  271. package/dist/trpc/routers/workflows.js +23 -2
  272. package/dist/trpc/routers/workflows.js.map +1 -1
  273. package/dist/trpc/sandbox-coverage.d.ts.map +1 -1
  274. package/dist/trpc/sandbox-coverage.js +90 -0
  275. package/dist/trpc/sandbox-coverage.js.map +1 -1
  276. package/dist/websocket-client-session.d.ts +2 -0
  277. package/dist/websocket-client-session.d.ts.map +1 -1
  278. package/dist/websocket-client-session.js +14 -0
  279. package/dist/websocket-client-session.js.map +1 -1
  280. package/package.json +56 -41
  281. package/dist/extension-cdp-bridge.d.ts +0 -85
  282. package/dist/extension-cdp-bridge.d.ts.map +0 -1
  283. package/dist/extension-cdp-bridge.js +0 -163
  284. package/dist/extension-cdp-bridge.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"games.d.ts","sourceRoot":"","sources":["../../../src/trpc/routers/games.ts"],"names":[],"mappings":"AA2MA,eAAO,MAAM,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsRtB,CAAC"}
1
+ {"version":3,"file":"games.d.ts","sourceRoot":"","sources":["../../../src/trpc/routers/games.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAsSxB,eAAO,MAAM,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2WtB,CAAC"}
@@ -2,18 +2,24 @@ import { createHash, randomUUID } from "node:crypto";
2
2
  import { join } from "node:path";
3
3
  import { z } from "zod";
4
4
  import sharp from "sharp";
5
- import { getManagedWorkspaceDir, managedWorkspaceKey, workspaceStorageKind } from "@nodetool-ai/config";
6
- import { AmbiguousGameIdError, Asset, Game, Project, Workspace } from "@nodetool-ai/models";
7
- import { exampleGameSummary, gameAssetBinding, gameDocument, installExampleGameInput } from "@nodetool-ai/protocol/game.js";
8
- import { createTopDownRoomGame, gameDocumentOp, GameOpError, validateGame } from "@nodetool-ai/game-runtime";
5
+ import { createLogger, getManagedWorkspaceDir, managedWorkspaceKey, workspaceStorageKind } from "@nodetool-ai/config";
6
+ import { AmbiguousGameIdError, InvalidGameDocumentError, Asset, Game, Project, Workspace } from "@nodetool-ai/models";
7
+ import { exampleGameSummary, anyGameAssetBinding, gameAssetBinding, gameAssetBinding3D, gamePreparedCollider3D, gameModelImportSettings3D, parseGameDocument, anyGameDocument as gameDocument, installExampleGameInput } from "@nodetool-ai/protocol";
8
+ import { createTopDownRoomGame, createNative3DGame, anyGameDocumentOp as gameDocumentOp, GameOpError, decodePreparedGameCollider3D, trackGameAuthoringEdits, validateAnyGame } from "@nodetool-ai/game-runtime";
9
+ import { normalizeGameModel3D, prepareGameModelBinding3D } from "@nodetool-ai/game-renderer/preparation3d";
10
+ import { createCapabilityRun, gateFromContext } from "@nodetool-ai/agents";
11
+ import { gameAuthoringCandidate, gameAuthoringProgram, gameAuthoringConflict } from "@nodetool-ai/protocol";
12
+ import { PERMISSION_GATE_CONTEXT_KEY, ProcessingContext, headlessGate } from "@nodetool-ai/runtime";
9
13
  import { getAssetAdapter } from "../../lib/storage.js";
10
14
  import { getAssetStorageKey, retrieveAssetBytes } from "../../lib/asset-paths.js";
11
- import { installExampleGameAssets, listExampleGames } from "../../lib/example-games.js";
15
+ import { getExampleGameBundle, installExampleGameAssets, listExampleGames } from "../../lib/example-games.js";
12
16
  import { workspaceFromRow } from "../../lib/workflow-workspace.js";
13
17
  import { ApiErrorCode } from "../../error-codes.js";
14
18
  import { router } from "../index.js";
15
19
  import { protectedProcedure } from "../middleware.js";
16
20
  import { throwApiError } from "../error-formatter.js";
21
+ import { boundedGameDraftHistory, MAX_GAME_DRAFT_OPS } from "./gameDraftHistory.js";
22
+ const log = createLogger("nodetool.games");
17
23
  const idInput = z.object({ id: z.string() });
18
24
  const gameInfo = z.object({
19
25
  id: z.string(),
@@ -27,6 +33,14 @@ const gameInfo = z.object({
27
33
  updatedAt: z.string()
28
34
  });
29
35
  const gameWithDocument = z.object({ game: gameInfo, document: gameDocument });
36
+ const authoringPreview = z.object({
37
+ candidate: gameAuthoringCandidate,
38
+ document: gameDocument,
39
+ conflicts: z.array(gameAuthoringConflict),
40
+ affected_entities: z.array(z.string()),
41
+ changed_dependencies: z.array(z.string()),
42
+ restart_required: z.boolean()
43
+ });
30
44
  const gameRevisionInfo = z.object({ revision: z.string(), modifiedAt: z.number(), current: z.boolean(), message: z.string().nullable() });
31
45
  function info(game) {
32
46
  return {
@@ -44,6 +58,18 @@ function info(game) {
44
58
  function newRevision() {
45
59
  return randomUUID().replace(/-/g, "");
46
60
  }
61
+ function authoringRun(userId) {
62
+ const context = new ProcessingContext({ jobId: `game-authoring-${randomUUID()}`, userId });
63
+ context.set(PERMISSION_GATE_CONTEXT_KEY, headlessGate("game.authoring"));
64
+ return createCapabilityRun({ context, gate: gateFromContext(context, "game.authoring") });
65
+ }
66
+ function checkAuthoringResult(result) {
67
+ if (result !== null && typeof result === "object" && "error" in result && typeof result.error === "string") {
68
+ const code = /stale|concurrent|changed since/i.test(result.error)
69
+ ? ApiErrorCode.ALREADY_EXISTS : ApiErrorCode.INVALID_INPUT;
70
+ throwApiError(code, result.error);
71
+ }
72
+ }
47
73
  function sourcePath(game, revision) {
48
74
  return `${game.source_root}/revisions/${revision}/game.json`;
49
75
  }
@@ -74,6 +100,36 @@ async function gameWorkspace(userId, game) {
74
100
  }
75
101
  return workspace;
76
102
  }
103
+ async function persistGameAsset(userId, game, workspace, draftUpdatedAt, slot, binding, bytes, extension, contentType) {
104
+ await workspace.write(`${game.source_root}/assets/${binding.digest}.${extension}`, bytes, contentType);
105
+ const installed = await Asset.create({
106
+ user_id: userId, project_id: game.project_id, parent_id: userId,
107
+ name: `${slot}.${extension}`, content_type: contentType, size: bytes.byteLength,
108
+ metadata: { game_source_asset_id: binding.mediaKind === "model" ? binding.sourceAssetId ?? binding.assetId : binding.assetId,
109
+ game_digest: binding.digest }
110
+ });
111
+ if (!(installed instanceof Asset)) {
112
+ throwApiError(ApiErrorCode.INTERNAL_ERROR, "Asset creation failed");
113
+ }
114
+ const storage = getAssetAdapter();
115
+ let uri = null;
116
+ try {
117
+ uri = await storage.store(getAssetStorageKey(userId, installed.id, contentType), bytes, contentType);
118
+ const op = gameDocumentOp.parse({ op: "bind_asset", slot, binding: { ...binding, assetId: installed.id } });
119
+ const saved = await Game.updateDraft(userId, game.id, draftUpdatedAt, [op], workspace, { actor: "user" });
120
+ if (!saved) {
121
+ throwApiError(ApiErrorCode.ALREADY_EXISTS, "Game draft was modified concurrently");
122
+ }
123
+ return { game: info(saved.game), document: saved.document };
124
+ }
125
+ catch (error) {
126
+ if (uri) {
127
+ await storage.delete(uri);
128
+ }
129
+ await installed.delete();
130
+ throw error;
131
+ }
132
+ }
77
133
  async function projectWorkspace(userId, projectId) {
78
134
  const rows = await Workspace.listByProject(userId, projectId);
79
135
  const existing = rows.find((row) => row.isAccessible() && (process.env["NODETOOL_ENV"] !== "production" || row.isManaged()));
@@ -105,10 +161,14 @@ async function projectWorkspace(userId, projectId) {
105
161
  }));
106
162
  }
107
163
  function validatedDocument(value, id, revision) {
108
- const source = gameDocument.parse(value);
109
- const result = validateGame({ ...source, id, revision });
164
+ const parsed = parseGameDocument(value);
165
+ if (!parsed.ok) {
166
+ throwApiError(ApiErrorCode.INVALID_INPUT, parsed.diagnostics.map((issue) => `${issue.code} ${issue.path.join(".")}: ${issue.message}`).join("; "));
167
+ }
168
+ const source = parsed.document;
169
+ const result = validateAnyGame({ ...source, id, revision });
110
170
  if (!result.valid || !result.document) {
111
- throwApiError(ApiErrorCode.INVALID_INPUT, result.errors.join("; "));
171
+ throwApiError(ApiErrorCode.INVALID_INPUT, result.diagnostics.map((issue) => `${issue.path.join(".")}: ${issue.message}`).join("; "));
112
172
  }
113
173
  return result.document;
114
174
  }
@@ -129,7 +189,7 @@ async function readRevision(workspace, game, revision) {
129
189
  async function writeRevision(workspace, game, document) {
130
190
  await workspace.write(sourcePath(game, document.revision), JSON.stringify(document), "application/json");
131
191
  }
132
- async function publishDocument(userId, game, baseRevision, value, message) {
192
+ async function publishDocument(userId, game, baseRevision, value, message, restoreAuthoring = false, expectedDraftUpdatedAt, expectedDigest) {
133
193
  if (baseRevision !== game.current_revision) {
134
194
  throwApiError(ApiErrorCode.ALREADY_EXISTS, "Game was modified concurrently");
135
195
  }
@@ -138,21 +198,52 @@ async function publishDocument(userId, game, baseRevision, value, message) {
138
198
  if (!draft) {
139
199
  throwApiError(ApiErrorCode.NOT_FOUND, "Game draft not found");
140
200
  }
201
+ if ((value !== undefined || restoreAuthoring) && !expectedDraftUpdatedAt) {
202
+ throwApiError(ApiErrorCode.INVALID_INPUT, "A draft token is required for publish and restore");
203
+ }
204
+ if (expectedDraftUpdatedAt !== undefined && expectedDraftUpdatedAt !== draft.game.draft_updated_at) {
205
+ throwApiError(ApiErrorCode.ALREADY_EXISTS, "Game draft was modified concurrently");
206
+ }
207
+ const candidate = validatedDocument(value ?? draft.document, game.id, draft.game.current_revision);
208
+ const digest = createHash("sha256").update(JSON.stringify(candidate)).digest("hex");
209
+ if (expectedDigest !== undefined && digest !== expectedDigest) {
210
+ throwApiError(ApiErrorCode.ALREADY_EXISTS, "The validated game document changed before publish");
211
+ }
141
212
  const revision = newRevision();
142
- const document = validatedDocument(value ?? draft?.document, game.id, revision);
213
+ let document = { ...candidate, revision };
214
+ if (!restoreAuthoring && value !== undefined && JSON.stringify(document.authoring) !== JSON.stringify(draft.document.authoring)) {
215
+ throwApiError(ApiErrorCode.INVALID_INPUT, "Retained construction must be changed through preview and apply");
216
+ }
217
+ if (!restoreAuthoring && draft.document.authoring) {
218
+ document = trackGameAuthoringEdits(draft.document, document);
219
+ }
220
+ if ((document.schemaVersion === 3) !== (draft.document.schemaVersion === 3)) {
221
+ throwApiError(ApiErrorCode.INVALID_INPUT, "A game cannot change dimension");
222
+ }
143
223
  await writeRevision(workspace, game, document);
144
224
  const updated = await Game.publish(userId, game.id, baseRevision, revision, draft.game.draft_updated_at, workspace, message);
145
225
  if (!updated) {
146
- await workspace.delete(sourcePath(game, revision));
226
+ try {
227
+ await workspace.delete(sourcePath(game, revision));
228
+ }
229
+ catch (error) {
230
+ log.error("Losing game publication revision cleanup failed", { gameId: game.id, revision, error: String(error) });
231
+ }
147
232
  throwApiError(ApiErrorCode.ALREADY_EXISTS, "Game was modified concurrently");
148
233
  }
149
- if (draft.game.draft_version_id) {
150
- await workspace.delete(`${game.source_root}/drafts/${draft.game.draft_version_id}.json`);
234
+ try {
235
+ if (draft.game.draft_version_id) {
236
+ await workspace.delete(`${game.source_root}/drafts/${draft.game.draft_version_id}.json`);
237
+ }
238
+ await workspace.write(`${game.source_root}/draft.json`, JSON.stringify(document), "application/json");
239
+ await Game.pruneRevisionFiles(userId, game.id, workspace);
240
+ }
241
+ catch (error) {
242
+ log.error("Game post-publish cleanup failed", { gameId: game.id, error: String(error) });
151
243
  }
152
- await workspace.write(`${game.source_root}/draft.json`, JSON.stringify(document), "application/json");
153
244
  return { game: info(updated), document };
154
245
  }
155
- async function createGame(userId, projectId, name, source) {
246
+ async function createGame(userId, projectId, name, source, dimension = "2d") {
156
247
  if (!(await Project.findOwned(userId, projectId))) {
157
248
  throwApiError(ApiErrorCode.NOT_FOUND, "Project not found");
158
249
  }
@@ -163,7 +254,10 @@ async function createGame(userId, projectId, name, source) {
163
254
  }
164
255
  const id = randomUUID().replace(/-/g, "");
165
256
  const revision = newRevision();
166
- const document = validatedDocument(source ?? createTopDownRoomGame(id), id, revision);
257
+ const document = validatedDocument(source ?? (dimension === "3d" ? createNative3DGame(id) : createTopDownRoomGame(id)), id, revision);
258
+ if (document.authoring) {
259
+ throwApiError(ApiErrorCode.INVALID_INPUT, "Attach retained construction through preview and apply after creating the game");
260
+ }
167
261
  const candidate = new Game({
168
262
  id,
169
263
  user_id: userId,
@@ -196,12 +290,27 @@ export const gamesRouter = router({
196
290
  return (await Game.listByProject(ctx.userId, input.projectId)).map(info);
197
291
  }),
198
292
  create: protectedProcedure
199
- .input(z.object({ projectId: z.string(), name: z.string().min(1).max(200), document: gameDocument.optional() }))
293
+ .input(z.object({ projectId: z.string(), name: z.string().min(1).max(200), dimension: z.enum(["2d", "3d"]).optional(), document: gameDocument.optional() }))
200
294
  .output(gameWithDocument)
201
- .mutation(({ ctx, input }) => createGame(ctx.userId, input.projectId, input.name, input.document)),
295
+ .mutation(({ ctx, input }) => {
296
+ if (input.dimension && input.document && ((input.document.schemaVersion === 3) !== (input.dimension === "3d"))) {
297
+ throwApiError(ApiErrorCode.INVALID_INPUT, "Requested dimension does not match the supplied game document");
298
+ }
299
+ return createGame(ctx.userId, input.projectId, input.name, input.document, input.dimension);
300
+ }),
202
301
  examples: protectedProcedure
203
302
  .output(z.array(exampleGameSummary))
204
303
  .query(({ ctx }) => listExampleGames(ctx.apiOptions)),
304
+ example: protectedProcedure
305
+ .input(z.object({ slug: z.string().min(1) }))
306
+ .output(z.object({ name: z.string(), document: gameDocument }))
307
+ .query(({ ctx, input }) => {
308
+ const bundle = getExampleGameBundle(ctx.apiOptions, input.slug);
309
+ if (!bundle) {
310
+ throwApiError(ApiErrorCode.NOT_FOUND, "Example game not found");
311
+ }
312
+ return { name: bundle.name, document: bundle.document };
313
+ }),
205
314
  installExample: protectedProcedure
206
315
  .input(installExampleGameInput)
207
316
  .output(gameWithDocument)
@@ -241,7 +350,7 @@ export const gamesRouter = router({
241
350
  return { game: info(draft.game), document: draft.document };
242
351
  }),
243
352
  saveDraft: protectedProcedure
244
- .input(idInput.extend({ baseUpdatedAt: z.string(), ops: z.array(gameDocumentOp).min(1) }))
353
+ .input(idInput.extend({ baseUpdatedAt: z.string(), ops: z.array(gameDocumentOp).min(1).max(MAX_GAME_DRAFT_OPS) }))
245
354
  .output(gameWithDocument)
246
355
  .mutation(async ({ ctx, input }) => {
247
356
  const game = await ownedGame(ctx.userId, input.id);
@@ -255,9 +364,40 @@ export const gamesRouter = router({
255
364
  if (error instanceof GameOpError) {
256
365
  throwApiError(ApiErrorCode.INVALID_INPUT, `Op ${error.opIndex}: ${error.path}: ${error.message}`);
257
366
  }
367
+ if (error instanceof InvalidGameDocumentError) {
368
+ throwApiError(ApiErrorCode.INVALID_INPUT, error.message);
369
+ }
258
370
  throw error;
259
371
  }
260
372
  }),
373
+ previewAuthoring: protectedProcedure
374
+ .input(idInput.extend({ program: gameAuthoringProgram.optional() }).strict())
375
+ .output(authoringPreview)
376
+ .mutation(async ({ ctx, input }) => {
377
+ const game = await ownedGame(ctx.userId, input.id);
378
+ const args = { game_id: game.id };
379
+ if (input.program) {
380
+ args.program = input.program;
381
+ }
382
+ const result = await authoringRun(ctx.userId).invoke("preview_native_game_authoring", args);
383
+ checkAuthoringResult(result);
384
+ return authoringPreview.parse(result);
385
+ }),
386
+ applyAuthoring: protectedProcedure
387
+ .input(idInput.extend({ candidate: gameAuthoringCandidate }).strict())
388
+ .output(gameWithDocument)
389
+ .mutation(async ({ ctx, input }) => {
390
+ const game = await ownedGame(ctx.userId, input.id);
391
+ const result = await authoringRun(ctx.userId).invoke("apply_native_game_authoring", {
392
+ game_id: game.id, candidate: input.candidate
393
+ });
394
+ checkAuthoringResult(result);
395
+ const draft = await Game.readDraft(ctx.userId, game.id, await gameWorkspace(ctx.userId, game));
396
+ if (!draft) {
397
+ throwApiError(ApiErrorCode.NOT_FOUND, "Game draft not found");
398
+ }
399
+ return { game: info(draft.game), document: draft.document };
400
+ }),
261
401
  draftChanges: protectedProcedure
262
402
  .input(idInput)
263
403
  .output(z.array(z.object({
@@ -268,7 +408,7 @@ export const gamesRouter = router({
268
408
  })))
269
409
  .query(async ({ ctx, input }) => {
270
410
  const game = await ownedGame(ctx.userId, input.id);
271
- return (await Game.listDraftChanges(ctx.userId, game.id)).map(({ gameId: _gameId, ...change }) => change);
411
+ return boundedGameDraftHistory((await Game.listDraftChanges(ctx.userId, game.id)).map(({ gameId: _gameId, ...change }) => change));
272
412
  }),
273
413
  draftBeforeChange: protectedProcedure
274
414
  .input(idInput.extend({ changeId: z.string() }))
@@ -296,17 +436,17 @@ export const gamesRouter = router({
296
436
  return revisions.sort((a, b) => b.modifiedAt - a.modifiedAt);
297
437
  }),
298
438
  publish: protectedProcedure
299
- .input(idInput.extend({ baseRevision: z.string(), document: gameDocument.optional(), message: z.string().trim().max(500).optional() }))
439
+ .input(idInput.extend({ baseRevision: z.string(), baseUpdatedAt: z.string().optional(), expectedDigest: z.string().regex(/^[a-f0-9]{64}$/).optional(), document: gameDocument.optional(), message: z.string().trim().max(500).optional() }))
300
440
  .output(gameWithDocument)
301
- .mutation(async ({ ctx, input }) => publishDocument(ctx.userId, await ownedGame(ctx.userId, input.id), input.baseRevision, input.document, input.message)),
441
+ .mutation(async ({ ctx, input }) => publishDocument(ctx.userId, await ownedGame(ctx.userId, input.id), input.baseRevision, input.document, input.message, false, input.baseUpdatedAt, input.expectedDigest)),
302
442
  restore: protectedProcedure
303
- .input(idInput.extend({ baseRevision: z.string(), revision: z.string() }))
443
+ .input(idInput.extend({ baseRevision: z.string(), baseUpdatedAt: z.string(), revision: z.string() }))
304
444
  .output(gameWithDocument)
305
445
  .mutation(async ({ ctx, input }) => {
306
446
  const game = await ownedGame(ctx.userId, input.id);
307
447
  const workspace = await gameWorkspace(ctx.userId, game);
308
448
  const oldDocument = await readRevision(workspace, game, input.revision);
309
- return publishDocument(ctx.userId, game, input.baseRevision, oldDocument);
449
+ return publishDocument(ctx.userId, game, input.baseRevision, oldDocument, undefined, true, input.baseUpdatedAt);
310
450
  }),
311
451
  restoreDraft: protectedProcedure
312
452
  .input(idInput.extend({ baseUpdatedAt: z.string(), revision: z.string() }))
@@ -314,42 +454,83 @@ export const gamesRouter = router({
314
454
  .mutation(async ({ ctx, input }) => {
315
455
  const game = await ownedGame(ctx.userId, input.id);
316
456
  const workspace = await gameWorkspace(ctx.userId, game);
317
- const document = await readRevision(workspace, game, input.revision);
318
- const restored = await Game.replaceDraft(ctx.userId, game.id, input.baseUpdatedAt, document, workspace);
319
- if (!restored)
320
- throwApiError(ApiErrorCode.ALREADY_EXISTS, "Game draft was modified concurrently");
321
- return { game: info(restored.game), document: restored.document };
457
+ try {
458
+ const document = await readRevision(workspace, game, input.revision);
459
+ const restored = await Game.replaceDraft(ctx.userId, game.id, input.baseUpdatedAt, document, workspace);
460
+ if (!restored)
461
+ throwApiError(ApiErrorCode.ALREADY_EXISTS, "Game draft was modified concurrently");
462
+ return { game: info(restored.game), document: restored.document };
463
+ }
464
+ catch (error) {
465
+ if (error instanceof InvalidGameDocumentError || error instanceof z.ZodError) {
466
+ throwApiError(ApiErrorCode.INVALID_INPUT, error.message);
467
+ }
468
+ throw error;
469
+ }
322
470
  }),
323
471
  installAsset: protectedProcedure
324
- .input(idInput.extend({ baseRevision: z.string().optional(), baseUpdatedAt: z.string().optional(), slot: z.string().min(1), assetId: z.string(), expectedDigest: z.string().optional() }))
472
+ .input(idInput.extend({ baseRevision: z.string().optional(), baseUpdatedAt: z.string().optional(), slot: z.string().min(1),
473
+ assetId: z.string(), expectedDigest: z.string().optional(), importSettings: gameModelImportSettings3D.partial().optional(),
474
+ dependencyAssetIds: z.record(z.string(), z.string()).refine((value) => Object.keys(value).length <= 320, "Too many model dependencies").optional() }))
325
475
  .output(gameWithDocument)
326
476
  .mutation(async ({ ctx, input }) => {
327
477
  const game = await ownedGame(ctx.userId, input.id);
478
+ const workspace = await gameWorkspace(ctx.userId, game);
479
+ const draft = await Game.readDraft(ctx.userId, game.id, workspace);
480
+ if (!draft) {
481
+ throwApiError(ApiErrorCode.NOT_FOUND, "Game draft not found");
482
+ }
483
+ if (input.baseRevision && game.current_revision !== input.baseRevision) {
484
+ throwApiError(ApiErrorCode.ALREADY_EXISTS, "Game was modified concurrently");
485
+ }
486
+ if (input.baseUpdatedAt && draft.game.draft_updated_at !== input.baseUpdatedAt) {
487
+ throwApiError(ApiErrorCode.ALREADY_EXISTS, "Game draft was modified concurrently");
488
+ }
489
+ const is3D = draft.document.schemaVersion === 3;
328
490
  const asset = await Asset.find(ctx.userId, input.assetId);
329
- if (!asset || !asset.content_type.startsWith("image/")) {
330
- throwApiError(ApiErrorCode.NOT_FOUND, "Image asset not found");
491
+ if (!asset || (is3D ? !["model/gltf-binary", "model/gltf+json"].includes(asset.content_type) : !asset.content_type.startsWith("image/"))) {
492
+ throwApiError(ApiErrorCode.NOT_FOUND, is3D ? "Model asset not found" : "Image asset not found");
493
+ }
494
+ if (is3D && asset.size !== null && asset.size > 64 * 1024 * 1024) {
495
+ throwApiError(ApiErrorCode.INVALID_INPUT, "Model source exceeds import byte budget");
331
496
  }
332
497
  const bytes = await retrieveAssetBytes(getAssetAdapter(), ctx.userId, asset.id, asset.content_type);
333
- if (!bytes)
334
- throwApiError(ApiErrorCode.NOT_FOUND, "Image bytes not found");
498
+ if (!bytes) {
499
+ throwApiError(ApiErrorCode.NOT_FOUND, is3D ? "Model bytes not found" : "Image bytes not found");
500
+ }
335
501
  const digest = createHash("sha256").update(bytes).digest("hex");
336
502
  if (input.expectedDigest && digest !== input.expectedDigest) {
337
- throwApiError(ApiErrorCode.INVALID_INPUT, "Image content digest changed");
503
+ throwApiError(ApiErrorCode.INVALID_INPUT, is3D ? "Model content digest changed" : "Image content digest changed");
504
+ }
505
+ if (draft.document.schemaVersion === 3) {
506
+ const normalized = await normalizeGameModel3D(bytes, {
507
+ assetId: asset.id, sourceAssetId: asset.id, importSettings: input.importSettings,
508
+ provenance: asset.workflow_id ?? undefined,
509
+ resolveDependency: async (uri) => {
510
+ const dependencyId = input.dependencyAssetIds && Object.hasOwn(input.dependencyAssetIds, uri)
511
+ ? input.dependencyAssetIds[uri] : undefined;
512
+ if (!dependencyId) {
513
+ return null;
514
+ }
515
+ const dependency = await Asset.find(ctx.userId, dependencyId);
516
+ if (!dependency) {
517
+ throwApiError(ApiErrorCode.NOT_FOUND, "Model dependency asset not found");
518
+ }
519
+ if (dependency.size !== null && dependency.size > 64 * 1024 * 1024) {
520
+ throwApiError(ApiErrorCode.INVALID_INPUT, "Model dependency exceeds import byte budget");
521
+ }
522
+ return retrieveAssetBytes(getAssetAdapter(), ctx.userId, dependency.id, dependency.content_type);
523
+ }
524
+ });
525
+ if (!normalized.ok) {
526
+ throwApiError(ApiErrorCode.INVALID_INPUT, normalized.diagnostics.map((issue) => issue.message).join("; "));
527
+ }
528
+ return persistGameAsset(ctx.userId, game, workspace, draft.game.draft_updated_at, input.slot, normalized.binding, normalized.bytes, "glb", "model/gltf-binary");
338
529
  }
339
530
  const metadata = await sharp(bytes).metadata();
340
531
  if (!metadata.width || !metadata.height) {
341
532
  throwApiError(ApiErrorCode.INVALID_INPUT, "Image dimensions are unavailable");
342
533
  }
343
- const workspace = await gameWorkspace(ctx.userId, game);
344
- const draft = await Game.readDraft(ctx.userId, game.id, workspace);
345
- if (!draft)
346
- throwApiError(ApiErrorCode.NOT_FOUND, "Game draft not found");
347
- if (input.baseRevision && game.current_revision !== input.baseRevision) {
348
- throwApiError(ApiErrorCode.ALREADY_EXISTS, "Game was modified concurrently");
349
- }
350
- if (input.baseUpdatedAt && draft.game.draft_updated_at !== input.baseUpdatedAt) {
351
- throwApiError(ApiErrorCode.ALREADY_EXISTS, "Game draft was modified concurrently");
352
- }
353
534
  const saved = await Game.updateDraft(ctx.userId, game.id, draft.game.draft_updated_at, [{
354
535
  op: "bind_asset", slot: input.slot,
355
536
  binding: {
@@ -359,8 +540,9 @@ export const gamesRouter = router({
359
540
  provenance: asset.workflow_id ?? undefined
360
541
  }
361
542
  }], workspace, { actor: "user" });
362
- if (!saved)
543
+ if (!saved) {
363
544
  throwApiError(ApiErrorCode.ALREADY_EXISTS, "Game draft was modified concurrently");
545
+ }
364
546
  return { game: info(saved.game), document: saved.document };
365
547
  }),
366
548
  installCandidate: protectedProcedure
@@ -369,7 +551,7 @@ export const gamesRouter = router({
369
551
  baseUpdatedAt: z.string().optional(),
370
552
  slot: z.string().min(1),
371
553
  candidateWorkspaceId: z.string().optional(),
372
- binding: gameAssetBinding
554
+ binding: anyGameAssetBinding
373
555
  }))
374
556
  .output(gameWithDocument)
375
557
  .mutation(async ({ ctx, input }) => {
@@ -392,11 +574,15 @@ export const gamesRouter = router({
392
574
  if (input.binding.mediaKind === "font" && !input.binding.fontFormat) {
393
575
  throwApiError(ApiErrorCode.INVALID_INPUT, "Font binding needs a TrueType or OpenType format");
394
576
  }
395
- const formats = input.binding.mediaKind === "audio"
396
- ? [["wav", "audio/wav"], ["mp3", "audio/mpeg"], ["ogg", "audio/ogg"]]
397
- : input.binding.mediaKind === "font"
398
- ? [[input.binding.fontFormat, `font/${input.binding.fontFormat}`]]
399
- : [["png", "image/png"], ["jpg", "image/jpeg"], ["webp", "image/webp"]];
577
+ const formats = input.binding.mediaKind === "model"
578
+ ? [["glb", "model/gltf-binary"]]
579
+ : input.binding.mediaKind === "collider"
580
+ ? [["json", "application/json"]]
581
+ : input.binding.mediaKind === "audio"
582
+ ? [["wav", "audio/wav"], ["mp3", "audio/mpeg"], ["ogg", "audio/ogg"]]
583
+ : input.binding.mediaKind === "font"
584
+ ? [[input.binding.fontFormat, `font/${input.binding.fontFormat}`]]
585
+ : [["png", "image/png"], ["jpg", "image/jpeg"], ["webp", "image/webp"]];
400
586
  let candidate = null;
401
587
  for (const [extension, contentType] of formats) {
402
588
  if (!extension || !contentType)
@@ -404,14 +590,70 @@ export const gamesRouter = router({
404
590
  const path = `${game.source_root}/assets/${digest}.${extension}`;
405
591
  const bytes = await candidateWorkspace.read(path);
406
592
  if (bytes) {
407
- candidate = { path, extension, contentType, bytes };
593
+ candidate = { extension, contentType, bytes };
408
594
  break;
409
595
  }
410
596
  }
411
597
  if (!candidate || createHash("sha256").update(candidate.bytes).digest("hex") !== digest) {
412
598
  throwApiError(ApiErrorCode.INVALID_INPUT, "Candidate asset is missing or changed");
413
599
  }
414
- const { path, extension, contentType, bytes } = candidate;
600
+ const { extension, contentType, bytes } = candidate;
601
+ let binding = input.binding;
602
+ if (binding.mediaKind === "model") {
603
+ const prepared = await prepareGameModelBinding3D(bytes, { assetId: binding.assetId, expectedDigest: digest });
604
+ if (!prepared.ok) {
605
+ throwApiError(ApiErrorCode.INVALID_INPUT, prepared.diagnostics.map((issue) => issue.message).join("; "));
606
+ }
607
+ const sourceAsset = binding.sourceAssetId ? await Asset.find(ctx.userId, binding.sourceAssetId) : null;
608
+ if (binding.sourceAssetId && !sourceAsset) {
609
+ throwApiError(ApiErrorCode.INVALID_INPUT, "Model source asset is not owned");
610
+ }
611
+ const canonical = { ...prepared.binding, required: binding.required };
612
+ if (binding.provenance) {
613
+ canonical.provenance = binding.provenance;
614
+ }
615
+ if (binding.importSettings) {
616
+ canonical.importSettings = binding.importSettings;
617
+ }
618
+ if (binding.sourceDigest) {
619
+ canonical.sourceDigest = binding.sourceDigest;
620
+ }
621
+ if (sourceAsset) {
622
+ canonical.sourceAssetId = sourceAsset.id;
623
+ }
624
+ binding = canonical;
625
+ }
626
+ else if (binding.mediaKind === "collider") {
627
+ let geometry;
628
+ try {
629
+ geometry = JSON.parse(new TextDecoder().decode(bytes));
630
+ }
631
+ catch {
632
+ throwApiError(ApiErrorCode.INVALID_INPUT, "Prepared collider is not valid JSON");
633
+ }
634
+ const parsed = gamePreparedCollider3D.safeParse(geometry);
635
+ if (!parsed.success || binding.shape === "triangleMesh" && !parsed.data.indices?.length) {
636
+ throwApiError(ApiErrorCode.INVALID_INPUT, "Prepared collider has invalid vertices or triangle indices");
637
+ }
638
+ const { vertices, indices } = parsed.data;
639
+ const minimum = { x: Infinity, y: Infinity, z: Infinity };
640
+ const maximum = { x: -Infinity, y: -Infinity, z: -Infinity };
641
+ for (let index = 0; index < vertices.length; index += 3) {
642
+ minimum.x = Math.min(minimum.x, vertices[index]);
643
+ maximum.x = Math.max(maximum.x, vertices[index]);
644
+ minimum.y = Math.min(minimum.y, vertices[index + 1]);
645
+ maximum.y = Math.max(maximum.y, vertices[index + 1]);
646
+ minimum.z = Math.min(minimum.z, vertices[index + 2]);
647
+ maximum.z = Math.max(maximum.z, vertices[index + 2]);
648
+ }
649
+ binding = { ...binding, preparationVersion: "1", bounds: { min: minimum, max: maximum }, vertices: vertices.length / 3, triangles: (indices?.length ?? 0) / 3 };
650
+ try {
651
+ await decodePreparedGameCollider3D(bytes, gameAssetBinding3D.options[1].parse(binding));
652
+ }
653
+ catch (error) {
654
+ throwApiError(ApiErrorCode.INVALID_INPUT, error instanceof Error ? error.message : "Prepared collider is invalid");
655
+ }
656
+ }
415
657
  if (input.baseRevision && game.current_revision !== input.baseRevision) {
416
658
  throwApiError(ApiErrorCode.ALREADY_EXISTS, "Game was modified concurrently");
417
659
  }
@@ -421,36 +663,12 @@ export const gamesRouter = router({
421
663
  if (input.baseUpdatedAt && draft.game.draft_updated_at !== input.baseUpdatedAt) {
422
664
  throwApiError(ApiErrorCode.ALREADY_EXISTS, "Game draft was modified concurrently");
423
665
  }
424
- if (candidateRow && candidateRow.id !== game.workspace_id) {
425
- await workspace.write(path, bytes, contentType);
426
- }
427
- const installed = (await Asset.create({
428
- user_id: ctx.userId,
429
- project_id: game.project_id,
430
- parent_id: ctx.userId,
431
- name: `${input.slot}.${extension}`,
432
- content_type: contentType,
433
- size: bytes.byteLength,
434
- metadata: { game_source_asset_id: input.binding.assetId, game_digest: digest }
435
- }));
436
- const storage = getAssetAdapter();
437
- const key = getAssetStorageKey(ctx.userId, installed.id, contentType);
438
- let uri = null;
439
- try {
440
- uri = await storage.store(key, bytes, contentType);
441
- const saved = await Game.updateDraft(ctx.userId, game.id, draft.game.draft_updated_at, [{
442
- op: "bind_asset", slot: input.slot, binding: { ...input.binding, assetId: installed.id }
443
- }], workspace, { actor: "user" });
444
- if (!saved)
445
- throwApiError(ApiErrorCode.ALREADY_EXISTS, "Game draft was modified concurrently");
446
- return { game: info(saved.game), document: saved.document };
447
- }
448
- catch (error) {
449
- if (uri)
450
- await storage.delete(uri);
451
- await installed.delete();
452
- throw error;
666
+ const targetBinding = draft.document.schemaVersion === 3 ? gameAssetBinding3D.safeParse(binding) :
667
+ gameAssetBinding.safeParse(binding);
668
+ if (!targetBinding.success || draft.document.schemaVersion !== 3 && (binding.mediaKind === "model" || binding.mediaKind === "collider")) {
669
+ throwApiError(ApiErrorCode.INVALID_INPUT, "Asset binding does not match the game dimension");
453
670
  }
671
+ return persistGameAsset(ctx.userId, game, workspace, draft.game.draft_updated_at, input.slot, targetBinding.data, bytes, extension, contentType);
454
672
  })
455
673
  });
456
674
  //# sourceMappingURL=games.js.map