Document and type-hint

This commit is contained in:
Nguyễn Gia Phong 2019-09-21 21:24:30 +07:00
parent 91a6b54e04
commit 0d306a8a6b
4 changed files with 69 additions and 39 deletions

View File

@ -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(

View File

@ -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()

View File

@ -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]

View File

@ -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.
"""