codexpast-exam-of-the-year-1-of-the-computer-science-course-of-the-university-of-oxford2016imperative-resit-decorator-uml.py
past-exam-of-the-year-1-of-the-computer-science-course-of-the-university-of-oxford/2016/imperative-resit-decorator-uml.py
"""Cable-TV decorator UML. Python 3.14; matplotlib 3.10.7; writes PNG to CWD."""
from pathlib import Path
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
from matplotlib.patches import Rectangle, FancyArrowPatch
def main():
fig, ax = plt.subplots(figsize=(12.8, 7.3), facecolor='white')
ax.set(xlim=(0, 16), ylim=(0, 9))
ax.axis('off')
def box(x, y, w, h, title, body, tint='#f2f6fa'):
ax.add_patch(Rectangle((x-w/2, y-h/2), w, h, facecolor=tint,
edgecolor='#25364a', linewidth=1.4, zorder=3))
split=y+h/2-.53
ax.plot([x-w/2,x+w/2],[split,split],color='#25364a',lw=1,zorder=4)
ax.text(x,y+h/2-.26,title,ha='center',va='center',fontsize=11,
fontweight='bold',zorder=5)
ax.text(x-w/2+.13,split-.15,body,ha='left',va='top',fontsize=10.5,
linespacing=1.45,zorder=5)
def edge(start, end, dashed=False):
ax.add_patch(FancyArrowPatch(start,end,arrowstyle='-|>',mutation_scale=19,
edgecolor='#25364a',facecolor='white',linewidth=1.3,
linestyle='--' if dashed else '-',zorder=1))
box(7.6,7.35,4.2,1.6,'«interface» CableTV','+ cost: Double\n+ packages: String')
box(2.6,4.5,3.6,1.9,'BasicPlan','+ cost = 30\n+ packages = "Basic plan"')
box(9.4,4.5,4.0,1.9,'«abstract» Packages','- account: CableTV\n+ cost, packages: delegate')
edge((2.6,5.45),(6.2,6.55),True)
edge((8.5,5.45),(8.0,6.55),True)
# A plain navigable association denotes a reference, not exclusive ownership.
ax.plot([11.4,13.8,13.8,9.7],[4.75,4.75,7.35,7.35],color='#25364a',lw=1.3,zorder=1)
ax.annotate('',xy=(9.7,7.35),xytext=(10.2,7.35),
arrowprops=dict(arrowstyle='->',color='#25364a',lw=1.3))
ax.text(13.95,6.2,'account\n1',fontsize=10.5,va='center')
for x,title,cost,label in [(2.8,'Movies','10','Movies'),
(8.0,'HDChannels','7','HD channels'),
(13.2,'Sports','5','Sports')]:
box(x,1.35,4.5,1.7,title,f'+ cost = super.cost + {cost}\n+ packages: append "{label}"',
'#fff6df' if title=='Sports' else '#f2f6fa')
edge((x,2.2),(9.4,3.55))
ax.text(.45,8.65,'Cable TV: one component interface, nested package wrappers',
fontsize=14,weight='bold')
ax.text(.45,.05,'Hollow triangle: generalization · Dashed triangle: interface realization',
fontsize=10,color='#354354')
fig.tight_layout(pad=.6)
fig.savefig(Path.cwd()/'imperative-resit-decorator-uml.png',dpi=115,
facecolor='white',transparent=False)
plt.close(fig)
if __name__ == '__main__':
main()