/******************************************************************** Constraint-based Graphical Programming in B-Prolog % animate the selection sort algorithm *********************************************************************/ go:- anim_sort(20). anim_sort(N):- anim_sort(N,200). anim_sort(N,Speed):- cgWindow(Win,"Animating the Selection Sort Algorithm"),Win^topMargin #= 30,Win^leftMargin #= 30, createControlPanel(N,Speed,Win,CP), generateAndShowData(CP,Data), generateEventHandlers(CP,Data), handleWindowClosing(Win). handleWindowClosing(Win),{windowClosing(Win)} => cgClose(Win). generateEventHandlers(CP,Data):- CP=cp(Win,Size,Speed,Reset,Start,Pause,Resume,Status,EV), inputSize(Size,CP), inputRate(Speed,CP), handleReset(Reset,CP,Data), handleStart(Start,CP,Data), handlePause(Pause,CP,Data), handleResume(Resume,CP,Data). inputSize(Size,CP),{keyTyped(Size,_)} => disableStart(CP). inputRate(Rate,CP),{keyTyped(Rate,_)} => disableStart(CP). handleReset(Reset,CP,Data), {actionPerformed(Reset)} => getWindow(CP,Win), getSize(CP,N), setStatus(CP,stop), % kill the sorting agent getRate(CP,Rate), cgClose(Win), anim_sort(N,Rate). handleStart(Start,CP,Data), {actionPerformed(Start)} => disableStart(CP), enablePause(CP), getRate(CP,Rate), getSize(CP,N), disableSpeed(CP), disableSize(CP), setStatus(CP,running), selectionSort(CP,Data,1,N). handlePause(Pause,CP,Data),{actionPerformed(Pause)} => enableResume(CP), disablePause(CP), setStatus(CP,waiting). handleResume(Resume,CP,Data),{actionPerformed(Resume)} => enablePause(CP), disableResume(CP), setStatus(CP,running). /* operations on control panel */ createControlPanel(N,Rate,Win,CP):- CP=cp(Win,Size,Speed,Reset,Start,Pause,Resume,Status,EV), cgLabel([LabSize,LabSpeed],["Size:","Rate:"]), number_codes(N,NString), cgTextField(Size), cgSetColumns([Size,Speed],5),cgSetText(Size,NString), % cgTextField(Speed), number_codes(Rate,RString), cgSetText(Speed,RString), % cgButton([Reset,Start,Pause,Resume],["Reset","Start","Pause","Resume"]), Reset^height #= 20,cgSame([Reset,Start,Pause,Resume],width,40), Pause^x #= Win^width//2, % constrain the components cgTable([[LabSize,Size,LabSpeed,Speed], [Reset,Start,Pause,Resume]],10,3), cgAbove(LabSize,Reset), % Comps=[LabSize,Size,LabSpeed,Speed,Reset,Start,Pause,Resume], cgSame(Comps,window,Win), cgShow(Comps), disablePause(CP), disableResume(CP). getWindow(CP,Win):- CP=cp(Win,Size,Speed,Reset,Start,Pause,Resume,Status,EV). getSize(CP,N):- CP=cp(Win,Size,Speed,Reset,Start,Pause,Resume,Status,EV), cgGetText(Size,NString), catch(number_codes(N,NString),_,N=3). getCenterX(CP,X):- CP=cp(Win,Size,Speed,Reset,Start,Pause,Resume,Status,EV), X #= (Start^rightX+Pause^x)//2. getRate(CP,Rate):- CP=cp(Win,Size,Speed,Reset,Start,Pause,Resume,Status,EV), cgGetText(Speed,NString), catch(number_codes(Rate,NString),_,Rate=200). getStatus(CP,Status):- CP=cp(Win,Size,Speed,Reset,Start,Pause,Resume,Status,EV). setStatus(CP,running):-!, CP=cp(Win,Size,Speed,Reset,Start,Pause,Resume,Status,EV), setarg(8,CP,running), post(event(EV)). %activate the plan executor setStatus(CP,Status):- setarg(8,CP,Status). getControlPanelHeight(CP,Height):- CP=cp(Win,Size,Speed,Reset,Start,Pause,Resume,Status,EV), Height #= Size^height+Reset^height. disableStart(CP):- CP=cp(Win,Size,Speed,Reset,Start,Pause,Resume,Status,EV), disable(Start). enableStart(CP):- CP=cp(Win,Size,Speed,Reset,Start,Pause,Resume,Status,EV), enable(Start). disablePause(CP):- CP=cp(Win,Size,Speed,Reset,Start,Pause,Resume,Status,EV), disable(Pause). enablePause(CP):- CP=cp(Win,Size,Speed,Reset,Start,Pause,Resume,Status,EV), enable(Pause). disableResume(CP):- CP=cp(Win,Size,Speed,Reset,Start,Pause,Resume,Status,EV), disable(Resume). enableResume(CP):- CP=cp(Win,Size,Speed,Reset,Start,Pause,Resume,Status,EV), enable(Resume). disableSpeed(CP):- CP=cp(Win,Size,Speed,Reset,Start,Pause,Resume,Status,EV), disable(Speed). enableSpeed(CP):- CP=cp(Win,Size,Speed,Reset,Start,Pause,Resume,Status,EV), enable(Speed). disableSize(CP):- CP=cp(Win,Size,Speed,Reset,Start,Pause,Resume,Status,EV), disable(Size). enableSize(CP):- CP=cp(Win,Size,Speed,Reset,Start,Pause,Resume,Status,EV), enable(Size). enable(Comp):-cgSetEnabled(Comp,1), cgShow(Comp). disable(Comp):-cgSetEnabled(Comp,0), cgShow(Comp). %% generateAndShowData(CP,Data):- getSize(CP,N), getWindow(CP,Win), getControlPanelHeight(CP,CpHeight), new_array(Data,[N]), Height #= (Win^height-Win^topMargin-CpHeight-20)//(N+4)-3, Y0 #= Win^topMargin+CpHeight+10, generateRandomArray(Data,Labs,Recs,1,N,Win,Y0,Height), % for each random number, generate a label and a rectangle cgLeft(Labs,Recs), cgShow(Labs),cgShow(Recs), enableStart(CP). generateRandomArray(Data,Labs,Recs,N0,N,Win,Y,Height):-N0>N,!,Labs=[],Recs=[]. generateRandomArray(Data,Labs,Recs,N0,N,Win,Y,Height):- IntNum is round(abs(random)) mod 450+1, cgRectangle(Rec), Rec^width #= IntNum,Rec^window #= Win, number_codes(IntNum,NumString), cgString(Lab,NumString), cgTable([[Lab,Rec]]), Lab^height #= Height, Lab^y #= Y, Lab^window #= Win, Data^[N0] @= elm(IntNum,Lab,Rec), Labs=[Lab|Labs1], Recs=[Rec|Recs1], N1 is N0+1, Y1 #= Y+Height+3, generateRandomArray(Data,Labs1,Recs1,N1,N,Win,Y1,Height). %% selectionSort(CP,Data,N0,N), cp(Win,Size,Speed,Reset,Start,Pause,Resume,waiting,EV)=CP, {event(EV)} => true. %wait until Resume is clicked selectionSort(CP,Data,N0,N),N0 N1 is N0+1, Data^[N0] @= elm(Min0,_,_), selectMin(Data,N1,N,Min0,N0,I), swapAndShow(CP,Data,N0,I), selectionSort(CP,Data,N1,N). selectionSort(CP,Data,N0,N),N0=:=N => setColor(Data,N,red),disablePause(CP). selectionSort(CP,Data,N0,N) => true. %come here if Status is "stop" selectMin(Data,N0,N,Min0,MinI0,I):-N0>N,!,I=MinI0. selectMin(Data,N0,N,Min0,MinI0,I):- Data^[N0] @= elm(Elm,_,_), (Elm Min1=Elm,MinI1=N0; Min1=Min0,MinI1=MinI0), N1 is N0+1, selectMin(Data,N1,N,Min1,MinI1,I). swapAndShow(CP,Data,I,MinI):- setColor(Data,MinI,blue), getRate(CP,Time), cgSleep(Time), swapPosition(Data,I,MinI), setColor(Data,I,red), cgSleep(Time). setColor(Data,I,Color):- Data^[I] @= elm(_,Lab,Rec), Lab^color #:= Color, Rec^color #:= Color, cgShow([Lab,Rec]). swapPosition(Data,I,J):- Data^[I] @= Ai, Ai=elm(Elmi,Labi,Reci), Data^[J] @= Aj, Aj=elm(Elmj,Labj,Recj), TempYi #= Labi^y, TempYj #= Labj^y, Labi^y #:= TempYj, Reci^y #:= TempYj, Labj^y #:= TempYi, Recj^y #:= TempYi, Data^[I] @:= Aj, Data^[J] @:= Ai, cgShow([Labi,Reci,Labj,Recj]).