code-battles 1.0.0

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 (129) hide show
  1. package/LICENSE.md +7 -0
  2. package/README.md +39 -0
  3. package/dist/cjs/index.js +18532 -0
  4. package/dist/cjs/styles.css +5 -0
  5. package/dist/cjs/types/CodeBattles.d.ts +10 -0
  6. package/dist/cjs/types/components/App.d.ts +7 -0
  7. package/dist/cjs/types/components/AutoScrollButton.d.ts +3 -0
  8. package/dist/cjs/types/components/LogViewer.d.ts +6 -0
  9. package/dist/cjs/types/components/Login.d.ts +3 -0
  10. package/dist/cjs/types/components/ShowLogsButtons.d.ts +8 -0
  11. package/dist/cjs/types/components/TimerAndVolume.d.ts +3 -0
  12. package/dist/cjs/types/components/TopPane.d.ts +3 -0
  13. package/dist/cjs/types/components/blocks/AdminBlock.d.ts +3 -0
  14. package/dist/cjs/types/components/blocks/Block.d.ts +8 -0
  15. package/dist/cjs/types/components/blocks/BotSelector.d.ts +10 -0
  16. package/dist/cjs/types/components/blocks/PickBotBlock.d.ts +3 -0
  17. package/dist/cjs/types/components/blocks/RunSimulationBlock.d.ts +3 -0
  18. package/dist/cjs/types/components/blocks/TournamentBlock.d.ts +8 -0
  19. package/dist/cjs/types/components/blocks/UploadBlock.d.ts +3 -0
  20. package/dist/cjs/types/components/index.d.ts +3 -0
  21. package/dist/cjs/types/components/pages/HomePage.d.ts +6 -0
  22. package/dist/cjs/types/components/pages/NotFoundPage.d.ts +3 -0
  23. package/dist/cjs/types/components/pages/RoundPage.d.ts +3 -0
  24. package/dist/cjs/types/components/pages/SettingsPage.d.ts +3 -0
  25. package/dist/cjs/types/components/pages/SimulationPage.d.ts +3 -0
  26. package/dist/cjs/types/components/pages/ViewAPIPage.d.ts +3 -0
  27. package/dist/cjs/types/configuration.d.ts +35 -0
  28. package/dist/cjs/types/hooks.d.ts +17 -0
  29. package/dist/cjs/types/index.d.ts +10 -0
  30. package/dist/cjs/types/initialize.d.ts +5 -0
  31. package/dist/cjs/types/particles.d.ts +2 -0
  32. package/dist/cjs/types/utilities.d.ts +14 -0
  33. package/dist/code_battles/__init__.py +13 -0
  34. package/dist/code_battles/battles.py +531 -0
  35. package/dist/code_battles/js.pyi +114 -0
  36. package/dist/code_battles/pyodide/ffi/__init__.pyi +2 -0
  37. package/dist/code_battles/pyscript/ffi/__init__.pyi +3 -0
  38. package/dist/code_battles/utilities.py +200 -0
  39. package/dist/esm/index.js +18528 -0
  40. package/dist/esm/styles.css +5 -0
  41. package/dist/esm/types/CodeBattles.d.ts +10 -0
  42. package/dist/esm/types/components/App.d.ts +7 -0
  43. package/dist/esm/types/components/AutoScrollButton.d.ts +3 -0
  44. package/dist/esm/types/components/LogViewer.d.ts +6 -0
  45. package/dist/esm/types/components/Login.d.ts +3 -0
  46. package/dist/esm/types/components/ShowLogsButtons.d.ts +8 -0
  47. package/dist/esm/types/components/TimerAndVolume.d.ts +3 -0
  48. package/dist/esm/types/components/TopPane.d.ts +3 -0
  49. package/dist/esm/types/components/blocks/AdminBlock.d.ts +3 -0
  50. package/dist/esm/types/components/blocks/Block.d.ts +8 -0
  51. package/dist/esm/types/components/blocks/BotSelector.d.ts +10 -0
  52. package/dist/esm/types/components/blocks/PickBotBlock.d.ts +3 -0
  53. package/dist/esm/types/components/blocks/RunSimulationBlock.d.ts +3 -0
  54. package/dist/esm/types/components/blocks/TournamentBlock.d.ts +8 -0
  55. package/dist/esm/types/components/blocks/UploadBlock.d.ts +3 -0
  56. package/dist/esm/types/components/index.d.ts +3 -0
  57. package/dist/esm/types/components/pages/HomePage.d.ts +6 -0
  58. package/dist/esm/types/components/pages/NotFoundPage.d.ts +3 -0
  59. package/dist/esm/types/components/pages/RoundPage.d.ts +3 -0
  60. package/dist/esm/types/components/pages/SettingsPage.d.ts +3 -0
  61. package/dist/esm/types/components/pages/SimulationPage.d.ts +3 -0
  62. package/dist/esm/types/components/pages/ViewAPIPage.d.ts +3 -0
  63. package/dist/esm/types/configuration.d.ts +35 -0
  64. package/dist/esm/types/hooks.d.ts +17 -0
  65. package/dist/esm/types/index.d.ts +10 -0
  66. package/dist/esm/types/initialize.d.ts +5 -0
  67. package/dist/esm/types/particles.d.ts +2 -0
  68. package/dist/esm/types/utilities.d.ts +14 -0
  69. package/dist/index.d.ts +44 -0
  70. package/dist/pdoc-template/custom.css +22 -0
  71. package/dist/pdoc-template/module.html.jinja2 +306 -0
  72. package/dist/pdoc-template/syntax-highlighting.css +248 -0
  73. package/dist/pyscript/codemirror-BEtcgaoQ.js +2 -0
  74. package/dist/pyscript/codemirror-BEtcgaoQ.js.map +1 -0
  75. package/dist/pyscript/codemirror_commands-DDxffOmd.js +2 -0
  76. package/dist/pyscript/codemirror_commands-DDxffOmd.js.map +1 -0
  77. package/dist/pyscript/codemirror_lang-python-CnWnFqxD.js +2 -0
  78. package/dist/pyscript/codemirror_lang-python-CnWnFqxD.js.map +1 -0
  79. package/dist/pyscript/codemirror_language-CjmvX4ix.js +2 -0
  80. package/dist/pyscript/codemirror_language-CjmvX4ix.js.map +1 -0
  81. package/dist/pyscript/codemirror_state-D1qTXrff.js +2 -0
  82. package/dist/pyscript/codemirror_state-D1qTXrff.js.map +1 -0
  83. package/dist/pyscript/codemirror_view-DVb8uYMr.js +2 -0
  84. package/dist/pyscript/codemirror_view-DVb8uYMr.js.map +1 -0
  85. package/dist/pyscript/core-CZGzC87D.js +2 -0
  86. package/dist/pyscript/core-CZGzC87D.js.map +1 -0
  87. package/dist/pyscript/core.css +1 -0
  88. package/dist/pyscript/core.js +2 -0
  89. package/dist/pyscript/core.js.map +1 -0
  90. package/dist/pyscript/deprecations-manager-B8Tn4H-t.js +2 -0
  91. package/dist/pyscript/deprecations-manager-B8Tn4H-t.js.map +1 -0
  92. package/dist/pyscript/error-Dmba-E9f.js +2 -0
  93. package/dist/pyscript/error-Dmba-E9f.js.map +1 -0
  94. package/dist/pyscript/index-S1Do43bx.js +2 -0
  95. package/dist/pyscript/index-S1Do43bx.js.map +1 -0
  96. package/dist/pyscript/mpy-BnYOGs9W.js +2 -0
  97. package/dist/pyscript/mpy-BnYOGs9W.js.map +1 -0
  98. package/dist/pyscript/py-D2NmpN63.js +2 -0
  99. package/dist/pyscript/py-D2NmpN63.js.map +1 -0
  100. package/dist/pyscript/py-editor-Czy2e-Jt.js +2 -0
  101. package/dist/pyscript/py-editor-Czy2e-Jt.js.map +1 -0
  102. package/dist/pyscript/py-terminal-w87wZryi.js +2 -0
  103. package/dist/pyscript/py-terminal-w87wZryi.js.map +1 -0
  104. package/dist/pyscript/storage.js +2 -0
  105. package/dist/pyscript/storage.js.map +1 -0
  106. package/dist/pyscript/toml-CvAfdf9_.js +3 -0
  107. package/dist/pyscript/toml-CvAfdf9_.js.map +1 -0
  108. package/dist/pyscript/toml-DiUM0_qs.js +3 -0
  109. package/dist/pyscript/toml-DiUM0_qs.js.map +1 -0
  110. package/dist/pyscript/xterm-BY7uk_OU.js +2 -0
  111. package/dist/pyscript/xterm-BY7uk_OU.js.map +1 -0
  112. package/dist/pyscript/xterm-readline-CZfBw7ic.js +2 -0
  113. package/dist/pyscript/xterm-readline-CZfBw7ic.js.map +1 -0
  114. package/dist/pyscript/xterm.css +7 -0
  115. package/dist/pyscript/xterm_addon-fit--gyF3PcZ.js +2 -0
  116. package/dist/pyscript/xterm_addon-fit--gyF3PcZ.js.map +1 -0
  117. package/dist/pyscript/xterm_addon-web-links-Cnej-nJ6.js +2 -0
  118. package/dist/pyscript/xterm_addon-web-links-Cnej-nJ6.js.map +1 -0
  119. package/dist/pyscript/zip-DrwYHuF9.js +2 -0
  120. package/dist/pyscript/zip-DrwYHuF9.js.map +1 -0
  121. package/dist/webfonts/fa-brands-400.ttf +0 -0
  122. package/dist/webfonts/fa-brands-400.woff2 +0 -0
  123. package/dist/webfonts/fa-regular-400.ttf +0 -0
  124. package/dist/webfonts/fa-regular-400.woff2 +0 -0
  125. package/dist/webfonts/fa-solid-900.ttf +0 -0
  126. package/dist/webfonts/fa-solid-900.woff2 +0 -0
  127. package/dist/webfonts/fa-v4compatibility.ttf +0 -0
  128. package/dist/webfonts/fa-v4compatibility.woff2 +0 -0
  129. package/package.json +70 -0
