feat: updated questions obrona magister

This commit is contained in:
Krzysztof kuhy Rudnicki 2026-02-16 12:41:12 +01:00
parent d517f3558a
commit b6b20191a3
22 changed files with 3969 additions and 177 deletions

File diff suppressed because it is too large Load Diff

View 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)")

View 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)")

View 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}/")

Binary file not shown.

After

Width:  |  Height:  |  Size: 173 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 248 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 164 KiB

BIN
pytania/img/c4_model.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 335 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 217 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 175 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 204 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 122 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 156 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 240 KiB

BIN
pytania/img/paxos_flow.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 95 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 166 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 85 KiB

BIN
pytania/img/togaf_adm.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 211 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 150 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 125 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 182 KiB

View File

@ -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