adding importable roll tables and generative CLI

This commit is contained in:
evilchili 2024-01-17 21:15:39 -08:00
parent f15b974a48
commit 1217c73c17
4 changed files with 51 additions and 63 deletions

View File

@ -1,4 +1,5 @@
from rolltable.types import RollTable from rolltable.types import RollTable
from rolltable import tables
import typer import typer
from enum import Enum from enum import Enum
from rich import print from rich import print
@ -15,43 +16,6 @@ class OUTPUT_FORMATS(Enum):
markdown = 'markdown' markdown = 'markdown'
@app.command("psychadelic-effects")
def psycheffects():
"""
Generate a roll table of psychadelic effects.
"""
rt = RollTable([(Path(__file__).parent / 'sources' / 'psychadelic_effects.yaml').read_text()])
print(rt.as_table())
@app.command("trinkets")
def trinkets():
"""
Generate a roll table of random junk.
"""
rt = RollTable([(Path(__file__).parent / 'sources' / 'trinkets.yaml').read_text()])
print(rt.as_table())
@app.command("wild-magic")
def wildmagic():
"""
Generate a wild magic surge table.
"""
rt = RollTable([(Path(__file__).parent / 'sources' / 'wild_magic.yaml').read_text()])
print(rt.as_table())
@app.command("spells")
def spells():
"""
Generate a random spell table.
"""
rt = RollTable([(Path(__file__).parent / 'sources' / 'spells.yaml').read_text()])
rt.set_headers('Level', 'Name', 'School', None, None, None, None, None)
print(rt.as_table())
@app.command("custom") @app.command("custom")
def custom( def custom(
sources: List[Path] = typer.Argument( sources: List[Path] = typer.Argument(
@ -92,5 +56,19 @@ def custom(
print(rt.as_table(width=width, expanded=not collapsed)) print(rt.as_table(width=width, expanded=not collapsed))
def make_callback(roll_table_instance):
def inner():
print(roll_table_instance.as_table())
return inner
# step through all the predfined tables and create a cli for each
for name, table in tables.index.items():
help_text = name.replace('_', ' ').title()
app.command(name=name, help=f"Create a roll table of {help_text}")(
make_callback(table)
)
if __name__ == '__main__': if __name__ == '__main__':
app() app()

22
rolltable/tables.py Normal file
View File

@ -0,0 +1,22 @@
from pathlib import Path
from rolltable.types import RollTable
from typing import Any
def from_sources(names: list[str] = []) -> list:
return RollTable([
(Path(__file__).parent / "sources" / name).read_text()
for name in names
])
index = dict(
psychadelic_effects=from_sources(['psychadelic_effects.yaml']),
trinkets=from_sources(['trinkets.yaml']),
wild_magic=from_sources(['wild_magic.yaml']),
spells=from_sources(['spells.yaml'])
)
def __getattr__(name: str) -> Any:
return index[name]

View File

@ -33,9 +33,9 @@ class RollTable:
die: Optional[int] = 20, hide_rolls: bool = False) -> None: die: Optional[int] = 20, hide_rolls: bool = False) -> None:
self._sources = sources self._sources = sources
self._frequency = frequency self._frequency = frequency
self._die = die self.die = die
self._hide_rolls = hide_rolls self.hide_rolls = hide_rolls
self._data = None self.data = None
self._rows = None self._rows = None
self._headers = None self._headers = None
self._header_excludes = None self._header_excludes = None
@ -46,10 +46,6 @@ class RollTable:
def datasources(self) -> List: def datasources(self) -> List:
return self._data return self._data
@property
def die(self) -> int:
return self._die
@property @property
def headers(self) -> List: def headers(self) -> List:
return self._headers return self._headers
@ -90,7 +86,7 @@ class RollTable:
offset = 0 offset = 0
self._rows = [self._column_filter(['Roll'] + self.headers)] self._rows = [self._column_filter(['Roll'] + self.headers)]
for face in range(self._die): for face in range(self.die):
row = self._values[face] row = self._values[face]
if not lastrow: if not lastrow:
lastrow = row lastrow = row
@ -106,7 +102,7 @@ class RollTable:
@property @property
def expanded_rows(self) -> List: def expanded_rows(self) -> List:
self._rows = [self._column_filter(['Roll'] + self.headers)] self._rows = [self._column_filter(['Roll'] + self.headers)]
for face in range(self._die): for face in range(self.die):
row = self._values[face] row = self._values[face]
self._rows.append(self._column_filter([f'd{face+1}'] + row)) self._rows.append(self._column_filter([f'd{face+1}'] + row))
return self._rows return self._rows
@ -167,7 +163,7 @@ class RollTable:
# pad the row with empty columns if there are more headers than columns # pad the row with empty columns if there are more headers than columns
cols = cols + [''] * (1 + len(self.headers) - len(row)) cols = cols + [''] * (1 + len(self.headers) - len(row))
# strip the leading column if we're hiding the dice rolls # strip the leading column if we're hiding the dice rolls
return cols[1:] if self._hide_rolls else cols return cols[1:] if self.hide_rolls else cols
def _flatten(self, obj: List) -> List: def _flatten(self, obj: List) -> List:
for member in obj: for member in obj:

View File

@ -1,22 +1,14 @@
import pytest import pytest
from pathlib import Path from rolltable import tables
from rolltable.types import RollTable
sources = Path(__file__).parent / '..' / 'rolltable' / 'sources' @pytest.mark.parametrize('table, expected', [
(tables.wild_magic, ['d1000 ', 'A third eye', 'Advantage on perception checks']),
flat_list = (sources / 'trinkets.yaml').read_text() (tables.trinkets, ['d1000 ', 'ivory mimic']),
dict_of_dicts = (sources / 'wild_magic.yaml').read_text() (tables.psychadelic_effects, ['d1000', 'Cosmic', 'mind expands', 'it will become so']),
dict_of_lists = (sources / 'psychadelic_effects.yaml').read_text()
@pytest.mark.parametrize('data, expected', [
([dict_of_dicts], ['d1000 ', 'A third eye', 'Advantage on perception checks']),
([flat_list], ['d1000 ', 'ivory mimic']),
([dict_of_lists], ['d1000', 'Cosmic', 'mind expands', 'it will become so']),
]) ])
def test_flat(data, expected): def test_flat(table, expected):
rt = RollTable(data, die=1000) table.die = 1000
for txt in expected: for txt in expected:
assert txt in str(rt) assert txt in str(table)