puzzles: add in support for monolithic categories

This also supports static or dynamic puzzles within a category following the
earlier design strategy.

Tested on a monolithic category, needs testing with a variety of category types.
This commit is contained in:
J. Patrick Avery, Jr 2016-10-20 17:07:34 -06:00
parent 2849d7d628
commit 168549b50e
1 changed files with 33 additions and 6 deletions

View File

@ -55,7 +55,7 @@ class Puzzle:
ANSWER_WORDS = [w.strip() for w in open(os.path.join(os.path.dirname(__file__), ANSWER_WORDS = [w.strip() for w in open(os.path.join(os.path.dirname(__file__),
'answer_words.txt'))] 'answer_words.txt'))]
def __init__(self, category_seed, path=None, points=None): def __init__(self, category_seed, path=None, points=None, category=None):
"""A MOTH Puzzle. """A MOTH Puzzle.
:param category_seed: A byte string to use as a seed for random numbers for this puzzle. :param category_seed: A byte string to use as a seed for random numbers for this puzzle.
It is combined with the puzzle points. It is combined with the puzzle points.
@ -83,11 +83,14 @@ class Puzzle:
super().__init__() super().__init__()
if (points is None and path is None) or (points is not None and path is not None): assert any([
raise ValueError("Either points or path must be set, but not both.") points is None and path is not None,
points is not None and path is None,
points is not None and category is not None]), \
"Either points or path must be set, but not both."
self._dict = defaultdict(lambda: []) self._dict = defaultdict(lambda: [])
if os.path.isdir(path): if path is not None and os.path.isdir(path):
self.puzzle_dir = path self.puzzle_dir = path
else: else:
self.puzzle_dir = None self.puzzle_dir = None
@ -131,6 +134,9 @@ class Puzzle:
puzzle_mod.make(self) puzzle_mod.make(self)
else: else:
self.body = '# `puzzle.py` does not define a `make` function' self.body = '# `puzzle.py` does not define a `make` function'
elif category is not None and points is not None:
category.make(self, points)
def cleanup(self): def cleanup(self):
"""Cleanup any outstanding temporary files.""" """Cleanup any outstanding temporary files."""
@ -328,15 +334,36 @@ class Category:
self.path = path self.path = path
self.seed = seed self.seed = seed
self.pointvals = [] self.pointvals = []
self.catmod = None
try:
catmod = SourceFileLoader(
'catmod',
os.path.join(path, 'category.py')).load_module()
assert all([
hasattr(catmod, 'make'),
hasattr(catmod, 'points'),
type(catmod.points) is list,
])
self.catmod = catmod
self.pointvals.extend(catmod.points)
except:
pass
for fpath in glob.glob(os.path.join(path, "[0-9]*")): for fpath in glob.glob(os.path.join(path, "[0-9]*")):
pn = os.path.basename(fpath) pn = os.path.basename(fpath)
points = int(pn) points = int(pn)
self.pointvals.append(points) self.pointvals.append(points)
self.pointvals.sort() self.pointvals.sort()
def puzzle(self, points): def puzzle(self, points):
path = os.path.join(self.path, str(points)) print("Category.puzzle! %r %r" % (points, self.catmod.points))
return Puzzle(self.seed, path) if self.catmod is not None and points in self.catmod.points:
return Puzzle(self.seed, points=points, category=self.catmod)
else:
path = os.path.join(self.path, str(points))
return Puzzle(self.seed, path=path)
def puzzles(self): def puzzles(self):
for points in self.pointvals: for points in self.pointvals: