| 178 | |
| 179 | |
| 180 | def write_svg() -> None: |
| 181 | root_y = 72 |
| 182 | closed_group_y = 170 |
| 183 | open_group_y = 610 |
| 184 | closed_ys = [220 + idx * 44 for idx in range(len(CLOSED_ROWS))] |
| 185 | open_ys = [660 + idx * 44 for idx in range(len(OPEN_ROWS))] |
| 186 | stem_x = GROUP_X + 84 |
| 187 | leaf_join_x = LEAF_X - 26 |
| 188 | bar_x = VALUE_X - MAX_BAR_W - 20 |
| 189 | |
| 190 | parts = [ |
| 191 | f'<svg xmlns="http://www.w3.org/2000/svg" width="{W}" height="{H}" viewBox="0 0 {W} {H}">', |
| 192 | '<rect width="100%" height="100%" fill="white"/>', |
| 193 | f'<line x1="{ROOT_X + 72}" y1="{root_y + 27}" x2="{ROOT_X + 72}" y2="{open_group_y}" stroke="{rgb(LINE)}" stroke-width="2"/>', |
| 194 | ] |
| 195 | |
| 196 | for group_y, leaf_ys, color in [(closed_group_y, closed_ys, CLOSED), (open_group_y, open_ys, OPEN)]: |
| 197 | parts.append(f'<line x1="{ROOT_X + 72}" y1="{group_y}" x2="{GROUP_X - 64}" y2="{group_y}" stroke="{rgb(LINE)}" stroke-width="2"/>') |
| 198 | parts.append(f'<line x1="{GROUP_X + 72}" y1="{group_y}" x2="{stem_x}" y2="{group_y}" stroke="{rgb(LINE)}" stroke-width="2"/>') |
| 199 | parts.append(f'<line x1="{stem_x}" y1="{min(leaf_ys)}" x2="{stem_x}" y2="{max(leaf_ys)}" stroke="{rgb(LINE)}" stroke-width="2"/>') |
| 200 | for y in leaf_ys: |
| 201 | parts.append(f'<line x1="{stem_x}" y1="{y}" x2="{leaf_join_x}" y2="{y}" stroke="{rgb(LINE)}" stroke-width="2"/>') |
| 202 | parts.append(f'<circle cx="{leaf_join_x}" cy="{y}" r="5" fill="{rgb(color)}"/>') |
| 203 | |
| 204 | parts.extend(svg_node(ROOT_X + 72, root_y, "TokenCost", 30, TEXT)) |
| 205 | parts.extend(svg_node(GROUP_X, closed_group_y, "Closed API", 27, CLOSED)) |
| 206 | parts.extend(svg_node(GROUP_X, open_group_y, "Open / open-access", 27, OPEN)) |
| 207 | |
| 208 | for y, (name, value) in zip(closed_ys, CLOSED_ROWS): |
| 209 | color = PAPERFLOW if name == "PaperFlow" else CLOSED |
| 210 | label_color = PAPERFLOW if name == "PaperFlow" else TEXT |
| 211 | bar_w = round((value / MAX_VALUE) * MAX_BAR_W) |
| 212 | parts.append(f'<text x="{LEAF_X}" y="{y + 8}" font-family="Times New Roman" font-size="24" font-weight="700" fill="{rgb(label_color)}">{name}</text>') |
| 213 | parts.append(f'<rect x="{bar_x}" y="{y - 9}" width="{MAX_BAR_W}" height="18" rx="5" fill="{rgb(BAR_BG)}"/>') |
| 214 | parts.append(f'<rect x="{bar_x}" y="{y - 9}" width="{bar_w}" height="18" rx="5" fill="{rgb(color)}"/>') |
| 215 | parts.append(f'<text x="{VALUE_X}" y="{y + 8}" font-family="Times New Roman" font-size="22" font-weight="700" fill="{rgb(color)}">{value / 1_000_000:.1f}M</text>') |
| 216 | |
| 217 | for y, (name, value) in zip(open_ys, OPEN_ROWS): |
| 218 | bar_w = round((value / MAX_VALUE) * MAX_BAR_W) |
| 219 | parts.append(f'<text x="{LEAF_X}" y="{y + 8}" font-family="Times New Roman" font-size="24" font-weight="700" fill="{rgb(TEXT)}">{name}</text>') |
| 220 | parts.append(f'<rect x="{bar_x}" y="{y - 9}" width="{MAX_BAR_W}" height="18" rx="5" fill="{rgb(BAR_BG)}"/>') |
| 221 | parts.append(f'<rect x="{bar_x}" y="{y - 9}" width="{bar_w}" height="18" rx="5" fill="{rgb(OPEN)}"/>') |
| 222 | parts.append(f'<text x="{VALUE_X}" y="{y + 8}" font-family="Times New Roman" font-size="22" font-weight="700" fill="{rgb(OPEN)}">{value / 1_000_000:.1f}M</text>') |
| 223 | |
| 224 | parts.append("</svg>") |
| 225 | SVG_OUT.write_text("\n".join(parts), encoding="utf-8") |
| 226 | |
| 227 | |
| 228 | def main() -> None: |