## to enable special symbols such as the pound sign to work correctly on all browsers
func decodeHTML {};
${{
/* Replaces HTML character entities in a string with the equivalent real characters with the
* following exceptions: & < > " '
*/
root.lookup("decodeHTML").assign ( (function() {
var element = document.createElement('div');
function decodeHTML (str) {
if(typeof(str) == 'string') {
//Strip html tags
str = str.replace(/&(amp|#38|lt|#60|gt|#62|quot|#34|apos|#39);/g, "&$1;");
str = str.replace(/&([^\s;]*\s)/g, "&$1");
str = str.replace(/A simple shopping construal
Note:
This construal has been developed for collaborative interaction using features that are only available in the most recent 'construit' variant of JS-EDEN which you find at the url http://jseden.dcs.warwick.ac.uk/construit .
You may need to move this HTML window aside in order to see other windows in the display.
You may also find it helpful to resize the display: this can be done by assigning a new value to the observable scaleWidth.
To ensure that the entire display is visible, you may need to expand the Canvas HTML5 display downwards to reveal the prices of the items, and to the right in order to show the textual annotations of the display components in full.
The purpose of this construal is to illustrate how the basic concepts of observables, dependencies and agents/agency are represented in a simple shopping scenario. Simple examples of observables are: the coins in the purse, the items for sale, the items in the basket, and whether or not you have enough money in your purse to buy the items in your basket. The value of an observable may be explicitly specified (in which case its value can be changed by making an assignment - designated by '='). It may also be specified implicitly in terms of the values of other observables (in which case, its value is specified via a definition - designated by 'is'). An 'is' definition expresses a dependency: if the value on the RHS of a definition changes at any point, the value on the LHS is automatically updated, as in a spreadsheet.
The construal can be viewed as a rather open-ended and incompletely specified explanatory, exploratory or educational resource.
The precise way in which observables, dependencies and agency are configured will depend on how the construal is to be exercised - that is to say, what kind of explanatory, exploratory or educational role it is at present intended to serve.
It is common for this role to be in flux, and reconfiguration is generally relatively straightforward. This is in contrast to what is typically involved in modifying a traditional program to meet a new requirement.
The extent to which a construal can be readily adapted to serve different roles is a pragmatic measure of its quality. This is in keeping with the way in which the merits of commonsense everyday construals are assessed.
In its present form, the shopping construal is set up as an environment within which a learner unfamiliar with UK currency or unaccustomed to mental arithmetic can interact and experiment. The display has two parts - an upper portion which represents a purse with eight randomly generated UK coins, and a lower portion which represents six items for sale (the prices are intended to be fairly realistic, making allowance for the fact that grapes and strawberries are sold in punnets rather than individually). Coins to be offered in making a purchase can be taken into / out of the purse by clicking on them using the mouse. Items to be placed in the basket for purchase can be selected / deselected in a similar fashion.
The observables, dependencies and agency in the model can be inspected by creating instances of views using the drop-down menu under the New tab on the left at the top of the JS-EDEN display, and inserting suitable 'regular expressions (RE)' into the search boxes in each of these views. The following views and REs can be used for instance:
- Observable Lists with the REs 'basket|bill|items', 'purse|coins|tendered' and 'change|short|hav' which give relevant information about the items for sale, the spending money available and the status of a potential purchase (is there enough money in the purse? how much change would I get from the money tendered? etc).
-
A Function List with the RE 'mon|cost|coi' to identify some of the user-defined functions that have been introduced to express dependency relations
-
An Agent List with the RE 'coin|item' that identifies the actions that are performed when the coins and items are selected using the mouse.
For this particular way of exercising the construal, the eight coins in the purse have been defined by generating eight indices ix1, ix2, ..., ix8 at random. The values of these indices determine the denominations of the coins in the purse. For instance, if ix4 is 100, the 'fourth' coin in the purse is a pound coin etc. To change the contents of the purse, you can copy-and-paste the following code into the Input Window and press Submit:
ix1 = randomInteger(1, 8);
ix2 = randomInteger(1, 8);
ix3 = randomInteger(1, 8);
ix4 = randomInteger(1, 8);
ix5 = randomInteger(1, 8);
ix6 = randomInteger(1, 8);
ix7 = randomInteger(1, 8);
ix8 = randomInteger(1, 8);
Acknowledgements: The images and presentation of coins were adapted from these websites:
http://projectbritain.com/money/coins.htm
http://www.mathsisfun.com/money/currency.html
");
## Auto-Generated Script of Model by JS-Eden
## Auto calculation is turned off to until the model has been fully loaded
autocalc = 0;
## Observable Assignments:
price1 = 1.5;
price2 = 0.36;
price3 = 1.25;
price4 = 1;
price5 = 0.4;
price6 = 2.48;
imagelocation = "http://www.dcs.warwick.ac.uk/~jonny/ukcurrency/";
/*
width50 = 69;
width200 = 72;
width5 = 46;
width10 = 62;
width1 = 51;
width100 = 57;
width20 = 54;
width2 = 66;
*/
scaleWidth = 60;
## Observable Definitions:
ix1 is int(random()*8)+1;
ix2 is int(random()*8)+1;
ix3 is int(random()*8)+1;
ix4 is int(random()*8)+1;
ix5 is int(random()*8)+1;
ix6 is int(random()*8)+1;
ix7 is int(random()*8)+1;
ix8 is int(random()*8)+1;
item1 is [ "id1", price1];
item2 is [ "id2", price2];
item3 is [ "id3", price3];
item4 is [ "id4", price4];
item5 is [ "id5", price5];
item6 is [ "id6", price6];
forsale is [item1, item2, item3, item4, item5, item6];
basket is listitems(forsale, itemsselected);
bill is round(costitems(forsale, itemsselected),2);
## bill is costitems(forsale, itemsselected);
coinlist is [1,2,5,10,20,50,100,200];
purse is [coinlist[ix1], coinlist[ix2], coinlist[ix3], coinlist[ix4], coinlist[ix5], coinlist[ix6], coinlist[ix7], coinlist[ix8]];
spendingmoney is (purse[1]+purse[2]+purse[3]+purse[4]+purse[5]+purse[6]+purse[7]+purse[8])/100;
/*
testcoindisplay is coindisplay(ix1);
testdenomdisplay is denomdisplay(ix7);
testdisplaycurrency is displaycurrency(spendingmoney);
*/
haveenoughmoney is (bill bill)? round(tendered - bill, 2) : 0;
/*
widths is [width1, width2, width5, width10, width20, width50, width100, width200];
currwidths is [widths[ix1], widths[ix2], widths[ix3], widths[ix4], widths[ix5], widths[ix6], widths[ix7], widths[ix8]];
*/
items is [item1, item2, item3, item4, item5, item6];
coin1pic is HTMLImage("coin1pic",0,2*scaleWidth*coinsselected[1],scaleWidth,scaleWidth,imagelocation // coindisplay(ix1));
coin2pic is HTMLImage("coin2pic", scaleWidth,2*scaleWidth*coinsselected[2],scaleWidth,scaleWidth,imagelocation // coindisplay(ix2));
coin3pic is HTMLImage("coin3pic", scaleWidth*2,2*scaleWidth*coinsselected[3],scaleWidth,scaleWidth,imagelocation // coindisplay(ix3));
coin4pic is HTMLImage("coin4pic", scaleWidth*3,2*scaleWidth*coinsselected[4],scaleWidth,scaleWidth,imagelocation // coindisplay(ix4));
coin5pic is HTMLImage("coin5pic", scaleWidth*4,2*scaleWidth*coinsselected[5],scaleWidth,scaleWidth,imagelocation // coindisplay(ix5));
coin6pic is HTMLImage("coin6pic", scaleWidth*5,2*scaleWidth*coinsselected[6],scaleWidth,scaleWidth,imagelocation // coindisplay(ix6));
coin7pic is HTMLImage("coin7pic", scaleWidth*6,2*scaleWidth*coinsselected[7],scaleWidth,scaleWidth,imagelocation // coindisplay(ix7));
coin8pic is HTMLImage("coin8pic", scaleWidth*7,2*scaleWidth*coinsselected[8],scaleWidth,scaleWidth,imagelocation // coindisplay(ix8));
item1pic is HTMLImage("item1pic",scaleWidth*0.5,5.5*scaleWidth-2*scaleWidth,scaleWidth,scaleWidth,imagelocation // itemdisplay(1));
item2pic is HTMLImage("item2pic", scaleWidth*1.8, 5.5*scaleWidth-2*scaleWidth,scaleWidth,scaleWidth,imagelocation // itemdisplay(2));
item3pic is HTMLImage("item3pic", scaleWidth*3.1, 5.5*scaleWidth-2*scaleWidth,scaleWidth,scaleWidth,imagelocation // itemdisplay(3));
item4pic is HTMLImage("item4pic", scaleWidth*4.4, 5.5*scaleWidth-2*scaleWidth,scaleWidth,scaleWidth,imagelocation // itemdisplay(4));
item5pic is HTMLImage("item5pic", scaleWidth*5.7, 5.5*scaleWidth-2*scaleWidth,scaleWidth,scaleWidth,imagelocation // itemdisplay(5));
item6pic is HTMLImage("item6pic", scaleWidth*7, 5.5*scaleWidth-2*scaleWidth,scaleWidth,scaleWidth,imagelocation // itemdisplay(6));
item1pic0 is HTMLImage("item1pic0",scaleWidth*0.5,5.5*scaleWidth,scaleWidth,scaleWidth,imagelocation // itemdisplay(1));
item2pic0 is HTMLImage("item2pic0", scaleWidth*1.8, 5.5*scaleWidth,scaleWidth,scaleWidth,imagelocation // itemdisplay(2));
item3pic0 is HTMLImage("item3pic0", scaleWidth*3.1, 5.5*scaleWidth,scaleWidth,scaleWidth,imagelocation // itemdisplay(3));
item4pic0 is HTMLImage("item4pic0", scaleWidth*4.4, 5.5*scaleWidth,scaleWidth,scaleWidth,imagelocation // itemdisplay(4));
item5pic0 is HTMLImage("item5pic0", scaleWidth*5.7, 5.5*scaleWidth,scaleWidth,scaleWidth,imagelocation // itemdisplay(5));
item6pic0 is HTMLImage("item6pic0", scaleWidth*7, 5.5*scaleWidth,scaleWidth,scaleWidth,imagelocation // itemdisplay(6));
coin1text is Text(denomdisplay(ix1), 0.2*scaleWidth,1.5*scaleWidth);
coin2text is Text(denomdisplay(ix2), 1.2*scaleWidth,1.5*scaleWidth);
coin3text is Text(denomdisplay(ix3), 2.2*scaleWidth,1.5*scaleWidth);
coin4text is Text(denomdisplay(ix4), 3.2*scaleWidth,1.5*scaleWidth);
coin5text is Text(denomdisplay(ix5), 4.2*scaleWidth,1.5*scaleWidth);
coin6text is Text(denomdisplay(ix6), 5.2*scaleWidth,1.5*scaleWidth);
coin7text is Text(denomdisplay(ix7), 6.2*scaleWidth,1.5*scaleWidth);
coin8text is Text(denomdisplay(ix8), 7.2*scaleWidth,1.5*scaleWidth);
func mkstr {
para ix;
return (ix==0) ? "" : str(ix);
}
item1numtext is Text(mkstr(itemsselected[1]), 0.6*scaleWidth,5*scaleWidth);
item2numtext is Text(mkstr(itemsselected[2]), 1.9*scaleWidth,5*scaleWidth);
item3numtext is Text(mkstr(itemsselected[3]), 3.2*scaleWidth,5*scaleWidth);
item4numtext is Text(mkstr(itemsselected[4]), 4.5*scaleWidth,5*scaleWidth);
item5numtext is Text(mkstr(itemsselected[5]), 5.8*scaleWidth,5*scaleWidth);
item6numtext is Text(mkstr(itemsselected[6]), 7.1*scaleWidth,5*scaleWidth);
/*
item1text is Text(pricedisplay(1), 0.6*scaleWidth,7*scaleWidth);
item2text is Text(pricedisplay(2), 1.9*scaleWidth,7*scaleWidth);
item3text is Text(pricedisplay(3), 3.2*scaleWidth,7*scaleWidth);
item4text is Text(pricedisplay(4), 4.5*scaleWidth,7*scaleWidth);
item5text is Text(pricedisplay(5), 5.8*scaleWidth,7*scaleWidth);
item6text is Text(pricedisplay(6), 7.1*scaleWidth,7*scaleWidth);
*/
item1text is Text(pricedisplay(1, items), 0.6*scaleWidth,7*scaleWidth);
item2text is Text(pricedisplay(2, items), 1.9*scaleWidth,7*scaleWidth);
item3text is Text(pricedisplay(3, items), 3.2*scaleWidth,7*scaleWidth);
item4text is Text(pricedisplay(4, items), 4.5*scaleWidth,7*scaleWidth);
item5text is Text(pricedisplay(5, items), 5.8*scaleWidth,7*scaleWidth);
item6text is Text(pricedisplay(6, items), 7.1*scaleWidth,7*scaleWidth);
## Action Definitions:
proc coin1picMove : coin1pic_click {
if(coin1pic_click)
coinsselected[1] = 1 - coinsselected[1];
}
proc coin2picMove : coin2pic_click {
if(coin2pic_click)
coinsselected[2] = 1 - coinsselected[2];
}
proc coin3picMove : coin3pic_click {
if(coin3pic_click)
coinsselected[3] = 1 - coinsselected[3];
}
proc coin4picMove : coin4pic_click {
if(coin4pic_click)
coinsselected[4] = 1 - coinsselected[4];
}
proc coin5picMove : coin5pic_click {
if(coin5pic_click)
coinsselected[5] = 1 - coinsselected[5];
}
proc coin6picMove : coin6pic_click {
if(coin6pic_click)
coinsselected[6] = 1 - coinsselected[6];
}
proc coin7picMove : coin7pic_click {
if(coin7pic_click)
coinsselected[7] = 1 - coinsselected[7];
}
proc coin8picMove : coin8pic_click {
if(coin8pic_click)
coinsselected[8] = 1 - coinsselected[8];
}
proc item1pic0Move : item1pic0_click {
if(item1pic0_click)
itemsselected[1] = 1 + itemsselected[1];
}
proc item2pic0Move : item2pic0_click {
if(item2pic0_click)
itemsselected[2] = 1 + itemsselected[2];
}
proc item3pic0Move : item3pic0_click {
if(item3pic0_click)
itemsselected[3] = 1 + itemsselected[3];
}
proc item4pic0Move : item4pic0_click {
if(item4pic0_click)
itemsselected[4] = 1 + itemsselected[4];
}
proc item5pic0Move : item5pic0_click {
if(item5pic0_click)
itemsselected[5] = 1 + itemsselected[5];
}
proc item6pic0Move : item6pic0_click {
if(item6pic0_click)
itemsselected[6] = 1 + itemsselected[6];
}
proc item1picMove : item1pic_click {
if(item1pic_click)
itemsselected[1] = itemsselected[1] - 1;
}
proc item2picMove : item2pic_click {
if(item2pic_click)
itemsselected[2] = itemsselected[2]-1;
}
proc item3picMove : item3pic_click {
if(item3pic_click)
itemsselected[3] = itemsselected[3]-1;
}
proc item4picMove : item4pic_click {
if(item4pic_click)
itemsselected[4] = itemsselected[4]-1;
}
proc item5picMove : item5pic_click {
if(item5pic_click)
itemsselected[5] = itemsselected[5]-1;
}
proc item6picMove : item6pic_click {
if(item6pic_click)
itemsselected[6] = itemsselected[6]-1;
}
## Function Definitions:
func listitems {
para onsale, chosen;
auto result, i;
result = [];
for (i=1; i<=onsale#; i++)
if (chosen[i]) result = result // [onsale[i][1]];
return result;
}
/*
func costitems {
para onsale, chosen;
auto result, i;
result = 0;
for (i=1; i<=onsale#; i++)
if (chosen[i]) result = result + onsale[i][2];
return result;
*/
func costitems {
para onsale, chosen;
auto result, i;
result = 0;
for (i=1; i<=onsale#; i++)
if (chosen[i]) result = result + onsale[i][2]*chosen[i];
return result;
}
func moneyinhand {
para allcoins, chosen;
auto result, i;
result = 0;
for (i=1; i<=allcoins#; i++)
if (chosen[i]) result = result + allcoins[i];
return result/100;
}
func coindisplay {
para ix;
if (ix==1) return "1p.gif";
if (ix==2) return "2p.gif";
if (ix==3) return "5p.gif";
if (ix==4) return "10p.gif";
if (ix==5) return "20p.jpg";
if (ix==6) return "50p.jpg";
if (ix==7) return "pound.gif";
if (ix==8) return "2pounds.gif";
}
func listcoins {
para allcoins, chosen;
auto result, i;
result = [];
for (i=1; i<=allcoins#; i++)
if (chosen[i]) result = result // [allcoins[i]];
return result;
}
func itemdisplay {
para ix, scaleWidth;
if (ix==1) return "a.png";
if (ix==2) return "b.png";
if (ix==3) return "c.jpg";
if (ix==4) return "d.jpg";
if (ix==5) return "e.jpg";
if (ix==6) return "f.jpg";
}
func denomdisplay {
para ix;
if (ix==1) return "1p";
if (ix==2) return "2p";
if (ix==3) return "5p";
if (ix==4) return "10p";
if (ix==5) return "20p";
if (ix==6) return "50p";
if (ix==7) return decodeHTML("£1");
if (ix==8) return decodeHTML("£2");;
}
func displaycurrency {
para amount;
auto pounds, pence;
pence = 100*amount;
pounds = int (pence / 100);
pence = round(pence - pounds*100);
return decodeHTML("£") // ((pounds>0) ? str(pounds) : "0") // ((pence>0) ? "-" // str(pence) // "p" : "");
}
func pricedisplay {
para ix, itemlist;
if (ix==1) return displaycurrency(itemlist[1][2]);
if (ix==2) return displaycurrency(itemlist[2][2]);
if (ix==3) return displaycurrency(itemlist[3][2]);
if (ix==4) return displaycurrency(itemlist[4][2]);
if (ix==5) return displaycurrency(itemlist[5][2]);
if (ix==6) return displaycurrency(itemlist[6][2]);
}
## Picture Definition:
picture is [coin1pic,coin2pic,coin3pic,coin4pic,coin5pic,coin6pic,coin7pic,coin8pic, item1pic,item2pic,item3pic,item4pic,item5pic,item6pic,
coin1text,coin2text,coin3text,coin4text,coin5text,coin6text,coin7text,coin8text,item1text,item2text,item3text,item4text,item5text,item6text];
## Auto calculation is turned on and the updating is fired
autocalc = 1;
## End of Auto-Generated Script
coinsselected = [0,0,0,0,0,0,0,0];
itemsselected = [0,0,0,0,0,0];
ix1 = randomInteger(1, 8);
ix2 = randomInteger(1, 8);
ix3 = randomInteger(1, 8);
ix4 = randomInteger(1, 8);
ix5 = randomInteger(1, 8);
ix6 = randomInteger(1, 8);
ix7 = randomInteger(1, 8);
ix8 = randomInteger(1, 8);
PurseContentText is Text("Content of purse", 8.3*scaleWidth,0.5*scaleWidth, "blue", 18);
CoinsInHandText is Text("Coins to hand", 8.3*scaleWidth,2.5*scaleWidth, "red", 18);
BasketContentText is Text("Content of basket", 8.3*scaleWidth,4*scaleWidth, "red", 18);
ItemsForSaleText is Text("Items for sale", 8.3*scaleWidth,6*scaleWidth, "blue", 18);
## NumberOfItemsSelectedText is Text("Items for sale", 8.3*scaleWidth,6*scaleWidth, "blue", 18);
/*
picture is [coin1pic,coin2pic,coin3pic,coin4pic,coin5pic,coin6pic,coin7pic,coin8pic, item1pic,item2pic,item3pic,item4pic,item5pic,item6pic,
coin1text,coin2text,coin3text,coin4text,coin5text,coin6text,coin7text,coin8text,item1text,item2text,item3text,item4text,item5text,item6text,
PurseContentText,CoinsInHandText,BasketContentText,ItemsForSaleText];
*/
picture is [coin1pic, coin2pic, coin3pic, coin4pic, coin5pic, coin6pic, coin7pic, coin8pic, item1pic, item2pic, item3pic, item4pic, item5pic, item6pic, item1pic0, item2pic0, item3pic0, item4pic0, item5pic0, item6pic0, coin1text, coin2text, coin3text, coin4text, coin5text, coin6text, coin7text, coin8text, item1text, item2text, item3text, item4text, item5text, item6text, item1numtext, item2numtext, item3numtext, item4numtext, item5numtext, item6numtext, PurseContentText, CoinsInHandText, BasketContentText, ItemsForSaleText];
optpic1 is (itemsselected[1]>0) ? [item1pic] : [];
optpic2 is (itemsselected[2]>0) ? [item2pic] : [];
optpic3 is (itemsselected[3]>0) ? [item3pic] : [];
optpic4 is (itemsselected[4]>0) ? [item4pic] : [];
optpic5 is (itemsselected[5]>0) ? [item5pic] : [];
optpic6 is (itemsselected[6]>0) ? [item6pic] : [];
picture is [coin1pic, coin2pic, coin3pic, coin4pic, coin5pic, coin6pic, coin7pic, coin8pic] // optpic1 // optpic2 // optpic3 // optpic4 // optpic5 // optpic6 // [item1pic0, item2pic0, item3pic0, item4pic0, item5pic0, item6pic0, coin1text, coin2text, coin3text, coin4text, coin5text, coin6text, coin7text, coin8text, item1text, item2text, item3text, item4text, item5text, item6text, item1numtext, item2numtext, item3numtext, item4numtext, item5numtext, item6numtext, PurseContentText, CoinsInHandText, BasketContentText, ItemsForSaleText];
### extensions
price1 = 0.31; price2 = 1.64; price3 = 0.39; price4 = 2.0; price5 = 0.29; price6 = 0.42;