Document and type-hint
This commit is contained in:
parent
91a6b54e04
commit
0d306a8a6b
13
axuy/misc.py
13
axuy/misc.py
|
@ -19,6 +19,7 @@
|
|||
from itertools import (chain, combinations_with_replacement,
|
||||
permutations, product)
|
||||
from random import choices, shuffle
|
||||
from typing import Iterator, List, Tuple
|
||||
|
||||
import numpy
|
||||
from pkg_resources import resource_filename
|
||||
|
@ -30,17 +31,17 @@ SPACE = numpy.load(resource_filename('axuy', 'map.npy'))
|
|||
COLORS = tuple(map(numpy.float32, permutations((1.0, 0.5, 0.0))))
|
||||
|
||||
|
||||
def abspath(resource_name):
|
||||
def abspath(resource_name) -> str:
|
||||
"""Return a true filesystem path for the specified resource."""
|
||||
return resource_filename('axuy', resource_name)
|
||||
|
||||
|
||||
def color(code, value):
|
||||
def color(code, value) -> numpy.float32:
|
||||
"""Return NumPy float32 array of RGB colors from color name."""
|
||||
return COLORS[code] * (value + 1) * 0.5
|
||||
|
||||
|
||||
def mapidgen(replacement=False):
|
||||
def mapidgen(replacement=False) -> List[int, ...]:
|
||||
"""Return a randomly generated map ID."""
|
||||
mapid = list(range(48))
|
||||
if replacement: return choices(mapid, k=48)
|
||||
|
@ -59,7 +60,7 @@ def mapgen(mapid):
|
|||
return space
|
||||
|
||||
|
||||
def neighbors(x, y, z):
|
||||
def neighbors(x, y, z) -> Iterator[Tuple[int, int, int]]:
|
||||
"""Return a generator of coordinates of images point (x, y, z)
|
||||
in neighbor universes.
|
||||
"""
|
||||
|
@ -71,7 +72,7 @@ def norm(vector):
|
|||
return numpy.sqrt(numpy.sum(vector**2))
|
||||
|
||||
|
||||
def normalized(*vector):
|
||||
def normalized(*vector) -> numpy.float32:
|
||||
"""Return normalized vector as a NumPy array of float32."""
|
||||
v = numpy.float32(vector)
|
||||
if not v.any(): return v
|
||||
|
@ -95,7 +96,7 @@ def nine(x) -> int:
|
|||
return int(x % 9)
|
||||
|
||||
|
||||
def placeable(space, x, y, z, r):
|
||||
def placeable(space, x, y, z, r) -> bool:
|
||||
"""Return whether a sphere of radius r
|
||||
can be placed at (x, y, z) in given space."""
|
||||
return not any(space[i][j][k] for i, j, k in product(
|
||||
|
|
61
axuy/peer.py
61
axuy/peer.py
|
@ -24,6 +24,7 @@ from pickle import dumps, loads
|
|||
from queue import Empty, Queue
|
||||
from socket import socket, SOCK_DGRAM, SOL_SOCKET, SO_REUSEADDR
|
||||
from threading import Thread
|
||||
from typing import Iterator, Tuple
|
||||
|
||||
from .misc import mapgen, mapidgen
|
||||
from .pico import Picobot
|
||||
|
@ -32,7 +33,29 @@ from .view import ConfigReader, View
|
|||
|
||||
class Peer:
|
||||
"""Axuy peer.
|
||||
TODO: Documentation
|
||||
|
||||
Parameters
|
||||
----------
|
||||
config : ConfigReader
|
||||
Networking and other configurations.
|
||||
|
||||
Attributes
|
||||
----------
|
||||
sock : socket
|
||||
UDP socket for exchanging instantaneous states with other peers.
|
||||
addr : Tuple[str, int]
|
||||
Own's address.
|
||||
q : Queue[Tuple[bytes, Tuple[str, int]]]
|
||||
Queue of (data, addr), where addr is the address of the peer
|
||||
who sent the raw data.
|
||||
peers : List[Tuple[str, int], ...]
|
||||
Addresses of connected peers.
|
||||
space : numpy.ndarray of shape (12, 12, 9) of bools
|
||||
3D array of occupied space.
|
||||
pico : Picobot
|
||||
Protagonist.
|
||||
view : View
|
||||
World representation and renderer.
|
||||
"""
|
||||
|
||||
def __init__(self, config):
|
||||
|
@ -61,6 +84,19 @@ class Peer:
|
|||
"""Peer status."""
|
||||
return self.view.is_running
|
||||
|
||||
@property
|
||||
def ready(self) -> Iterator[Tuple[bytes, Tuple[str, int]]]:
|
||||
"""Iterator of (data, addr) that can be used without waiting,
|
||||
where addr is the address of the peer who sent the data.
|
||||
"""
|
||||
while True:
|
||||
try:
|
||||
yield self.q.get_nowait()
|
||||
except Empty:
|
||||
break
|
||||
else:
|
||||
self.q.task_done()
|
||||
|
||||
def serve(self, mapid):
|
||||
"""Initiate other peers."""
|
||||
with socket() as server: # TCP server
|
||||
|
@ -76,21 +112,17 @@ class Peer:
|
|||
def pull(self):
|
||||
"""Receive other peers' state."""
|
||||
while self.is_running: self.q.put(self.sock.recvfrom(1<<16))
|
||||
while not self.q.empty():
|
||||
self.q.get()
|
||||
self.q.task_done()
|
||||
|
||||
def update(self):
|
||||
"""Update the local states and send them to other peers."""
|
||||
while True:
|
||||
try:
|
||||
data, addr = self.q.get_nowait()
|
||||
except Empty:
|
||||
break
|
||||
else:
|
||||
health, pos, rot, shards = loads(data)
|
||||
if addr not in self.view.picos:
|
||||
self.peers.append(addr)
|
||||
self.view.add_pico(addr)
|
||||
self.view.picos[addr].sync(health, pos, rot, shards)
|
||||
self.q.task_done()
|
||||
for data, addr in self.ready:
|
||||
if addr not in self.view.picos:
|
||||
self.peers.append(addr)
|
||||
self.view.add_pico(addr)
|
||||
self.view.picos[addr].sync(*loads(data))
|
||||
|
||||
self.view.update()
|
||||
pico = self.pico
|
||||
|
@ -102,9 +134,6 @@ class Peer:
|
|||
def __enter__(self): return self
|
||||
|
||||
def __exit__(self, exc_type, exc_value, traceback):
|
||||
while not self.q.empty():
|
||||
self.q.get()
|
||||
self.q.task_done()
|
||||
self.q.join()
|
||||
self.sock.close()
|
||||
self.view.close()
|
||||
|
|
16
axuy/pico.py
16
axuy/pico.py
|
@ -51,7 +51,7 @@ class Shard:
|
|||
|
||||
Parameters
|
||||
----------
|
||||
address : (str, int)
|
||||
address : Tuple[str, int]
|
||||
IP address (host, port).
|
||||
space : np.ndarray of shape (12, 12, 9) of bools
|
||||
3D array of occupied space.
|
||||
|
@ -64,7 +64,7 @@ class Shard:
|
|||
|
||||
Attributes
|
||||
----------
|
||||
addr : (str, int)
|
||||
addr : Tuple[str, int]
|
||||
IP address (host, port).
|
||||
power : int
|
||||
Relative destructive power.
|
||||
|
@ -83,7 +83,7 @@ class Shard:
|
|||
self.rot = rotation
|
||||
|
||||
@property
|
||||
def pos(self):
|
||||
def pos(self) -> np.float32:
|
||||
"""Position in a NumPy array."""
|
||||
return np.float32([self.x, self.y, self.z])
|
||||
|
||||
|
@ -95,7 +95,7 @@ class Shard:
|
|||
self.z = z % 9
|
||||
|
||||
@property
|
||||
def forward(self):
|
||||
def forward(self) -> np.float32:
|
||||
"""Direction in a NumPy array."""
|
||||
return self.rot[-1]
|
||||
|
||||
|
@ -139,7 +139,7 @@ class Picobot:
|
|||
|
||||
Parameters
|
||||
----------
|
||||
address : (str, int)
|
||||
address : Tuple[str, int]
|
||||
IP address (host, port).
|
||||
space : np.ndarray of shape (12, 12, 9) of bools
|
||||
3D array of occupied space.
|
||||
|
@ -152,7 +152,7 @@ class Picobot:
|
|||
|
||||
Attributes
|
||||
----------
|
||||
addr : (str, int)
|
||||
addr : Tuple[str, int]
|
||||
IP address (host, port).
|
||||
space : np.ndarray of shape (12, 12, 9) of bools
|
||||
3D array of occupied space.
|
||||
|
@ -162,7 +162,7 @@ class Picobot:
|
|||
Position.
|
||||
rot : np.ndarray of shape (3, 3) of np.float32
|
||||
Rotational matrix.
|
||||
shards : dict of Shard
|
||||
shards : Dict[int, Shard]
|
||||
Active shards.
|
||||
recoil_u : np.ndarray of length 3 of np.float32
|
||||
Recoil direction (unit vector).
|
||||
|
@ -201,7 +201,7 @@ class Picobot:
|
|||
return self.health < 0
|
||||
|
||||
@property
|
||||
def forward(self):
|
||||
def forward(self) -> np.float32:
|
||||
"""Direction in a NumPy array."""
|
||||
return self.rot[-1]
|
||||
|
||||
|
|
18
axuy/view.py
18
axuy/view.py
|
@ -91,13 +91,13 @@ class ConfigReader:
|
|||
Port to bind the peer to.
|
||||
seeder : str
|
||||
Address of the peer that created the map.
|
||||
size : (int, int)
|
||||
size : Tuple[int, int]
|
||||
GLFW window resolution.
|
||||
vsync : bool
|
||||
Vertical synchronization.
|
||||
zmlvl : float
|
||||
Zoom level.
|
||||
key, mouse : dict of (str, int)
|
||||
key, mouse : Dict[str, int]
|
||||
Input control.
|
||||
mouspeed : float
|
||||
Relative camera rotational speed.
|
||||
|
@ -192,30 +192,30 @@ class View:
|
|||
|
||||
Parameters
|
||||
----------
|
||||
address : (str, int)
|
||||
address : Tuple[str, int]
|
||||
IP address (host, port).
|
||||
camera : Picobot
|
||||
Protagonist whose view is the camera.
|
||||
space : np.ndarray of shape (12, 12, 9) of bools
|
||||
3D array of occupied space.
|
||||
size : (int, int)
|
||||
size : Tuple[int, int]
|
||||
GLFW window resolution.
|
||||
vsync : bool
|
||||
Vertical synchronization.
|
||||
ctl : dict of (str, int)
|
||||
ctl : Dict[str, int]
|
||||
Input control.
|
||||
|
||||
Attributes
|
||||
----------
|
||||
addr : (str, int)
|
||||
addr : Tuple[str, int]
|
||||
IP address (host, port).
|
||||
space : np.ndarray of shape (12, 12, 9) of bools
|
||||
3D array of occupied space.
|
||||
camera : Picobot
|
||||
Protagonist whose view is the camera.
|
||||
picos : dict of (address, Picobot)
|
||||
picos : Dict[Tuple[str, int], Picobot]
|
||||
Enemies characters.
|
||||
colors : dict of (address, str)
|
||||
colors : Dict[Tuple[str, int], str]
|
||||
Color names of enemies.
|
||||
window : GLFW window
|
||||
zmlvl : float
|
||||
|
@ -253,7 +253,7 @@ class View:
|
|||
Frame buffers for bloom-effect post-processing.
|
||||
last_time : float
|
||||
timestamp in seconds of the previous frame.
|
||||
fpses : deque of floats
|
||||
fpses : Deque[float, ...]
|
||||
FPS during the last 5 seconds to display the average.
|
||||
"""
|
||||
|
||||
|
|
Loading…
Reference in New Issue