diff --git a/deadsands/site_tools/campaign.py b/deadsands/site_tools/campaign.py index f191937..9848b44 100644 --- a/deadsands/site_tools/campaign.py +++ b/deadsands/site_tools/campaign.py @@ -4,14 +4,14 @@ from pathlib import Path import shutil import yaml -from telisar.reckoning import telisaran +from reckoning import telisaran -def _string_to_date(date): +def string_to_date(date): return telisaran.datetime.from_expression(f"on {date}", timeline={}) -def _date_to_string(date): +def date_to_string(date): return date.numeric @@ -47,8 +47,8 @@ def save(campaign, path='.', name='dnd_campaign'): target = Path(f"{savepath}.000") shutil.move(savepath, target) - campaign['date'] = _date_to_string(campaign['date']) - campaign['start_date'] = _date_to_string(campaign['start_date']) + campaign['date'] = date_to_string(campaign['date']) + campaign['start_date'] = date_to_string(campaign['start_date']) savepath.write_text(yaml.safe_dump(dict(campaign))) return savepath, (backup_count or 0) + 2 @@ -56,7 +56,7 @@ def save(campaign, path='.', name='dnd_campaign'): def load(path=".", name='dnd_campaign', start_date='', backup=None, console=None): ext = "" if backup is None else f".{backup:03d}" - default_date = _string_to_date(start_date) + default_date = string_to_date(start_date) campaign = defaultdict(str) campaign['start_date'] = default_date campaign['date'] = default_date @@ -67,8 +67,8 @@ def load(path=".", name='dnd_campaign', start_date='', backup=None, console=None target = Path(path).expanduser() / f"{name}.yaml{ext}" with open(target, 'rb') as f: loaded = yaml.safe_load(f) - loaded['start_date'] = _string_to_date(loaded['start_date']) - loaded['date'] = _string_to_date(loaded['date']) + loaded['start_date'] = string_to_date(loaded['start_date']) + loaded['date'] = string_to_date(loaded['date']) campaign.update(loaded) if console: console.print(f"Successfully loaded Campaign {name} from {target}!") diff --git a/deadsands/site_tools/shell/interactive_shell.py b/deadsands/site_tools/shell/interactive_shell.py index fd8a622..5915f05 100644 --- a/deadsands/site_tools/shell/interactive_shell.py +++ b/deadsands/site_tools/shell/interactive_shell.py @@ -11,6 +11,8 @@ from site_tools import campaign from npc.generator.base import generate_npc from reckoning.calendar import TelisaranCalendar +from reckoning.telisaran import Day +from reckoning.telisaran import ReckoningError BINDINGS = KeyBindings() @@ -64,40 +66,88 @@ class DMShell(BasePrompt): self.npc() @self.key_bindings.add("f4") - def calendar(event): - self.calendar() + def date(event): + self.date() @self.key_bindings.add("f8") def save(event): self.save() @command(usage=""" - [title]Calendar[/title] + [title]Date[/title] - Print the Telisaran calendar, including the current date. + Work with the Telisaran calendar, including the current campaign date. - [title]calendar[/title] + [title]USAGE[/title] - [link]> calendar [season][/link] + [link]> date [COMMAND[, ARGS]][/link] + + COMMAND Description + + season Print the spans of the current season, highlighting today + year Print the full year's calendar, highlighting today. + inc N Increment the current date by N days; defaults to 1. + dec N Decrement the current date by N days; defaults to 1. + set DATE Set the current date to DATE, in numeric format, such as + [link]2.1125.1.45[/link]. """, completer=WordCompleter( [ 'season', + 'year', + 'inc', + 'dec', + 'set', ] )) - def calendar(self, parts=[]): + def date(self, parts=[]): if not self.cache['calendar']: - self.cache['calendar'] = TelisaranCalendar(today=self._campaign['start_date']) + self.cache['calendar'] = TelisaranCalendar(today=self._campaign['date']) if not parts: - self.console.print(self.cache['calendar'].__doc__) - self.console.print(f"Today is {self._campaign['date'].short}") + self.console.print(f"Today is {self._campaign['date'].short} ({self._campaign['date'].numeric})") return - if parts[0] == 'season': - self.console.print(self.cache['calendar'].season) + cmd = parts[0] + try: + val = parts[1] + except IndexError: + val = None + + print(cmd) + + handler = getattr(self, f"_handler_date_{cmd}", None) + if not handler: + self.console.error(f"Unsupported command: {cmd}. Try 'help date'.") return + return handler(val) + + def _handler_date_season(self, *args): + self.console.print(self.cache['calendar'].season) + + def _handler_date_year(self, *args): + self.console.print(self.cache['calendar'].calendar) + + def _handler_date_inc(self, days): + offset = int(days or 1) * Day.length_in_seconds + self._campaign['date'] = self._campaign['date'] + offset + return self.date() + + def _handler_date_dec(self, days): + offset = int(days or 1) * Day.length_in_seconds + self._campaign['date'] = self._campaign['date'] - offset + return self.date() + + def _handler_date_set(self, new_date): + try: + self._campaign['date'] = campaign.string_to_date(new_date) + except ReckoningError as e: + self.console.error(str(e)) + self.console.error("Invalid date. Use numeric formats; see 'help date' for more.") + self.cache['calendar'] = TelisaranCalendar(today=self._campaign['date']) + return self.date() + @command(usage=""" [title]Save[/title] @@ -194,21 +244,6 @@ class DMShell(BasePrompt): super().help(parts) return True - @command(usage=""" - [title]INCREMENT DATE[/title] - - [b]id[/b] Increments the calendar date by one day. - - [title]USAGE[/title] - - [link]id[/link] - """) - def id(self, parts=[]): - """ - Increment the date by one day. - """ - raise NotImplementedError() - @command( usage=""" [title]LOCATION[/title]