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.
- package/LICENSE.md +7 -0
- package/README.md +39 -0
- package/dist/cjs/index.js +18532 -0
- package/dist/cjs/styles.css +5 -0
- package/dist/cjs/types/CodeBattles.d.ts +10 -0
- package/dist/cjs/types/components/App.d.ts +7 -0
- package/dist/cjs/types/components/AutoScrollButton.d.ts +3 -0
- package/dist/cjs/types/components/LogViewer.d.ts +6 -0
- package/dist/cjs/types/components/Login.d.ts +3 -0
- package/dist/cjs/types/components/ShowLogsButtons.d.ts +8 -0
- package/dist/cjs/types/components/TimerAndVolume.d.ts +3 -0
- package/dist/cjs/types/components/TopPane.d.ts +3 -0
- package/dist/cjs/types/components/blocks/AdminBlock.d.ts +3 -0
- package/dist/cjs/types/components/blocks/Block.d.ts +8 -0
- package/dist/cjs/types/components/blocks/BotSelector.d.ts +10 -0
- package/dist/cjs/types/components/blocks/PickBotBlock.d.ts +3 -0
- package/dist/cjs/types/components/blocks/RunSimulationBlock.d.ts +3 -0
- package/dist/cjs/types/components/blocks/TournamentBlock.d.ts +8 -0
- package/dist/cjs/types/components/blocks/UploadBlock.d.ts +3 -0
- package/dist/cjs/types/components/index.d.ts +3 -0
- package/dist/cjs/types/components/pages/HomePage.d.ts +6 -0
- package/dist/cjs/types/components/pages/NotFoundPage.d.ts +3 -0
- package/dist/cjs/types/components/pages/RoundPage.d.ts +3 -0
- package/dist/cjs/types/components/pages/SettingsPage.d.ts +3 -0
- package/dist/cjs/types/components/pages/SimulationPage.d.ts +3 -0
- package/dist/cjs/types/components/pages/ViewAPIPage.d.ts +3 -0
- package/dist/cjs/types/configuration.d.ts +35 -0
- package/dist/cjs/types/hooks.d.ts +17 -0
- package/dist/cjs/types/index.d.ts +10 -0
- package/dist/cjs/types/initialize.d.ts +5 -0
- package/dist/cjs/types/particles.d.ts +2 -0
- package/dist/cjs/types/utilities.d.ts +14 -0
- package/dist/code_battles/__init__.py +13 -0
- package/dist/code_battles/battles.py +531 -0
- package/dist/code_battles/js.pyi +114 -0
- package/dist/code_battles/pyodide/ffi/__init__.pyi +2 -0
- package/dist/code_battles/pyscript/ffi/__init__.pyi +3 -0
- package/dist/code_battles/utilities.py +200 -0
- package/dist/esm/index.js +18528 -0
- package/dist/esm/styles.css +5 -0
- package/dist/esm/types/CodeBattles.d.ts +10 -0
- package/dist/esm/types/components/App.d.ts +7 -0
- package/dist/esm/types/components/AutoScrollButton.d.ts +3 -0
- package/dist/esm/types/components/LogViewer.d.ts +6 -0
- package/dist/esm/types/components/Login.d.ts +3 -0
- package/dist/esm/types/components/ShowLogsButtons.d.ts +8 -0
- package/dist/esm/types/components/TimerAndVolume.d.ts +3 -0
- package/dist/esm/types/components/TopPane.d.ts +3 -0
- package/dist/esm/types/components/blocks/AdminBlock.d.ts +3 -0
- package/dist/esm/types/components/blocks/Block.d.ts +8 -0
- package/dist/esm/types/components/blocks/BotSelector.d.ts +10 -0
- package/dist/esm/types/components/blocks/PickBotBlock.d.ts +3 -0
- package/dist/esm/types/components/blocks/RunSimulationBlock.d.ts +3 -0
- package/dist/esm/types/components/blocks/TournamentBlock.d.ts +8 -0
- package/dist/esm/types/components/blocks/UploadBlock.d.ts +3 -0
- package/dist/esm/types/components/index.d.ts +3 -0
- package/dist/esm/types/components/pages/HomePage.d.ts +6 -0
- package/dist/esm/types/components/pages/NotFoundPage.d.ts +3 -0
- package/dist/esm/types/components/pages/RoundPage.d.ts +3 -0
- package/dist/esm/types/components/pages/SettingsPage.d.ts +3 -0
- package/dist/esm/types/components/pages/SimulationPage.d.ts +3 -0
- package/dist/esm/types/components/pages/ViewAPIPage.d.ts +3 -0
- package/dist/esm/types/configuration.d.ts +35 -0
- package/dist/esm/types/hooks.d.ts +17 -0
- package/dist/esm/types/index.d.ts +10 -0
- package/dist/esm/types/initialize.d.ts +5 -0
- package/dist/esm/types/particles.d.ts +2 -0
- package/dist/esm/types/utilities.d.ts +14 -0
- package/dist/index.d.ts +44 -0
- package/dist/pdoc-template/custom.css +22 -0
- package/dist/pdoc-template/module.html.jinja2 +306 -0
- package/dist/pdoc-template/syntax-highlighting.css +248 -0
- package/dist/pyscript/codemirror-BEtcgaoQ.js +2 -0
- package/dist/pyscript/codemirror-BEtcgaoQ.js.map +1 -0
- package/dist/pyscript/codemirror_commands-DDxffOmd.js +2 -0
- package/dist/pyscript/codemirror_commands-DDxffOmd.js.map +1 -0
- package/dist/pyscript/codemirror_lang-python-CnWnFqxD.js +2 -0
- package/dist/pyscript/codemirror_lang-python-CnWnFqxD.js.map +1 -0
- package/dist/pyscript/codemirror_language-CjmvX4ix.js +2 -0
- package/dist/pyscript/codemirror_language-CjmvX4ix.js.map +1 -0
- package/dist/pyscript/codemirror_state-D1qTXrff.js +2 -0
- package/dist/pyscript/codemirror_state-D1qTXrff.js.map +1 -0
- package/dist/pyscript/codemirror_view-DVb8uYMr.js +2 -0
- package/dist/pyscript/codemirror_view-DVb8uYMr.js.map +1 -0
- package/dist/pyscript/core-CZGzC87D.js +2 -0
- package/dist/pyscript/core-CZGzC87D.js.map +1 -0
- package/dist/pyscript/core.css +1 -0
- package/dist/pyscript/core.js +2 -0
- package/dist/pyscript/core.js.map +1 -0
- package/dist/pyscript/deprecations-manager-B8Tn4H-t.js +2 -0
- package/dist/pyscript/deprecations-manager-B8Tn4H-t.js.map +1 -0
- package/dist/pyscript/error-Dmba-E9f.js +2 -0
- package/dist/pyscript/error-Dmba-E9f.js.map +1 -0
- package/dist/pyscript/index-S1Do43bx.js +2 -0
- package/dist/pyscript/index-S1Do43bx.js.map +1 -0
- package/dist/pyscript/mpy-BnYOGs9W.js +2 -0
- package/dist/pyscript/mpy-BnYOGs9W.js.map +1 -0
- package/dist/pyscript/py-D2NmpN63.js +2 -0
- package/dist/pyscript/py-D2NmpN63.js.map +1 -0
- package/dist/pyscript/py-editor-Czy2e-Jt.js +2 -0
- package/dist/pyscript/py-editor-Czy2e-Jt.js.map +1 -0
- package/dist/pyscript/py-terminal-w87wZryi.js +2 -0
- package/dist/pyscript/py-terminal-w87wZryi.js.map +1 -0
- package/dist/pyscript/storage.js +2 -0
- package/dist/pyscript/storage.js.map +1 -0
- package/dist/pyscript/toml-CvAfdf9_.js +3 -0
- package/dist/pyscript/toml-CvAfdf9_.js.map +1 -0
- package/dist/pyscript/toml-DiUM0_qs.js +3 -0
- package/dist/pyscript/toml-DiUM0_qs.js.map +1 -0
- package/dist/pyscript/xterm-BY7uk_OU.js +2 -0
- package/dist/pyscript/xterm-BY7uk_OU.js.map +1 -0
- package/dist/pyscript/xterm-readline-CZfBw7ic.js +2 -0
- package/dist/pyscript/xterm-readline-CZfBw7ic.js.map +1 -0
- package/dist/pyscript/xterm.css +7 -0
- package/dist/pyscript/xterm_addon-fit--gyF3PcZ.js +2 -0
- package/dist/pyscript/xterm_addon-fit--gyF3PcZ.js.map +1 -0
- package/dist/pyscript/xterm_addon-web-links-Cnej-nJ6.js +2 -0
- package/dist/pyscript/xterm_addon-web-links-Cnej-nJ6.js.map +1 -0
- package/dist/pyscript/zip-DrwYHuF9.js +2 -0
- package/dist/pyscript/zip-DrwYHuF9.js.map +1 -0
- package/dist/webfonts/fa-brands-400.ttf +0 -0
- package/dist/webfonts/fa-brands-400.woff2 +0 -0
- package/dist/webfonts/fa-regular-400.ttf +0 -0
- package/dist/webfonts/fa-regular-400.woff2 +0 -0
- package/dist/webfonts/fa-solid-900.ttf +0 -0
- package/dist/webfonts/fa-solid-900.woff2 +0 -0
- package/dist/webfonts/fa-v4compatibility.ttf +0 -0
- package/dist/webfonts/fa-v4compatibility.woff2 +0 -0
- 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
|