codex/past-exam-of-the-year-1-of-the-computer-science-course-of-the-university-of-oxford/2016/digital-resit-visitor-controller.py

past-exam-of-the-year-1-of-the-computer-science-course-of-the-university-of-oxford/2016/digital-resit-visitor-controller.py
"""Draw the complete four-state entry controller; output to cwd."""
from pathlib import Path
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
from matplotlib.patches import Circle, FancyArrowPatch

def main():
    fig, ax = plt.subplots(figsize=(9,6),dpi=100,facecolor='white')
    pos={'A':(-1.7,1.25),'B':(1.7,1.25),'C':(1.7,-1.25),'I':(-1.7,-1.25)}
    for name,(x,y) in pos.items():
        ax.add_patch(Circle((x,y),.46,facecolor='#d9efdf'if name=='I'else'#edf2f8',edgecolor='#25364a',lw=1.6,zorder=3))
        ax.text(x,y+.08,name,ha='center',va='center',fontsize=17,zorder=4)
        ax.text(x,y-.18,'INC = '+str(int(name=='I')),ha='center',fontsize=10,zorder=4)
    def edge(src,dst,label,rad=0,offset=(0,0)):
        start,end=pos[src],pos[dst]
        ax.add_patch(FancyArrowPatch(start,end,connectionstyle=f'arc3,rad={rad}',arrowstyle='-|>',mutation_scale=15,
                                   shrinkA=35,shrinkB=35,lw=1.5,color='#25364a',zorder=2))
        x=(start[0]+end[0])/2+offset[0];y=(start[1]+end[1])/2+offset[1]
        ax.text(x,y,label,ha='center',va='center',fontsize=12,bbox=dict(facecolor='white',edgecolor='none',pad=1),zorder=5)
    edge('A','B','01, 11',-.12,(0,.34));edge('B','A','00',-.12,(0,-.34))
    edge('B','C','10',-.13,(.43,0));edge('C','B','01, 11',-.13,(-.43,0))
    edge('C','I','00',0,(0,-.18));edge('I','A','00, 10',0,(-.46,0))
    edge('I','B','01, 11',0,(-.18,-.25))
    for name,label in [('A','00, 10'),('B','01, 11'),('C','10')]:
        x,y=pos[name]
        start=(x+.41,y+.22) if name=='C' else (x-.22,y+.41)
        end=(x+.41,y-.22) if name=='C' else (x+.22,y+.41)
        ax.add_patch(FancyArrowPatch(start,end,connectionstyle='arc3,rad=-2.4',arrowstyle='-|>',mutation_scale=14,lw=1.5,color='#25364a'))
        ax.text(x+.95 if name=='C' else x,y if name=='C' else y+1.0,label,ha='center',fontsize=11,bbox=dict(facecolor='white',edgecolor='none',pad=1))
    ax.annotate('reset',xy=(-2.16,1.25),xytext=(-2.9,1.25),ha='center',va='center',arrowprops=dict(arrowstyle='->',lw=1.5))
    ax.set_xlim(-3.2,3.0);ax.set_ylim(-2.0,2.7);ax.set_aspect('equal');ax.axis('off')
    fig.suptitle('Visitor entry controller — labels are x₁x₀',fontsize=15,y=.97)
    fig.text(.5,.035,'Only state I emits a pulse; every transition from I leaves it.',ha='center',fontsize=11)
    fig.subplots_adjust(left=.02,right=.98,top=.91,bottom=.09)
    fig.savefig(Path.cwd()/'digital-resit-visitor-controller.png',facecolor='white',transparent=False)
    plt.close(fig)
if __name__ == '__main__': main()