Source code for pooltool.objects.table.specs

#! /usr/bin/env python

from __future__ import annotations

from typing import Protocol

from attrs import define, field

from pooltool.ani.constants import model_dir
from pooltool.error import ConfigError
from pooltool.utils import panda_path, strenum


[docs] @define(frozen=True) class TableModelDescr: """A table model specifier Attributes: name: The name of the table model. """ name: str
[docs] def get_path(self, use_pbr: bool = False) -> str: """Get the path of the model based on PBR preference The path is searched for in ``pooltool/models/table/{name}/{name}[_pbr].glb``. If the PBR variant is requested but doesn't exist, falls back to the non-PBR variant. Args: use_pbr: Whether to use physical based rendering variant Raises: ConfigError: If model path cannot be found from name. Returns: str: A filename specified with Panda3D filename syntax (see https://docs.panda3d.org/1.10/python/programming/advanced-loading/filename-syntax). """ base_path = model_dir / "table" / self.name / (self.name + ".glb") pbr_path = model_dir / "table" / self.name / (self.name + "_pbr.glb") if use_pbr and pbr_path.exists(): return panda_path(pbr_path) if base_path.exists(): return panda_path(base_path) raise ConfigError(f"Couldn't find table model with name: {self.name}")
[docs] @staticmethod def null() -> TableModelDescr: return TableModelDescr(name="null")
[docs] class TableType(strenum.StrEnum): """An Enum describing the table type. Attributes: POCKET: BILLIARD: SNOOKER: OTHER: """ POCKET = strenum.auto() BILLIARD = strenum.auto() SNOOKER = strenum.auto() OTHER = strenum.auto()
class TableSpecs(Protocol): @property def table_type(self) -> TableType: ... @property def height(self) -> float: ... @property def lights_height(self) -> float: ... @property def model_descr(self) -> TableModelDescr: ...
[docs] @define(frozen=True) class PocketTableSpecs: """Parameter specifications for a pocket table. See Also: - See the :doc:`Table Specification </resources/table_specs>` resource for visualizations and descriptions of each attribute. - See :class:`pooltool.objects.BilliardTableSpecs` for billiard table specs. - See :class:`pooltool.objects.SnookerTableSpecs` for snooker table specs. Default parameters match :attr:`pooltool.objects.TableName.SEVEN_FOOT_SHOWOOD`. """ # 7-foot table (78x39 in^2 playing surface) l: float = field(default=1.9812) # noqa E741 w: float = field(default=1.9812 / 2) cushion_width: float = field(default=2 * 2.54 / 100) cushion_height: float = field(default=0.64 * 2 * 0.028575) cushion_nose_radius: float = field(default=0.005) corner_pocket_width: float = field(default=0.118) corner_pocket_angle: float = field(default=5.3) # degrees corner_pocket_depth: float = field(default=0.0417) corner_pocket_radius: float = field(default=0.062) corner_jaw_radius: float = field(default=0.02095) side_pocket_width: float = field(default=0.137) side_pocket_angle: float = field(default=7.14) # degrees side_pocket_depth: float = field(default=0.0685) side_pocket_radius: float = field(default=0.0645) side_jaw_radius: float = field(default=0.00795) # For visualization height: float = field(default=0.708) lights_height: float = field(default=1.99) model_descr: TableModelDescr = field(factory=TableModelDescr.null) table_type: TableType = field(init=False, default=TableType.POCKET)
[docs] @define(frozen=True) class BilliardTableSpecs: """Parameter specifications for a billiards (pocketless) table. See Also: - See the :doc:`Table Specification </resources/table_specs>` resource for visualizations and descriptions of each attribute. - See :class:`pooltool.objects.PocketTableSpecs` for billiard table specs. - See :class:`pooltool.objects.SnookerTableSpecs` for snooker table specs. """ # https://web.archive.org/web/20130801042614/http://www.umb.org/Rules/Carom_Rules.pdf l: float = field(default=2.84) w: float = field(default=1.42) cushion_width: float = field(default=2 * 2.54 / 100) cushion_height: float = field(default=0.037) cushion_nose_radius: float = field(default=0.005) # For visualization height: float = field(default=0.708) lights_height: float = field(default=1.99) model_descr: TableModelDescr = field(factory=TableModelDescr.null) table_type: TableType = field(init=False, default=TableType.BILLIARD)
[docs] @define(frozen=True) class SnookerTableSpecs: """Parameter specifications for a snooker table. See Also: - See the :doc:`Table Specification </resources/table_specs>` resource for visualizations and descriptions of each attribute. - See :class:`pooltool.objects.BilliardTableSpecs` for billiard table specs. - See :class:`pooltool.objects.PocketTableSpecs` for pocket table specs. Note: Currently, this class is an identical clone of :class:`pooltool.objects.PocketTableSpecs`, but with different defaults. That's not very useful, but it's likely that some time in the future, snooker tables may have some parameters distinct from standard pool tables (*e.g.* directional cloth), causing these classes to diverge. """ # https://wpbsa.com/rules/ # The playing area is within the cushion faces and shall measure # 11 ft 8½ in x 5 ft 10 in (3569 mm x 1778 mm) with a tolerance on both dimensions of +/- ½ in (13 mm). l: float = field(default=3.5445) # noqa E741 w: float = field(default=1.7465) cushion_width: float = field(default=1.55 * 25.4 / 1000) cushion_height: float = field(default=0.028) cushion_nose_radius: float = field(default=0.005) corner_pocket_width: float = field(default=0.083) corner_pocket_angle: float = field(default=0) corner_pocket_depth: float = field(default=0.036) corner_pocket_radius: float = field(default=4 * 25.4 / 1000) corner_jaw_radius: float = field(default=4 * 25.4 / 1000) side_pocket_width: float = field(default=0.087) side_pocket_angle: float = field(default=0) side_pocket_depth: float = field(default=0.95 * 25.4 / 1000) side_pocket_radius: float = field(default=1.68 * 25.4 / 1000) side_jaw_radius: float = field(default=2.5 * 25.4 / 1000) # For visualization height: float = field(default=0.708) lights_height: float = field(default=1.99) model_descr: TableModelDescr = field(factory=TableModelDescr.null) table_type: TableType = field(init=False, default=TableType.SNOOKER)