@@ -0,0 +1,200 @@
1
+ """Generic useful utilities for creating games with PyScript."""
2
+
3
+ import asyncio
4
+ from typing import Callable, List, Union
5
+ from enum import Enum
6
+
7
+ from js import Element, Image, window
8
+
9
+
10
+ class Alignment(Enum):
11
+ CENTER = 0
12
+ TOP_LEFT = 1
13
+
14
+
15
+ def download_image(src: str) -> Image:
16
+ result = asyncio.Future()
17
+ image = Image.new()
18
+ image.onload = lambda _: result.set_result(image)
19
+ image.src = src
20
+ return result
21
+
22
+
23
+ def show_alert(
24
+ title: str, alert: str, color: str, icon: str, limit_time: int = 5000, is_code=True
25
+ ):
26
+ if hasattr(window, "showAlert"):
27
+ try:
28
+ window.showAlert(title, alert, color, icon, limit_time, is_code)
29
+ except Exception as e:
30
+ print(e)
31
+
32
+
33
+ def set_results(player_names: List[str], places: List[int], map: str, verbose: bool):
34
+ if hasattr(window, "setResults"):
35
+ try:
36
+ window.setResults(player_names, places, map, verbose)
37
+ except Exception as e:
38
+ print(e)
39
+
40
+
41
+ def download_json(filename: str, contents: str):
42
+ if hasattr(window, "downloadJson"):
43
+ try:
44
+ window.downloadJson(filename, contents)
45
+ except Exception as e:
46
+ print(e)
47
+
48
+
49
+ def console_log(player_index: int, text: str, color: str):
50
+ if hasattr(window, "consoleLog"):
51
+ try:
52
+ window.consoleLog(player_index, text, color)
53
+ except Exception as e:
54
+ print(e)
55
+
56
+
57
+ async def with_timeout(fn: Callable[[], None], timeout_seconds: float):
58
+ async def f():
59
+ fn()
60
+
61
+ await asyncio.wait_for(f(), timeout_seconds)
62
+
63
+
64
+ class GameCanvas:
65
+ """
66
+ A nice wrapper around HTML Canvas for drawing map-based multiplayer games.
67
+ """
68
+
69
+ _scale: float
70
+
71
+ def __init__(
72
+ self,
73
+ canvas: Element,
74
+ player_count: int,
75
+ map_image: Image,
76
+ max_width: int,
77
+ max_height: int,
78
+ extra_height: int,
79
+ ):
80
+ self.canvas = canvas
81
+ self.player_count = player_count
82
+ self.map_image = map_image
83
+ self.extra_height = extra_height
84
+
85
+ self._fit_into(max_width, max_height)
86
+
87
+ def draw_element(
88
+ self,
89
+ image: Image,
90
+ x: int,
91
+ y: int,
92
+ width: int,
93
+ board_index=0,
94
+ direction: Union[float, None] = None,
95
+ alignment=Alignment.CENTER,
96
+ ):
97
+ """
98
+ Draws the given image on the specified board.
99
+
100
+ Scaled to fit `width` in map pixels, be on position ``(x, y)`` in map pixels and face `direction`
101
+ where 0 is no rotation and the direction is clockwise positive.
102
+ """
103
+
104
+ if direction is None:
105
+ direction = 0
106
+
107
+ x, y = self._translate_position(board_index, x, y)
108
+ width, height = self._translate_width(width, image.width / image.height)
109
+
110
+ if alignment == Alignment.TOP_LEFT:
111
+ x += width / 2
112
+ y += height / 2
113
+
114
+ self.context.save()
115
+ self.context.translate(x, y)
116
+ self.context.rotate(direction)
117
+ self.context.translate(-width / 2, -height / 2)
118
+ self.context.drawImage(image, 0, 0, width, height)
119
+ self.context.restore()
120
+
121
+ def draw_text(
122
+ self,
123
+ text: str,
124
+ x: int,
125
+ y: int,
126
+ color="black",
127
+ board_index=0,
128
+ text_size=15,
129
+ font="",
130
+ ):
131
+ """
132
+ Draws the given text in the given coordinates (in map pixels).
133
+ """
134
+
135
+ if font != "":
136
+ font += ", "
137
+
138
+ x, y = self._translate_position(board_index, x, y)
139
+ self.context.font = f"{text_size * self._scale}pt {font}system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif, 'Noto Emoji'"
140
+ self.context.fillStyle = color
141
+ self.context.fillText(text, x, y)
142
+
143
+ def clear(self):
144
+ """Clears the canvas and re-draws the players' maps."""
145
+
146
+ self.context.clearRect(0, 0, self.canvas.width, self.canvas.height)
147
+ self.context.fillStyle = "#fff"
148
+ self.context.fillRect(0, 0, self.canvas.width, self.canvas.height)
149
+
150
+ for i in range(self.player_count):
151
+ self.context.drawImage(
152
+ self.map_image,
153
+ i * self.canvas.width / self.player_count,
154
+ 0,
155
+ self.map_image.width * self._scale,
156
+ self.map_image.height * self._scale,
157
+ )
158
+
159
+ @property
160
+ def total_width(self) -> float:
161
+ """The total width of the canvas (in map pixels)."""
162
+
163
+ return self.map_image.width * self.player_count
164
+
165
+ def _fit_into(self, max_width: int, max_height: int):
166
+ if self.map_image.width == 0 or self.map_image.height == 0:
167
+ raise Exception("Map image invalid!")
168
+ aspect_ratio = (
169
+ self.map_image.width
170
+ * self.player_count
171
+ / (self.map_image.height + self.extra_height)
172
+ )
173
+ width = min(max_width, max_height * aspect_ratio)
174
+ height = width / aspect_ratio
175
+ self.canvas.style.width = f"{width}px"
176
+ self.canvas.style.height = f"{height}px"
177
+ self.canvas.width = width * window.devicePixelRatio
178
+ self.canvas.height = height * window.devicePixelRatio
179
+ self._scale = self.canvas.width / self.player_count / self.map_image.width
180
+ self.context = self.canvas.getContext("2d")
181
+ self.context.textAlign = "center"
182
+ self.context.textBaseline = "middle"
183
+
184
+ self.canvas_map_width = self.canvas.width / self.player_count
185
+ self.canvas_map_height = (
186
+ self.canvas_map_width * self.map_image.height / self.map_image.width
187
+ )
188
+
189
+ def _translate_position(self, board_index: int, x: float, y: float):
190
+ x *= self._scale
191
+ y *= self._scale
192
+ x += board_index * self.map_image.width * self._scale
193
+
194
+ return x, y
195
+
196
+ def _translate_width(self, width: float, aspect_ratio: float):
197
+ """Aspect ratio: w/h"""
198
+ width *= self._scale
199
+ height = width / aspect_ratio
200
+ return width, height