## Auto-Generated Script of Model by JS-Eden J-version ## Auto calculation is turned off to until the model has been fully loaded autocalc = 0; ## Observable Assignments: target = 1; capA = 5; capB = 7; contentA = 0; contentB = 0; widthB = 5; widthA = 5; Error = 0; updating = 0; viscosity = 100; jugwidth = 60; base = 200; scale = 20; left = 50; spacing = 30; linewidth = 0; comboboxlocx = 500; selobs_value = 1; permid = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]; perm = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]; gap = 40; gap_Y = 20; A_value = 1; B_value = 1; C_value = 1; D_value = 1; E_value = 1; F_value = 1; G_value = 1; H_value = 1; I_value = 1; J_value = 1; K_value = 1; L_value = 1; gapY = 10; nextperm0 = [4, 9, 12, 11, 8, 10, 7, 6, 5, 3, 2, 1]; currperm = [4, 9, 12, 11, 8, 10, 7, 6, 5, 3, 2, 1]; ## Observable Definitions: Afull is *observables[2]==*observables[4]; Bfull is *observables[3]==*observables[5]; height is max(*observables[2],*observables[3])+2; menu is ["1:Fill A","2:Fill B","3:Empty A","4:Empty B","5:Pour"]; valid1 is ((updating==0)||(updating==1)) && !Afull; valid2 is ((updating==0)||(updating==2)) && !Bfull; valid3 is ((updating==0)||(updating==3)) && (*observables[4] != 0); valid4 is ((updating==0)||(updating==4)) && (*observables[5] != 0); valid5 is valid6 || valid7; valid6 is ((updating==0)||(updating==6)) && (*observables[4] != 0) && !Bfull; valid7 is ((updating==0)||(updating==7)) && (*observables[5] != 0) && !Afull; menustatus is [valid1, valid2, valid3, valid4, valid5, valid6, valid7]; finish is ((*observables[4]==*observables[1])||(*observables[5]==*observables[1]))&&!updating; status is (Error)?"invalid option": ((updating)?"updating":"awaiting input"); totstat is (finish) ? "Success!" : status; ## targ is ("Target is " // str(*observables[permguess[perm[1]]]) // " : "); targ is ("Target is " // str(*observables0[1]) // " : "); ## targ is ("Target is " // str(*observables[1]) // " : "); jugA_left is Line(left,base+linewidth,left,base - (scale * capA)); jugA_right is Line(left+jugwidth,base+linewidth,left+jugwidth,base - (scale * capA)); jugA_base is Line(left,base+linewidth,left+jugwidth,base+linewidth); right is left+jugwidth+spacing; jugB_left is Line(right,base+linewidth,right,base - (scale * capB)); jugB_right is Line(right+jugwidth,base+linewidth,right+jugwidth,base - (scale * capB)); jugB_base is Line(right,base+linewidth,right+jugwidth,base+linewidth); jugA_water is Rectangle(left+linewidth,base - (scale * contentA),jugwidth-(2*linewidth),scale * contentA,"blue"); jugB_water is Rectangle(right+linewidth,base - (scale * contentB),jugwidth-(2*linewidth),scale * contentB,"blue"); statuslabel is Text(targ // " " // totstat, 250, base - ((capB * scale) / 2), "black"); but1 is Button("but1",menu[1], 50, base+80, valid1); but2 is Button("but2",menu[2], 50+70, base+80, valid2); but3 is Button("but3",menu[3], 50+150, base+80, valid3); but4 is Button("but4",menu[4], 50+250, base+80, valid4); but5 is Button("but5",menu[5], 50+340, base+80, valid5); observables is permls(permls(observables0, perm), permguess); observables0 is [&target, &capA, &capB, &contentA, &contentB, &jugwidth, &base, &scale, &left, &spacing, &linewidth, &updating]; obsvalselect is Combobox("selobs", [1,2,3,4,5,6,7,8,9,10,11,12], comboboxlocx,30, true); incval is Button("increment", "++", comboboxlocx+60, 30, true); decval is Button("decrement", "--", comboboxlocx+100, 30, true); obscorrtable is Table("obscorr", comboboxlocx+50, 50, comboboxlocx+700, 250, [["", "Description"], ["A", "The quantity of water to be achieved"], ["B", "How much water Jug A can hold"], ["C","How much water Jug B can hold"], ["D", "How much water there is in Jug A"], ["E", "How much water there is in Jug B"], ["F", "The width of the base of the jugs"], ["G", "The basepoint for the button and Jugs figure on the display"], ["H", "The scale at which the jugs are drawn"], ["I", "The leftmost point of the jugs display"], ["J", "The size of the space that separates the jugs"], ["K", "The thickness of the sides and base of the jugs"], ["L", "Whether the state is in the process of updating"]]); permguess is [int(A_value), int(B_value), int(C_value), int(D_value), int(E_value), int(F_value), int(G_value), int(H_value), int(I_value), int(J_value), int(K_value), int(L_value)]; comboA is Combobox("A", permid // ["*"], comboboxlocx, 280+gap_Y, true); comboB is Combobox("B", permid // ["*"], comboboxlocx+gap, 280+gap_Y, true); comboC is Combobox("C", permid // ["*"], comboboxlocx+gap*2, 280+gap_Y, true); comboD is Combobox("D", permid // ["*"], comboboxlocx+gap*3, 280+gap_Y, true); comboE is Combobox("E", permid // ["*"], comboboxlocx+gap*4, 280+gap_Y, true); comboF is Combobox("F", permid // ["*"], comboboxlocx+gap*5, 280+gap_Y, true); comboG is Combobox("G", permid // ["*"], comboboxlocx+gap*6, 280+gap_Y, true); comboH is Combobox("H", permid // ["*"], comboboxlocx+gap*7, 280+gap_Y, true); comboI is Combobox("I", permid // ["*"], comboboxlocx+gap*8, 280+gap_Y, true); comboJ is Combobox("J", permid // ["*"], comboboxlocx+gap*9, 280+gap_Y, true); comboK is Combobox("K", permid // ["*"], comboboxlocx+gap*10, 280+gap_Y, true); comboL is Combobox("L", permid // ["*"], comboboxlocx+gap*11, 280+gap_Y, true); labcomboA is Text("A", comboboxlocx, 280+gapY, (permguess[perm[1]]==1) ? "green" : "red"); labcomboB is Text("B", comboboxlocx+gap, 280+gapY, (permguess[perm[2]]==2) ? "green" : "red"); labcomboC is Text("C", comboboxlocx+gap*2, 280+gapY, (permguess[perm[3]]==3) ? "green" : "red"); labcomboD is Text("D", comboboxlocx+gap*3, 280+gapY, (permguess[perm[4]]==4) ? "green" : "red"); labcomboE is Text("E", comboboxlocx+gap*4, 280+gapY, (permguess[perm[5]]==5) ? "green" : "red"); labcomboF is Text("F", comboboxlocx+gap*5, 280+gapY, (permguess[perm[6]]==6) ? "green" : "red"); labcomboG is Text("G", comboboxlocx+gap*6, 280+gapY, (permguess[perm[7]]==7) ? "green" : "red"); labcomboH is Text("H", comboboxlocx+gap*7, 280+gapY, (permguess[perm[8]]==8) ? "green" : "red"); labcomboI is Text("I", comboboxlocx+gap*8, 280+gapY, (permguess[perm[9]]==9) ? "green" : "red"); labcomboJ is Text("J", comboboxlocx+gap*9, 280+gapY, (permguess[perm[10]]==10) ? "green" : "red"); labcomboK is Text("K", comboboxlocx+gap*10, 280+gapY, (permguess[perm[11]]==11) ? "green" : "red"); labcomboL is Text("L", comboboxlocx+gap*11, 280+gapY, (permguess[perm[12]]==12) ? "green" : "red"); labcomboA is Text("A", comboboxlocx, 280+gapY, (perm[A_value]==1) ? "green" : "red"); labcomboB is Text("B", comboboxlocx+gap, 280+gapY, (perm[B_value]==2) ? "green" : "red"); labcomboC is Text("C", comboboxlocx+gap*2, 280+gapY, (perm[C_value]==3) ? "green" : "red"); labcomboD is Text("D", comboboxlocx+gap*3, 280+gapY, (perm[D_value]==4) ? "green" : "red"); labcomboE is Text("E", comboboxlocx+gap*4, 280+gapY, (perm[E_value]==5) ? "green" : "red"); labcomboF is Text("F", comboboxlocx+gap*5, 280+gapY, (perm[F_value]==6) ? "green" : "red"); labcomboG is Text("G", comboboxlocx+gap*6, 280+gapY, (perm[G_value]==7) ? "green" : "red"); labcomboH is Text("H", comboboxlocx+gap*7, 280+gapY, (perm[H_value]==8) ? "green" : "red"); labcomboI is Text("I", comboboxlocx+gap*8, 280+gapY, (perm[I_value]==9) ? "green" : "red"); labcomboJ is Text("J", comboboxlocx+gap*9, 280+gapY, (perm[J_value]==10) ? "green" : "red"); labcomboK is Text("K", comboboxlocx+gap*10, 280+gapY, (perm[K_value]==11) ? "green" : "red"); labcomboL is Text("L", comboboxlocx+gap*11, 280+gapY, (perm[L_value]==12) ? "green" : "red"); jugA_left2 is Line(left+linewidth,base,left+linewidth,base - (scale * capA)); jugA_right2 is Line(left+jugwidth-linewidth,base,left+jugwidth-linewidth,base - (scale * capA)); jugB_left2 is Line(right+linewidth,base,right+linewidth,base - (scale * capB)); jugB_right2 is Line(right+jugwidth-linewidth,base,right+jugwidth-linewidth,base - (scale * capB)); topA_left is Line(left, base-(scale*capA), left+linewidth, base-(scale*capA)); topA_right is Line(left+jugwidth, base-(scale*capA), left+jugwidth-linewidth, base-(scale*capA)); topB_left is Line(right, base-(scale*capB), right+linewidth, base-(scale*capB)); topB_right is Line(right+jugwidth, base-(scale*capB), right+jugwidth-linewidth, base-(scale*capB)); nextperm1 is insertcurrpermix(nextperm0, 12); nextperm2 is insertcurrpermix(nextperm1, 11); nextperm3 is insertcurrpermix(nextperm2, 10); nextperm4 is insertcurrpermix(nextperm3, 9); nextperm5 is insertcurrpermix(nextperm4, 8); nextperm6 is insertcurrpermix(nextperm5, 7); nextperm7 is insertcurrpermix(nextperm6, 6); nextperm8 is insertcurrpermix(nextperm7, 5); nextperm9 is insertcurrpermix(nextperm8, 4); nextperm10 is insertcurrpermix(nextperm9, 3); nextperm11 is insertcurrpermix(nextperm10, 2); nextperm12 is insertcurrpermix(nextperm11, 1); puzzlesolved is permeqid(prodperm(perm, permguess), permid); nextpuzzlebutlabel is (puzzlesolved) ? "New puzzle" : "Quit puzzle"; nextpuzzlebut is Button("newpuzzle",nextpuzzlebutlabel, 900, 30, true); visualreset is Button("resetvisual","Visual reset", 750, 30, true); ## Action Definitions: proc updatevalues { A_value = 1; B_value = 2; C_value=3; D_value=4; E_value=5; F_value=6; G_value=7; H_value=8; I_value=9; J_value=10; K_value=11; L_value=12; } proc init_pour : input { updating = 1; if (int(input) == 5) { content5 = contentA + contentB; contentB is content5 - contentA; option = valid6 ? 6 : 7; } else option = int(input); step = 0; } proc pour : step { if (avail(option)) { switch (option) { case 1: contentA = contentA + 1; break; case 2: contentB = contentB + 1; break; case 3: contentA = contentA - 1; break; case 4: contentB = contentB - 1; break; case 6: contentA = contentA - 1; break; case 7: contentA = contentA + 1; break; default: writeln("option = ", option); return; } after (viscosity) { step++; } } else { contentA = contentA; contentB = contentB; updating = 0; } } proc but1agent : but1_clicked { if (but1_clicked == true) { *observables[4]++; updating = (valid1) ? 1 : 0; } } proc but2agent : but2_clicked { if (but2_clicked == true) { *observables[5]++; updating = (valid2) ? 2 : 0; } } proc but3agent : but3_clicked { if (but3_clicked == true) { *observables[4]--; updating = (valid3) ? 3 : 0; } } proc but4agent : but4_clicked { if (but4_clicked == true) { *observables[5]--; updating = (valid4) ? 4 : 0; } } proc but5agent : but5_clicked { if (but5_clicked == true) { if (valid6) { *observables[5]++; *observables[4]--; updating = (valid6) ? 6 : 0; } else { *observables[5]--; *observables[4]++; updating = (valid7) ? 7 : 0; } } } proc incbutagent : increment_clicked { if (increment_clicked == true) { *observables[invertpermguess(int(selobs_value))]++; } } proc decbutagent : decrement_clicked { if (decrement_clicked == true) { *observables[invertpermguess(int(selobs_value))]--; } } proc mkvisualreset : resetvisual_clicked { if (resetvisual_clicked) { target = 1; capA = 5; capB = 7; contentA = 0; contentB = 0; updating = 0; jugwidth = 60; base = 200; scale = 20; left = 50; spacing = 30; linewidth = 0; } } proc mknewpuzzle : newpuzzle_clicked { if (newpuzzle_clicked) { if (puzzlesolved) { perm = currperm; nextperm0 = [0,0,0,0,0,0,0,0,0,0,0,0]; currperm = nextperm12; } else { perm = permid; } ## shouldn't be necessary? updatevalues(); } } ## Function Definitions: func max { return $1<$2 ? $2 : $1; } func avail { /* indicates whether the menu option with parameter $1 is open */ auto t; t = menustatus[$1]; return t; } func Table { para name, x, y, width, height, dataRows; auto html, i, j; html = "
| "; html = html // dataRows[j][i]; html = html // " | \n"; } html = html // "
The JUGS puzzle is intended to introduce the concept of an observables in a way that emphasises the interactive and exploratory way in which observables are identified. In order to solve the puzzle, it is not necessary to know the names of the observables in the model, but only to be able to recognise them from their description. There are 12 observables of interest, labelled A,B,C,D,E,F,G,H,I,J,K,L: the characterisation of each is given in the table on the right-hand side of the display.
When you first load the puzzle, the array of comboboxes on the right-hand side should be indexed in sequence by the numbers 1 to 12, and labelled in green by the letters A to L. At this point, the observables in the JUGS model are correctly configured.
As a prequisite for solving the puzzle, you should first be familiar with the normal semi-automated behaviour of the JUGS model. You can gain this familiarity by playing around with the model using the Fill, Empty and Pour buttons on the left-hand side of the display.
Tackling the puzzle
When you interact with the puzzle, you are in effect manipulating some anonymous observables labelled 1 through 12. These observables are initially configured so that observables 1 to 12 map to observables A to L respectively. There is a single combobox in the middle of the display at the top. You can use this box to select any one of the observables from 1 to 12 and examine what happens when you increase and decrease the value of this observable by pressing the buttons labelled '++' and '--' to the right of the combobox. When the JUGS model is in its correct state, you may like to confirm that the correspondence between the indices 1 to 12 and the observables A to L is exactly as you would expect. For instance, incrementing observable 4 increases the value of observable D which represents the amount of water in Jug A. An alternative way of incrementing observable 4 is then to press the button 'Fill A'.
To set up a new puzzle, you press the 'New Puzzle' button. The effect of pressing this button is to scramble the observables in the JUGS model so that there is a new (randomly specified) correspondence between the observables 1 to 12 and the observables A to L. When you press the buttons in the JUGS model, the effect of (e.g.) filling A is to increment observable 4 as before, but the probable effect will be to change the value of some other observable. If you can identify this observable (as, say, the size of the space that separates the jugs) you can record this by selecting the index 4 in the combobox labelled J. The aim in the puzzle is to renumber the comboboxes in such a way that the JUGS model behaves as you'd expect.
As a warm up exercise, you can use the combobox at the topleft to select an index in the range 1-12 and change the value of a mystery observable with that index using the '++' and '--' buttons. By observing the response in the JUGS display, you should be able to determine what each of the observables 1 to 12 represents - for instance, to establish that the observable with index 6 references the thickness of the sides and base of the jugs etc. You register this fact by selecting 6 in the combobox labelled K at the foot of the RH part of the display.
When you've done the warm up, it's good to see if you can solve the puzzle by using only the button interface on the Jugs display (hard if even possible in general I think, though there is a strategy that I think is quite good and versatile that I leave you to discover). You know when you are making progress towards the right answer since the label above a combobox at the bottom (initially red) turns to green when you've got that particular identification of an index with an observable right.
Footnotes:Note that there is a sort of bug in the Jugs (at least in the version that I've constructed here), whereby (even when the observables are all correctly indexed) it's possible by pressing the buttons fast to overshoot on filling and emptying jugs. I presume this has to do with the way in which input, calculation and display get synchronised when the browser is pushed to respond at speed. You are advised not to press the buttons too fast for this reason.
"); updatevalues();