@mnbroatch/boardgame.io 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (296) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +102 -0
  3. package/ai/package.json +7 -0
  4. package/client/package.json +7 -0
  5. package/core/package.json +7 -0
  6. package/debug/package.json +7 -0
  7. package/dist/boardgameio.es.js +14238 -0
  8. package/dist/boardgameio.js +14277 -0
  9. package/dist/boardgameio.min.js +16 -0
  10. package/dist/cjs/Debug-9d141c06.js +9586 -0
  11. package/dist/cjs/ai-e0e8a768.js +377 -0
  12. package/dist/cjs/ai.js +20 -0
  13. package/dist/cjs/client-76dec77b.js +258 -0
  14. package/dist/cjs/client-a22d7500.js +524 -0
  15. package/dist/cjs/client.js +26 -0
  16. package/dist/cjs/core.js +52 -0
  17. package/dist/cjs/debug.js +18 -0
  18. package/dist/cjs/filter-player-view-bb02e2f6.js +89 -0
  19. package/dist/cjs/initialize-267fcd69.js +61 -0
  20. package/dist/cjs/internal.js +25 -0
  21. package/dist/cjs/master-2904879d.js +320 -0
  22. package/dist/cjs/master.js +18 -0
  23. package/dist/cjs/multiplayer.js +23 -0
  24. package/dist/cjs/plugin-random-7425844d.js +229 -0
  25. package/dist/cjs/plugins.js +59 -0
  26. package/dist/cjs/react-native.js +182 -0
  27. package/dist/cjs/react.js +727 -0
  28. package/dist/cjs/reducer-16eec232.js +1203 -0
  29. package/dist/cjs/server.js +4087 -0
  30. package/dist/cjs/socketio-7a0837eb.js +478 -0
  31. package/dist/cjs/testing.js +30 -0
  32. package/dist/cjs/transport-b1874dfa.js +37 -0
  33. package/dist/cjs/turn-order-b2ff8740.js +1136 -0
  34. package/dist/cjs/util-fcfd8fb8.js +140 -0
  35. package/dist/esm/Debug-0141fe2d.js +9577 -0
  36. package/dist/esm/ai-5c06e761.js +371 -0
  37. package/dist/esm/ai.js +8 -0
  38. package/dist/esm/client-2e653027.js +522 -0
  39. package/dist/esm/client-5f57c3f2.js +255 -0
  40. package/dist/esm/client.js +16 -0
  41. package/dist/esm/core.js +40 -0
  42. package/dist/esm/debug.js +10 -0
  43. package/dist/esm/filter-player-view-2c6cc96f.js +87 -0
  44. package/dist/esm/initialize-11d626ca.js +59 -0
  45. package/dist/esm/internal.js +10 -0
  46. package/dist/esm/master-fa8f2e43.js +318 -0
  47. package/dist/esm/master.js +10 -0
  48. package/dist/esm/multiplayer.js +14 -0
  49. package/dist/esm/plugin-random-087f861e.js +226 -0
  50. package/dist/esm/plugins.js +55 -0
  51. package/dist/esm/react-native.js +173 -0
  52. package/dist/esm/react.js +716 -0
  53. package/dist/esm/reducer-c46da7e5.js +1198 -0
  54. package/dist/esm/socketio-c22ffa65.js +455 -0
  55. package/dist/esm/testing.js +26 -0
  56. package/dist/esm/transport-ce07b771.js +35 -0
  57. package/dist/esm/turn-order-376d315e.js +1091 -0
  58. package/dist/esm/util-b6147cef.js +135 -0
  59. package/dist/types/packages/ai.d.ts +5 -0
  60. package/dist/types/packages/client.d.ts +3 -0
  61. package/dist/types/packages/core.d.ts +5 -0
  62. package/dist/types/packages/debug.d.ts +2 -0
  63. package/dist/types/packages/internal.d.ts +8 -0
  64. package/dist/types/packages/master.d.ts +2 -0
  65. package/dist/types/packages/multiplayer.d.ts +3 -0
  66. package/dist/types/packages/plugins.d.ts +3 -0
  67. package/dist/types/packages/react-native.d.ts +2 -0
  68. package/dist/types/packages/react.d.ts +3 -0
  69. package/dist/types/packages/server.d.ts +6 -0
  70. package/dist/types/packages/testing.d.ts +1 -0
  71. package/dist/types/src/ai/ai.d.ts +53 -0
  72. package/dist/types/src/ai/ai.test.d.ts +1 -0
  73. package/dist/types/src/ai/bot.d.ts +40 -0
  74. package/dist/types/src/ai/mcts-bot.d.ts +60 -0
  75. package/dist/types/src/ai/random-bot.d.ts +27 -0
  76. package/dist/types/src/client/client.d.ts +104 -0
  77. package/dist/types/src/client/client.test.d.ts +1 -0
  78. package/dist/types/src/client/debug/tests/debug.test.d.ts +1 -0
  79. package/dist/types/src/client/manager.d.ts +61 -0
  80. package/dist/types/src/client/react.d.ts +75 -0
  81. package/dist/types/src/client/react.ssr.test.d.ts +4 -0
  82. package/dist/types/src/client/react.test.d.ts +1 -0
  83. package/dist/types/src/client/transport/dummy.d.ts +18 -0
  84. package/dist/types/src/client/transport/local.d.ts +59 -0
  85. package/dist/types/src/client/transport/local.test.d.ts +1 -0
  86. package/dist/types/src/client/transport/socketio.d.ts +45 -0
  87. package/dist/types/src/client/transport/socketio.test.d.ts +1 -0
  88. package/dist/types/src/client/transport/transport.d.ts +50 -0
  89. package/dist/types/src/client/transport/transport.test.d.ts +1 -0
  90. package/dist/types/src/core/action-creators.d.ts +144 -0
  91. package/dist/types/src/core/action-types.d.ts +10 -0
  92. package/dist/types/src/core/backwards-compatibility.d.ts +12 -0
  93. package/dist/types/src/core/constants.d.ts +6 -0
  94. package/dist/types/src/core/errors.d.ts +15 -0
  95. package/dist/types/src/core/flow.d.ts +28 -0
  96. package/dist/types/src/core/flow.test.d.ts +1 -0
  97. package/dist/types/src/core/game-methods.d.ts +9 -0
  98. package/dist/types/src/core/game.d.ts +26 -0
  99. package/dist/types/src/core/game.test.d.ts +1 -0
  100. package/dist/types/src/core/initialize.d.ts +9 -0
  101. package/dist/types/src/core/logger.d.ts +2 -0
  102. package/dist/types/src/core/player-view.d.ts +7 -0
  103. package/dist/types/src/core/player-view.test.d.ts +1 -0
  104. package/dist/types/src/core/reducer.d.ts +155 -0
  105. package/dist/types/src/core/reducer.test.d.ts +1 -0
  106. package/dist/types/src/core/turn-order.d.ts +179 -0
  107. package/dist/types/src/core/turn-order.test.d.ts +8 -0
  108. package/dist/types/src/lobby/client.d.ts +194 -0
  109. package/dist/types/src/lobby/client.test.d.ts +1 -0
  110. package/dist/types/src/lobby/connection.d.ts +44 -0
  111. package/dist/types/src/lobby/connection.test.d.ts +1 -0
  112. package/dist/types/src/lobby/create-match-form.d.ts +26 -0
  113. package/dist/types/src/lobby/login-form.d.ts +23 -0
  114. package/dist/types/src/lobby/match-instance.d.ts +31 -0
  115. package/dist/types/src/lobby/react.d.ts +113 -0
  116. package/dist/types/src/lobby/react.ssr.test.d.ts +4 -0
  117. package/dist/types/src/lobby/react.test.d.ts +1 -0
  118. package/dist/types/src/master/filter-player-view.d.ts +96 -0
  119. package/dist/types/src/master/filter-player-view.test.d.ts +1 -0
  120. package/dist/types/src/master/master.d.ts +94 -0
  121. package/dist/types/src/master/master.test.d.ts +1 -0
  122. package/dist/types/src/plugins/events/events.d.ts +54 -0
  123. package/dist/types/src/plugins/events/events.test.d.ts +1 -0
  124. package/dist/types/src/plugins/main.d.ts +75 -0
  125. package/dist/types/src/plugins/main.test.d.ts +1 -0
  126. package/dist/types/src/plugins/plugin-events.d.ts +5 -0
  127. package/dist/types/src/plugins/plugin-immer.d.ts +7 -0
  128. package/dist/types/src/plugins/plugin-immer.test.d.ts +1 -0
  129. package/dist/types/src/plugins/plugin-log.d.ts +14 -0
  130. package/dist/types/src/plugins/plugin-log.test.d.ts +1 -0
  131. package/dist/types/src/plugins/plugin-player.d.ts +29 -0
  132. package/dist/types/src/plugins/plugin-player.test.d.ts +1 -0
  133. package/dist/types/src/plugins/plugin-random.d.ts +4 -0
  134. package/dist/types/src/plugins/plugin-serializable.d.ts +7 -0
  135. package/dist/types/src/plugins/plugin-serializable.test.d.ts +1 -0
  136. package/dist/types/src/plugins/random/random.alea.d.ts +19 -0
  137. package/dist/types/src/plugins/random/random.d.ts +54 -0
  138. package/dist/types/src/plugins/random/random.test.d.ts +1 -0
  139. package/dist/types/src/server/api.d.ts +13 -0
  140. package/dist/types/src/server/api.test.d.ts +1 -0
  141. package/dist/types/src/server/auth.d.ts +38 -0
  142. package/dist/types/src/server/auth.test.d.ts +1 -0
  143. package/dist/types/src/server/cors.d.ts +4 -0
  144. package/dist/types/src/server/cors.test.d.ts +1 -0
  145. package/dist/types/src/server/db/base.d.ts +192 -0
  146. package/dist/types/src/server/db/flatfile.d.ts +44 -0
  147. package/dist/types/src/server/db/flatfile.test.d.ts +1 -0
  148. package/dist/types/src/server/db/index.d.ts +4 -0
  149. package/dist/types/src/server/db/index.test.d.ts +1 -0
  150. package/dist/types/src/server/db/inmemory.d.ts +43 -0
  151. package/dist/types/src/server/db/inmemory.test.d.ts +1 -0
  152. package/dist/types/src/server/db/localstorage.d.ts +7 -0
  153. package/dist/types/src/server/db/localstorage.test.d.ts +1 -0
  154. package/dist/types/src/server/index.d.ts +68 -0
  155. package/dist/types/src/server/index.test.d.ts +1 -0
  156. package/dist/types/src/server/transport/pubsub/generic-pub-sub.d.ts +6 -0
  157. package/dist/types/src/server/transport/pubsub/in-memory-pub-sub.d.ts +7 -0
  158. package/dist/types/src/server/transport/pubsub/in-memory-pub-sub.test.d.ts +1 -0
  159. package/dist/types/src/server/transport/socketio-simultaneous.test.d.ts +1 -0
  160. package/dist/types/src/server/transport/socketio.d.ts +65 -0
  161. package/dist/types/src/server/transport/socketio.test.d.ts +1 -0
  162. package/dist/types/src/server/util.d.ts +35 -0
  163. package/dist/types/src/testing/mock-random.d.ts +15 -0
  164. package/dist/types/src/testing/mock-random.test.d.ts +1 -0
  165. package/dist/types/src/types.d.ts +387 -0
  166. package/internal/package.json +7 -0
  167. package/master/package.json +7 -0
  168. package/multiplayer/package.json +7 -0
  169. package/package.json +211 -0
  170. package/plugins/package.json +7 -0
  171. package/react/package.json +7 -0
  172. package/react-native/package.json +7 -0
  173. package/server/package.json +6 -0
  174. package/src/ai/ai.test.ts +433 -0
  175. package/src/ai/ai.ts +84 -0
  176. package/src/ai/bot.ts +122 -0
  177. package/src/ai/mcts-bot.ts +331 -0
  178. package/src/ai/random-bot.ts +20 -0
  179. package/src/client/client.test.ts +993 -0
  180. package/src/client/client.ts +588 -0
  181. package/src/client/debug/Debug.svelte +239 -0
  182. package/src/client/debug/Menu.svelte +65 -0
  183. package/src/client/debug/ai/AI.svelte +215 -0
  184. package/src/client/debug/ai/Options.svelte +48 -0
  185. package/src/client/debug/info/Info.svelte +22 -0
  186. package/src/client/debug/info/Item.svelte +24 -0
  187. package/src/client/debug/log/Log.svelte +157 -0
  188. package/src/client/debug/log/LogEvent.svelte +149 -0
  189. package/src/client/debug/log/LogMetadata.svelte +7 -0
  190. package/src/client/debug/log/PhaseMarker.svelte +27 -0
  191. package/src/client/debug/log/TurnMarker.svelte +23 -0
  192. package/src/client/debug/main/ClientSwitcher.svelte +59 -0
  193. package/src/client/debug/main/Controls.svelte +58 -0
  194. package/src/client/debug/main/Hotkey.svelte +84 -0
  195. package/src/client/debug/main/InteractiveFunction.svelte +85 -0
  196. package/src/client/debug/main/Main.svelte +121 -0
  197. package/src/client/debug/main/Move.svelte +68 -0
  198. package/src/client/debug/main/PlayerInfo.svelte +70 -0
  199. package/src/client/debug/mcts/Action.svelte +22 -0
  200. package/src/client/debug/mcts/MCTS.svelte +78 -0
  201. package/src/client/debug/mcts/Table.svelte +98 -0
  202. package/src/client/debug/tests/JSONTree.mock.svelte +3 -0
  203. package/src/client/debug/tests/debug.test.ts +183 -0
  204. package/src/client/debug/utils/shortcuts.js +50 -0
  205. package/src/client/debug/utils/shortcuts.test.js +49 -0
  206. package/src/client/manager.ts +177 -0
  207. package/src/client/react-native.js +136 -0
  208. package/src/client/react-native.test.js +229 -0
  209. package/src/client/react.ssr.test.tsx +24 -0
  210. package/src/client/react.test.tsx +213 -0
  211. package/src/client/react.tsx +192 -0
  212. package/src/client/transport/dummy.ts +19 -0
  213. package/src/client/transport/local.test.ts +353 -0
  214. package/src/client/transport/local.ts +230 -0
  215. package/src/client/transport/socketio.test.ts +328 -0
  216. package/src/client/transport/socketio.ts +210 -0
  217. package/src/client/transport/transport.test.ts +27 -0
  218. package/src/client/transport/transport.ts +95 -0
  219. package/src/core/action-creators.ts +159 -0
  220. package/src/core/action-types.ts +18 -0
  221. package/src/core/backwards-compatibility.ts +23 -0
  222. package/src/core/constants.ts +6 -0
  223. package/src/core/errors.ts +35 -0
  224. package/src/core/flow.test.ts +2433 -0
  225. package/src/core/flow.ts +897 -0
  226. package/src/core/game-methods.ts +9 -0
  227. package/src/core/game.test.ts +286 -0
  228. package/src/core/game.ts +114 -0
  229. package/src/core/initialize.ts +77 -0
  230. package/src/core/logger.test.js +90 -0
  231. package/src/core/logger.ts +18 -0
  232. package/src/core/player-view.test.ts +50 -0
  233. package/src/core/player-view.ts +39 -0
  234. package/src/core/reducer.test.ts +991 -0
  235. package/src/core/reducer.ts +532 -0
  236. package/src/core/turn-order.test.ts +1123 -0
  237. package/src/core/turn-order.ts +473 -0
  238. package/src/lobby/client.test.ts +385 -0
  239. package/src/lobby/client.ts +358 -0
  240. package/src/lobby/connection.test.ts +207 -0
  241. package/src/lobby/connection.ts +162 -0
  242. package/src/lobby/create-match-form.tsx +122 -0
  243. package/src/lobby/login-form.tsx +75 -0
  244. package/src/lobby/match-instance.tsx +135 -0
  245. package/src/lobby/react.ssr.test.tsx +22 -0
  246. package/src/lobby/react.test.tsx +594 -0
  247. package/src/lobby/react.tsx +402 -0
  248. package/src/master/filter-player-view.test.ts +381 -0
  249. package/src/master/filter-player-view.ts +102 -0
  250. package/src/master/master.test.ts +1068 -0
  251. package/src/master/master.ts +492 -0
  252. package/src/plugins/events/events.test.ts +108 -0
  253. package/src/plugins/events/events.ts +209 -0
  254. package/src/plugins/main.test.ts +411 -0
  255. package/src/plugins/main.ts +314 -0
  256. package/src/plugins/plugin-events.ts +40 -0
  257. package/src/plugins/plugin-immer.test.ts +86 -0
  258. package/src/plugins/plugin-immer.ts +37 -0
  259. package/src/plugins/plugin-log.test.ts +37 -0
  260. package/src/plugins/plugin-log.ts +40 -0
  261. package/src/plugins/plugin-player.test.ts +172 -0
  262. package/src/plugins/plugin-player.ts +100 -0
  263. package/src/plugins/plugin-random.ts +40 -0
  264. package/src/plugins/plugin-serializable.test.ts +40 -0
  265. package/src/plugins/plugin-serializable.ts +55 -0
  266. package/src/plugins/random/random.alea.ts +109 -0
  267. package/src/plugins/random/random.test.ts +167 -0
  268. package/src/plugins/random/random.ts +198 -0
  269. package/src/server/api.test.ts +1699 -0
  270. package/src/server/api.ts +527 -0
  271. package/src/server/auth.test.ts +275 -0
  272. package/src/server/auth.ts +89 -0
  273. package/src/server/cors.test.ts +121 -0
  274. package/src/server/cors.ts +7 -0
  275. package/src/server/db/base.ts +296 -0
  276. package/src/server/db/flatfile.test.ts +221 -0
  277. package/src/server/db/flatfile.ts +228 -0
  278. package/src/server/db/index.test.ts +8 -0
  279. package/src/server/db/index.ts +12 -0
  280. package/src/server/db/inmemory.test.ts +143 -0
  281. package/src/server/db/inmemory.ts +143 -0
  282. package/src/server/db/localstorage.test.ts +73 -0
  283. package/src/server/db/localstorage.ts +44 -0
  284. package/src/server/index.test.ts +265 -0
  285. package/src/server/index.ts +175 -0
  286. package/src/server/transport/pubsub/generic-pub-sub.ts +11 -0
  287. package/src/server/transport/pubsub/in-memory-pub-sub.test.ts +47 -0
  288. package/src/server/transport/pubsub/in-memory-pub-sub.ts +28 -0
  289. package/src/server/transport/socketio-simultaneous.test.ts +603 -0
  290. package/src/server/transport/socketio.test.ts +303 -0
  291. package/src/server/transport/socketio.ts +279 -0
  292. package/src/server/util.ts +85 -0
  293. package/src/testing/mock-random.test.ts +45 -0
  294. package/src/testing/mock-random.ts +27 -0
  295. package/src/types.ts +511 -0
  296. package/testing/package.json +7 -0
