Want to know a really useful thing about using Silverlight and making cross domain REST calls?
http://msdn.microsoft.com/en-us/library/cc645032(v=vs.95).aspx
I found a way to make the code look better. gist.github.com. I might format it even better in the future. It is way better now though. Copy the whole thing and pop it in a browser. Very likely it will work.
Here is the code that is used in the memory leak detection:
public class MemoryLeak {
HashMap hm = new HashMap();
long curValue;
MemoryLeak()
{
curValue = 0;
}
public static void main ( String [] args )
{
try {
MemoryLeak ml = new MemoryLeak();
for ( int j = 0; j < 100; j++ )
{
for ( int u = 0; u < 5000; u++ )
{
ml.leakMemory();
ml.curValue++;
}
Thread.currentThread().sleep(2000); // Wait 2 seconds
}
}
catch ( Exception ex )
{
System.out.println("exception: ex = " + ex);
}
}
void setReference( GeneralClass gc )
{
hm.put( curValue, gc );
}
public void leakMemory()
{
try {
GeneralClass gc = new GeneralClass();
setReference( gc );
}
catch ( Exception ex )
{
System.out.println("exception: ex = " + ex);
}
}
}
class GeneralClass
{
int a;
int b;
String s1;
String s2;
GeneralClass()
{
a = 0;
b = 4;
s1 = "s1";
s2 = "s2";
}
}
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTM 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<!--
Drink Making game (AKA SimBar). Author: Ruth. http://www.amazingknife.com and http://youtube.com/ruthj180
Make some drinks for your customers. Earn money making drinks and spend money buying supplies and
dealing with events. This game runs only in the browser. There is no server it is communicating with, so
it will not save your progress if you navigate away or refresh. The game is developed with HTML, CSS,
JavaScript and the Dojo Toolkit. Always drink responsibly. Enjoy the game!
If you use any of this code for your own projects, please give me credit. If you would like to buy my game,
or hire me, please let me know.
-->
<html>
<head>
<!-- Author: Ruth. amazingknife.com -->
<title>Drink Making Game</title>
<!--
Thanks Google for hosting the Dojo Toolkit on your CDN (Content Distribution Network).
http://code.google.com/apis/ajaxlibs/documentation/
-->
<link rel="stylesheet" href="http://ajax.googleapis.com/ajax/libs/dojo/1.3.1/dijit/themes/tundra/tundra.css" />
<link rel="stylesheet" href="http://ajax.googleapis.com/ajax/libs/dojo/1.3.1/dojox/widget/Dialog/Dialog.css" />
<link rel="stylesheet" href="http://ajax.googleapis.com/ajax/libs/dojo/1.3.1/dojo/resources/dojo.css" />
<link rel="stylesheet" href="http://ajax.googleapis.com/ajax/libs/dojo/1.3.1/dojox/widget/Toaster/Toaster.css" />
<!-- Author: Ruth. amazingknife.com -->
<style type="text/css">
.counter {
margin: 10px;
background: black;
color: white;
padding: 5px;
}
.bigCell {
width: 280px;
height: 40px;
}
.regularCell {
width: 200px;
height: 40px;
}
.smallCell {
width: 150px;
height: 40px;
}
</style>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/dojo/1.3.1/dojo/dojo.xd.js"
djConfig="parseOnLoad: true"></script>
<!-- Author: Ruth. amazingknife.com -->
<script type="text/javascript">
dojo.require("dijit.ProgressBar");
dojo.require("dijit.form.Button");
dojo.require("dijit.form.MultiSelect");
dojo.require("dijit.Dialog");
dojo.require("dijit.form.CheckBox");
dojo.require("dojox.widget.Toaster");
dojo.require("dijit.Tooltip");
// the require is a different statement. look at the api
//dojo.require("dojox.timing.Timer");
// regular javascript has a one shot timer:
// setTimeout("alert('hi');", 1000); // one second timer
dojo.require("dojo.parser");
// Author: Ruth. amazingknife.com
var drinkCount = 0;
var moneyTotal = 0.00;
var customerDrinkToMake = "";
// The const keyword doesn't work in IE.
// https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Statements/const
var BEER_PRICE = 3;
var WINE_PRICE = 6;
var COCKTAIL_PRICE = 8;
// Make all these look like constants
var KEG_PRICE = 150;
var RUM_BOTTLE_PRICE = 25;
var GIN_BOTTLE_PRICE = 25;
var VODKA_BOTTLE_PRICE = 25;
var WINE_BOTTLE_PRICE = 20;
// A keg equals 124 pints
var PINTS_PER_KEG = 124;
var beerLeft = 124;
// About 6 glasses (4 oz) of wine per 750 ml bottle
var GLASSES_WINE_PER_BOTTLE = 6;
var wineLeft = 6;
// 750 ml divided by 30 ml = 25, so 25 drinks per bottle ( 1 oz per drink )
var SHOTS_PER_BOTTLE = 25;
var ginLeft = 25;
var rumLeft = 25;
var vodkaLeft = 25;
// This makes a random number from 0 to 5 - if 0 or 1 then beer (beer frequency is a little higher)
var randomNumber = Math.floor(Math.random()*6);
// Make all these look like constants
var beerPhrase = "The customer would like a beer."
var winePhrase = "The customer would like a glass of wine."
var ginntonicPhrase = "The customer would like a gin and tonic."
var rumncokePhrase = "The customer would like a rum and coke."
var vodkatonicPhrase = "The customer would like a vodka tonic."
var needGreenFairy = false;
var boozillaHappened = false;
var turnsSinceBoozilla = 0;
// Popularity is in the range of 0 - 100
var popularityValue = 40;
var UNPOPULAR = 20; // 20 or less
var MEDIOCRE = 50;
var PRETTY_NIFFTY = 70;
var UNPOPULAR_PHRASE = "People would rather go to a symposium about the amobia than go to your bar.";
var MEDIOCRE_PHRASE = "Your bar is kind of popular. But if a hacky sack tournament happens, the customers will probably leave.";
var NIFFTY_PHRASE = "Your bar is good, and it is getter better."
var SUPERSTAR_PHRASE = "Your bar is super popular. It is the shizitz! Shake your groove thing."
var SUCK_PHRASE = "You suck! How did you do that? Your bar is so unpopular you will never recover. Refresh the page to try again."
// Make all these look like constants
var beerLabel = "beer";
var wineLabel = "wine";
var ginLabel = "gin";
var rumLabel = "rum";
var vodkaLabel = "vodka";
var keyPressConnectionHandle = null;
function tauntBoozilla()
{
// Need to add a way to show different taunts
//taunt boozilla
dijit.byId("toast").setContent( "Hey Boozilla! Your mother dresses you funny and you stink!", "message" , 5000 );
dijit.byId("toast").show();
//mytimer.start(); // start the timer
dijit.byId("toast").setContent( "Boozilla becomes enraged and drinks.", "message" , 5000 );
dijit.byId("toast").show();
dojo.byId("tauntButton").style.backgroundColor = "";
// Hide the button again
dijit.byId("tauntButton").attr("style", "display:none");
updateBarPopularity( 5 );
//sarcastic remark, or insult intended to demoralize the recipient and encourage reactionary behaviors without
//thinking.
//Boozilla, your mother dresses you funny and you stink!
//What kind of name is Boozilla? Godzilla thinks you're a poo poo head.
//Boozilla, Boozilla, stick that vodka bottle up your nose!
//Boozilla becomes enraged and drinks.
dojo.byId("moneyCounter").style.backgroundColor = "black";
}
// Author: Ruth. amazingknife.com
function init() {
new dijit.ProgressBar({id: "keg", progress: PINTS_PER_KEG, maximum: PINTS_PER_KEG,
report:function(percent){
return dojo.string.substitute("${0} out of ${1} drinks", [this.progress, this.maximum]);
}
}, dojo.byId("keg"));
new dijit.ProgressBar({id: "wineBottle", progress: GLASSES_WINE_PER_BOTTLE, maximum: GLASSES_WINE_PER_BOTTLE,
report:function(percent){
return dojo.string.substitute("${0} out of ${1} drinks", [this.progress, this.maximum]);
}
}, dojo.byId("wineBottle"));
new dijit.ProgressBar({id: "ginBottle", progress: SHOTS_PER_BOTTLE, maximum: SHOTS_PER_BOTTLE,
report:function(percent){
return dojo.string.substitute("${0} out of ${1} drinks", [this.progress, this.maximum]);
}
}, dojo.byId("ginBottle"));
new dijit.ProgressBar({id: "rumBottle", progress: SHOTS_PER_BOTTLE, maximum: SHOTS_PER_BOTTLE,
report:function(percent){
return dojo.string.substitute("${0} out of ${1} drinks", [this.progress, this.maximum]);
}
}, dojo.byId("rumBottle"));
new dijit.ProgressBar({id: "vodkaBottle", progress: SHOTS_PER_BOTTLE, maximum: SHOTS_PER_BOTTLE,
report:function(percent){
return dojo.string.substitute("${0} out of ${1} drinks", [this.progress, this.maximum]);
}
}, dojo.byId("vodkaBottle"));
// var mytimer = new dojox.timing.Timer({
// setInterval: 5000,
// onTick: function () {
// alert("here is the interval");
// }
// });
// Make the Taunt Boozilla button but don't display it yet.
var tb = new dijit.form.Button({
label: "Taunt Boozilla (Key = 7)",
style: "display:none",
onClick: function(){ tauntBoozilla(); }
}, dojo.byId("tauntButton"));
// Give the user a nice start.
// Don't offer the possibility for Boozilla or any other craziness yet.
setNewDrinkToMake();
connectKeyPressHandlers();
}
// Make sure the page is loaded before we set an element.
dojo.addOnLoad( init );
// Author: Ruth. amazingknife.com
function connectKeyPressHandlers() {
// sample code
// button = dojo.byId('helloButton');
// dojo.connect(button, 'onclick', 'helloPressed');
// To disconnect listeners from events, you simply pass the connection handle (the return value of dojo.connect to dojo.disconnect.
// "1" is decimal 49 in ascii
keyPressConnectionHandle = dojo.connect(document, "onkeypress", function(e) {
var key = e.keyCode || e.charCode;
if (key == 49) {
dojo.byId("drinks").value = "beer";
makeDrink();
}
else if (key == 50) {
dojo.byId("drinks").value = "wine";
makeDrink();
}
else if (key == 51) {
dojo.byId("drinks").value = "ginntonic";
makeDrink();
}
else if (key == 52) {
dojo.byId("drinks").value = "rumncoke";
makeDrink();
}
else if (key == 53) {
dojo.byId("drinks").value = "vodkatonic";
makeDrink();
}
else if (key == 54) {
shop();
}
else if (key == 55) {
tauntBoozilla();
}
});
}
// Author: Ruth. amazingknife.com
function disableAllControls()
{
// disconnect the old keyPress handler otherwise it will do both functions.
dojo.disconnect(keyPressConnectionHandle);
dojo.connect(document, "onkeypress", function(e) {
});
dojo.connect(document, "onclick", function(e) {
});
dojo.byId("drinks").style.display = "none";
dojo.byId("shopButton").style.display = "none";
dojo.byId("tauntButton").style.display = "none";
dojo.byId("chooseDrink").style.display = "none";
dojo.byId("drinkCounter").style.display = "none";
dojo.byId("moneyCounter").style.display = "none";
dojo.byId("customerDrink").style.display = "none";
dojo.byId("keg").style.display = "none";
dojo.byId("wineBottle").style.display = "none";
dojo.byId("ginBottle").style.display = "none";
dojo.byId("rumBottle").style.display = "none";
dojo.byId("vodkaBottle").style.display = "none";
dojo.byId("beerProgressLabel").style.display = "none";
dojo.byId("wineProgressLabel").style.display = "none";
dojo.byId("ginProgressLabel").style.display = "none";
dojo.byId("rumProgressLabel").style.display = "none";
dojo.byId("vodkaProgressLabel").style.display = "none";
}
// Author: Ruth. amazingknife.com
function updateBarPopularity( popValue )
{
var previousPopularityValue = popularityValue;
popularityValue += popValue;
if ( popularityValue <= 0 ) {
// Disable everything.
dojo.byId("popularityDisplay").innerHTML = SUCK_PHRASE;
popularityValue = 0;
disableAllControls();
}
else if ( ( popularityValue <= UNPOPULAR ) && ( previousPopularityValue > UNPOPULAR ) ) {
dojo.byId("popularityDisplay").innerHTML = UNPOPULAR_PHRASE;
}
else if ( ( ( popularityValue <= MEDIOCRE ) && ( previousPopularityValue > MEDIOCRE ) && ( popularityValue > UNPOPULAR ) )
||
( ( popularityValue <= MEDIOCRE ) && ( popularityValue > UNPOPULAR ) && ( previousPopularityValue <= UNPOPULAR ) ) ) {
dojo.byId("popularityDisplay").innerHTML = MEDIOCRE_PHRASE;
}
else if ( ( ( popularityValue <= PRETTY_NIFFTY ) && ( previousPopularityValue > PRETTY_NIFFTY ) && ( popularityValue > MEDIOCRE ) )
||
( ( popularityValue <= PRETTY_NIFFTY ) && ( popularityValue > MEDIOCRE ) && ( previousPopularityValue <= MEDIOCRE ) ) ) {
dojo.byId("popularityDisplay").innerHTML = NIFFTY_PHRASE;
}
else if ( ( popularityValue > PRETTY_NIFFTY ) && ( previousPopularityValue <= PRETTY_NIFFTY ) ) {
dojo.byId("popularityDisplay").innerHTML = SUPERSTAR_PHRASE;
}
else if ( popularityValue > 100 ) {
popularityValue = 100;
}
dojo.byId("popularityIntegerDisplay").innerHTML = "Bar Popularity = " + popularityValue;
}
// Author: Ruth. amazingknife.com
// Update the drink count and the alcohol level.
function updateCount() {
var drink = dojo.byId("drinks").value;
if ( drinkCount == 1 )
{
dojo.byId("drinkCounter").innerHTML = "You have made " + drinkCount + " drink.";
}
else
{
dojo.byId("drinkCounter").innerHTML = "You have made " + drinkCount + " drinks.";
}
if ( drink == "beer" ) {
dijit.byId("keg").update({
maximum: PINTS_PER_KEG,
progress: --beerLeft
});
}
else if ( drink == "wine" ) {
dijit.byId("wineBottle").update({
maximum: GLASSES_WINE_PER_BOTTLE,
progress: --wineLeft
});
}
else if ( drink == "ginntonic" ) {
dijit.byId("ginBottle").update({
maximum: SHOTS_PER_BOTTLE,
progress: --ginLeft
});
}
else if ( drink == "vodkatonic" ) {
dijit.byId("vodkaBottle").update({
maximum: SHOTS_PER_BOTTLE,
progress: --vodkaLeft
});
}
else if ( drink == "rumncoke" ) {
dijit.byId("rumBottle").update({
maximum: SHOTS_PER_BOTTLE,
progress: --rumLeft
});
}
}
// Author: Ruth. amazingknife.com
// Based on the listbox selection, return the price
// of the drink.
function getDrinkPrice() {
var drink = dojo.byId("drinks").value;
if ( drink == "beer" ) {
return BEER_PRICE;
}
else if ( drink == "wine" ) {
return WINE_PRICE;
}
else {
return COCKTAIL_PRICE;
}
}
// Author: Ruth. amazingknife.com
function updateMoney() {
moneyTotal += getDrinkPrice();
}
// Author: Ruth. amazingknife.com
function updateMoneyDisplay() {
dojo.byId("moneyCounter").innerHTML = "You have $" + moneyTotal + ".";
}
// Author: Ruth. amazingknife.com
function checkForEnoughIngredients(drink) {
if ( drink == "beer" ) {
if ( beerLeft <= 0 ) {
showOutOfDrinkToast( beerLabel, BEER_PRICE );
return -1;
}
}
else if ( drink == "wine" ) {
if ( wineLeft <= 0 ) {
showOutOfDrinkToast( wineLabel, WINE_PRICE );
return -1;
}
}
else if ( drink == "ginntonic" ) {
if ( ginLeft <= 0 ) {
showOutOfDrinkToast( ginLabel, COCKTAIL_PRICE );
return -1;
}
}
else if ( drink == "rumncoke" ) {
if ( rumLeft <= 0 ) {
showOutOfDrinkToast( rumLabel, COCKTAIL_PRICE );
return -1;
}
}
else if ( drink == "vodkatonic" ) {
if ( vodkaLeft <= 0 ) {
showOutOfDrinkToast(vodkaLabel, COCKTAIL_PRICE);
return -1;
}
}
}
// Author: Ruth. amazingknife.com
function getDrinkLabel(drink) {
var drinkLabel = "";
if (drink == "beer") {
drinkLabel = "beer";
}
else if (drink == "wine") {
drinkLabel = "wine";
}
else if (drink == "ginntonic") {
drinkLabel = "Gin and Tonic";
}
else if (drink == "rumncoke") {
drinkLabel = "Rum and Coke";
}
else if (drink == "vodkatonic") {
drinkLabel = "Vodka Tonic";
}
return drinkLabel;
}
Arduino code
///////////////////////////////////////////
// Maurice Ribble
// 4-6-2008
// http://www.glacialwanderer.com/hobbyrobotics
// Modified a bit by Ruth. Thanks for the awesome code, Maurice!
// This code just lets you turn a digital out pin on and off. That's
// all that is needed to verify a relay curcuit is working.
// Press the space bar to toggle the relay on and off.
#define RELAY_PIN3 3
#define RELAY_PIN2 2
void setup()
{
pinMode(RELAY_PIN3, OUTPUT);
pinMode(RELAY_PIN2, OUTPUT);
Serial.begin(9600); // open serial
Serial.println("Press the spacebar to toggle relay on/off");
}
void loop()
{
static int relayVal1 = 0;
static int relayVal2 = 0;
int cmd;
while (Serial.available() > 0)
{
cmd = Serial.read();
switch (cmd)
{
case ' ':
{
relayVal1 = 1; // xor current value with 1 (causes value to toggle)
if (relayVal1)
Serial.println("Relay 1 on");
else
Serial.println("Relay 1 off");
break;
}
case 'a':
{
relayVal2 = 1; // xor current value with 1 (causes value to toggle)
if (relayVal2)
Serial.println("Relay 2 on");
else
Serial.println("Relay 2 off");
break;
}
default:
{
Serial.println("Press the spacebar to toggle relay on/off");
}
}
if (relayVal1)
{
digitalWrite(RELAY_PIN3, HIGH);
delay(200);
digitalWrite(RELAY_PIN3, LOW);
delay(150);
digitalWrite(RELAY_PIN3, HIGH);
delay(200);
digitalWrite(RELAY_PIN3, LOW);
delay(150);
digitalWrite(RELAY_PIN2, HIGH);
delay(300);
digitalWrite(RELAY_PIN2, LOW);
delay(300);
relayVal1 = 0;
}
if (relayVal2)
{
digitalWrite(RELAY_PIN2, HIGH);
delay(200);
digitalWrite(RELAY_PIN2, LOW);
delay(300);
relayVal2 = 0;
}
}
}