from datetime import datetime from structures import Gantt, Row, Job from gantt_types import Second, Millisecond import structures import utility import operator COLORS = [ "#d50000", "#00bfa5", "#ff6f00", "#aa00ff", "#006064", "#ffd600", "#64dd17", ] HEADER_COLUMN_WIDTH = 240 def ms_to_px(ms: Millisecond) -> float: return ms / 10 def job_to_html(job: Job, start: datetime, color: str) -> str: left = ms_to_px(utility.duration_ms(start, job.start)) + HEADER_COLUMN_WIDTH width = ms_to_px(structures.job_duration_ms(job)) return f"""""" def row_to_html( row: Row, start: datetime, process_num: int, color: str, width: float ) -> str: legend_html = f"""Concurrency Slot {process_num} ({utility.ms_to_s(structures.row_computing_duration_ms(row)):.1f}s)""" jobs_html = "\n".join([job_to_html(job, start, color) for job in row.jobs]) return ( f"""
{legend_html}{jobs_html}
""" ) def rownum_to_top(num: int) -> float: return num * 2 def make_axis_span(left: float, s: Second) -> str: return f"""{s} sec""" def make_axis_html(max_seconds: Second) -> str: seconds = [Second(i * 2) for i in range(1000)] seconds = [i for i in seconds if i < max_seconds] axis_spans = "".join( [ make_axis_span(ms_to_px(utility.s_to_ms(s)) + HEADER_COLUMN_WIDTH, s) for s in seconds ] ) return f"""
Total Processing Time {axis_spans}
""" def gantt_to_html(g: Gantt) -> str: if not g: return "" start = min([row.jobs[0].start for row in g]) max_seconds = max([utility.ms_to_s(structures.row_duration_ms(row)) for row in g]) rows_html = "\n".join( [ row_to_html( row, start, num + 1, COLORS[num % len(COLORS)], ms_to_px(utility.s_to_ms(max_seconds)) + HEADER_COLUMN_WIDTH, ) for num, row in enumerate( sorted( g, reverse=True, key=lambda r: structures.row_computing_duration_ms(r), ) ) ] ) return f"""
{make_axis_html(max_seconds)}{rows_html}
""" def style() -> str: with open("./gantt/output.css") as css: return f"""""" def html(g: Gantt) -> str: html = f"""

Gantt Chart

Max parallelism: {len(g)}

{gantt_to_html(g)}

Explanation

{style()} """ return html if g else ""