feat: updated questions obrona magister
589
pytania/generate_arch_diagrams.py
Normal file
@ -0,0 +1,589 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
Generate architecture modeling diagrams for PYTANIE 13 (AIS):
|
||||||
|
1. TOGAF ADM cycle
|
||||||
|
2. 4+1 View Model (Kruchten)
|
||||||
|
3. C4 Model — 4 zoom levels
|
||||||
|
4. Zachman Framework grid
|
||||||
|
5. ArchiMate layers
|
||||||
|
|
||||||
|
All: A4-compatible, B&W, 300 DPI, laser-printer-friendly.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import matplotlib
|
||||||
|
matplotlib.use('Agg')
|
||||||
|
import matplotlib.pyplot as plt
|
||||||
|
import matplotlib.patches as mpatches
|
||||||
|
from matplotlib.patches import FancyBboxPatch, Polygon, Wedge, Arc
|
||||||
|
from matplotlib.path import Path
|
||||||
|
import numpy as np
|
||||||
|
import os
|
||||||
|
|
||||||
|
DPI = 300
|
||||||
|
BG = 'white'
|
||||||
|
LN = 'black'
|
||||||
|
FS = 9
|
||||||
|
FS_TITLE = 14
|
||||||
|
OUTPUT_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'img')
|
||||||
|
os.makedirs(OUTPUT_DIR, exist_ok=True)
|
||||||
|
|
||||||
|
# Light grays for B&W contrast
|
||||||
|
GRAY1 = '#E8E8E8'
|
||||||
|
GRAY2 = '#D0D0D0'
|
||||||
|
GRAY3 = '#B8B8B8'
|
||||||
|
GRAY4 = '#F5F5F5'
|
||||||
|
|
||||||
|
|
||||||
|
def draw_arrow(ax, x1, y1, x2, y2, lw=1.3):
|
||||||
|
ax.annotate("", xy=(x2, y2), xytext=(x1, y1),
|
||||||
|
arrowprops=dict(arrowstyle='->', color=LN, lw=lw))
|
||||||
|
|
||||||
|
|
||||||
|
def draw_line(ax, x1, y1, x2, y2, lw=1.3, ls='-'):
|
||||||
|
ax.plot([x1, x2], [y1, y2], color=LN, lw=lw, linestyle=ls)
|
||||||
|
|
||||||
|
|
||||||
|
def draw_box(ax, x, y, w, h, text, fill='white', lw=1.5, fontsize=FS,
|
||||||
|
fontweight='normal', ha='center', va='center', rounded=False):
|
||||||
|
if rounded:
|
||||||
|
rect = FancyBboxPatch((x, y), w, h, boxstyle="round,pad=0.2",
|
||||||
|
lw=lw, edgecolor=LN, facecolor=fill)
|
||||||
|
else:
|
||||||
|
rect = plt.Rectangle((x, y), w, h, lw=lw, edgecolor=LN, facecolor=fill)
|
||||||
|
ax.add_patch(rect)
|
||||||
|
ax.text(x + w/2, y + h/2, text, ha=ha, va=va, fontsize=fontsize,
|
||||||
|
fontweight=fontweight, wrap=True)
|
||||||
|
|
||||||
|
|
||||||
|
# =========================================================================
|
||||||
|
# 1. TOGAF ADM Cycle
|
||||||
|
# =========================================================================
|
||||||
|
def generate_togaf_adm():
|
||||||
|
fig, ax = plt.subplots(figsize=(8.27, 8.27))
|
||||||
|
ax.set_xlim(-12, 12)
|
||||||
|
ax.set_ylim(-12, 12)
|
||||||
|
ax.set_aspect('equal')
|
||||||
|
ax.axis('off')
|
||||||
|
fig.patch.set_facecolor(BG)
|
||||||
|
ax.set_title("TOGAF ADM (Architecture Development Method)",
|
||||||
|
fontsize=FS_TITLE, fontweight='bold', pad=15)
|
||||||
|
|
||||||
|
# Center: Requirements Management
|
||||||
|
c = plt.Circle((0, 0), 2.5, lw=2, edgecolor=LN, facecolor=GRAY2)
|
||||||
|
ax.add_patch(c)
|
||||||
|
ax.text(0, 0, "Requirements\nManagement", ha='center', va='center',
|
||||||
|
fontsize=8, fontweight='bold')
|
||||||
|
|
||||||
|
# Phases around the circle
|
||||||
|
phases = [
|
||||||
|
("Preliminary", 90),
|
||||||
|
("A: Architecture\nVision", 45),
|
||||||
|
("B: Business\nArchitecture", 0),
|
||||||
|
("C: Information\nSystems Arch.", -45),
|
||||||
|
("D: Technology\nArchitecture", -90),
|
||||||
|
("E: Opportunities\n& Solutions", -135),
|
||||||
|
("F: Migration\nPlanning", 180),
|
||||||
|
("G: Implementation\nGovernance", 135),
|
||||||
|
]
|
||||||
|
# H: Architecture Change Management between G and Preliminary
|
||||||
|
# Put it at ~112 degrees
|
||||||
|
|
||||||
|
R = 8 # radius of phase placement
|
||||||
|
box_w = 4.5
|
||||||
|
box_h = 2.2
|
||||||
|
|
||||||
|
for i, (label, angle_deg) in enumerate(phases):
|
||||||
|
angle = np.radians(angle_deg)
|
||||||
|
cx = R * np.cos(angle)
|
||||||
|
cy = R * np.sin(angle)
|
||||||
|
|
||||||
|
fill = GRAY1 if i % 2 == 0 else GRAY4
|
||||||
|
rect = FancyBboxPatch((cx - box_w/2, cy - box_h/2), box_w, box_h,
|
||||||
|
boxstyle="round,pad=0.2", lw=1.5,
|
||||||
|
edgecolor=LN, facecolor=fill)
|
||||||
|
ax.add_patch(rect)
|
||||||
|
ax.text(cx, cy, label, ha='center', va='center', fontsize=7,
|
||||||
|
fontweight='bold')
|
||||||
|
|
||||||
|
# Arrow from this phase toward center (representing link to Requirements)
|
||||||
|
inner_r = 2.8
|
||||||
|
ix = inner_r * np.cos(angle)
|
||||||
|
iy = inner_r * np.sin(angle)
|
||||||
|
outer_r = R - box_w/2 - 0.3
|
||||||
|
ox = outer_r * np.cos(angle)
|
||||||
|
oy = outer_r * np.sin(angle)
|
||||||
|
# Dashed line to center
|
||||||
|
draw_line(ax, ix, iy, ox * 0.75, oy * 0.75, lw=0.6, ls='--')
|
||||||
|
|
||||||
|
# Curved arrows between successive phases (outer ring)
|
||||||
|
for i in range(len(phases)):
|
||||||
|
a1 = np.radians(phases[i][1])
|
||||||
|
a2 = np.radians(phases[(i + 1) % len(phases)][1])
|
||||||
|
|
||||||
|
# Midpoint arc arrow
|
||||||
|
mid_angle = (a1 + a2) / 2
|
||||||
|
if phases[i][1] < phases[(i + 1) % len(phases)][1]:
|
||||||
|
mid_angle += np.pi # handle wrap
|
||||||
|
ar = R + 0.3
|
||||||
|
mx = ar * np.cos(mid_angle)
|
||||||
|
my = ar * np.sin(mid_angle)
|
||||||
|
|
||||||
|
# Simple arrow from phase i endpoint to phase i+1 start
|
||||||
|
r_arr = R
|
||||||
|
# arrow a bit outside the boxes
|
||||||
|
src_angle = a1 - np.radians(18)
|
||||||
|
dst_angle = a2 + np.radians(18)
|
||||||
|
sx = (R + 2.8) * np.cos(src_angle)
|
||||||
|
sy = (R + 2.8) * np.sin(src_angle)
|
||||||
|
dx = (R + 2.8) * np.cos(dst_angle)
|
||||||
|
dy = (R + 2.8) * np.sin(dst_angle)
|
||||||
|
|
||||||
|
ax.annotate("", xy=(dx, dy), xytext=(sx, sy),
|
||||||
|
arrowprops=dict(arrowstyle='->', color=LN, lw=1,
|
||||||
|
connectionstyle="arc3,rad=0.3"))
|
||||||
|
|
||||||
|
# Legend note
|
||||||
|
ax.text(0, -11.5, "Cykl iteracyjny: ka\u017cda faza mo\u017ce wraca\u0107 do wcze\u015bniejszych.\n"
|
||||||
|
"Requirements Management w centrum \u2014 wp\u0142ywa na ka\u017cd\u0105 faz\u0119.",
|
||||||
|
ha='center', va='center', fontsize=7, fontstyle='italic')
|
||||||
|
|
||||||
|
fig.tight_layout()
|
||||||
|
fig.savefig(os.path.join(OUTPUT_DIR, 'togaf_adm.png'),
|
||||||
|
dpi=DPI, facecolor='white', bbox_inches='tight')
|
||||||
|
plt.close(fig)
|
||||||
|
print(" OK TOGAF ADM")
|
||||||
|
|
||||||
|
|
||||||
|
# =========================================================================
|
||||||
|
# 2. 4+1 View Model (Kruchten)
|
||||||
|
# =========================================================================
|
||||||
|
def generate_4plus1():
|
||||||
|
fig, ax = plt.subplots(figsize=(8.27, 6))
|
||||||
|
ax.set_xlim(0, 100)
|
||||||
|
ax.set_ylim(0, 65)
|
||||||
|
ax.set_aspect('equal')
|
||||||
|
ax.axis('off')
|
||||||
|
fig.patch.set_facecolor(BG)
|
||||||
|
ax.set_title("4+1 View Model (Kruchten, 1995)",
|
||||||
|
fontsize=FS_TITLE, fontweight='bold', pad=12)
|
||||||
|
|
||||||
|
cx, cy = 50, 32
|
||||||
|
# Center: Scenarios (+1)
|
||||||
|
cw, ch = 18, 8
|
||||||
|
draw_box(ax, cx - cw/2, cy - ch/2, cw, ch, "+1\nScenarios\n(Use Cases)",
|
||||||
|
fill=GRAY2, lw=2, fontsize=9, fontweight='bold', rounded=True)
|
||||||
|
|
||||||
|
# 4 views around
|
||||||
|
views = [
|
||||||
|
("Logical View\n(Funkcjonalno\u015b\u0107:\nklasy, modu\u0142y)", cx, cy + 18, "Programista"),
|
||||||
|
("Process View\n(Wsp\u00f3\u0142bie\u017cno\u015b\u0107,\nprzep\u0142yw danych)", cx + 28, cy, "Integrator"),
|
||||||
|
("Development View\n(Organizacja kodu:\npakiety, warstwy)", cx, cy - 18, "Developer"),
|
||||||
|
("Physical View\n(Wdro\u017cenie:\nserwery, kontenery)", cx - 28, cy, "Admin/DevOps"),
|
||||||
|
]
|
||||||
|
|
||||||
|
bw, bh = 22, 10
|
||||||
|
for label, vx, vy, stakeholder in views:
|
||||||
|
draw_box(ax, vx - bw/2, vy - bh/2, bw, bh, label,
|
||||||
|
fill=GRAY1, lw=1.5, fontsize=8, fontweight='bold', rounded=True)
|
||||||
|
# Label stakeholder below/beside
|
||||||
|
if vy > cy:
|
||||||
|
ax.text(vx, vy + bh/2 + 1.5, f"\u2190 {stakeholder}", fontsize=7,
|
||||||
|
ha='center', fontstyle='italic')
|
||||||
|
elif vy < cy:
|
||||||
|
ax.text(vx, vy - bh/2 - 1.5, f"\u2190 {stakeholder}", fontsize=7,
|
||||||
|
ha='center', fontstyle='italic')
|
||||||
|
elif vx > cx:
|
||||||
|
ax.text(vx + bw/2 + 1, vy, f"\u2190 {stakeholder}", fontsize=7,
|
||||||
|
va='center', fontstyle='italic')
|
||||||
|
else:
|
||||||
|
ax.text(vx - bw/2 - 1, vy, f"{stakeholder} \u2192", fontsize=7,
|
||||||
|
va='center', ha='right', fontstyle='italic')
|
||||||
|
|
||||||
|
# Arrow from view to center
|
||||||
|
# Calculate direction
|
||||||
|
dx = cx - vx
|
||||||
|
dy = cy - vy
|
||||||
|
dist = np.sqrt(dx**2 + dy**2)
|
||||||
|
ndx, ndy = dx/dist, dy/dist
|
||||||
|
# Start from edge of view box, end at edge of center box
|
||||||
|
sx = vx + ndx * (bw/2 + 0.5) if abs(dx) > abs(dy) else vx + ndx * 2
|
||||||
|
sy = vy + ndy * (bh/2 + 0.5) if abs(dy) > abs(dx) else vy + ndy * 2
|
||||||
|
ex = cx - ndx * (cw/2 + 0.5) if abs(dx) > abs(dy) else cx - ndx * 2
|
||||||
|
ey = cy - ndy * (ch/2 + 0.5) if abs(dy) > abs(dx) else cy - ndy * 2
|
||||||
|
|
||||||
|
draw_arrow(ax, sx, sy, ex, ey, lw=1.2)
|
||||||
|
|
||||||
|
# Note
|
||||||
|
ax.text(50, 2, "Ka\u017cdy widok odpowiada innemu interesariuszowi.\n"
|
||||||
|
"Scenarios (\u0142\u0105cz\u0105cy +1) weryfikuj\u0105 sp\u00f3jno\u015b\u0107 4 widok\u00f3w.",
|
||||||
|
ha='center', fontsize=7, fontstyle='italic')
|
||||||
|
|
||||||
|
fig.tight_layout()
|
||||||
|
fig.savefig(os.path.join(OUTPUT_DIR, '4plus1_view_model.png'),
|
||||||
|
dpi=DPI, facecolor='white', bbox_inches='tight')
|
||||||
|
plt.close(fig)
|
||||||
|
print(" OK 4+1 View Model")
|
||||||
|
|
||||||
|
|
||||||
|
# =========================================================================
|
||||||
|
# 3. C4 Model — 4 Zoom Levels
|
||||||
|
# =========================================================================
|
||||||
|
def generate_c4():
|
||||||
|
fig, axes = plt.subplots(2, 2, figsize=(8.27, 10))
|
||||||
|
fig.patch.set_facecolor(BG)
|
||||||
|
fig.suptitle("C4 Model (Simon Brown) \u2014 4 poziomy zoomu",
|
||||||
|
fontsize=FS_TITLE, fontweight='bold', y=0.98)
|
||||||
|
|
||||||
|
titles = [
|
||||||
|
"Level 1: System Context",
|
||||||
|
"Level 2: Container",
|
||||||
|
"Level 3: Component",
|
||||||
|
"Level 4: Code (UML)"
|
||||||
|
]
|
||||||
|
|
||||||
|
for idx, ax_item in enumerate(axes.flat):
|
||||||
|
ax_item.set_xlim(0, 100)
|
||||||
|
ax_item.set_ylim(0, 80)
|
||||||
|
ax_item.set_aspect('equal')
|
||||||
|
ax_item.axis('off')
|
||||||
|
ax_item.set_title(titles[idx], fontsize=10, fontweight='bold', pad=8)
|
||||||
|
|
||||||
|
# --- Level 1: System Context ---
|
||||||
|
ax1 = axes[0, 0]
|
||||||
|
# Person
|
||||||
|
ax1.add_patch(plt.Circle((20, 55), 4, lw=1.5, edgecolor=LN, facecolor=GRAY1))
|
||||||
|
# Head (smaller circle on top)
|
||||||
|
ax1.add_patch(plt.Circle((20, 57.5), 1.5, lw=1.2, edgecolor=LN, facecolor='white'))
|
||||||
|
# Body (lines)
|
||||||
|
draw_line(ax1, 20, 56, 20, 52.5, lw=1.2)
|
||||||
|
draw_line(ax1, 17, 55, 23, 55, lw=1.2)
|
||||||
|
ax1.text(20, 48, "Klient", ha='center', fontsize=8, fontweight='bold')
|
||||||
|
|
||||||
|
# System
|
||||||
|
draw_box(ax1, 38, 43, 24, 18, "System\nE-commerce", fill=GRAY2, lw=2,
|
||||||
|
fontsize=9, fontweight='bold', rounded=True)
|
||||||
|
|
||||||
|
# External
|
||||||
|
draw_box(ax1, 72, 48, 20, 12, "System\nP\u0142atno\u015bci\n(zewn.)",
|
||||||
|
fill=GRAY4, lw=1.5, fontsize=7, rounded=True)
|
||||||
|
ax1.add_patch(plt.Rectangle((72, 48), 20, 12, lw=1.5, edgecolor=LN,
|
||||||
|
facecolor='none', linestyle='--'))
|
||||||
|
|
||||||
|
draw_arrow(ax1, 24, 54, 38, 54)
|
||||||
|
ax1.text(31, 56, "sk\u0142ada\nzam\u00f3wienia", fontsize=6, ha='center')
|
||||||
|
draw_arrow(ax1, 62, 54, 72, 54)
|
||||||
|
ax1.text(67, 56, "API", fontsize=6, ha='center')
|
||||||
|
|
||||||
|
ax1.text(50, 20, "Kto u\u017cywa systemu?\nZ czym si\u0119 integruje?",
|
||||||
|
ha='center', fontsize=7, fontstyle='italic',
|
||||||
|
bbox=dict(boxstyle='round', facecolor=GRAY4, edgecolor=LN, lw=0.5))
|
||||||
|
|
||||||
|
# --- Level 2: Container ---
|
||||||
|
ax2 = axes[0, 1]
|
||||||
|
# Big system boundary
|
||||||
|
ax2.add_patch(plt.Rectangle((5, 15), 90, 58, lw=1.5, edgecolor=LN,
|
||||||
|
facecolor='none', linestyle='--'))
|
||||||
|
ax2.text(50, 75, "System E-commerce", ha='center', fontsize=8,
|
||||||
|
fontweight='bold', fontstyle='italic')
|
||||||
|
|
||||||
|
containers = [
|
||||||
|
("SPA\n(React)", 15, 50, 18, 12, GRAY1),
|
||||||
|
("API\nServer\n(Node.js)", 42, 50, 18, 12, GRAY2),
|
||||||
|
("Database\n(PostgreSQL)", 70, 50, 18, 12, GRAY3),
|
||||||
|
("Worker\n(Python)", 42, 25, 18, 12, GRAY1),
|
||||||
|
]
|
||||||
|
for label, x, y, w, h, fill in containers:
|
||||||
|
draw_box(ax2, x, y, w, h, label, fill=fill, lw=1.5, fontsize=7,
|
||||||
|
fontweight='bold', rounded=True)
|
||||||
|
|
||||||
|
draw_arrow(ax2, 33, 56, 42, 56)
|
||||||
|
ax2.text(37.5, 58, "REST", fontsize=6, ha='center')
|
||||||
|
draw_arrow(ax2, 60, 56, 70, 56)
|
||||||
|
ax2.text(65, 58, "SQL", fontsize=6, ha='center')
|
||||||
|
draw_arrow(ax2, 51, 50, 51, 37)
|
||||||
|
ax2.text(53, 44, "async", fontsize=6)
|
||||||
|
|
||||||
|
ax2.text(50, 8, "Jakie kontenery techniczne\nsk\u0142adaj\u0105 si\u0119 na system?",
|
||||||
|
ha='center', fontsize=7, fontstyle='italic',
|
||||||
|
bbox=dict(boxstyle='round', facecolor=GRAY4, edgecolor=LN, lw=0.5))
|
||||||
|
|
||||||
|
# --- Level 3: Component ---
|
||||||
|
ax3 = axes[1, 0]
|
||||||
|
ax3.add_patch(plt.Rectangle((5, 15), 90, 58, lw=1.5, edgecolor=LN,
|
||||||
|
facecolor='none', linestyle='--'))
|
||||||
|
ax3.text(50, 75, "API Server (Node.js)", ha='center', fontsize=8,
|
||||||
|
fontweight='bold', fontstyle='italic')
|
||||||
|
|
||||||
|
components = [
|
||||||
|
("OrderController", 10, 50, 22, 10, GRAY1),
|
||||||
|
("AuthService", 40, 50, 22, 10, GRAY2),
|
||||||
|
("PaymentGateway\n(adapter)", 70, 50, 22, 10, GRAY1),
|
||||||
|
("OrderRepository", 25, 25, 22, 10, GRAY2),
|
||||||
|
("NotificationService", 57, 25, 22, 10, GRAY1),
|
||||||
|
]
|
||||||
|
for label, x, y, w, h, fill in components:
|
||||||
|
draw_box(ax3, x, y, w, h, label, fill=fill, lw=1.5, fontsize=6.5,
|
||||||
|
fontweight='bold', rounded=True)
|
||||||
|
|
||||||
|
draw_arrow(ax3, 32, 55, 40, 55)
|
||||||
|
draw_arrow(ax3, 62, 55, 70, 55)
|
||||||
|
draw_arrow(ax3, 21, 50, 30, 35)
|
||||||
|
draw_arrow(ax3, 51, 50, 62, 35)
|
||||||
|
|
||||||
|
ax3.text(50, 8, "Jakie modu\u0142y/komponenty\nwewn\u0105trz kontenera?",
|
||||||
|
ha='center', fontsize=7, fontstyle='italic',
|
||||||
|
bbox=dict(boxstyle='round', facecolor=GRAY4, edgecolor=LN, lw=0.5))
|
||||||
|
|
||||||
|
# --- Level 4: Code ---
|
||||||
|
ax4 = axes[1, 1]
|
||||||
|
# UML-style class boxes
|
||||||
|
def draw_class(ax, x, y, name, attrs, methods, w=28, fill=GRAY1):
|
||||||
|
h_name = 6
|
||||||
|
h_attr = len(attrs) * 4 + 2
|
||||||
|
h_meth = len(methods) * 4 + 2
|
||||||
|
h_total = h_name + h_attr + h_meth
|
||||||
|
# Name
|
||||||
|
ax.add_patch(plt.Rectangle((x, y), w, h_total, lw=1.5,
|
||||||
|
edgecolor=LN, facecolor=fill))
|
||||||
|
ax.plot([x, x+w], [y + h_total - h_name, y + h_total - h_name],
|
||||||
|
color=LN, lw=1)
|
||||||
|
ax.text(x + w/2, y + h_total - h_name/2, name, ha='center', va='center',
|
||||||
|
fontsize=7, fontweight='bold')
|
||||||
|
# Attrs
|
||||||
|
ax.plot([x, x+w], [y + h_meth, y + h_meth], color=LN, lw=1)
|
||||||
|
for i, a in enumerate(attrs):
|
||||||
|
ax.text(x + 2, y + h_total - h_name - 2 - i*4, a,
|
||||||
|
fontsize=6, va='top', family='monospace')
|
||||||
|
# Methods
|
||||||
|
for i, m in enumerate(methods):
|
||||||
|
ax.text(x + 2, y + h_meth - 2 - i*4, m,
|
||||||
|
fontsize=6, va='top', family='monospace')
|
||||||
|
|
||||||
|
draw_class(ax4, 5, 40, "\u00abinterface\u00bb\nIOrderRepository",
|
||||||
|
[], ["+save(order)", "+findById(id)"], w=32, fill=GRAY4)
|
||||||
|
draw_class(ax4, 55, 40, "OrderRepository",
|
||||||
|
["-db: Database"], ["+save(order)", "+findById(id)"], w=32, fill=GRAY1)
|
||||||
|
draw_class(ax4, 30, 10, "Order",
|
||||||
|
["-id: UUID", "-items: List", "-total: Money"],
|
||||||
|
["+addItem(item)", "+calculateTotal()"], w=32, fill=GRAY2)
|
||||||
|
|
||||||
|
# Implements arrow (dashed)
|
||||||
|
ax4.annotate("", xy=(37, 46), xytext=(55, 50),
|
||||||
|
arrowprops=dict(arrowstyle='-|>', color=LN, lw=1.2, linestyle='--'))
|
||||||
|
ax4.text(46, 52, "\u00abimplements\u00bb", fontsize=6, ha='center', fontstyle='italic')
|
||||||
|
|
||||||
|
# Dependency
|
||||||
|
draw_arrow(ax4, 71, 40, 50, 24)
|
||||||
|
ax4.text(64, 32, "uses", fontsize=6, fontstyle='italic')
|
||||||
|
|
||||||
|
ax4.text(50, 3, "Diagramy klas UML\n(opcjonalny poziom szczeg\u00f3\u0142owo\u015bci)",
|
||||||
|
ha='center', fontsize=7, fontstyle='italic',
|
||||||
|
bbox=dict(boxstyle='round', facecolor=GRAY4, edgecolor=LN, lw=0.5))
|
||||||
|
|
||||||
|
fig.tight_layout(rect=[0, 0, 1, 0.96])
|
||||||
|
fig.savefig(os.path.join(OUTPUT_DIR, 'c4_model.png'),
|
||||||
|
dpi=DPI, facecolor='white', bbox_inches='tight')
|
||||||
|
plt.close(fig)
|
||||||
|
print(" OK C4 Model")
|
||||||
|
|
||||||
|
|
||||||
|
# =========================================================================
|
||||||
|
# 4. Zachman Framework Grid
|
||||||
|
# =========================================================================
|
||||||
|
def generate_zachman():
|
||||||
|
fig, ax = plt.subplots(figsize=(8.27, 6))
|
||||||
|
ax.set_xlim(0, 100)
|
||||||
|
ax.set_ylim(0, 65)
|
||||||
|
ax.set_aspect('equal')
|
||||||
|
ax.axis('off')
|
||||||
|
fig.patch.set_facecolor(BG)
|
||||||
|
ax.set_title("Zachman Framework \u2014 taksonomia architektury",
|
||||||
|
fontsize=FS_TITLE, fontweight='bold', pad=12)
|
||||||
|
|
||||||
|
rows = ["Kontekst\n(Planner)", "Konceptualny\n(Owner)", "Logiczny\n(Designer)",
|
||||||
|
"Fizyczny\n(Builder)", "Szczeg\u00f3\u0142owy\n(Subcontractor)"]
|
||||||
|
cols = ["Co?\n(dane)", "Jak?\n(funkcje)", "Gdzie?\n(sie\u0107)", "Kto?\n(ludzie)",
|
||||||
|
"Kiedy?\n(czas)", "Dlaczego?\n(cel)"]
|
||||||
|
|
||||||
|
n_rows = len(rows)
|
||||||
|
n_cols = len(cols)
|
||||||
|
|
||||||
|
x0 = 18
|
||||||
|
y0 = 5
|
||||||
|
cw = 12.5 # cell width
|
||||||
|
ch = 9 # cell height
|
||||||
|
rh_label = 14 # row label width
|
||||||
|
|
||||||
|
# Column headers
|
||||||
|
for j, col in enumerate(cols):
|
||||||
|
x = x0 + j * cw
|
||||||
|
draw_box(ax, x, y0 + n_rows * ch, cw, 7, col, fill=GRAY2, lw=1.5,
|
||||||
|
fontsize=6.5, fontweight='bold')
|
||||||
|
|
||||||
|
# Row headers
|
||||||
|
for i, row in enumerate(rows):
|
||||||
|
y = y0 + (n_rows - 1 - i) * ch
|
||||||
|
draw_box(ax, x0 - rh_label, y, rh_label, ch, row, fill=GRAY2, lw=1.5,
|
||||||
|
fontsize=6.5, fontweight='bold')
|
||||||
|
|
||||||
|
# Cells
|
||||||
|
fills = [GRAY4, 'white']
|
||||||
|
for i in range(n_rows):
|
||||||
|
for j in range(n_cols):
|
||||||
|
x = x0 + j * cw
|
||||||
|
y = y0 + (n_rows - 1 - i) * ch
|
||||||
|
fill = fills[(i + j) % 2]
|
||||||
|
ax.add_patch(plt.Rectangle((x, y), cw, ch, lw=0.8,
|
||||||
|
edgecolor=LN, facecolor=fill))
|
||||||
|
|
||||||
|
# Sample content in a few cells
|
||||||
|
examples = {
|
||||||
|
(0, 0): "Lista\nencji",
|
||||||
|
(0, 1): "Lista\nproces\u00f3w",
|
||||||
|
(0, 2): "Lokalizacje",
|
||||||
|
(1, 0): "Model\npoj\u0119ciowy",
|
||||||
|
(1, 1): "Model\nproces\u00f3w",
|
||||||
|
(2, 0): "ERD",
|
||||||
|
(2, 1): "Data Flow",
|
||||||
|
(3, 0): "Schemat\nDB",
|
||||||
|
(3, 1): "Kod\nprogramu",
|
||||||
|
(0, 3): "Role",
|
||||||
|
(1, 3): "Org chart",
|
||||||
|
(0, 4): "Harmonogram",
|
||||||
|
(0, 5): "Cele\nbiznesowe",
|
||||||
|
}
|
||||||
|
for (i, j), text in examples.items():
|
||||||
|
x = x0 + j * cw
|
||||||
|
y = y0 + (n_rows - 1 - i) * ch
|
||||||
|
ax.text(x + cw/2, y + ch/2, text, ha='center', va='center',
|
||||||
|
fontsize=5.5, fontstyle='italic', color='#444444')
|
||||||
|
|
||||||
|
# Note
|
||||||
|
ax.text(50, 1, "Ka\u017cda kom\u00f3rka = artefakt opisuj\u0105cy system z danej perspektywy i aspektu.\n"
|
||||||
|
"Zachman nie m\u00f3wi JAK modelowa\u0107 \u2014 m\u00f3wi CO nale\u017cy udokumentowa\u0107.",
|
||||||
|
ha='center', fontsize=7, fontstyle='italic')
|
||||||
|
|
||||||
|
fig.tight_layout()
|
||||||
|
fig.savefig(os.path.join(OUTPUT_DIR, 'zachman_framework.png'),
|
||||||
|
dpi=DPI, facecolor='white', bbox_inches='tight')
|
||||||
|
plt.close(fig)
|
||||||
|
print(" OK Zachman Framework")
|
||||||
|
|
||||||
|
|
||||||
|
# =========================================================================
|
||||||
|
# 5. ArchiMate Layers
|
||||||
|
# =========================================================================
|
||||||
|
def generate_archimate():
|
||||||
|
fig, ax = plt.subplots(figsize=(8.27, 9))
|
||||||
|
ax.set_xlim(0, 100)
|
||||||
|
ax.set_ylim(0, 100)
|
||||||
|
ax.set_aspect('equal')
|
||||||
|
ax.axis('off')
|
||||||
|
fig.patch.set_facecolor(BG)
|
||||||
|
ax.set_title("ArchiMate \u2014 3 warstwy \u00d7 3 aspekty",
|
||||||
|
fontsize=FS_TITLE, fontweight='bold', pad=12)
|
||||||
|
|
||||||
|
# Column headers (aspects)
|
||||||
|
headers = [
|
||||||
|
("Active Structure\n(KTO?)", 0),
|
||||||
|
("Behavior\n(CO robi?)", 1),
|
||||||
|
("Passive Structure\n(NA CZYM?)", 2),
|
||||||
|
]
|
||||||
|
|
||||||
|
x0 = 10
|
||||||
|
y0 = 10
|
||||||
|
cw = 26
|
||||||
|
ch = 20
|
||||||
|
gap = 1
|
||||||
|
header_h = 8
|
||||||
|
row_label_w = 14
|
||||||
|
|
||||||
|
# Column headers
|
||||||
|
for label, j in headers:
|
||||||
|
x = x0 + row_label_w + j * (cw + gap)
|
||||||
|
draw_box(ax, x, y0 + 3 * (ch + gap), cw, header_h, label,
|
||||||
|
fill=GRAY3, lw=1.5, fontsize=8, fontweight='bold')
|
||||||
|
|
||||||
|
# Layers (rows)
|
||||||
|
layers = [
|
||||||
|
("Business\nLayer", GRAY1, [
|
||||||
|
("Business\nActor", "Business\nProcess", "Business\nObject"),
|
||||||
|
("(Kto wykonuje?)", "(Co si\u0119 dzieje?)", "(Na czym dzia\u0142a?)"),
|
||||||
|
("np. Klient,\nHandlowiec", "np. Obs\u0142uga\nzam\u00f3wienia", "np. Zam\u00f3wienie,\nFaktura"),
|
||||||
|
]),
|
||||||
|
("Application\nLayer", GRAY4, [
|
||||||
|
("Application\nComponent", "Application\nService", "Data\nObject"),
|
||||||
|
("(Jaki modu\u0142?)", "(Jaka us\u0142uga?)", "(Jakie dane?)"),
|
||||||
|
("np. CRM,\nERP", "np. API\nzam\u00f3wie\u0144", "np. tabela\nOrders"),
|
||||||
|
]),
|
||||||
|
("Technology\nLayer", 'white', [
|
||||||
|
("Node /\nDevice", "Infrastructure\nService", "Artifact"),
|
||||||
|
("(Jaki sprz\u0119t?)", "(Jaka infra?)", "(Jaki plik?)"),
|
||||||
|
("np. Serwer\nLinux, K8s", "np. Load\nBalancer", "np. .jar,\n.war, image"),
|
||||||
|
]),
|
||||||
|
]
|
||||||
|
|
||||||
|
for i, (layer_name, fill, cells) in enumerate(layers):
|
||||||
|
y = y0 + (2 - i) * (ch + gap)
|
||||||
|
|
||||||
|
# Row label
|
||||||
|
draw_box(ax, x0, y, row_label_w, ch, layer_name,
|
||||||
|
fill=GRAY2, lw=1.5, fontsize=8, fontweight='bold')
|
||||||
|
|
||||||
|
for j in range(3):
|
||||||
|
x = x0 + row_label_w + j * (cw + gap)
|
||||||
|
ax.add_patch(plt.Rectangle((x, y), cw, ch, lw=1.5,
|
||||||
|
edgecolor=LN, facecolor=fill))
|
||||||
|
# Element name (bold)
|
||||||
|
ax.text(x + cw/2, y + ch - 3, cells[0][j], ha='center', va='top',
|
||||||
|
fontsize=7, fontweight='bold')
|
||||||
|
# Role description
|
||||||
|
ax.text(x + cw/2, y + ch/2, cells[1][j], ha='center', va='center',
|
||||||
|
fontsize=6, fontstyle='italic', color='#555555')
|
||||||
|
# Example
|
||||||
|
ax.text(x + cw/2, y + 3, cells[2][j], ha='center', va='bottom',
|
||||||
|
fontsize=6, color='#333333')
|
||||||
|
|
||||||
|
# Vertical arrows between layers
|
||||||
|
for j in range(3):
|
||||||
|
x = x0 + row_label_w + j * (cw + gap) + cw/2
|
||||||
|
for i in range(2):
|
||||||
|
y_top = y0 + (2 - i) * (ch + gap)
|
||||||
|
y_bot = y0 + (2 - i - 1) * (ch + gap) + ch
|
||||||
|
draw_arrow(ax, x, y_top, x, y_bot + 0.3, lw=1)
|
||||||
|
|
||||||
|
# Arrow labels
|
||||||
|
mid_x = x0 + row_label_w - 3
|
||||||
|
ax.text(mid_x, y0 + 2 * (ch + gap) - gap/2,
|
||||||
|
"realizacja \u2193", fontsize=6, ha='right', va='center',
|
||||||
|
fontstyle='italic', rotation=90)
|
||||||
|
ax.text(mid_x, y0 + 1 * (ch + gap) - gap/2,
|
||||||
|
"realizacja \u2193", fontsize=6, ha='right', va='center',
|
||||||
|
fontstyle='italic', rotation=90)
|
||||||
|
|
||||||
|
# Note
|
||||||
|
ax.text(50, 4, "Warstwy czytamy z g\u00f3ry (biznes) na d\u00f3\u0142 (technologia).\n"
|
||||||
|
"Ni\u017csze warstwy REALIZUJ\u0104 wy\u017csze. "
|
||||||
|
"ArchiMate jest komplementarny z TOGAF.",
|
||||||
|
ha='center', fontsize=7, fontstyle='italic')
|
||||||
|
|
||||||
|
fig.tight_layout()
|
||||||
|
fig.savefig(os.path.join(OUTPUT_DIR, 'archimate_layers.png'),
|
||||||
|
dpi=DPI, facecolor='white', bbox_inches='tight')
|
||||||
|
plt.close(fig)
|
||||||
|
print(" OK ArchiMate")
|
||||||
|
|
||||||
|
|
||||||
|
# =========================================================================
|
||||||
|
if __name__ == '__main__':
|
||||||
|
print(f"Generating architecture diagrams to {OUTPUT_DIR}/...")
|
||||||
|
generate_togaf_adm()
|
||||||
|
generate_4plus1()
|
||||||
|
generate_c4()
|
||||||
|
generate_zachman()
|
||||||
|
generate_archimate()
|
||||||
|
print(f"\nAll diagrams saved to {OUTPUT_DIR}/")
|
||||||
|
for f in sorted(os.listdir(OUTPUT_DIR)):
|
||||||
|
if 'togaf' in f or '4plus1' in f or 'c4' in f or 'zachman' in f or 'archimate' in f:
|
||||||
|
size_kb = os.path.getsize(os.path.join(OUTPUT_DIR, f)) / 1024
|
||||||
|
print(f" {f} ({size_kb:.0f} KB)")
|
||||||
542
pytania/generate_process_diagrams.py
Normal file
@ -0,0 +1,542 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
Generate 4 process modeling diagrams (BPMN, UML Activity, EPC, Flowchart)
|
||||||
|
all representing the same process: "Obsluga reklamacji" (Complaint Handling).
|
||||||
|
Output: A4-compatible, black & white, laser-printer-friendly PNG files.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import matplotlib
|
||||||
|
matplotlib.use('Agg')
|
||||||
|
import matplotlib.pyplot as plt
|
||||||
|
import matplotlib.patches as mpatches
|
||||||
|
from matplotlib.patches import FancyBboxPatch, Polygon
|
||||||
|
from matplotlib.path import Path
|
||||||
|
import os
|
||||||
|
|
||||||
|
# --- Common settings ---
|
||||||
|
DPI = 300
|
||||||
|
BG_COLOR = 'white'
|
||||||
|
LINE_COLOR = 'black'
|
||||||
|
FONT_SIZE = 9
|
||||||
|
TITLE_SIZE = 14
|
||||||
|
OUTPUT_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'img')
|
||||||
|
os.makedirs(OUTPUT_DIR, exist_ok=True)
|
||||||
|
|
||||||
|
|
||||||
|
def draw_arrow(ax, x1, y1, x2, y2):
|
||||||
|
ax.annotate("", xy=(x2, y2), xytext=(x1, y1),
|
||||||
|
arrowprops=dict(arrowstyle='->', color=LINE_COLOR, lw=1.3))
|
||||||
|
|
||||||
|
|
||||||
|
def draw_line(ax, x1, y1, x2, y2):
|
||||||
|
ax.plot([x1, x2], [y1, y2], color=LINE_COLOR, lw=1.3, solid_capstyle='round')
|
||||||
|
|
||||||
|
|
||||||
|
def draw_rounded_rect(ax, x, y, w, h, text, fill='white', lw=1.5, fontsize=FONT_SIZE):
|
||||||
|
rect = FancyBboxPatch((x - w/2, y - h/2), w, h,
|
||||||
|
boxstyle="round,pad=0.3", linewidth=lw,
|
||||||
|
edgecolor=LINE_COLOR, facecolor=fill)
|
||||||
|
ax.add_patch(rect)
|
||||||
|
ax.text(x, y, text, ha='center', va='center', fontsize=fontsize)
|
||||||
|
|
||||||
|
|
||||||
|
def draw_diamond(ax, x, y, size, text="", fill='white', fontsize=8):
|
||||||
|
s = size
|
||||||
|
diamond = Polygon([(x, y+s), (x+s, y), (x, y-s), (x-s, y)],
|
||||||
|
closed=True, linewidth=1.5,
|
||||||
|
edgecolor=LINE_COLOR, facecolor=fill)
|
||||||
|
ax.add_patch(diamond)
|
||||||
|
if text:
|
||||||
|
ax.text(x, y, text, ha='center', va='center', fontsize=fontsize,
|
||||||
|
fontweight='bold')
|
||||||
|
|
||||||
|
|
||||||
|
# =========================================================================
|
||||||
|
# 1. BPMN 2.0 Diagram
|
||||||
|
# =========================================================================
|
||||||
|
def generate_bpmn():
|
||||||
|
fig, ax = plt.subplots(figsize=(11, 7.5))
|
||||||
|
ax.set_xlim(0, 110)
|
||||||
|
ax.set_ylim(0, 75)
|
||||||
|
ax.set_aspect('equal')
|
||||||
|
ax.axis('off')
|
||||||
|
fig.patch.set_facecolor(BG_COLOR)
|
||||||
|
ax.set_title("BPMN 2.0 \u2014 Obs\u0142uga reklamacji", fontsize=TITLE_SIZE,
|
||||||
|
fontweight='bold', pad=12)
|
||||||
|
|
||||||
|
# --- Pool outline ---
|
||||||
|
pool_x, pool_y, pool_w, pool_h = 3, 3, 104, 68
|
||||||
|
ax.add_patch(plt.Rectangle((pool_x, pool_y), pool_w, pool_h,
|
||||||
|
lw=2, edgecolor=LINE_COLOR, facecolor='white'))
|
||||||
|
|
||||||
|
# Pool label
|
||||||
|
label_strip = pool_x + 4
|
||||||
|
ax.plot([label_strip, label_strip], [pool_y, pool_y + pool_h],
|
||||||
|
color=LINE_COLOR, lw=1.5)
|
||||||
|
ax.text(pool_x + 2, pool_y + pool_h/2, "FIRMA",
|
||||||
|
fontsize=11, fontweight='bold', rotation=90, ha='center', va='center')
|
||||||
|
|
||||||
|
# --- Lanes ---
|
||||||
|
lane_top = pool_y + pool_h
|
||||||
|
lane_mid1 = pool_y + pool_h * 2/3
|
||||||
|
lane_mid2 = pool_y + pool_h * 1/3
|
||||||
|
|
||||||
|
ax.plot([label_strip, pool_x + pool_w], [lane_mid1, lane_mid1],
|
||||||
|
color=LINE_COLOR, lw=1)
|
||||||
|
ax.plot([label_strip, pool_x + pool_w], [lane_mid2, lane_mid2],
|
||||||
|
color=LINE_COLOR, lw=1)
|
||||||
|
|
||||||
|
y_bok = (lane_top + lane_mid1) / 2
|
||||||
|
y_jak = (lane_mid1 + lane_mid2) / 2
|
||||||
|
y_mag = (lane_mid2 + pool_y) / 2
|
||||||
|
|
||||||
|
ax.text(label_strip + 2.5, y_bok, "BOK", fontsize=8, ha='center', va='center',
|
||||||
|
rotation=90, fontstyle='italic')
|
||||||
|
ax.text(label_strip + 2.5, y_jak, "Jako\u015b\u0107", fontsize=8, ha='center',
|
||||||
|
va='center', rotation=90, fontstyle='italic')
|
||||||
|
ax.text(label_strip + 2.5, y_mag, "Magazyn", fontsize=8, ha='center', va='center',
|
||||||
|
rotation=90, fontstyle='italic')
|
||||||
|
|
||||||
|
content_left = label_strip + 5
|
||||||
|
|
||||||
|
# --- Elements ---
|
||||||
|
# Start event
|
||||||
|
sx = content_left + 4
|
||||||
|
ax.add_patch(plt.Circle((sx, y_bok), 2, lw=2, edgecolor=LINE_COLOR, facecolor='white'))
|
||||||
|
ax.text(sx, y_bok - 3.5, "Reklamacja\nwp\u0142ywa", fontsize=6, ha='center')
|
||||||
|
|
||||||
|
# Task 1: Przyjmij zg\u0142oszenie (BOK)
|
||||||
|
t1x = sx + 14
|
||||||
|
draw_rounded_rect(ax, t1x, y_bok, 14, 6, "Przyjmij\nzg\u0142oszenie")
|
||||||
|
draw_arrow(ax, sx + 2, y_bok, t1x - 7, y_bok)
|
||||||
|
|
||||||
|
# Task 2: Zweryfikuj zasadno\u015b\u0107 (Jako\u015b\u0107) \u2014 elbow routing
|
||||||
|
t2x = t1x + 18
|
||||||
|
draw_rounded_rect(ax, t2x, y_jak, 14, 6, "Zweryfikuj\nzasadno\u015b\u0107")
|
||||||
|
elbow_x = t1x + 10
|
||||||
|
draw_line(ax, t1x + 7, y_bok, elbow_x, y_bok)
|
||||||
|
draw_line(ax, elbow_x, y_bok, elbow_x, y_jak)
|
||||||
|
draw_arrow(ax, elbow_x, y_jak, t2x - 7, y_jak)
|
||||||
|
|
||||||
|
# XOR Gateway (split)
|
||||||
|
gx = t2x + 14
|
||||||
|
draw_diamond(ax, gx, y_jak, 3.5, "X")
|
||||||
|
draw_arrow(ax, t2x + 7, y_jak, gx - 3.5, y_jak)
|
||||||
|
|
||||||
|
# YES: down to Magazyn
|
||||||
|
t3x = gx + 14
|
||||||
|
draw_rounded_rect(ax, t3x, y_mag, 14, 6, "Przygotuj\nwymian\u0119/zwrot")
|
||||||
|
draw_line(ax, gx, y_jak - 3.5, gx, y_mag)
|
||||||
|
draw_arrow(ax, gx, y_mag, t3x - 7, y_mag)
|
||||||
|
ax.text(gx + 1.5, y_jak - 6, "Tak", fontsize=7, ha='left')
|
||||||
|
|
||||||
|
# NO: right in Jako\u015b\u0107
|
||||||
|
t4x = gx + 14
|
||||||
|
draw_rounded_rect(ax, t4x, y_jak, 14, 6, "Odrzu\u0107\nreklamacj\u0119")
|
||||||
|
draw_arrow(ax, gx + 3.5, y_jak, t4x - 7, y_jak)
|
||||||
|
ax.text(gx + 4, y_jak + 2, "Nie", fontsize=7, ha='left')
|
||||||
|
|
||||||
|
# XOR merge (in BOK)
|
||||||
|
mx = t4x + 14
|
||||||
|
draw_diamond(ax, mx, y_bok, 3.5, "X")
|
||||||
|
# From Odrzu\u0107 up to merge
|
||||||
|
draw_line(ax, t4x + 7, y_jak, mx, y_jak)
|
||||||
|
draw_arrow(ax, mx, y_jak, mx, y_bok - 3.5)
|
||||||
|
# From Przygotuj wymian\u0119 up to merge (offset to avoid overlap)
|
||||||
|
draw_line(ax, t3x + 7, y_mag, mx - 4, y_mag)
|
||||||
|
draw_line(ax, mx - 4, y_mag, mx - 4, y_bok)
|
||||||
|
draw_arrow(ax, mx - 4, y_bok, mx - 3.5, y_bok)
|
||||||
|
|
||||||
|
# Task 5: Powiadom klienta (BOK)
|
||||||
|
t5x = mx + 13
|
||||||
|
draw_rounded_rect(ax, t5x, y_bok, 14, 6, "Powiadom\nklienta")
|
||||||
|
draw_arrow(ax, mx + 3.5, y_bok, t5x - 7, y_bok)
|
||||||
|
|
||||||
|
# End event
|
||||||
|
ex = t5x + 12
|
||||||
|
ax.add_patch(plt.Circle((ex, y_bok), 2, lw=3, edgecolor=LINE_COLOR, facecolor='white'))
|
||||||
|
draw_arrow(ax, t5x + 7, y_bok, ex - 2, y_bok)
|
||||||
|
ax.text(ex, y_bok - 3.5, "Koniec", fontsize=6, ha='center')
|
||||||
|
|
||||||
|
# --- Legend ---
|
||||||
|
ly = 1
|
||||||
|
ax.text(12, ly, "Legenda:", fontsize=7, fontweight='bold', va='center')
|
||||||
|
ax.add_patch(plt.Circle((22, ly), 1, lw=2, edgecolor=LINE_COLOR, facecolor='white'))
|
||||||
|
ax.text(24, ly, "Start", fontsize=6, va='center')
|
||||||
|
ax.add_patch(plt.Circle((30, ly), 1, lw=3, edgecolor=LINE_COLOR, facecolor='white'))
|
||||||
|
ax.text(32, ly, "Koniec", fontsize=6, va='center')
|
||||||
|
draw_diamond(ax, 40, ly, 1.5, "X", fontsize=5)
|
||||||
|
ax.text(43, ly, "Bramka XOR", fontsize=6, va='center')
|
||||||
|
draw_rounded_rect(ax, 58, ly, 7, 2.5, "Zadanie", fontsize=6)
|
||||||
|
ax.text(65, ly, "Sequence Flow \u2192", fontsize=6, va='center')
|
||||||
|
|
||||||
|
fig.tight_layout()
|
||||||
|
fig.savefig(os.path.join(OUTPUT_DIR, 'bpmn_reklamacja.png'),
|
||||||
|
dpi=DPI, facecolor='white', bbox_inches='tight')
|
||||||
|
plt.close(fig)
|
||||||
|
print(" OK BPMN saved")
|
||||||
|
|
||||||
|
|
||||||
|
# =========================================================================
|
||||||
|
# 2. UML Activity Diagram
|
||||||
|
# =========================================================================
|
||||||
|
def generate_uml_activity():
|
||||||
|
fig, ax = plt.subplots(figsize=(8.27, 10))
|
||||||
|
ax.set_xlim(0, 100)
|
||||||
|
ax.set_ylim(0, 100)
|
||||||
|
ax.set_aspect('equal')
|
||||||
|
ax.axis('off')
|
||||||
|
fig.patch.set_facecolor(BG_COLOR)
|
||||||
|
ax.set_title("UML Activity Diagram \u2014 Obs\u0142uga reklamacji",
|
||||||
|
fontsize=TITLE_SIZE, fontweight='bold', pad=12)
|
||||||
|
|
||||||
|
cx = 50
|
||||||
|
y = 93
|
||||||
|
step = 11
|
||||||
|
|
||||||
|
# Initial node
|
||||||
|
ax.add_patch(plt.Circle((cx, y), 1.8, facecolor='black', edgecolor='black'))
|
||||||
|
|
||||||
|
# Action 1
|
||||||
|
y -= step
|
||||||
|
draw_rounded_rect(ax, cx, y, 28, 6, "Przyjmij zg\u0142oszenie reklamacji")
|
||||||
|
draw_arrow(ax, cx, y + step - 1.8, cx, y + 3)
|
||||||
|
|
||||||
|
# Action 2
|
||||||
|
y -= step
|
||||||
|
draw_rounded_rect(ax, cx, y, 28, 6, "Zweryfikuj zasadno\u015b\u0107")
|
||||||
|
draw_arrow(ax, cx, y + step - 3, cx, y + 3)
|
||||||
|
|
||||||
|
# Decision
|
||||||
|
y -= step
|
||||||
|
draw_diamond(ax, cx, y, 4)
|
||||||
|
draw_arrow(ax, cx, y + step - 3, cx, y + 4)
|
||||||
|
ax.text(cx + 6, y + 5, "[zasadna?]", fontsize=8, fontstyle='italic')
|
||||||
|
|
||||||
|
dec_y = y
|
||||||
|
branch_y = dec_y - step
|
||||||
|
|
||||||
|
# Left [tak]
|
||||||
|
left_x = cx - 24
|
||||||
|
draw_rounded_rect(ax, left_x, branch_y, 22, 6, "Przygotuj\nwymian\u0119/zwrot")
|
||||||
|
draw_line(ax, cx - 4, dec_y, left_x, dec_y)
|
||||||
|
draw_arrow(ax, left_x, dec_y, left_x, branch_y + 3)
|
||||||
|
ax.text(left_x + 2, dec_y + 1.5, "[tak]", fontsize=8, fontstyle='italic')
|
||||||
|
|
||||||
|
# Right [nie]
|
||||||
|
right_x = cx + 24
|
||||||
|
draw_rounded_rect(ax, right_x, branch_y, 22, 6, "Odrzu\u0107\nreklamacj\u0119")
|
||||||
|
draw_line(ax, cx + 4, dec_y, right_x, dec_y)
|
||||||
|
draw_arrow(ax, right_x, dec_y, right_x, branch_y + 3)
|
||||||
|
ax.text(right_x - 12, dec_y + 1.5, "[nie]", fontsize=8, fontstyle='italic')
|
||||||
|
|
||||||
|
# Merge
|
||||||
|
merge_y = branch_y - step
|
||||||
|
draw_diamond(ax, cx, merge_y, 4)
|
||||||
|
draw_line(ax, left_x, branch_y - 3, left_x, merge_y)
|
||||||
|
draw_line(ax, left_x, merge_y, cx - 4, merge_y)
|
||||||
|
draw_line(ax, right_x, branch_y - 3, right_x, merge_y)
|
||||||
|
draw_line(ax, right_x, merge_y, cx + 4, merge_y)
|
||||||
|
|
||||||
|
# Action: Powiadom
|
||||||
|
y = merge_y - step
|
||||||
|
draw_rounded_rect(ax, cx, y, 28, 6, "Powiadom klienta")
|
||||||
|
draw_arrow(ax, cx, merge_y - 4, cx, y + 3)
|
||||||
|
|
||||||
|
# Final node
|
||||||
|
ey = y - step
|
||||||
|
ax.add_patch(plt.Circle((cx, ey), 2.5, lw=2, facecolor='white', edgecolor='black'))
|
||||||
|
ax.add_patch(plt.Circle((cx, ey), 1.5, facecolor='black', edgecolor='black'))
|
||||||
|
draw_arrow(ax, cx, y - 3, cx, ey + 2.5)
|
||||||
|
|
||||||
|
# Legend
|
||||||
|
ly = 5
|
||||||
|
ax.add_patch(plt.Circle((12, ly), 1.2, facecolor='black', edgecolor='black'))
|
||||||
|
ax.text(15, ly, "= Pocz\u0105tek", fontsize=7, va='center')
|
||||||
|
ax.add_patch(plt.Circle((32, ly), 1.3, lw=2, facecolor='white', edgecolor='black'))
|
||||||
|
ax.add_patch(plt.Circle((32, ly), 0.8, facecolor='black', edgecolor='black'))
|
||||||
|
ax.text(35, ly, "= Koniec", fontsize=7, va='center')
|
||||||
|
draw_diamond(ax, 50, ly, 1.5)
|
||||||
|
ax.text(53, ly, "= Decyzja/Merge", fontsize=7, va='center')
|
||||||
|
draw_rounded_rect(ax, 78, ly, 9, 3, "Akcja", fontsize=7)
|
||||||
|
|
||||||
|
fig.tight_layout()
|
||||||
|
fig.savefig(os.path.join(OUTPUT_DIR, 'uml_activity_reklamacja.png'),
|
||||||
|
dpi=DPI, facecolor='white', bbox_inches='tight')
|
||||||
|
plt.close(fig)
|
||||||
|
print(" OK UML Activity saved")
|
||||||
|
|
||||||
|
|
||||||
|
# =========================================================================
|
||||||
|
# 3. EPC (Event-driven Process Chain)
|
||||||
|
# =========================================================================
|
||||||
|
def generate_epc():
|
||||||
|
fig, ax = plt.subplots(figsize=(8.27, 11))
|
||||||
|
ax.set_xlim(0, 100)
|
||||||
|
ax.set_ylim(0, 120)
|
||||||
|
ax.set_aspect('equal')
|
||||||
|
ax.axis('off')
|
||||||
|
fig.patch.set_facecolor(BG_COLOR)
|
||||||
|
ax.set_title("EPC (Event-driven Process Chain) \u2014 Obs\u0142uga reklamacji",
|
||||||
|
fontsize=TITLE_SIZE, fontweight='bold', pad=12)
|
||||||
|
|
||||||
|
cx = 50
|
||||||
|
y = 114
|
||||||
|
step = 9.5
|
||||||
|
|
||||||
|
def draw_epc_event(x, y, text):
|
||||||
|
w, h = 26, 5.5
|
||||||
|
rect = FancyBboxPatch((x - w/2, y - h/2), w, h,
|
||||||
|
boxstyle="round,pad=0.5", lw=1.5,
|
||||||
|
edgecolor=LINE_COLOR, facecolor='#D8D8D8')
|
||||||
|
ax.add_patch(rect)
|
||||||
|
ax.text(x, y, text, ha='center', va='center', fontsize=8)
|
||||||
|
|
||||||
|
def draw_epc_function(x, y, text):
|
||||||
|
w, h = 26, 5.5
|
||||||
|
rect = FancyBboxPatch((x - w/2, y - h/2), w, h,
|
||||||
|
boxstyle="round,pad=0.3", lw=2,
|
||||||
|
edgecolor=LINE_COLOR, facecolor='white')
|
||||||
|
ax.add_patch(rect)
|
||||||
|
ax.text(x, y, text, ha='center', va='center', fontsize=8,
|
||||||
|
fontweight='bold')
|
||||||
|
|
||||||
|
def draw_epc_connector(x, y, text):
|
||||||
|
c = plt.Circle((x, y), 2.8, lw=1.5, edgecolor=LINE_COLOR, facecolor='white')
|
||||||
|
ax.add_patch(c)
|
||||||
|
ax.text(x, y, text, ha='center', va='center', fontsize=9, fontweight='bold')
|
||||||
|
|
||||||
|
# E1
|
||||||
|
draw_epc_event(cx, y, "Reklamacja wp\u0142yn\u0119\u0142a")
|
||||||
|
|
||||||
|
# F1
|
||||||
|
y -= step
|
||||||
|
draw_epc_function(cx, y, "Przyjmij zg\u0142oszenie")
|
||||||
|
draw_arrow(ax, cx, y + step - 2.8, cx, y + 2.8)
|
||||||
|
|
||||||
|
# E2
|
||||||
|
y -= step
|
||||||
|
draw_epc_event(cx, y, "Zg\u0142oszenie przyj\u0119te")
|
||||||
|
draw_arrow(ax, cx, y + step - 2.8, cx, y + 2.8)
|
||||||
|
|
||||||
|
# F2
|
||||||
|
y -= step
|
||||||
|
draw_epc_function(cx, y, "Zweryfikuj zasadno\u015b\u0107")
|
||||||
|
draw_arrow(ax, cx, y + step - 2.8, cx, y + 2.8)
|
||||||
|
|
||||||
|
# E3
|
||||||
|
y -= step
|
||||||
|
draw_epc_event(cx, y, "Zasadno\u015b\u0107 oceniona")
|
||||||
|
draw_arrow(ax, cx, y + step - 2.8, cx, y + 2.8)
|
||||||
|
|
||||||
|
# XOR split
|
||||||
|
y -= step
|
||||||
|
draw_epc_connector(cx, y, "XOR")
|
||||||
|
draw_arrow(ax, cx, y + step - 2.8, cx, y + 2.8)
|
||||||
|
split_y = y
|
||||||
|
|
||||||
|
left_x = cx - 28
|
||||||
|
right_x = cx + 28
|
||||||
|
|
||||||
|
# Left branch
|
||||||
|
by = split_y - step
|
||||||
|
draw_epc_event(left_x, by, "Reklamacja zasadna")
|
||||||
|
draw_line(ax, cx - 2.8, split_y, left_x, split_y)
|
||||||
|
draw_arrow(ax, left_x, split_y, left_x, by + 2.8)
|
||||||
|
|
||||||
|
by2 = by - step
|
||||||
|
draw_epc_function(left_x, by2, "Przygotuj wymian\u0119/zwrot")
|
||||||
|
draw_arrow(ax, left_x, by - 2.8, left_x, by2 + 2.8)
|
||||||
|
|
||||||
|
by3 = by2 - step
|
||||||
|
draw_epc_event(left_x, by3, "Wymiana przygotowana")
|
||||||
|
draw_arrow(ax, left_x, by2 - 2.8, left_x, by3 + 2.8)
|
||||||
|
|
||||||
|
# Right branch
|
||||||
|
draw_epc_event(right_x, by, "Reklamacja niezasadna")
|
||||||
|
draw_line(ax, cx + 2.8, split_y, right_x, split_y)
|
||||||
|
draw_arrow(ax, right_x, split_y, right_x, by + 2.8)
|
||||||
|
|
||||||
|
draw_epc_function(right_x, by2, "Odrzu\u0107 reklamacj\u0119")
|
||||||
|
draw_arrow(ax, right_x, by - 2.8, right_x, by2 + 2.8)
|
||||||
|
|
||||||
|
draw_epc_event(right_x, by3, "Reklamacja odrzucona")
|
||||||
|
draw_arrow(ax, right_x, by2 - 2.8, right_x, by3 + 2.8)
|
||||||
|
|
||||||
|
# XOR merge
|
||||||
|
merge_y = by3 - step
|
||||||
|
draw_epc_connector(cx, merge_y, "XOR")
|
||||||
|
draw_line(ax, left_x, by3 - 2.8, left_x, merge_y)
|
||||||
|
draw_line(ax, left_x, merge_y, cx - 2.8, merge_y)
|
||||||
|
draw_line(ax, right_x, by3 - 2.8, right_x, merge_y)
|
||||||
|
draw_line(ax, right_x, merge_y, cx + 2.8, merge_y)
|
||||||
|
|
||||||
|
# F: Powiadom
|
||||||
|
y = merge_y - step
|
||||||
|
draw_epc_function(cx, y, "Powiadom klienta")
|
||||||
|
draw_arrow(ax, cx, merge_y - 2.8, cx, y + 2.8)
|
||||||
|
|
||||||
|
# E: Klient powiadomiony
|
||||||
|
y -= step
|
||||||
|
draw_epc_event(cx, y, "Klient powiadomiony")
|
||||||
|
draw_arrow(ax, cx, y + step - 2.8, cx, y + 2.8)
|
||||||
|
|
||||||
|
# Legend
|
||||||
|
ly = 3
|
||||||
|
draw_epc_event(16, ly, "Zdarzenie")
|
||||||
|
draw_epc_function(46, ly, "Funkcja")
|
||||||
|
draw_epc_connector(68, ly, "XOR")
|
||||||
|
ax.text(72, ly, "= \u0141\u0105cznik logiczny", fontsize=7, va='center')
|
||||||
|
|
||||||
|
fig.tight_layout()
|
||||||
|
fig.savefig(os.path.join(OUTPUT_DIR, 'epc_reklamacja.png'),
|
||||||
|
dpi=DPI, facecolor='white', bbox_inches='tight')
|
||||||
|
plt.close(fig)
|
||||||
|
print(" OK EPC saved")
|
||||||
|
|
||||||
|
|
||||||
|
# =========================================================================
|
||||||
|
# 4. Classic Flowchart
|
||||||
|
# =========================================================================
|
||||||
|
def generate_flowchart():
|
||||||
|
fig, ax = plt.subplots(figsize=(8.27, 11))
|
||||||
|
ax.set_xlim(0, 100)
|
||||||
|
ax.set_ylim(0, 110)
|
||||||
|
ax.set_aspect('equal')
|
||||||
|
ax.axis('off')
|
||||||
|
fig.patch.set_facecolor(BG_COLOR)
|
||||||
|
ax.set_title("Schemat blokowy (Flowchart) \u2014 Obs\u0142uga reklamacji",
|
||||||
|
fontsize=TITLE_SIZE, fontweight='bold', pad=12)
|
||||||
|
|
||||||
|
cx = 50
|
||||||
|
y = 103
|
||||||
|
step = 11
|
||||||
|
|
||||||
|
def draw_terminal(x, y, text):
|
||||||
|
w, h = 20, 5.5
|
||||||
|
rect = FancyBboxPatch((x - w/2, y - h/2), w, h,
|
||||||
|
boxstyle="round,pad=1.0", lw=2,
|
||||||
|
edgecolor=LINE_COLOR, facecolor='#E0E0E0')
|
||||||
|
ax.add_patch(rect)
|
||||||
|
ax.text(x, y, text, ha='center', va='center', fontsize=FONT_SIZE,
|
||||||
|
fontweight='bold')
|
||||||
|
|
||||||
|
def draw_process_box(x, y, text):
|
||||||
|
w, h = 26, 6
|
||||||
|
rect = plt.Rectangle((x - w/2, y - h/2), w, h,
|
||||||
|
lw=1.5, edgecolor=LINE_COLOR, facecolor='white')
|
||||||
|
ax.add_patch(rect)
|
||||||
|
ax.text(x, y, text, ha='center', va='center', fontsize=FONT_SIZE)
|
||||||
|
|
||||||
|
def draw_io_shape(x, y, text):
|
||||||
|
w, h = 26, 5.5
|
||||||
|
skew = 3
|
||||||
|
verts = [(x - w/2 + skew, y + h/2),
|
||||||
|
(x + w/2 + skew, y + h/2),
|
||||||
|
(x + w/2 - skew, y - h/2),
|
||||||
|
(x - w/2 - skew, y - h/2),
|
||||||
|
(x - w/2 + skew, y + h/2)]
|
||||||
|
codes = [Path.MOVETO, Path.LINETO, Path.LINETO, Path.LINETO, Path.CLOSEPOLY]
|
||||||
|
patch = mpatches.PathPatch(Path(verts, codes),
|
||||||
|
facecolor='white', edgecolor=LINE_COLOR, lw=1.5)
|
||||||
|
ax.add_patch(patch)
|
||||||
|
ax.text(x, y, text, ha='center', va='center', fontsize=FONT_SIZE)
|
||||||
|
|
||||||
|
# Start
|
||||||
|
draw_terminal(cx, y, "START")
|
||||||
|
|
||||||
|
# I/O
|
||||||
|
y -= step
|
||||||
|
draw_io_shape(cx, y, "Reklamacja od klienta")
|
||||||
|
draw_arrow(ax, cx, y + step - 2.8, cx, y + 2.8)
|
||||||
|
|
||||||
|
# Process
|
||||||
|
y -= step
|
||||||
|
draw_process_box(cx, y, "Przyjmij zg\u0142oszenie")
|
||||||
|
draw_arrow(ax, cx, y + step - 2.8, cx, y + 3)
|
||||||
|
|
||||||
|
# Process
|
||||||
|
y -= step
|
||||||
|
draw_process_box(cx, y, "Zweryfikuj zasadno\u015b\u0107")
|
||||||
|
draw_arrow(ax, cx, y + step - 3, cx, y + 3)
|
||||||
|
|
||||||
|
# Decision
|
||||||
|
y -= step
|
||||||
|
draw_diamond(ax, cx, y, 4.5, "Zasadna?")
|
||||||
|
draw_arrow(ax, cx, y + step - 3, cx, y + 4.5)
|
||||||
|
dec_y = y
|
||||||
|
|
||||||
|
# Left: Tak
|
||||||
|
left_x = cx - 26
|
||||||
|
draw_process_box(left_x, dec_y, "Przygotuj wymian\u0119/zwrot")
|
||||||
|
draw_line(ax, cx - 4.5, dec_y, left_x + 13, dec_y)
|
||||||
|
ax.text(cx - 7, dec_y + 2, "Tak", fontsize=8, ha='center', fontweight='bold')
|
||||||
|
|
||||||
|
# Right: Nie
|
||||||
|
right_x = cx + 26
|
||||||
|
draw_process_box(right_x, dec_y, "Odrzu\u0107 reklamacj\u0119")
|
||||||
|
draw_line(ax, cx + 4.5, dec_y, right_x - 13, dec_y)
|
||||||
|
ax.text(cx + 7, dec_y + 2, "Nie", fontsize=8, ha='center', fontweight='bold')
|
||||||
|
|
||||||
|
# Merge
|
||||||
|
merge_y = dec_y - step
|
||||||
|
draw_line(ax, left_x, dec_y - 3, left_x, merge_y)
|
||||||
|
draw_line(ax, right_x, dec_y - 3, right_x, merge_y)
|
||||||
|
draw_line(ax, left_x, merge_y, right_x, merge_y)
|
||||||
|
ax.plot(cx, merge_y, 'ko', markersize=4)
|
||||||
|
|
||||||
|
# Process: Powiadom
|
||||||
|
y = merge_y - step + 3
|
||||||
|
draw_process_box(cx, y, "Powiadom klienta")
|
||||||
|
draw_arrow(ax, cx, merge_y, cx, y + 3)
|
||||||
|
|
||||||
|
# I/O
|
||||||
|
y -= step
|
||||||
|
draw_io_shape(cx, y, "Odpowied\u017a do klienta")
|
||||||
|
draw_arrow(ax, cx, y + step - 3, cx, y + 2.8)
|
||||||
|
|
||||||
|
# End
|
||||||
|
y -= step
|
||||||
|
draw_terminal(cx, y, "KONIEC")
|
||||||
|
draw_arrow(ax, cx, y + step - 2.8, cx, y + 2.8)
|
||||||
|
|
||||||
|
# Legend
|
||||||
|
ly = 4
|
||||||
|
ax.text(5, ly, "Legenda:", fontsize=7, fontweight='bold', va='center')
|
||||||
|
draw_terminal(18, ly, "")
|
||||||
|
ax.text(18, ly, "Start/\nKoniec", fontsize=5.5, ha='center', va='center')
|
||||||
|
w, h = 9, 3
|
||||||
|
ax.add_patch(plt.Rectangle((32 - w/2, ly - h/2), w, h,
|
||||||
|
lw=1.5, edgecolor=LINE_COLOR, facecolor='white'))
|
||||||
|
ax.text(32, ly, "Proces", fontsize=6, ha='center', va='center')
|
||||||
|
draw_diamond(ax, 46, ly, 2)
|
||||||
|
ax.text(49.5, ly, "= Decyzja", fontsize=6, va='center')
|
||||||
|
skew = 1.5
|
||||||
|
w2, h2 = 9, 3
|
||||||
|
verts = [(62 - w2/2 + skew, ly + h2/2), (62 + w2/2 + skew, ly + h2/2),
|
||||||
|
(62 + w2/2 - skew, ly - h2/2), (62 - w2/2 - skew, ly - h2/2),
|
||||||
|
(62 - w2/2 + skew, ly + h2/2)]
|
||||||
|
codes = [Path.MOVETO, Path.LINETO, Path.LINETO, Path.LINETO, Path.CLOSEPOLY]
|
||||||
|
ax.add_patch(mpatches.PathPatch(Path(verts, codes),
|
||||||
|
facecolor='white', edgecolor=LINE_COLOR, lw=1.2))
|
||||||
|
ax.text(62, ly, "We/Wy", fontsize=6, ha='center', va='center')
|
||||||
|
|
||||||
|
fig.tight_layout()
|
||||||
|
fig.savefig(os.path.join(OUTPUT_DIR, 'flowchart_reklamacja.png'),
|
||||||
|
dpi=DPI, facecolor='white', bbox_inches='tight')
|
||||||
|
plt.close(fig)
|
||||||
|
print(" OK Flowchart saved")
|
||||||
|
|
||||||
|
|
||||||
|
# =========================================================================
|
||||||
|
if __name__ == '__main__':
|
||||||
|
print(f"Generating diagrams to {OUTPUT_DIR}/...")
|
||||||
|
generate_bpmn()
|
||||||
|
generate_uml_activity()
|
||||||
|
generate_epc()
|
||||||
|
generate_flowchart()
|
||||||
|
print(f"\nAll 4 diagrams saved to {OUTPUT_DIR}/")
|
||||||
|
for f in sorted(os.listdir(OUTPUT_DIR)):
|
||||||
|
if f.endswith('.png'):
|
||||||
|
size_kb = os.path.getsize(os.path.join(OUTPUT_DIR, f)) / 1024
|
||||||
|
print(f" {f} ({size_kb:.0f} KB)")
|
||||||
602
pytania/generate_study_diagrams.py
Normal file
@ -0,0 +1,602 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
Generate study diagrams for defense preparation:
|
||||||
|
1. PYTANIE 12: Network optimization models (mnemonic overview)
|
||||||
|
2. PYTANIE 21: Vector clock timeline
|
||||||
|
3. PYTANIE 22: Linearizability vs Sequential consistency, Paxos flow
|
||||||
|
4. PYTANIE 23: Segmentation types and over-segmentation
|
||||||
|
5. PYTANIE 24: HOG pipeline, SVM margin, R-CNN vs YOLO architecture
|
||||||
|
|
||||||
|
All: A4-compatible, B&W, 300 DPI, laser-printer-friendly.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import matplotlib
|
||||||
|
matplotlib.use('Agg')
|
||||||
|
import matplotlib.pyplot as plt
|
||||||
|
import matplotlib.patches as mpatches
|
||||||
|
from matplotlib.patches import FancyBboxPatch, FancyArrowPatch
|
||||||
|
import numpy as np
|
||||||
|
import os
|
||||||
|
|
||||||
|
DPI = 300
|
||||||
|
BG = 'white'
|
||||||
|
LN = 'black'
|
||||||
|
FS = 8
|
||||||
|
FS_TITLE = 12
|
||||||
|
OUTPUT_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'img')
|
||||||
|
os.makedirs(OUTPUT_DIR, exist_ok=True)
|
||||||
|
|
||||||
|
GRAY1 = '#E8E8E8'
|
||||||
|
GRAY2 = '#D0D0D0'
|
||||||
|
GRAY3 = '#B8B8B8'
|
||||||
|
GRAY4 = '#F5F5F5'
|
||||||
|
GRAY5 = '#C0C0C0'
|
||||||
|
|
||||||
|
|
||||||
|
def draw_box(ax, x, y, w, h, text, fill='white', lw=1.2, fontsize=FS,
|
||||||
|
fontweight='normal', ha='center', va='center', rounded=True):
|
||||||
|
if rounded:
|
||||||
|
rect = FancyBboxPatch((x, y), w, h, boxstyle="round,pad=0.05",
|
||||||
|
lw=lw, edgecolor=LN, facecolor=fill)
|
||||||
|
else:
|
||||||
|
rect = mpatches.Rectangle((x, y), w, h, lw=lw, edgecolor=LN, facecolor=fill)
|
||||||
|
ax.add_patch(rect)
|
||||||
|
ax.text(x + w/2, y + h/2, text, ha=ha, va=va, fontsize=fontsize,
|
||||||
|
fontweight=fontweight, wrap=True)
|
||||||
|
|
||||||
|
|
||||||
|
def draw_arrow(ax, x1, y1, x2, y2, lw=1.2, style='->', color=LN):
|
||||||
|
ax.annotate("", xy=(x2, y2), xytext=(x1, y1),
|
||||||
|
arrowprops=dict(arrowstyle=style, color=color, lw=lw))
|
||||||
|
|
||||||
|
|
||||||
|
# ============================================================
|
||||||
|
# PYTANIE 12: Network Optimization Models (Mnemonic Overview)
|
||||||
|
# ============================================================
|
||||||
|
def draw_network_models():
|
||||||
|
fig, ax = plt.subplots(1, 1, figsize=(8.27, 5))
|
||||||
|
ax.set_xlim(0, 10)
|
||||||
|
ax.set_ylim(0, 7)
|
||||||
|
ax.set_aspect('equal')
|
||||||
|
ax.axis('off')
|
||||||
|
ax.set_title('Sieciowe modele optymalizacji — „Nasz Mały Mikołaj Przydzielił Trasy Ciężarówkom Mapując"',
|
||||||
|
fontsize=10, fontweight='bold', pad=10)
|
||||||
|
|
||||||
|
models = [
|
||||||
|
(1, "Najkrótsza\nścieżka", "GPS, routing\nDijkstra, A*", "A→B najszybciej?", GRAY1),
|
||||||
|
(2, "Maksymalny\nprzepływ", "Przepustowość\nFord-Fulkerson", "Ile max przesłać?", GRAY4),
|
||||||
|
(3, "Min koszt\nprzepływu", "Najtańszy transport\nSieciowy simpleks", "X jednostek najtaniej?", GRAY4),
|
||||||
|
(4, "Przydział\n(assignment)", "n→n, min koszt\nAlg. Węgierski O(n³)", "Kto robi co?", GRAY2),
|
||||||
|
(5, "TSP\n(komiwojażer)", "Objazd miast\nNP-trudny, heurystyki", "Objazd wszystkiego?", GRAY3),
|
||||||
|
(6, "CPM/PERT", "Harmonogram\nŚcieżka krytyczna", "Ile trwa projekt?", GRAY2),
|
||||||
|
(7, "MST\n(drzewo rozp.)", "Min połączenie\nKruskal, Prim", "Połącz najtaniej?", GRAY1),
|
||||||
|
]
|
||||||
|
|
||||||
|
# Layout: 3 pairs + 1, arranged in labeled groups
|
||||||
|
group_positions = [
|
||||||
|
# (group_label, [(model_idx, x, y), ...])
|
||||||
|
("DROGI", [(0, 0.3, 4.0), (6, 0.3, 1.5)]),
|
||||||
|
("PRZEPŁYW", [(1, 3.3, 4.0), (2, 3.3, 1.5)]),
|
||||||
|
("ZARZĄDZANIE", [(3, 6.3, 4.0), (5, 6.3, 1.5)]),
|
||||||
|
]
|
||||||
|
|
||||||
|
box_w = 2.6
|
||||||
|
box_h = 1.8
|
||||||
|
|
||||||
|
for group_label, items in group_positions:
|
||||||
|
xs = [x for _, x, y in items]
|
||||||
|
ys = [y for _, x, y in items]
|
||||||
|
gx = min(xs) - 0.15
|
||||||
|
gy = min(ys) - 0.3
|
||||||
|
gw = box_w + 0.3
|
||||||
|
gh = max(ys) - min(ys) + box_h + 0.6
|
||||||
|
rect = mpatches.FancyBboxPatch((gx, gy), gw, gh,
|
||||||
|
boxstyle="round,pad=0.1",
|
||||||
|
lw=0.8, edgecolor=GRAY3,
|
||||||
|
facecolor='white', linestyle='--')
|
||||||
|
ax.add_patch(rect)
|
||||||
|
ax.text(gx + gw/2, gy + gh + 0.12, group_label, ha='center',
|
||||||
|
fontsize=8, fontweight='bold', color='#555555')
|
||||||
|
|
||||||
|
for idx, x, y in items:
|
||||||
|
num, name, detail, question, fill = models[idx]
|
||||||
|
draw_box(ax, x, y, box_w, box_h, '', fill=fill, fontsize=FS)
|
||||||
|
ax.text(x + box_w/2, y + box_h - 0.25, f"{num}. {name}",
|
||||||
|
ha='center', va='top', fontsize=8, fontweight='bold')
|
||||||
|
ax.text(x + box_w/2, y + box_h/2 - 0.1, detail,
|
||||||
|
ha='center', va='center', fontsize=7)
|
||||||
|
ax.text(x + box_w/2, y + 0.2, f'→ „{question}"',
|
||||||
|
ha='center', va='bottom', fontsize=6.5, style='italic')
|
||||||
|
|
||||||
|
# TSP alone at bottom center
|
||||||
|
idx = 4
|
||||||
|
x, y = 4.5, -0.1
|
||||||
|
num, name, detail, question, fill = models[idx]
|
||||||
|
rect = mpatches.FancyBboxPatch((x - 0.15, y - 0.15), box_w + 0.3, box_h + 0.3,
|
||||||
|
boxstyle="round,pad=0.1",
|
||||||
|
lw=0.8, edgecolor=GRAY3,
|
||||||
|
facecolor='white', linestyle='--')
|
||||||
|
ax.add_patch(rect)
|
||||||
|
ax.text(x + box_w/2, y + box_h + 0.3, "SAM (NP-trudny)",
|
||||||
|
ha='center', fontsize=8, fontweight='bold', color='#555555')
|
||||||
|
draw_box(ax, x, y, box_w, box_h, '', fill=fill, fontsize=FS)
|
||||||
|
ax.text(x + box_w/2, y + box_h - 0.25, f"{num}. {name}",
|
||||||
|
ha='center', va='top', fontsize=8, fontweight='bold')
|
||||||
|
ax.text(x + box_w/2, y + box_h/2 - 0.1, detail,
|
||||||
|
ha='center', va='center', fontsize=7)
|
||||||
|
ax.text(x + box_w/2, y + 0.2, f'→ „{question}"',
|
||||||
|
ha='center', va='bottom', fontsize=6.5, style='italic')
|
||||||
|
|
||||||
|
ax.set_ylim(-0.5, 7.2)
|
||||||
|
|
||||||
|
plt.tight_layout()
|
||||||
|
plt.savefig(os.path.join(OUTPUT_DIR, 'network_models_mnemonic.png'), dpi=DPI,
|
||||||
|
bbox_inches='tight', facecolor=BG)
|
||||||
|
plt.close()
|
||||||
|
print(" ✓ network_models_mnemonic.png")
|
||||||
|
|
||||||
|
|
||||||
|
# ============================================================
|
||||||
|
# PYTANIE 21: Vector Clock Timeline
|
||||||
|
# ============================================================
|
||||||
|
def draw_vector_clock_timeline():
|
||||||
|
fig, ax = plt.subplots(1, 1, figsize=(8.27, 4.5))
|
||||||
|
ax.set_xlim(-0.5, 11)
|
||||||
|
ax.set_ylim(-0.5, 4.5)
|
||||||
|
ax.axis('off')
|
||||||
|
ax.set_title('Zegary wektorowe — przykład z 3 procesami', fontsize=FS_TITLE, fontweight='bold', pad=10)
|
||||||
|
|
||||||
|
# Process lines
|
||||||
|
procs = [('P₁', 3.5), ('P₂', 2.0), ('P₃', 0.5)]
|
||||||
|
for name, y in procs:
|
||||||
|
ax.plot([0.5, 10.5], [y, y], color=LN, lw=1.5)
|
||||||
|
ax.text(0.1, y, name, ha='right', va='center', fontsize=10, fontweight='bold')
|
||||||
|
|
||||||
|
# Events
|
||||||
|
events = [
|
||||||
|
# (name, process_y, x, vector, fill)
|
||||||
|
('A', 3.5, 1.5, '[1,0,0]', GRAY1),
|
||||||
|
('B', 2.0, 2.5, '[0,1,0]', GRAY2),
|
||||||
|
('C', 2.0, 5.0, '[1,2,0]', GRAY2),
|
||||||
|
('D', 0.5, 4.0, '[0,0,1]', GRAY3),
|
||||||
|
('E', 3.5, 6.5, '[2,0,0]', GRAY1),
|
||||||
|
('F', 2.0, 8.0, '[2,3,0]', GRAY2),
|
||||||
|
]
|
||||||
|
|
||||||
|
for name, y, x, vec, fill in events:
|
||||||
|
circle = plt.Circle((x, y), 0.25, facecolor=fill, edgecolor=LN, lw=1.5)
|
||||||
|
ax.add_patch(circle)
|
||||||
|
ax.text(x, y, name, ha='center', va='center', fontsize=9, fontweight='bold')
|
||||||
|
ax.text(x, y + 0.45, vec, ha='center', va='bottom', fontsize=7,
|
||||||
|
fontfamily='monospace', color='#333333')
|
||||||
|
|
||||||
|
# Messages (arrows between processes)
|
||||||
|
# P1:A → P2:C (msg sent after A, received at C)
|
||||||
|
ax.annotate("", xy=(4.75, 2.0), xytext=(1.75, 3.5),
|
||||||
|
arrowprops=dict(arrowstyle='->', color='#444444', lw=1.5,
|
||||||
|
connectionstyle='arc3,rad=0.05'))
|
||||||
|
ax.text(3.0, 3.0, 'msg₁', ha='center', fontsize=7, color='#444444', style='italic')
|
||||||
|
|
||||||
|
# P1:E → P2:F
|
||||||
|
ax.annotate("", xy=(7.75, 2.0), xytext=(6.75, 3.5),
|
||||||
|
arrowprops=dict(arrowstyle='->', color='#444444', lw=1.5,
|
||||||
|
connectionstyle='arc3,rad=0.05'))
|
||||||
|
ax.text(7.0, 3.0, 'msg₂', ha='center', fontsize=7, color='#444444', style='italic')
|
||||||
|
|
||||||
|
# Concurrency annotations
|
||||||
|
ax.annotate('A ∥ B\n(współbieżne)', xy=(2.0, 1.2), fontsize=7, ha='center',
|
||||||
|
bbox=dict(boxstyle='round,pad=0.2', facecolor=GRAY4, edgecolor=GRAY5))
|
||||||
|
ax.annotate('C ∥ D\n(współbieżne)', xy=(4.5, 0.9), fontsize=7, ha='center',
|
||||||
|
bbox=dict(boxstyle='round,pad=0.2', facecolor=GRAY4, edgecolor=GRAY5))
|
||||||
|
ax.annotate('A → C\n(przyczynowe)', xy=(3.3, 4.2), fontsize=7, ha='center',
|
||||||
|
bbox=dict(boxstyle='round,pad=0.2', facecolor=GRAY1, edgecolor=GRAY3))
|
||||||
|
|
||||||
|
# Time arrow
|
||||||
|
ax.annotate("", xy=(10.5, -0.3), xytext=(0.5, -0.3),
|
||||||
|
arrowprops=dict(arrowstyle='->', color=GRAY3, lw=1.0))
|
||||||
|
ax.text(5.5, -0.45, 'czas →', ha='center', fontsize=8, color='#777777')
|
||||||
|
|
||||||
|
plt.tight_layout()
|
||||||
|
plt.savefig(os.path.join(OUTPUT_DIR, 'vector_clock_timeline.png'), dpi=DPI,
|
||||||
|
bbox_inches='tight', facecolor=BG)
|
||||||
|
plt.close()
|
||||||
|
print(" ✓ vector_clock_timeline.png")
|
||||||
|
|
||||||
|
|
||||||
|
# ============================================================
|
||||||
|
# PYTANIE 22: Linearizability vs Sequential Consistency
|
||||||
|
# ============================================================
|
||||||
|
def draw_linearizability_vs_sequential():
|
||||||
|
fig, axes = plt.subplots(2, 1, figsize=(8.27, 5.5))
|
||||||
|
|
||||||
|
for i, (ax, title, subtitle, operations, result_text) in enumerate(zip(
|
||||||
|
axes,
|
||||||
|
['Linearizability', 'Sequential Consistency'],
|
||||||
|
['Operacja „wygląda" atomowo w czasie rzeczywistym',
|
||||||
|
'Globalny porządek zgodny z programem, ale NIE z czasem rzeczywistym'],
|
||||||
|
[
|
||||||
|
# Linearizability
|
||||||
|
[
|
||||||
|
('Klient A', 1, 3, 'write(x,1)', GRAY1),
|
||||||
|
('Klient B', 2, 4, 'read(x)→1 ✓', GRAY2),
|
||||||
|
('Klient A', 5, 7, 'write(x,2)', GRAY1),
|
||||||
|
],
|
||||||
|
# Sequential consistency
|
||||||
|
[
|
||||||
|
('Klient A', 1, 3, 'write(x,1)', GRAY1),
|
||||||
|
('Klient B', 2, 4, 'read(x)→0 ✓', GRAY2),
|
||||||
|
('Klient A', 5, 7, 'write(x,2)', GRAY1),
|
||||||
|
],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'read MUSI zwrócić 1 (write zakończony w czasie rzeczywistym)',
|
||||||
|
'read MOŻE zwrócić 0 (globalny porządek: read, write(1), write(2))',
|
||||||
|
]
|
||||||
|
)):
|
||||||
|
ax.set_xlim(0, 9)
|
||||||
|
ax.set_ylim(-0.5, 3.5)
|
||||||
|
ax.axis('off')
|
||||||
|
ax.set_title(f'{title}', fontsize=10, fontweight='bold')
|
||||||
|
ax.text(4.5, 3.2, subtitle, ha='center', fontsize=7, style='italic', color='#555555')
|
||||||
|
|
||||||
|
# Time axis
|
||||||
|
ax.plot([0.5, 8.5], [0, 0], color=GRAY3, lw=0.8)
|
||||||
|
for t in range(1, 9):
|
||||||
|
ax.plot([t, t], [-0.05, 0.05], color=GRAY3, lw=0.8)
|
||||||
|
ax.text(t, -0.2, f't{t}', ha='center', fontsize=6, color='#999999')
|
||||||
|
|
||||||
|
# Client labels
|
||||||
|
clients = list(dict.fromkeys([op[0] for op in operations]))
|
||||||
|
client_y = {c: 1.0 + idx * 1.2 for idx, c in enumerate(clients)}
|
||||||
|
|
||||||
|
for client_name, y_pos in client_y.items():
|
||||||
|
ax.text(0.3, y_pos, client_name, ha='right', va='center', fontsize=7, fontweight='bold')
|
||||||
|
ax.plot([0.5, 8.5], [y_pos, y_pos], color=GRAY5, lw=0.5, linestyle=':')
|
||||||
|
|
||||||
|
for client, t_start, t_end, label, fill in operations:
|
||||||
|
y = client_y[client]
|
||||||
|
rect = FancyBboxPatch((t_start, y - 0.2), t_end - t_start, 0.4,
|
||||||
|
boxstyle="round,pad=0.05", lw=1.2,
|
||||||
|
edgecolor=LN, facecolor=fill)
|
||||||
|
ax.add_patch(rect)
|
||||||
|
ax.text((t_start + t_end) / 2, y, label, ha='center', va='center', fontsize=7)
|
||||||
|
|
||||||
|
# Result annotation
|
||||||
|
ax.text(4.5, -0.45, result_text, ha='center', fontsize=7,
|
||||||
|
bbox=dict(boxstyle='round,pad=0.3', facecolor=GRAY4, edgecolor=GRAY5))
|
||||||
|
|
||||||
|
plt.tight_layout()
|
||||||
|
plt.savefig(os.path.join(OUTPUT_DIR, 'linearizability_vs_sequential.png'), dpi=DPI,
|
||||||
|
bbox_inches='tight', facecolor=BG)
|
||||||
|
plt.close()
|
||||||
|
print(" ✓ linearizability_vs_sequential.png")
|
||||||
|
|
||||||
|
|
||||||
|
# ============================================================
|
||||||
|
# PYTANIE 22: Paxos Protocol Flow
|
||||||
|
# ============================================================
|
||||||
|
def draw_paxos_flow():
|
||||||
|
fig, ax = plt.subplots(1, 1, figsize=(8.27, 4))
|
||||||
|
ax.set_xlim(-0.5, 10.5)
|
||||||
|
ax.set_ylim(-0.5, 5)
|
||||||
|
ax.axis('off')
|
||||||
|
ax.set_title('Paxos — uproszczony przebieg (zapis x=5)', fontsize=FS_TITLE, fontweight='bold', pad=10)
|
||||||
|
|
||||||
|
# Actors
|
||||||
|
actors = [
|
||||||
|
('Proposer', 1.5, 4.0, GRAY1),
|
||||||
|
('A₁', 4.5, 4.0, GRAY2),
|
||||||
|
('A₂', 6.5, 4.0, GRAY2),
|
||||||
|
('A₃', 8.5, 4.0, GRAY2),
|
||||||
|
]
|
||||||
|
for name, x, y, fill in actors:
|
||||||
|
draw_box(ax, x - 0.6, y, 1.2, 0.6, name, fill=fill, fontsize=8, fontweight='bold')
|
||||||
|
|
||||||
|
# Phase 1: Prepare
|
||||||
|
ax.text(-0.3, 3.5, 'FAZA 1\nPrepare', ha='center', fontsize=7, fontweight='bold',
|
||||||
|
bbox=dict(boxstyle='round,pad=0.2', facecolor=GRAY4, edgecolor=GRAY5))
|
||||||
|
|
||||||
|
y_prep = 3.3
|
||||||
|
for target_x in [4.5, 6.5, 8.5]:
|
||||||
|
draw_arrow(ax, 2.1, y_prep + 0.15, target_x - 0.6, y_prep + 0.15, lw=1.0)
|
||||||
|
ax.text(3.3, y_prep + 0.35, 'Prepare(n=1)', fontsize=6, ha='center')
|
||||||
|
|
||||||
|
# Promises back
|
||||||
|
y_prom = 2.7
|
||||||
|
for target_x in [4.5, 6.5]:
|
||||||
|
draw_arrow(ax, target_x - 0.6, y_prom + 0.15, 2.1, y_prom + 0.15, lw=1.0, color='#555555')
|
||||||
|
ax.text(3.3, y_prom + 0.35, 'Promise(n=1) ✓', fontsize=6, ha='center', color='#555555')
|
||||||
|
ax.text(8.5, y_prom + 0.15, '(slow)', fontsize=6, ha='center', color='#999999')
|
||||||
|
|
||||||
|
ax.text(1.5, y_prom - 0.15, 'majority\n(2/3) ✓', fontsize=6, ha='center',
|
||||||
|
bbox=dict(boxstyle='round,pad=0.15', facecolor=GRAY1, edgecolor=GRAY3))
|
||||||
|
|
||||||
|
# Phase 2: Accept
|
||||||
|
ax.text(-0.3, 1.8, 'FAZA 2\nAccept', ha='center', fontsize=7, fontweight='bold',
|
||||||
|
bbox=dict(boxstyle='round,pad=0.2', facecolor=GRAY4, edgecolor=GRAY5))
|
||||||
|
|
||||||
|
y_acc = 1.6
|
||||||
|
for target_x in [4.5, 6.5, 8.5]:
|
||||||
|
draw_arrow(ax, 2.1, y_acc + 0.15, target_x - 0.6, y_acc + 0.15, lw=1.0)
|
||||||
|
ax.text(3.3, y_acc + 0.35, 'Accept(n=1, x=5)', fontsize=6, ha='center')
|
||||||
|
|
||||||
|
# Accepted back
|
||||||
|
y_accd = 1.0
|
||||||
|
for target_x in [4.5, 6.5]:
|
||||||
|
draw_arrow(ax, target_x - 0.6, y_accd + 0.15, 2.1, y_accd + 0.15, lw=1.0, color='#555555')
|
||||||
|
ax.text(3.3, y_accd + 0.35, 'Accepted ✓', fontsize=6, ha='center', color='#555555')
|
||||||
|
|
||||||
|
# Result
|
||||||
|
ax.text(5.0, 0.1, 'x=5 UZGODNIONE (majority zaakceptowała) → Linearizable!',
|
||||||
|
fontsize=8, ha='center', fontweight='bold',
|
||||||
|
bbox=dict(boxstyle='round,pad=0.3', facecolor=GRAY1, edgecolor=LN))
|
||||||
|
|
||||||
|
plt.tight_layout()
|
||||||
|
plt.savefig(os.path.join(OUTPUT_DIR, 'paxos_flow.png'), dpi=DPI,
|
||||||
|
bbox_inches='tight', facecolor=BG)
|
||||||
|
plt.close()
|
||||||
|
print(" ✓ paxos_flow.png")
|
||||||
|
|
||||||
|
|
||||||
|
# ============================================================
|
||||||
|
# PYTANIE 24: HOG Pipeline Overview
|
||||||
|
# ============================================================
|
||||||
|
def draw_hog_pipeline():
|
||||||
|
fig, ax = plt.subplots(1, 1, figsize=(8.27, 3.5))
|
||||||
|
ax.set_xlim(0, 10)
|
||||||
|
ax.set_ylim(0, 4)
|
||||||
|
ax.axis('off')
|
||||||
|
ax.set_title('HOG + SVM — pipeline detekcji pieszych', fontsize=FS_TITLE, fontweight='bold', pad=10)
|
||||||
|
|
||||||
|
steps = [
|
||||||
|
(0.3, 'Obraz\nwejściowy', GRAY4),
|
||||||
|
(2.1, 'Oblicz\ngradienty\n(Gx, Gy)', GRAY1),
|
||||||
|
(3.9, 'Podziel na\nkomórki 8×8\nhistogramy', GRAY2),
|
||||||
|
(5.7, 'Normalizuj\nw blokach\n2×2', GRAY2),
|
||||||
|
(7.5, 'Wektor\ncech\n(3780-dim)', GRAY3),
|
||||||
|
(9.0, 'SVM\n→ pieszy\n/ nie', GRAY1),
|
||||||
|
]
|
||||||
|
|
||||||
|
box_w = 1.5
|
||||||
|
box_h = 1.8
|
||||||
|
y = 1.2
|
||||||
|
for i, (x, text, fill) in enumerate(steps):
|
||||||
|
draw_box(ax, x, y, box_w, box_h, '', fill=fill)
|
||||||
|
ax.text(x + box_w/2, y + box_h/2, text, ha='center', va='center', fontsize=7)
|
||||||
|
if i < len(steps) - 1:
|
||||||
|
next_x = steps[i+1][0]
|
||||||
|
draw_arrow(ax, x + box_w + 0.02, y + box_h/2, next_x - 0.02, y + box_h/2)
|
||||||
|
|
||||||
|
# Annotations below
|
||||||
|
annotations = [
|
||||||
|
(0.3 + box_w/2, 'pixel[x+1]-pixel[x-1]'),
|
||||||
|
(2.1 + box_w/2, 'magnitude + direction'),
|
||||||
|
(3.9 + box_w/2, '9 binów (0°-180°)'),
|
||||||
|
(5.7 + box_w/2, 'L2-normalizacja'),
|
||||||
|
(7.5 + box_w/2, 'wejście do SVM'),
|
||||||
|
(9.0 + box_w/2, 'hiperpłaszczyzna'),
|
||||||
|
]
|
||||||
|
for x, text in annotations:
|
||||||
|
ax.text(x, y - 0.15, text, ha='center', fontsize=5.5, color='#666666', style='italic')
|
||||||
|
|
||||||
|
# Title annotations
|
||||||
|
ax.text(1.05, y + box_h + 0.15, '① Gradient', ha='center', fontsize=7, fontweight='bold')
|
||||||
|
ax.text(2.85, y + box_h + 0.15, '② Histogram', ha='center', fontsize=7, fontweight='bold')
|
||||||
|
ax.text(4.65, y + box_h + 0.15, '③ Normalize', ha='center', fontsize=7, fontweight='bold')
|
||||||
|
ax.text(6.45, y + box_h + 0.15, '④ Feature vec', ha='center', fontsize=7, fontweight='bold')
|
||||||
|
ax.text(8.1, y + box_h + 0.15, '⑤ Classify', ha='center', fontsize=7, fontweight='bold')
|
||||||
|
|
||||||
|
plt.tight_layout()
|
||||||
|
plt.savefig(os.path.join(OUTPUT_DIR, 'hog_svm_pipeline.png'), dpi=DPI,
|
||||||
|
bbox_inches='tight', facecolor=BG)
|
||||||
|
plt.close()
|
||||||
|
print(" ✓ hog_svm_pipeline.png")
|
||||||
|
|
||||||
|
|
||||||
|
# ============================================================
|
||||||
|
# PYTANIE 24: R-CNN Evolution
|
||||||
|
# ============================================================
|
||||||
|
def draw_rcnn_evolution():
|
||||||
|
fig, ax = plt.subplots(1, 1, figsize=(8.27, 5))
|
||||||
|
ax.set_xlim(0, 10)
|
||||||
|
ax.set_ylim(0, 7)
|
||||||
|
ax.axis('off')
|
||||||
|
ax.set_title('Ewolucja detektorów: R-CNN → Fast R-CNN → Faster R-CNN → YOLO',
|
||||||
|
fontsize=10, fontweight='bold', pad=10)
|
||||||
|
|
||||||
|
models = [
|
||||||
|
{
|
||||||
|
'name': 'R-CNN (2014)',
|
||||||
|
'y': 5.3,
|
||||||
|
'steps': ['Selective\nSearch', '2000×\nCNN', '2000×\nSVM', 'NMS'],
|
||||||
|
'speed': '~50 sec/img',
|
||||||
|
'fill': GRAY4,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'name': 'Fast R-CNN (2015)',
|
||||||
|
'y': 3.7,
|
||||||
|
'steps': ['Selective\nSearch', 'CNN\n(1× cały)', 'ROI\nPooling', 'FC + NMS'],
|
||||||
|
'speed': '~2 sec/img',
|
||||||
|
'fill': GRAY2,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'name': 'Faster R-CNN (2015)',
|
||||||
|
'y': 2.1,
|
||||||
|
'steps': ['CNN\nbackbone', 'RPN\n(proposals)', 'ROI\nPooling', 'FC + NMS'],
|
||||||
|
'speed': '~0.2 sec (5 fps)',
|
||||||
|
'fill': GRAY1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'name': 'YOLO (2016)',
|
||||||
|
'y': 0.5,
|
||||||
|
'steps': ['CNN\nbackbone', 'Siatka\nS×S', 'bbox+klasa\nper komórka', 'NMS'],
|
||||||
|
'speed': '~7-22 ms (45-155 fps)',
|
||||||
|
'fill': GRAY3,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
for model in models:
|
||||||
|
y = model['y']
|
||||||
|
ax.text(0.2, y + 0.4, model['name'], fontsize=8, fontweight='bold', va='center')
|
||||||
|
ax.text(0.2, y + 0.05, model['speed'], fontsize=6, va='center', color='#666666')
|
||||||
|
|
||||||
|
bw = 1.5
|
||||||
|
bh = 0.8
|
||||||
|
for i, step in enumerate(model['steps']):
|
||||||
|
x = 2.5 + i * 1.9
|
||||||
|
draw_box(ax, x, y, bw, bh, step, fill=model['fill'], fontsize=6.5)
|
||||||
|
if i < len(model['steps']) - 1:
|
||||||
|
draw_arrow(ax, x + bw + 0.02, y + bh/2, x + 1.9 - 0.02, y + bh/2, lw=0.8)
|
||||||
|
|
||||||
|
# Speed improvement arrow on right
|
||||||
|
ax.annotate("", xy=(9.5, 5.7), xytext=(9.5, 0.9),
|
||||||
|
arrowprops=dict(arrowstyle='<->', color='#555555', lw=1.5))
|
||||||
|
ax.text(9.7, 3.3, '250×\nszybciej!', fontsize=8, fontweight='bold',
|
||||||
|
ha='center', va='center', rotation=90, color='#555555')
|
||||||
|
|
||||||
|
plt.tight_layout()
|
||||||
|
plt.savefig(os.path.join(OUTPUT_DIR, 'rcnn_evolution.png'), dpi=DPI,
|
||||||
|
bbox_inches='tight', facecolor=BG)
|
||||||
|
plt.close()
|
||||||
|
print(" ✓ rcnn_evolution.png")
|
||||||
|
|
||||||
|
|
||||||
|
# ============================================================
|
||||||
|
# PYTANIE 23: Segmentation types comparison
|
||||||
|
# ============================================================
|
||||||
|
def draw_segmentation_types():
|
||||||
|
fig, axes = plt.subplots(1, 4, figsize=(8.27, 2.5))
|
||||||
|
fig.suptitle('Typy segmentacji obrazu', fontsize=FS_TITLE, fontweight='bold', y=1.02)
|
||||||
|
|
||||||
|
titles = ['Obraz wejściowy', 'Semantic\nSegmentation', 'Instance\nSegmentation', 'Panoptic\nSegmentation']
|
||||||
|
for ax, title in zip(axes, titles):
|
||||||
|
ax.set_xlim(0, 6)
|
||||||
|
ax.set_ylim(0, 6)
|
||||||
|
ax.set_aspect('equal')
|
||||||
|
ax.axis('off')
|
||||||
|
ax.set_title(title, fontsize=8, fontweight='bold', pad=5)
|
||||||
|
|
||||||
|
# Image: sky (top), two cars (bottom), road
|
||||||
|
# Semantic: all sky=one color, all cars=one color, road=one color
|
||||||
|
# Instance: sky=one, car1=distinct, car2=distinct, road=one
|
||||||
|
# Panoptic: both
|
||||||
|
|
||||||
|
# Original image (stylized)
|
||||||
|
ax = axes[0]
|
||||||
|
ax.add_patch(mpatches.Rectangle((0, 4), 6, 2, facecolor='#DDDDDD', edgecolor=LN, lw=0.5)) # sky
|
||||||
|
ax.text(3, 5, 'niebo', ha='center', va='center', fontsize=7)
|
||||||
|
ax.add_patch(mpatches.Rectangle((0, 0), 6, 2.5, facecolor='#AAAAAA', edgecolor=LN, lw=0.5)) # road
|
||||||
|
ax.text(3, 1, 'droga', ha='center', va='center', fontsize=7)
|
||||||
|
ax.add_patch(mpatches.Rectangle((0.5, 2), 2, 1.5, facecolor='#888888', edgecolor=LN, lw=0.8)) # car1
|
||||||
|
ax.text(1.5, 2.75, 'auto', ha='center', va='center', fontsize=7, color='white')
|
||||||
|
ax.add_patch(mpatches.Rectangle((3.5, 2), 2, 1.5, facecolor='#666666', edgecolor=LN, lw=0.8)) # car2
|
||||||
|
ax.text(4.5, 2.75, 'auto', ha='center', va='center', fontsize=7, color='white')
|
||||||
|
|
||||||
|
# Semantic: same label for both cars
|
||||||
|
ax = axes[1]
|
||||||
|
ax.add_patch(mpatches.Rectangle((0, 4), 6, 2, facecolor='#E8E8E8', edgecolor=LN, lw=0.5))
|
||||||
|
ax.text(3, 5, 'niebo', ha='center', va='center', fontsize=7)
|
||||||
|
ax.add_patch(mpatches.Rectangle((0, 0), 6, 2.5, facecolor='#C8C8C8', edgecolor=LN, lw=0.5))
|
||||||
|
ax.text(3, 1, 'droga', ha='center', va='center', fontsize=7)
|
||||||
|
ax.add_patch(mpatches.Rectangle((0.5, 2), 2, 1.5, facecolor='#888888', edgecolor=LN, lw=0.8))
|
||||||
|
ax.text(1.5, 2.75, 'auto', ha='center', va='center', fontsize=6, color='white')
|
||||||
|
ax.add_patch(mpatches.Rectangle((3.5, 2), 2, 1.5, facecolor='#888888', edgecolor=LN, lw=0.8))
|
||||||
|
ax.text(4.5, 2.75, 'auto', ha='center', va='center', fontsize=6, color='white')
|
||||||
|
ax.text(3, -0.3, 'te same etykiety!', ha='center', fontsize=6, color='#555555', style='italic')
|
||||||
|
|
||||||
|
# Instance: different labels for cars
|
||||||
|
ax = axes[2]
|
||||||
|
ax.add_patch(mpatches.Rectangle((0, 4), 6, 2, facecolor='#E8E8E8', edgecolor=LN, lw=0.5))
|
||||||
|
ax.text(3, 5, '—', ha='center', va='center', fontsize=7, color='#999999')
|
||||||
|
ax.add_patch(mpatches.Rectangle((0, 0), 6, 2.5, facecolor='#E8E8E8', edgecolor=LN, lw=0.5))
|
||||||
|
ax.text(3, 1, '—', ha='center', va='center', fontsize=7, color='#999999')
|
||||||
|
ax.add_patch(mpatches.Rectangle((0.5, 2), 2, 1.5, facecolor='#888888', edgecolor=LN, lw=0.8))
|
||||||
|
ax.text(1.5, 2.75, 'auto#1', ha='center', va='center', fontsize=6, color='white')
|
||||||
|
ax.add_patch(mpatches.Rectangle((3.5, 2), 2, 1.5, facecolor='#555555', edgecolor=LN, lw=0.8))
|
||||||
|
ax.text(4.5, 2.75, 'auto#2', ha='center', va='center', fontsize=6, color='white')
|
||||||
|
ax.text(3, -0.3, 'RÓŻNE instancje!', ha='center', fontsize=6, color='#555555', style='italic')
|
||||||
|
|
||||||
|
# Panoptic: both semantic labels AND instance IDs
|
||||||
|
ax = axes[3]
|
||||||
|
ax.add_patch(mpatches.Rectangle((0, 4), 6, 2, facecolor='#E8E8E8', edgecolor=LN, lw=0.5))
|
||||||
|
ax.text(3, 5, 'niebo (stuff)', ha='center', va='center', fontsize=6)
|
||||||
|
ax.add_patch(mpatches.Rectangle((0, 0), 6, 2.5, facecolor='#C8C8C8', edgecolor=LN, lw=0.5))
|
||||||
|
ax.text(3, 1, 'droga (stuff)', ha='center', va='center', fontsize=6)
|
||||||
|
ax.add_patch(mpatches.Rectangle((0.5, 2), 2, 1.5, facecolor='#888888', edgecolor=LN, lw=0.8))
|
||||||
|
ax.text(1.5, 2.75, 'auto#1\n(thing)', ha='center', va='center', fontsize=5.5, color='white')
|
||||||
|
ax.add_patch(mpatches.Rectangle((3.5, 2), 2, 1.5, facecolor='#555555', edgecolor=LN, lw=0.8))
|
||||||
|
ax.text(4.5, 2.75, 'auto#2\n(thing)', ha='center', va='center', fontsize=5.5, color='white')
|
||||||
|
ax.text(3, -0.3, 'klasy + instancje!', ha='center', fontsize=6, color='#555555', style='italic')
|
||||||
|
|
||||||
|
plt.tight_layout()
|
||||||
|
plt.savefig(os.path.join(OUTPUT_DIR, 'segmentation_types.png'), dpi=DPI,
|
||||||
|
bbox_inches='tight', facecolor=BG)
|
||||||
|
plt.close()
|
||||||
|
print(" ✓ segmentation_types.png")
|
||||||
|
|
||||||
|
|
||||||
|
# ============================================================
|
||||||
|
# PYTANIE 32: FSD and SSD visualization
|
||||||
|
# ============================================================
|
||||||
|
def draw_fsd_ssd():
|
||||||
|
fig, axes = plt.subplots(1, 2, figsize=(8.27, 3.5))
|
||||||
|
fig.suptitle('Dominacja stochastyczna — FSD i SSD', fontsize=FS_TITLE, fontweight='bold', y=1.02)
|
||||||
|
|
||||||
|
# FSD: CDF comparison
|
||||||
|
ax = axes[0]
|
||||||
|
ax.set_title('FSD: F_A(x) ≤ F_B(x) ∀x', fontsize=9, fontweight='bold')
|
||||||
|
x = np.linspace(-2, 6, 200)
|
||||||
|
# A ~ shifted right (better), B ~ shifted left
|
||||||
|
from scipy.stats import norm
|
||||||
|
F_A = norm.cdf(x, loc=2.5, scale=1.0)
|
||||||
|
F_B = norm.cdf(x, loc=1.5, scale=1.0)
|
||||||
|
ax.plot(x, F_A, 'k-', lw=2, label='F_A (lepsza — niżej)')
|
||||||
|
ax.plot(x, F_B, 'k--', lw=2, label='F_B (gorsza — wyżej)')
|
||||||
|
ax.fill_between(x, F_A, F_B, alpha=0.15, color='gray')
|
||||||
|
ax.set_xlabel('x (wynik)', fontsize=8)
|
||||||
|
ax.set_ylabel('F(x) = P(X ≤ x)', fontsize=8)
|
||||||
|
ax.legend(fontsize=7, loc='lower right')
|
||||||
|
ax.text(0, 0.8, 'A ≥_FSD B\nF_A zawsze pod F_B\n→ KAŻDY racjonalny\n wybierze A',
|
||||||
|
fontsize=7, bbox=dict(boxstyle='round', facecolor=GRAY4))
|
||||||
|
ax.grid(True, alpha=0.3)
|
||||||
|
ax.tick_params(labelsize=7)
|
||||||
|
|
||||||
|
# SSD: CDFs can cross, but integral is less
|
||||||
|
ax = axes[1]
|
||||||
|
ax.set_title('SSD: ∫F_A ≤ ∫F_B ∀x (CDFs mogą się krzyżować)', fontsize=9, fontweight='bold')
|
||||||
|
F_A2 = norm.cdf(x, loc=2.0, scale=0.8)
|
||||||
|
F_B2 = norm.cdf(x, loc=2.0, scale=1.5) # same mean, more spread
|
||||||
|
ax.plot(x, F_A2, 'k-', lw=2, label='F_A (mniej ryzyka)')
|
||||||
|
ax.plot(x, F_B2, 'k--', lw=2, label='F_B (więcej ryzyka)')
|
||||||
|
ax.fill_between(x, F_A2, F_B2, where=F_A2 < F_B2, alpha=0.15, color='gray')
|
||||||
|
ax.fill_between(x, F_A2, F_B2, where=F_A2 >= F_B2, alpha=0.08, color='gray',
|
||||||
|
hatch='///')
|
||||||
|
ax.set_xlabel('x (wynik)', fontsize=8)
|
||||||
|
ax.set_ylabel('F(x)', fontsize=8)
|
||||||
|
ax.legend(fontsize=7, loc='lower right')
|
||||||
|
ax.text(-1.5, 0.75, 'A ≥_SSD B\nCDFs się krzyżują,\nale ∫F_A ≤ ∫F_B\n→ risk-averse\n wybierze A',
|
||||||
|
fontsize=7, bbox=dict(boxstyle='round', facecolor=GRAY4))
|
||||||
|
ax.grid(True, alpha=0.3)
|
||||||
|
ax.tick_params(labelsize=7)
|
||||||
|
|
||||||
|
plt.tight_layout()
|
||||||
|
plt.savefig(os.path.join(OUTPUT_DIR, 'fsd_ssd_comparison.png'), dpi=DPI,
|
||||||
|
bbox_inches='tight', facecolor=BG)
|
||||||
|
plt.close()
|
||||||
|
print(" ✓ fsd_ssd_comparison.png")
|
||||||
|
|
||||||
|
|
||||||
|
# ============================================================
|
||||||
|
# Main
|
||||||
|
# ============================================================
|
||||||
|
if __name__ == '__main__':
|
||||||
|
print("Generating study diagrams...")
|
||||||
|
draw_network_models()
|
||||||
|
draw_vector_clock_timeline()
|
||||||
|
draw_linearizability_vs_sequential()
|
||||||
|
draw_paxos_flow()
|
||||||
|
draw_hog_pipeline()
|
||||||
|
draw_rcnn_evolution()
|
||||||
|
draw_segmentation_types()
|
||||||
|
draw_fsd_ssd()
|
||||||
|
print(f"\nAll diagrams saved to {OUTPUT_DIR}/")
|
||||||
BIN
pytania/img/4plus1_view_model.png
Normal file
|
After Width: | Height: | Size: 173 KiB |
BIN
pytania/img/archimate_layers.png
Normal file
|
After Width: | Height: | Size: 248 KiB |
BIN
pytania/img/bpmn_reklamacja.png
Normal file
|
After Width: | Height: | Size: 164 KiB |
BIN
pytania/img/c4_model.png
Normal file
|
After Width: | Height: | Size: 335 KiB |
BIN
pytania/img/epc_reklamacja.png
Normal file
|
After Width: | Height: | Size: 217 KiB |
BIN
pytania/img/flowchart_reklamacja.png
Normal file
|
After Width: | Height: | Size: 175 KiB |
BIN
pytania/img/fsd_ssd_comparison.png
Normal file
|
After Width: | Height: | Size: 204 KiB |
BIN
pytania/img/hog_svm_pipeline.png
Normal file
|
After Width: | Height: | Size: 122 KiB |
BIN
pytania/img/linearizability_vs_sequential.png
Normal file
|
After Width: | Height: | Size: 156 KiB |
BIN
pytania/img/network_models_mnemonic.png
Normal file
|
After Width: | Height: | Size: 240 KiB |
BIN
pytania/img/paxos_flow.png
Normal file
|
After Width: | Height: | Size: 95 KiB |
BIN
pytania/img/rcnn_evolution.png
Normal file
|
After Width: | Height: | Size: 166 KiB |
BIN
pytania/img/segmentation_types.png
Normal file
|
After Width: | Height: | Size: 85 KiB |
BIN
pytania/img/togaf_adm.png
Normal file
|
After Width: | Height: | Size: 211 KiB |
BIN
pytania/img/uml_activity_reklamacja.png
Normal file
|
After Width: | Height: | Size: 150 KiB |
BIN
pytania/img/vector_clock_timeline.png
Normal file
|
After Width: | Height: | Size: 125 KiB |
BIN
pytania/img/zachman_framework.png
Normal file
|
After Width: | Height: | Size: 182 KiB |
@ -197,6 +197,7 @@ if [[ -z "$OUTPUT_PDF" ]]; then
|
|||||||
OUTPUT_PDF="/tmp/obrona_q${QUESTIONS[0]}.pdf"
|
OUTPUT_PDF="/tmp/obrona_q${QUESTIONS[0]}.pdf"
|
||||||
else
|
else
|
||||||
joined=$(IFS=_; echo "${QUESTIONS[*]}")
|
joined=$(IFS=_; echo "${QUESTIONS[*]}")
|
||||||
|
joined="${joined//\//-}" # Replace / with - for safe filenames
|
||||||
OUTPUT_PDF="/tmp/obrona_q${joined}.pdf"
|
OUTPUT_PDF="/tmp/obrona_q${joined}.pdf"
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|||||||