Moved stringify cruft into a render module.
authorEevee <eevee@nyarumaa.(none)>
Sat, 13 Dec 2008 05:10:35 +0000 (21:10 -0800)
committerEevee <eevee@nyarumaa.(none)>
Sat, 13 Dec 2008 05:10:35 +0000 (21:10 -0800)
Called pseudoku.render; currently contains classes for rendering to a
single line, a simple grid of symbols, or an ascii-art grid.

pseudoku/__init__.py
pseudoku/grid/__init__.py
pseudoku/render/__init__.py [new file with mode: 0644]
pseudoku/render/text.py [new file with mode: 0644]

index 3b6eeb9..853904b 100644 (file)
@@ -1,4 +1,5 @@
 from grid import Grid
+import render.text
 
 def main():
     grid = Grid.from_string("""
@@ -13,8 +14,9 @@ def main():
         1...6...9
     """)
 
-    print grid
+    r = render.text.AsciiArtGridRenderer()
+    print r.render_grid(grid)
 
     grid.solve()
 
-    print grid
+    print r.render_grid(grid)
index 2f77aaf..9370dd6 100644 (file)
@@ -117,14 +117,6 @@ class Cell(object):
             self.normalize()
 
 
-    def __str__(self):
-        """Stringification for pretty-printing."""
-        if self.value != None:
-            return symbols[self.value]
-
-        return '.'
-
-
 class Grid(object):
     """Represents a Sudoku grid."""
 
@@ -302,31 +294,3 @@ class Grid(object):
         """Normalizes every cell in the grid."""
         for cell in self._cells:
             cell.normalize()
-
-
-    def __str__(self):
-        """Pretty-printing."""
-        divider = '+'
-        for box in xrange(self._box_height):
-            for col in xrange(self._box_width):
-                divider += '-'
-            divider += '+'
-
-        res = ''
-        for row in xrange(self._size):
-            if row % self._box_height == 0:
-                res += divider
-                res += "\n"
-
-            for col in xrange(self._size):
-                if col % self._box_width == 0:
-                    res += '|'
-                res += str(self.cell(row, col))
-
-            res += '|'
-            res += "\n"
-
-        res += divider
-        res += "\n"
-
-        return res
diff --git a/pseudoku/render/__init__.py b/pseudoku/render/__init__.py
new file mode 100644 (file)
index 0000000..fb700bd
--- /dev/null
@@ -0,0 +1,94 @@
+from ..grid import symbols
+
+class GridRenderer(object):
+    """Class that renders a grid in some human-consumable form.
+    
+    This base class's methods result in a flat string of symbols, but it's easy
+    to create a more useful rendering by just overriding a few methods.
+    """
+
+    def render_grid(self, grid):
+        """Renders the entire grid.  Code on the outside probably only needs to
+        call this.
+
+        Returns a string.
+        """
+        parts = []
+
+        parts.append(self.before_grid(grid))
+        for idx, row in enumerate(grid._rows):
+            if idx and idx % grid._box_height == 0:
+                parts.append(self.inside_grid(grid))
+            parts.append(self.render_row(row))
+        parts.append(self.after_grid(grid))
+
+        return ''.join(parts)
+
+    def render_row(self, row):
+        """Renders a single row."""
+        parts = []
+
+        parts.append(self.before_row(row))
+        for idx, cell in enumerate(row.cells):
+            if idx and idx % row._grid._box_width == 0:
+                parts.append(self.inside_row(row))
+            parts.extend(self.render_cell(cell))
+        parts.append(self.after_row(row))
+
+        return ''.join(parts)
+
+    def render_cell(self, cell):
+        """Renders a single cell."""
+        return ''.join([
+            self.before_cell(cell),
+            self.inside_cell(cell),
+            self.after_cell(cell),
+        ])
+
+
+    def before_grid(self, grid):
+        """Content prepended before the entire grid."""
+        return self.inside_grid(grid)
+
+    def inside_grid(self, grid):
+        """Content inserted within the grid, between boxes."""
+        return ''
+
+    def after_grid(self, grid):
+        """Content appended after the entire grid."""
+        return self.inside_grid(grid)
+
+
+    def before_row(self, row):
+        """Content prepended before each row."""
+        return self.inside_row(row)
+
+    def inside_row(self, row):
+        """Content inserted within each row, between boxes."""
+        return ''
+
+    def after_row(self, row):
+        """Content appended after each row.
+
+        Note that newlines are not assumed; you must provide one if you want
+        one included in the rendering.
+        """
+
+        return self.inside_row(row)
+
+
+    def before_cell(self, cell):
+        """Content prepended before each cell in a row."""
+        return ''
+
+    def inside_cell(self, cell):
+        """Content used to represent the actual cell value."""
+        if cell.value:
+            return symbols[cell.value]
+        else:
+            return '.'
+
+    def after_cell(self, cell):
+        """Content appended after each row in a cell."""
+        return ''
+
diff --git a/pseudoku/render/text.py b/pseudoku/render/text.py
new file mode 100644 (file)
index 0000000..aab6c36
--- /dev/null
@@ -0,0 +1,37 @@
+from . import GridRenderer
+from ..grid import symbols
+
+class LineGridRenderer(GridRenderer):
+    """Renders a grid into a flat string, as puzzles are often presented in
+    plaintext collections.
+    """
+    pass
+
+
+class SquareGridRenderer(GridRenderer):
+    """Renders a grid as a square of characters."""
+
+    def after_row(self, row, new_box=False):
+        return '\n'
+
+
+class AsciiArtGridRenderer(SquareGridRenderer):
+    """Renders a questionably-pretty ASCII art drawing of a grid, with dividers
+    between rows and columns.
+    """
+
+    def inside_grid(self, grid):
+        box_header = '+' + '-' * grid._box_width
+        return box_header * grid._box_height + '+\n'
+
+    def inside_row(self, row):
+        return '|'
+
+    def after_row(self, row):
+        return '|\n'
+
+    def inside_cell(self, cell):
+        if cell.value:
+            return symbols[cell.value]
+        else:
+            return ' '