TRX/docs/render_progress

149 lines
3.6 KiB
Text
Raw Normal View History

2021-02-11 00:26:17 +01:00
#!/usr/bin/python3
import re
2021-02-11 00:26:17 +01:00
import typing as T
from dataclasses import dataclass
from pathlib import Path
MAX_X = 50
SQUARE_SIZE = 10
TEXT_SIZE = 15
2021-02-11 00:26:17 +01:00
SQUARE_MARGIN = 2
DOCS_DIR = Path(__file__).parent
PROGRESS_TXT_FILE = DOCS_DIR / "progress.txt"
PROGRESS_SVG_FILE = DOCS_DIR / "progress.svg"
2021-02-12 13:09:45 +01:00
COLOR_DECOMPILED = "green"
COLOR_TODO = "pink"
2021-02-11 00:26:17 +01:00
@dataclass
class Function:
name: str
offset: int
size: int
flags: str
@property
2021-02-12 13:09:45 +01:00
def is_decompiled(self):
2021-02-11 00:26:17 +01:00
return "+" in self.flags
def collect_functions() -> T.Iterable[Function]:
for line in PROGRESS_TXT_FILE.open():
if line.startswith("#"):
continue
func_name, offset, size, flags = re.split(r"\s+", line.strip())
yield Function(
name=func_name,
offset=int(offset, 16),
size=int(size, 16),
flags=flags,
)
2021-02-12 13:09:45 +01:00
class Shape:
@property
def bounds(self) -> T.Tuple[int, int, int, int]:
raise NotImplementedError("not implemented")
def render(self) -> str:
raise NotImplementedError("not implemented")
@dataclass
class Square(Shape):
x: int
y: int
color: str
@property
def bounds(self) -> T.Tuple[int, int, int, int]:
return (self.x, self.y, self.x + SQUARE_SIZE, self.y + SQUARE_SIZE)
def render(self) -> str:
return (
f"<rect "
f'width="{SQUARE_SIZE}" '
f'height="{SQUARE_SIZE}" '
f'x="{self.x}" '
f'y="{self.y}" '
f'fill="{self.color}"/>'
)
@dataclass
class Text(Shape):
x: int
y: int
text: str
@property
def bounds(self) -> T.Tuple[int, int, int, int]:
return (self.x, self.y, self.x, self.y + TEXT_SIZE)
def render(self) -> str:
return (
f'<text x="{self.x}" y="{self.y}" '
f'style="font-family: sans-serif; font-size: {TEXT_SIZE}px">'
f"{self.text}"
f"</text>"
)
def render_svg(functions: T.List[Function]) -> T.Iterable[Shape]:
for i, function in enumerate(functions):
x = (i % MAX_X) * (SQUARE_SIZE + SQUARE_MARGIN)
y = (i // MAX_X) * (SQUARE_SIZE + SQUARE_MARGIN)
if function.is_decompiled:
color = COLOR_DECOMPILED
else:
color = COLOR_TODO
yield Square(x=x, y=y, color=color)
y += SQUARE_SIZE
y += TEXT_SIZE
ready_functions = sum(function.is_decompiled for function in functions)
total_functions = len(functions)
ready_size = sum(
function.size for function in functions if function.is_decompiled
)
total_size = sum(function.size for function in functions)
2021-02-11 00:26:17 +01:00
2021-02-12 13:09:45 +01:00
yield Text(
x=0,
y=y,
text=f"Functions decompiled (count): {ready_functions/total_functions:.02%}",
2021-02-11 00:26:17 +01:00
)
2021-02-12 13:09:45 +01:00
y += TEXT_SIZE + SQUARE_MARGIN
yield Text(
x=0,
y=y,
text=f"Functions decompiled (bytesize): {ready_size/total_size:.02%}",
)
2021-02-11 00:26:17 +01:00
2021-02-12 13:09:45 +01:00
def main() -> None:
functions = list(collect_functions())
2021-02-11 00:26:17 +01:00
with PROGRESS_SVG_FILE.open("w") as handle:
2021-02-12 13:09:45 +01:00
shapes = list(render_svg(functions))
svg_width = max(shape.bounds[2] for shape in shapes)
svg_height = max(shape.bounds[3] for shape in shapes)
2021-02-11 00:26:17 +01:00
print(
f'<svg version="1.1" '
f'width="{svg_width}" '
f'height="{svg_height}" '
f'xmlns="http://www.w3.org/2000/svg">',
file=handle,
)
2021-02-12 13:09:45 +01:00
for shape in shapes:
print(shape.render(), file=handle)
2021-02-11 00:26:17 +01:00
print("</svg>", file=handle)
if __name__ == "__main__":
main()