@@ -0,0 +1,121 @@
1
+ <script>
2
+ export let client;
3
+ export let clientManager;
4
+ export let ToggleVisibility;
5
+
6
+ import { onDestroy } from 'svelte';
7
+ import JSONTree from 'svelte-json-tree-auto/src/Root.svelte';
8
+ import ClientSwitcher from './ClientSwitcher.svelte';
9
+ import Move from './Move.svelte';
10
+ import Controls from './Controls.svelte';
11
+ import PlayerInfo from './PlayerInfo.svelte';
12
+ import { AssignShortcuts } from '../utils/shortcuts';
13
+
14
+ const shortcuts = AssignShortcuts(client.moves, 'mlia');
15
+
16
+ function SanitizeCtx(ctx) {
17
+ let r = {};
18
+ for (const key in ctx) {
19
+ if (!key.startsWith('_')) {
20
+ r[key] = ctx[key];
21
+ }
22
+ }
23
+ return r;
24
+ }
25
+
26
+ let { playerID, moves, events } = client;
27
+ let ctx = {};
28
+ let G = {};
29
+ const unsubscribe = client.subscribe((state) => {
30
+ if (state) ({ G, ctx } = state);
31
+ ({ playerID, moves, events } = client);
32
+ });
33
+
34
+ onDestroy(unsubscribe);
35
+ </script>
36
+
37
+ <style>
38
+ .tree {
39
+ --json-tree-font-family: monospace;
40
+ --json-tree-font-size: 14px;
41
+ --json-tree-null-color: #757575;
42
+ }
43
+
44
+ .label {
45
+ margin-bottom: 0;
46
+ text-transform: none;
47
+ }
48
+
49
+ h3 {
50
+ text-transform: uppercase;
51
+ }
52
+
53
+ ul {
54
+ padding-left: 0;
55
+ }
56
+
57
+ li {
58
+ list-style: none;
59
+ margin: 0;
60
+ margin-bottom: 5px;
61
+ }
62
+ </style>
63
+
64
+ <section>
65
+ <h3>Controls</h3>
66
+ <Controls {client} {ToggleVisibility} />
67
+ </section>
68
+
69
+ <section>
70
+ <h3>Players</h3>
71
+ <PlayerInfo
72
+ on:change={(e) => clientManager.switchPlayerID(e.detail.playerID)}
73
+ ctx={ctx}
74
+ playerID={playerID}
75
+ />
76
+ </section>
77
+
78
+ <section>
79
+ <h3>Moves</h3>
80
+ <ul>
81
+ {#each Object.entries(moves) as [name, fn]}
82
+ <li>
83
+ <Move shortcut={shortcuts[name]} {fn} {name} />
84
+ </li>
85
+ {/each}
86
+ </ul>
87
+ </section>
88
+
89
+ <section>
90
+ <h3>Events</h3>
91
+
92
+ <ul>
93
+ {#if ctx.activePlayers && events.endStage}
94
+ <li>
95
+ <Move name="endStage" shortcut={7} fn={events.endStage} />
96
+ </li>
97
+ {/if}
98
+ {#if events.endTurn}
99
+ <li>
100
+ <Move name="endTurn" shortcut={8} fn={events.endTurn} />
101
+ </li>
102
+ {/if}
103
+ {#if ctx.phase && events.endPhase}
104
+ <li>
105
+ <Move name="endPhase" shortcut={9} fn={events.endPhase} />
106
+ </li>
107
+ {/if}
108
+ </ul>
109
+ </section>
110
+
111
+ <section class="tree">
112
+ <h3 class="label">G</h3>
113
+ <JSONTree value={G} />
114
+ </section>
115
+
116
+ <section class="tree">
117
+ <h3 class="label">ctx</h3>
118
+ <JSONTree value={SanitizeCtx(ctx)} />
119
+ </section>
120
+
121
+ <ClientSwitcher {clientManager} />
@@ -0,0 +1,68 @@
1
+ <script>
2
+ export let shortcut;
3
+ export let name;
4
+ export let fn;
5
+
6
+ import Hotkey from './Hotkey.svelte';
7
+ import InteractiveFunction from './InteractiveFunction.svelte';
8
+ import * as logger from '../../../core/logger';
9
+ import {getContext} from 'svelte';
10
+
11
+ const {disableHotkeys} = getContext('hotkeys');
12
+
13
+ let error = '';
14
+ let focus = false;
15
+ let enterArg = false;
16
+ let active = false;
17
+
18
+ function Activate() {
19
+ disableHotkeys.set(true);
20
+ active = true;
21
+ }
22
+
23
+ function Deactivate() {
24
+ disableHotkeys.set(false);
25
+ error = '';
26
+ active = false;
27
+ }
28
+
29
+ function Submit(e) {
30
+ error = '';
31
+ Deactivate();
32
+ fn.apply(this, e.detail);
33
+ }
34
+
35
+ function Error(e) {
36
+ error = e.detail;
37
+ logger.error(e.detail);
38
+ }
39
+ </script>
40
+
41
+ <style>
42
+ .move-error {
43
+ color: #a00;
44
+ font-weight: bold;
45
+ }
46
+
47
+ .wrapper {
48
+ display: flex;
49
+ flex-direction: row;
50
+ align-items: center;
51
+ }
52
+ </style>
53
+
54
+ <div>
55
+ <div class="wrapper">
56
+ <Hotkey value={shortcut} onPress={Activate} />
57
+ <InteractiveFunction
58
+ {Activate}
59
+ {Deactivate}
60
+ {name}
61
+ {active}
62
+ on:submit={Submit}
63
+ on:error={Error} />
64
+ </div>
65
+ {#if error}
66
+ <span class="move-error">{error}</span>
67
+ {/if}
68
+ </div>
@@ -0,0 +1,70 @@
1
+ <script>
2
+ export let ctx;
3
+ export let playerID;
4
+
5
+ import { createEventDispatcher } from 'svelte';
6
+
7
+ const dispatch = createEventDispatcher();
8
+ function OnClick(player) {
9
+ if (player == playerID) {
10
+ dispatch("change", { playerID: null });
11
+ } else {
12
+ dispatch("change", { playerID: player });
13
+ }
14
+ }
15
+
16
+ function playerLabel(player) {
17
+ const properties = [];
18
+ if (player == ctx.currentPlayer) properties.push('current');
19
+ if (player == playerID) properties.push('active');
20
+ let label = `Player ${player}`;
21
+ if (properties.length) label += ` (${properties.join(', ')})`;
22
+ return label;
23
+ }
24
+
25
+ let players;
26
+ $: players = ctx ? [...Array(ctx.numPlayers).keys()].map(i => i.toString()) : [];
27
+ </script>
28
+
29
+ <style>
30
+ .player-box {
31
+ display: flex;
32
+ flex-direction: row;
33
+ }
34
+
35
+ .player {
36
+ cursor: pointer;
37
+ text-align: center;
38
+ width: 30px;
39
+ height: 30px;
40
+ line-height: 30px;
41
+ background: #eee;
42
+ border: 3px solid #fefefe;
43
+ box-sizing: content-box;
44
+ padding: 0;
45
+ }
46
+
47
+ .player.current {
48
+ background: #555;
49
+ color: #eee;
50
+ font-weight: bold;
51
+ }
52
+
53
+ .player.active {
54
+ border: 3px solid #ff7f50;
55
+ }
56
+ </style>
57
+
58
+ <div class="player-box">
59
+ {#each players as player}
60
+ <button
61
+ class="player"
62
+ class:current={player == ctx.currentPlayer}
63
+ class:active={player == playerID}
64
+ on:click={() => OnClick(player)}
65
+ aria-label={playerLabel(player)}
66
+ >
67
+ {player}
68
+ </button>
69
+ {/each}
70
+ </div>
@@ -0,0 +1,22 @@
1
+ <script>
2
+ export let action;
3
+
4
+ let text;
5
+
6
+ $: {
7
+ const { type, args } = action.payload;
8
+ const argsFormatted = (args || []).join(',');
9
+ text = `${type}(${argsFormatted})`;
10
+ }
11
+ </script>
12
+
13
+ <style>
14
+ div {
15
+ white-space: nowrap;
16
+ text-overflow: ellipsis;
17
+ overflow: hidden;
18
+ max-width: 500px;
19
+ }
20
+ </style>
21
+
22
+ <div alt={text}>{text}</div>
@@ -0,0 +1,78 @@
1
+ <script>
2
+ export let metadata;
3
+
4
+ import Arrow from 'svelte-icons/fa/FaArrowAltCircleDown.svelte'
5
+
6
+ let nodes = [];
7
+ let prevNodes = [];
8
+ let preview = null;
9
+
10
+ import Table from './Table.svelte';
11
+
12
+ $: {
13
+ prevNodes = [];
14
+ nodes = [{ node: metadata }];
15
+ }
16
+
17
+ function SelectNode({ node, selectedIndex }, i) {
18
+ preview = null;
19
+ nodes[i].selectedIndex = selectedIndex;
20
+ nodes = [...nodes.slice(0, i + 1), { node }];
21
+ }
22
+
23
+ function PreviewNode({ node }, i) {
24
+ preview = node;
25
+ }
26
+ </script>
27
+
28
+ <style>
29
+ .visualizer {
30
+ display: flex;
31
+ flex-direction: column;
32
+ align-items: center;
33
+ padding: 50px;
34
+ }
35
+
36
+ .preview {
37
+ opacity: 0.5;
38
+ }
39
+
40
+ .icon {
41
+ color: #777;
42
+ width: 32px;
43
+ height: 32px;
44
+ margin-bottom: 20px;
45
+ }
46
+ </style>
47
+
48
+ <div class="visualizer">
49
+ {#each nodes as { node, selectedIndex }, i}
50
+ {#if i !== 0}
51
+ <div class="icon">
52
+ <Arrow/>
53
+ </div>
54
+ {/if}
55
+
56
+ <section>
57
+ {#if i === nodes.length - 1}
58
+ <Table on:select={e => SelectNode(e.detail, i)}
59
+ on:preview={e => PreviewNode(e.detail, i)}
60
+ root={node}/>
61
+ {:else}
62
+ <Table on:select={e => SelectNode(e.detail, i)}
63
+ root={node}
64
+ selectedIndex={selectedIndex}/>
65
+ {/if}
66
+ </section>
67
+ {/each}
68
+
69
+ {#if preview}
70
+ <div class="icon">
71
+ <Arrow/>
72
+ </div>
73
+
74
+ <section class="preview">
75
+ <Table root={preview}/>
76
+ </section>
77
+ {/if}
78
+ </div>
@@ -0,0 +1,98 @@
1
+ <script>
2
+ export let root;
3
+ export let selectedIndex = null;
4
+
5
+ import Action from './Action.svelte';
6
+ import { createEventDispatcher } from 'svelte';
7
+
8
+ const dispatch = createEventDispatcher();
9
+
10
+ let parents = [];
11
+ let children = [];
12
+
13
+ $: {
14
+ let t = root;
15
+ parents = [];
16
+ while (t.parent) {
17
+ const parent = t.parent;
18
+ const { type, args } = t.parentAction.payload;
19
+ const argsFormatted = (args || []).join(',');
20
+ const arrowText = `${type}(${argsFormatted})`;
21
+ parents.push({ parent, arrowText });
22
+ t = parent;
23
+ }
24
+ parents.reverse();
25
+
26
+ children = [...root.children]
27
+ .sort((a, b) => (a.visits < b.visits ? 1 : -1))
28
+ .slice(0, 50);
29
+ }
30
+
31
+ function Select(node, i) {
32
+ dispatch('select', { node, selectedIndex: i });
33
+ }
34
+
35
+ function Preview(node, i) {
36
+ if (selectedIndex === null) {
37
+ dispatch('preview', { node });
38
+ }
39
+ }
40
+ </script>
41
+
42
+ <style>
43
+ table {
44
+ font-size: 12px;
45
+ border-collapse: collapse;
46
+ border: 1px solid #ddd;
47
+ padding: 0;
48
+ }
49
+
50
+ tr {
51
+ cursor: pointer;
52
+ }
53
+
54
+ tr:hover td {
55
+ background: #eee;
56
+ }
57
+
58
+ tr.selected td {
59
+ background: #eee;
60
+ }
61
+
62
+ td {
63
+ padding: 10px;
64
+ height: 10px;
65
+ line-height: 10px;
66
+ font-size: 12px;
67
+ border: none;
68
+ }
69
+
70
+ th {
71
+ background: #888;
72
+ color: #fff;
73
+ padding: 10px;
74
+ text-align: center;
75
+ }
76
+ </style>
77
+
78
+ <table>
79
+ <thead>
80
+ <th>Value</th>
81
+ <th>Visits</th>
82
+ <th>Action</th>
83
+ </thead>
84
+
85
+ <tbody>
86
+ {#each children as child, i}
87
+ <tr class:clickable={children.length > 0}
88
+ class:selected={i === selectedIndex}
89
+ on:click={() => Select(child, i)}
90
+ on:mouseout={() => Preview(null, i)}
91
+ on:mouseover={() => Preview(child, i)}>
92
+ <td>{child.value}</td>
93
+ <td>{child.visits}</td>
94
+ <td><Action action={child.parentAction}/></td>
95
+ </tr>
96
+ {/each}
97
+ </tbody>
98
+ </table>
@@ -0,0 +1,3 @@
1
+ <script>
2
+ export let value;
3
+ </script>
@@ -0,0 +1,183 @@
1
+ /*
2
+ * Copyright 2019 The boardgame.io Authors
3
+ *
4
+ * Use of this source code is governed by a MIT-style
5
+ * license that can be found in the LICENSE file or at
6
+ * https://opensource.org/licenses/MIT.
7
+ */
8
+
9
+ import '@testing-library/jest-dom/extend-expect';
10
+ import { screen, fireEvent, waitFor } from '@testing-library/svelte';
11
+ import { Client } from '../../client';
12
+ import { Local } from '../../transport/local';
13
+
14
+ test('sanity', () => {
15
+ const client = Client({ game: {} });
16
+ client.start();
17
+ expect(screen.getByText('Controls')).toBeInTheDocument();
18
+ expect(screen.getByText('Players')).toBeInTheDocument();
19
+ expect(screen.getByText('G')).toBeInTheDocument();
20
+ expect(screen.getByText('ctx')).toBeInTheDocument();
21
+ client.stop();
22
+ });
23
+
24
+ test('switching panels', async () => {
25
+ const client = Client({ game: {} });
26
+ client.start();
27
+
28
+ // switch to info tab
29
+ const InfoTab = screen.getByText('Info');
30
+ await fireEvent.click(InfoTab);
31
+ expect(screen.getByText('matchID')).toBeInTheDocument();
32
+ expect(screen.getByText('playerID')).toBeInTheDocument();
33
+ expect(screen.getByText('isActive')).toBeInTheDocument();
34
+
35
+ // switch to AI tab
36
+ const AITab = screen.getByText('AI');
37
+ await fireEvent.click(AITab);
38
+ expect(screen.getByText('No bots available.')).toBeInTheDocument();
39
+ client.stop();
40
+ });
41
+
42
+ test('visibility toggle', async () => {
43
+ const client = Client({ game: {} });
44
+ client.start();
45
+
46
+ // Visibility toggle button & debug panel are rendered
47
+ const hideButton = screen.getByTitle('Hide Debug Panel');
48
+ expect(hideButton).toBeInTheDocument();
49
+ expect(screen.getByRole('heading', { name: 'Controls' })).toBeInTheDocument();
50
+
51
+ // Hide debug panel
52
+ await fireEvent.click(hideButton);
53
+ await waitFor(() => expect(hideButton).not.toBeInTheDocument());
54
+
55
+ // Show button is rendered & debug panel is not.
56
+ const showButton = screen.getByTitle('Show Debug Panel');
57
+ expect(showButton).toBeInTheDocument();
58
+ expect(
59
+ screen.queryByRole('heading', { name: 'Controls' })
60
+ ).not.toBeInTheDocument();
61
+
62
+ // Show debug panel
63
+ await fireEvent.click(showButton);
64
+ await waitFor(() => expect(showButton).not.toBeInTheDocument());
65
+
66
+ // Hide button & debug panel are rendered.
67
+ expect(screen.getByTitle('Hide Debug Panel')).toBeInTheDocument();
68
+ expect(screen.getByRole('heading', { name: 'Controls' })).toBeInTheDocument();
69
+
70
+ client.stop();
71
+ });
72
+
73
+ test('panel options', async () => {
74
+ const client = Client({
75
+ game: {},
76
+ debug: { hideToggleButton: true, collapseOnLoad: true },
77
+ });
78
+ client.start();
79
+
80
+ const hideButton = screen.queryByTitle('Hide Debug Panel');
81
+ expect(hideButton).not.toBeInTheDocument();
82
+
83
+ expect(
84
+ screen.queryByRole('heading', { name: 'Controls' })
85
+ ).not.toBeInTheDocument();
86
+
87
+ client.stop();
88
+ });
89
+
90
+ describe('multiple clients', () => {
91
+ const client0 = Client({
92
+ game: { name: 'game1' },
93
+ playerID: '0',
94
+ matchID: 'A',
95
+ });
96
+ const multiplayer = Local();
97
+ const client1 = Client({
98
+ game: { name: 'game2' },
99
+ playerID: '0',
100
+ matchID: 'B',
101
+ multiplayer,
102
+ });
103
+ const client2 = Client({
104
+ game: { name: 'game2' },
105
+ playerID: '1',
106
+ matchID: 'B',
107
+ multiplayer,
108
+ });
109
+
110
+ beforeEach(() => {
111
+ client0.start();
112
+ client1.start();
113
+ client2.start();
114
+ });
115
+
116
+ afterEach(() => {
117
+ client0.stop();
118
+ client1.stop();
119
+ client2.stop();
120
+ });
121
+
122
+ test('switching clients', async () => {
123
+ // Check if the client switcher is displayed.
124
+ await waitFor(() => screen.getByText('Client'));
125
+ // Get the client switcher select element.
126
+ const select = screen.getByLabelText('Client');
127
+ // Check it is displaying details for the client that rendered first.
128
+ expect(
129
+ screen.getByDisplayValue('0 — playerID: "0", matchID: "A" (game1)')
130
+ ).toBeInTheDocument();
131
+ // Switch to client1.
132
+ await fireEvent.change(select, { target: { value: 1 } });
133
+ // Check the client switcher now shows details for client1.
134
+ expect(
135
+ screen.getByDisplayValue('1 — playerID: "0", matchID: "B" (game2)')
136
+ ).toBeInTheDocument();
137
+
138
+ // Switch to the info tab and check if the matchID for client1 is displayed.
139
+ const InfoTab = screen.getByText('Info');
140
+ await fireEvent.click(InfoTab);
141
+ expect(screen.getByText('"B"')).toBeInTheDocument();
142
+ });
143
+
144
+ test('switching playerID for a solo client', async () => {
145
+ expect(client0.playerID).toBe('0');
146
+ // Toggle to playerID 1 by clicking on the “1” button.
147
+ await fireEvent.click(screen.getByRole('button', { name: 'Player 1' }));
148
+ // Check client0’s playerID was updated.
149
+ expect(
150
+ screen.getByDisplayValue('0 — playerID: "1", matchID: "A" (game1)')
151
+ ).toBeInTheDocument();
152
+ expect(client0.playerID).toBe('1');
153
+ });
154
+
155
+ test('switching playerID with multiplayer clients', async () => {
156
+ expect(client1.playerID).toBe('0');
157
+ expect(client2.playerID).toBe('1');
158
+ // Switch to client1.
159
+ const select = screen.getByLabelText('Client');
160
+ await fireEvent.change(select, { target: { value: 1 } });
161
+ // Check the client switcher now shows details for client1.
162
+ expect(
163
+ screen.getByDisplayValue('1 — playerID: "0", matchID: "B" (game2)')
164
+ ).toBeInTheDocument();
165
+ // Toggle to playerID 1 by clicking on the “1” button.
166
+ await fireEvent.click(screen.getByRole('button', { name: 'Player 1' }));
167
+ // Check the client switcher now shows details for client2.
168
+ expect(
169
+ screen.getByDisplayValue('2 — playerID: "1", matchID: "B" (game2)')
170
+ ).toBeInTheDocument();
171
+ // Client playerIDs have not changed.
172
+ expect(client1.playerID).toBe('0');
173
+ expect(client2.playerID).toBe('1');
174
+ });
175
+
176
+ test('switching to current client', async () => {
177
+ const select = screen.getByLabelText('Client');
178
+ await fireEvent.change(select, { target: { value: 0 } });
179
+ expect(
180
+ screen.getByDisplayValue('0 — playerID: "1", matchID: "A" (game1)')
181
+ ).toBeInTheDocument();
182
+ });
183
+ });
@@ -0,0 +1,50 @@
1
+ /*
2
+ * Copyright 2018 The boardgame.io Authors
3
+ *
4
+ * Use of this source code is governed by a MIT-style
5
+ * license that can be found in the LICENSE file or at
6
+ * https://opensource.org/licenses/MIT.
7
+ */
8
+
9
+ export function AssignShortcuts(moveNames, blacklist) {
10
+ let shortcuts = {};
11
+
12
+ const taken = {};
13
+ for (const c of blacklist) {
14
+ taken[c] = true;
15
+ }
16
+
17
+ // Try assigning the first char of each move as the shortcut.
18
+ let t = taken;
19
+ let canUseFirstChar = true;
20
+ for (const name in moveNames) {
21
+ const shortcut = name[0];
22
+ if (t[shortcut]) {
23
+ canUseFirstChar = false;
24
+ break;
25
+ }
26
+
27
+ t[shortcut] = true;
28
+ shortcuts[name] = shortcut;
29
+ }
30
+ if (canUseFirstChar) {
31
+ return shortcuts;
32
+ }
33
+
34
+ // If those aren't unique, use a-z.
35
+ t = taken;
36
+ let next = 97;
37
+ shortcuts = {};
38
+ for (const name in moveNames) {
39
+ let shortcut = String.fromCharCode(next);
40
+
41
+ while (t[shortcut]) {
42
+ next++;
43
+ shortcut = String.fromCharCode(next);
44
+ }
45
+
46
+ t[shortcut] = true;
47
+ shortcuts[name] = shortcut;
48
+ }
49
+ return shortcuts;
50
+ }