Refactor generator `traylayout`
* Use generic argument `sx` and `sy` to generate text traylayout * Add typing * Fix code style
This commit is contained in:
parent
0e4e373367
commit
fa2b2fe466
|
@ -13,81 +13,86 @@
|
||||||
#
|
#
|
||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
import boxes
|
import boxes
|
||||||
from boxes import *
|
from boxes import *
|
||||||
|
|
||||||
|
|
||||||
class TrayLayout(Boxes):
|
class TrayLayout(Boxes):
|
||||||
"""Generate a typetray from a layout file"""
|
"""Generate a layout file for a typetray."""
|
||||||
# This class generates the skeleton text file that can then be edited
|
# This class generates the skeleton text file that can then be edited
|
||||||
# to describe the actual box
|
# to describe the actual box
|
||||||
|
|
||||||
description = """This is a two step process. The layout is based on a grid
|
description = """This is a two step process. This is step 1.
|
||||||
of sizes in x and y direction. Choose how many distances you need in both directions. The actual sizes and all other settings can be entered in the second step."""
|
The layout is based on a grid of sizes in x and y direction.
|
||||||
|
Choose how many distances you need in both directions.
|
||||||
|
The actual sizes and all other settings can be entered in the second step."""
|
||||||
|
|
||||||
webinterface = True
|
webinterface = True
|
||||||
|
|
||||||
ui_group = "Tray"
|
ui_group = "Tray"
|
||||||
|
|
||||||
|
sx: list[float] = [] # arg input
|
||||||
|
sy: list[float] = [] # arg input
|
||||||
|
hwalls: list[list[bool]] = []
|
||||||
|
vwalls: list[list[bool]] = []
|
||||||
|
floors: list[list[bool]] = []
|
||||||
|
|
||||||
def __init__(self, input=None, webargs=False) -> None:
|
def __init__(self, input=None, webargs=False) -> None:
|
||||||
Boxes.__init__(self)
|
Boxes.__init__(self)
|
||||||
self.argparser = argparse.ArgumentParser()
|
self.argparser = argparse.ArgumentParser()
|
||||||
self.argparser.add_argument(
|
self.buildArgParser("sx", "sy")
|
||||||
"--x", action="store", type=int, default=2,
|
|
||||||
help="number of compartments side by side")
|
|
||||||
self.argparser.add_argument(
|
|
||||||
"--y", action="store", type=int, default=2,
|
|
||||||
help="number of compartments back to front")
|
|
||||||
self.argparser.add_argument(
|
self.argparser.add_argument(
|
||||||
"--output", action="store", type=str, default="traylayout.txt",
|
"--output", action="store", type=str, default="traylayout.txt",
|
||||||
help="name of the layout text file")
|
help="Name of the layout text file.")
|
||||||
|
|
||||||
# Use empty open and close methods to avoid initializing the whole
|
def open(self) -> None:
|
||||||
# drawing infrastructure
|
# Use empty open and close methods to avoid initializing the whole drawing infrastructure.
|
||||||
|
|
||||||
def open(self):
|
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def close(self):
|
def close(self) -> None:
|
||||||
|
# Use empty open and close methods to avoid initializing the whole drawing infrastructure.
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def fillDefault(self, x, y):
|
def fillDefault(self, sx: list[float], sy: list[float]) -> None:
|
||||||
self.x = [0.0] * x
|
self.sx = sx
|
||||||
self.y = [0.0] * y
|
self.sy = sy
|
||||||
self.hwalls = [[True for i in range(x)] for j in range(y + 1)]
|
x = len(sx)
|
||||||
self.vwalls = [[True for i in range(x + 1)] for j in range(y)]
|
y = len(sy)
|
||||||
self.floors = [[True for i in range(x)] for j in range(y)]
|
self.hwalls = [[True for _ in range(x)] for _ in range(y + 1)]
|
||||||
|
self.vwalls = [[True for _ in range(x + 1)] for _ in range(y)]
|
||||||
|
self.floors = [[True for _ in range(x)] for _ in range(y)]
|
||||||
|
|
||||||
def __str__(self) -> str:
|
def __str__(self) -> str:
|
||||||
r = []
|
r = []
|
||||||
|
|
||||||
for i, x in enumerate(self.x):
|
for i, x in enumerate(self.sx):
|
||||||
r.append(" |" * (i) + " ,> %.1fmm\n" % x)
|
r.append(" |" * i + " ,> %.1fmm\n" % x)
|
||||||
|
|
||||||
for hwalls, vwalls, floors, y in zip(
|
for hwalls, vwalls, floors, y in zip(self.hwalls, self.vwalls, self.floors, self.sy):
|
||||||
self.hwalls, self.vwalls, self.floors, self.y):
|
|
||||||
r.append("".join("+" + " -"[h] for h in hwalls) + "+\n")
|
r.append("".join("+" + " -"[h] for h in hwalls) + "+\n")
|
||||||
r.append("".join((" |"[v] + "X "[f] for v, f in zip(vwalls, floors)))
|
r.append("".join((" |"[v] + "X "[f] for v, f in zip(vwalls, floors))) + " |"[vwalls[-1]] + " %.1fmm\n" % y)
|
||||||
+ " |"[vwalls[-1]] + " %.1fmm\n" % y)
|
|
||||||
r.append("".join("+" + " -"[h] for h in self.hwalls[-1]) + "+\n")
|
r.append("".join("+" + " -"[h] for h in self.hwalls[-1]) + "+\n")
|
||||||
|
|
||||||
return "".join(r)
|
return "".join(r)
|
||||||
|
|
||||||
def render(self):
|
def render(self) -> None:
|
||||||
self.fillDefault(self.x, self.y)
|
self.fillDefault(self.sx, self.sy)
|
||||||
with open(self.output, 'w') as f:
|
with open(self.output, 'w') as f:
|
||||||
f.write(str(self))
|
f.write(str(self))
|
||||||
|
|
||||||
class TrayLayout2(TrayLayout):
|
|
||||||
"""Generate a typetray from a layout file"""
|
class TrayLayout2(Boxes):
|
||||||
|
"""Generate a typetray from a layout file."""
|
||||||
|
|
||||||
# This class reads in the layout either from a file (with --input) or
|
# This class reads in the layout either from a file (with --input) or
|
||||||
# as string (with --layout) and turns it into a drawing for a box.
|
# as string (with --layout) and turns it into a drawing for a box.
|
||||||
|
|
||||||
webinterface = True
|
webinterface = True
|
||||||
|
|
||||||
description = """Edit the layout text graphics to adjust your tray.
|
description = """This is a two step process. This is step 2.
|
||||||
|
Edit the layout text graphics to adjust your tray.
|
||||||
Put in the sizes for each column and row. You can replace the hyphens and
|
Put in the sizes for each column and row. You can replace the hyphens and
|
||||||
vertical bars representing the walls with a space character to remove the walls.
|
vertical bars representing the walls with a space character to remove the walls.
|
||||||
You can replace the space characters representing the floor by a "X" to remove the floor for this compartment.
|
You can replace the space characters representing the floor by a "X" to remove the floor for this compartment.
|
||||||
|
@ -100,30 +105,24 @@ You can replace the space characters representing the floor by a "X" to remove t
|
||||||
if not webargs:
|
if not webargs:
|
||||||
self.argparser.add_argument(
|
self.argparser.add_argument(
|
||||||
"--input", action="store", type=argparse.FileType('r'),
|
"--input", action="store", type=argparse.FileType('r'),
|
||||||
default='traylayout.txt',
|
default="traylayout.txt",
|
||||||
help="layout file")
|
help="layout file")
|
||||||
self.layout = None
|
self.layout = None
|
||||||
else:
|
else:
|
||||||
self.argparser.add_argument(
|
self.argparser.add_argument(
|
||||||
"--layout", action="store", type=str, default="")
|
"--layout", action="store", type=str, default="")
|
||||||
|
|
||||||
# Use normal open and close
|
def vWalls(self, x: int, y: int) -> int:
|
||||||
open = Boxes.open
|
"""Number of vertical walls at a crossing."""
|
||||||
close = Boxes.close
|
|
||||||
|
|
||||||
def vWalls(self, x, y):
|
|
||||||
"""Number of vertical walls at a crossing"""
|
|
||||||
result = 0
|
result = 0
|
||||||
if y > 0 and self.vwalls[y - 1][x]:
|
if y > 0 and self.vwalls[y - 1][x]:
|
||||||
result += 1
|
result += 1
|
||||||
|
|
||||||
if y < len(self.y) and self.vwalls[y][x]:
|
if y < len(self.y) and self.vwalls[y][x]:
|
||||||
result += 1
|
result += 1
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def hWalls(self, x, y):
|
def hWalls(self, x: int, y: int) -> int:
|
||||||
"""Number of horizontal walls at a crossing"""
|
"""Number of horizontal walls at a crossing."""
|
||||||
result = 0
|
result = 0
|
||||||
if x > 0 and self.hwalls[y][x - 1]:
|
if x > 0 and self.hwalls[y][x - 1]:
|
||||||
result += 1
|
result += 1
|
||||||
|
@ -131,22 +130,18 @@ You can replace the space characters representing the floor by a "X" to remove t
|
||||||
result += 1
|
result += 1
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def vFloor(self, x, y):
|
def vFloor(self, x: int, y: int) -> bool:
|
||||||
"""Is there floor under vertical wall"""
|
"""Is there floor under vertical wall."""
|
||||||
if y >= len(self.y):
|
if y >= len(self.y):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
return (
|
return (x > 0 and self.floors[y][x - 1]) or (x < len(self.x) and self.floors[y][x])
|
||||||
(x > 0 and self.floors[y][x - 1]) or
|
|
||||||
(x < len(self.x) and self.floors[y][x]))
|
|
||||||
|
|
||||||
def hFloor(self, x, y):
|
def hFloor(self, x: int, y: int) -> bool:
|
||||||
"""Is there foor under horizontal wall"""
|
"""Is there floor under horizontal wall."""
|
||||||
if x >= len(self.x):
|
if x >= len(self.x):
|
||||||
return False
|
return False
|
||||||
return (
|
return (y > 0 and self.floors[y - 1][x]) or (y < len(self.y) and self.floors[y][x])
|
||||||
(y > 0 and self.floors[y - 1][x]) or
|
|
||||||
(y < len(self.y) and self.floors[y][x]))
|
|
||||||
|
|
||||||
@restore
|
@restore
|
||||||
def edgeAt(self, edge, x, y, length, angle=0):
|
def edgeAt(self, edge, x, y, length, angle=0):
|
||||||
|
@ -168,7 +163,7 @@ You can replace the space characters representing the floor by a "X" to remove t
|
||||||
if self.hi:
|
if self.hi:
|
||||||
self.hi = self.adjustSize(self.hi, e2=False)
|
self.hi = self.adjustSize(self.hi, e2=False)
|
||||||
|
|
||||||
self.hi = hi = self.hi or self.h
|
self.hi = self.hi or self.h
|
||||||
self.edges["s"] = boxes.edges.Slot(self, self.hi / 2.0)
|
self.edges["s"] = boxes.edges.Slot(self, self.hi / 2.0)
|
||||||
self.edges["C"] = boxes.edges.CrossingFingerHoleEdge(self, self.hi)
|
self.edges["C"] = boxes.edges.CrossingFingerHoleEdge(self, self.hi)
|
||||||
self.edges["D"] = boxes.edges.CrossingFingerHoleEdge(self, self.hi, outset=self.thickness)
|
self.edges["D"] = boxes.edges.CrossingFingerHoleEdge(self, self.hi, outset=self.thickness)
|
||||||
|
@ -176,10 +171,9 @@ You can replace the space characters representing the floor by a "X" to remove t
|
||||||
def walls(self, move=None):
|
def walls(self, move=None):
|
||||||
lx = len(self.x)
|
lx = len(self.x)
|
||||||
ly = len(self.y)
|
ly = len(self.y)
|
||||||
t = self.thickness
|
# t = self.thickness
|
||||||
b = self.burn
|
# b = self.burn
|
||||||
t2 = self.thickness / 2.0
|
# t2 = self.thickness / 2.0
|
||||||
|
|
||||||
|
|
||||||
self.ctx.save()
|
self.ctx.save()
|
||||||
|
|
||||||
|
@ -212,8 +206,7 @@ You can replace the space characters representing the floor by a "X" to remove t
|
||||||
edges.append("E")
|
edges.append("E")
|
||||||
|
|
||||||
lengths.append(self.x[end])
|
lengths.append(self.x[end])
|
||||||
if (self.hFloor(end, y) == 0 and
|
if self.hFloor(end, y) == 0 and self.hFloor(end + 1, y) == 0:
|
||||||
self.hFloor(end+1, y) == 0):
|
|
||||||
edges.append("EDs"[self.vWalls(end + 1, y)])
|
edges.append("EDs"[self.vWalls(end + 1, y)])
|
||||||
else:
|
else:
|
||||||
edges.append("eCs"[self.vWalls(end + 1, y)])
|
edges.append("eCs"[self.vWalls(end + 1, y)])
|
||||||
|
@ -235,7 +228,6 @@ You can replace the space characters representing the floor by a "X" to remove t
|
||||||
self.rectangularWall(10, h, "ffef", move="up only")
|
self.rectangularWall(10, h, "ffef", move="up only")
|
||||||
self.ctx.save()
|
self.ctx.save()
|
||||||
|
|
||||||
|
|
||||||
# Vertical Walls
|
# Vertical Walls
|
||||||
for x in range(lx + 1):
|
for x in range(lx + 1):
|
||||||
if x == 0 or x == lx:
|
if x == 0 or x == lx:
|
||||||
|
@ -263,8 +255,7 @@ You can replace the space characters representing the floor by a "X" to remove t
|
||||||
edges.append("E")
|
edges.append("E")
|
||||||
|
|
||||||
lengths.append(self.y[end])
|
lengths.append(self.y[end])
|
||||||
if (self.vFloor(x, end) == 0 and
|
if self.vFloor(x, end) == 0 and self.vFloor(x, end + 1) == 0:
|
||||||
self.vFloor(x, end + 1) == 0):
|
|
||||||
edges.append("EDs"[self.hWalls(x, end + 1)])
|
edges.append("EDs"[self.hWalls(x, end + 1)])
|
||||||
else:
|
else:
|
||||||
edges.append("eCs"[self.hWalls(x, end + 1)])
|
edges.append("eCs"[self.hWalls(x, end + 1)])
|
||||||
|
@ -274,13 +265,12 @@ You can replace the space characters representing the floor by a "X" to remove t
|
||||||
lengths.pop()
|
lengths.pop()
|
||||||
edges.pop()
|
edges.pop()
|
||||||
|
|
||||||
upper = [{
|
upper = [{"f": "e",
|
||||||
"f": "e",
|
"s": "s",
|
||||||
"s": "s",
|
"e": "e",
|
||||||
"e": "e",
|
"E": "e",
|
||||||
"E": "e",
|
"C": "e",
|
||||||
"C": "e",
|
"D": "e"}[e] for e in reversed(edges)]
|
||||||
"D": "e"}[e] for e in reversed(edges)]
|
|
||||||
edges = ["e" if e == "s" else e for e in edges]
|
edges = ["e" if e == "s" else e for e in edges]
|
||||||
self.rectangularWall(sum(lengths), h, [
|
self.rectangularWall(sum(lengths), h, [
|
||||||
boxes.edges.CompoundEdge(self, edges, lengths),
|
boxes.edges.CompoundEdge(self, edges, lengths),
|
||||||
|
@ -300,7 +290,7 @@ You can replace the space characters representing the floor by a "X" to remove t
|
||||||
b = self.burn
|
b = self.burn
|
||||||
t2 = self.thickness / 2.0
|
t2 = self.thickness / 2.0
|
||||||
|
|
||||||
tw, th = sum(self.x) + (lx+1) * t, sum(self.y) + (ly + 1) * t
|
tw, th = sum(self.x) + (lx + 1) * t, sum(self.y) + (ly + 1) * t
|
||||||
|
|
||||||
if self.move(tw, th, move, True):
|
if self.move(tw, th, move, True):
|
||||||
return
|
return
|
||||||
|
@ -370,7 +360,7 @@ You can replace the space characters representing the floor by a "X" to remove t
|
||||||
if x == 0 or y == 0 or not self.floors[y - 1][x - 1]:
|
if x == 0 or y == 0 or not self.floors[y - 1][x - 1]:
|
||||||
self.edgeAt("e", posx - b, posy + self.y[y] + t, t, -90)
|
self.edgeAt("e", posx - b, posy + self.y[y] + t, t, -90)
|
||||||
if x == 0 or y == ly - 1 or not self.floors[y + 1][x - 1]:
|
if x == 0 or y == ly - 1 or not self.floors[y + 1][x - 1]:
|
||||||
self.edgeAt("e", posx -b, posy, t, -90)
|
self.edgeAt("e", posx - b, posy, t, -90)
|
||||||
posy += self.y[y] + self.thickness
|
posy += self.y[y] + self.thickness
|
||||||
if x < lx:
|
if x < lx:
|
||||||
posx += self.x[x] + self.thickness
|
posx += self.x[x] + self.thickness
|
||||||
|
@ -392,7 +382,7 @@ You can replace the space characters representing the floor by a "X" to remove t
|
||||||
continue
|
continue
|
||||||
if line[0] == '+':
|
if line[0] == '+':
|
||||||
w = []
|
w = []
|
||||||
for n, c in enumerate(line[:len(x)*2 + 1]):
|
for n, c in enumerate(line[:len(x) * 2 + 1]):
|
||||||
if n % 2:
|
if n % 2:
|
||||||
if c == ' ':
|
if c == ' ':
|
||||||
w.append(False)
|
w.append(False)
|
||||||
|
@ -417,20 +407,20 @@ You can replace the space characters representing the floor by a "X" to remove t
|
||||||
elif c == ' ':
|
elif c == ' ':
|
||||||
f.append(True)
|
f.append(True)
|
||||||
else:
|
else:
|
||||||
raise ValueError('''Can't parse line %i in layout: expected " ", "x" or "X" for char #%i''' % (nr+1, n+1))
|
raise ValueError("""Can't parse line %i in layout: expected " ", "x" or "X" for char #%i""" % (nr + 1, n + 1))
|
||||||
else:
|
else:
|
||||||
if c == ' ':
|
if c == ' ':
|
||||||
w.append(False)
|
w.append(False)
|
||||||
elif c == '|':
|
elif c == '|':
|
||||||
w.append(True)
|
w.append(True)
|
||||||
else:
|
else:
|
||||||
raise ValueError('''Can't parse line %i in layout: expected " ", or "|" for char #%i''' % (nr+1, n+1))
|
raise ValueError("""Can't parse line %i in layout: expected " ", or "|" for char #%i""" % (nr + 1, n + 1))
|
||||||
|
|
||||||
floors.append(f)
|
floors.append(f)
|
||||||
vwalls.append(w)
|
vwalls.append(w)
|
||||||
m = re.match(r"([ |][ xX])+[ |]\s*(\d*\.?\d+)\s*mm\s*", line)
|
m = re.match(r"([ |][ xX])+[ |]\s*(\d*\.?\d+)\s*mm\s*", line)
|
||||||
if not m:
|
if not m:
|
||||||
raise ValueError('''Can't parse line %i in layout: Can read height of the row''' % (nr+1))
|
raise ValueError("""Can't parse line %i in layout: Can read height of the row""" % (nr + 1))
|
||||||
else:
|
else:
|
||||||
y.append(float(m.group(2)))
|
y.append(float(m.group(2)))
|
||||||
|
|
||||||
|
@ -451,8 +441,7 @@ You can replace the space characters representing the floor by a "X" to remove t
|
||||||
raise ValueError("Wrong number of vertical wall lines: %i (%i expected)" % (len(vwalls), ly))
|
raise ValueError("Wrong number of vertical wall lines: %i (%i expected)" % (len(vwalls), ly))
|
||||||
for nr, walls in enumerate(vwalls):
|
for nr, walls in enumerate(vwalls):
|
||||||
if len(walls) != lx + 1:
|
if len(walls) != lx + 1:
|
||||||
raise ValueError(
|
raise ValueError("Wrong number of vertical walls in line %i: %i (%i expected)" % (nr, len(walls), lx + 1))
|
||||||
"Wrong number of vertical walls in line %i: %i (%i expected)" % (nr, len(walls), lx + 1))
|
|
||||||
|
|
||||||
self.x = x
|
self.x = x
|
||||||
self.y = y
|
self.y = y
|
||||||
|
@ -460,7 +449,7 @@ You can replace the space characters representing the floor by a "X" to remove t
|
||||||
self.vwalls = vwalls
|
self.vwalls = vwalls
|
||||||
self.floors = floors
|
self.floors = floors
|
||||||
|
|
||||||
def render(self):
|
def render(self) -> None:
|
||||||
self.prepare()
|
self.prepare()
|
||||||
self.walls()
|
self.walls()
|
||||||
self.base_plate()
|
self.base_plate()
|
||||||
|
|
|
@ -620,7 +620,7 @@ class BServer:
|
||||||
return self.genPageError(name, e, lang)
|
return self.genPageError(name, e, lang)
|
||||||
if name == "TrayLayout":
|
if name == "TrayLayout":
|
||||||
start_response(status, headers)
|
start_response(status, headers)
|
||||||
box.fillDefault(box.x, box.y)
|
box.fillDefault(box.sx, box.sy)
|
||||||
layout2 = boxes.generators.traylayout.TrayLayout2(self, webargs=True)
|
layout2 = boxes.generators.traylayout.TrayLayout2(self, webargs=True)
|
||||||
layout2.argparser.set_defaults(layout=str(box))
|
layout2.argparser.set_defaults(layout=str(box))
|
||||||
return self.args2html(name, layout2, lang, action="TrayLayout2")
|
return self.args2html(name, layout2, lang, action="TrayLayout2")
|
||||||
|
|
Loading…
Reference in New Issue