Voting

Category

real language

Bookmarking

Del.icio.us Digg Diigo DZone Earthlink Google Kick.ie
Windows Live LookLater Ma.gnolia Reddit Rojo StumbleUpon Technorati

Language Transcript

(to correct previous submission)

Date:12/28/05
Author:Mark Smith
URL:n/a
Comments:2
Info:http://www.runrev.com/
Score: (3.00 in 70 votes)
Local lyricSheet,startBottles,bottles,feelingSick=false

on mouseUp
  singBottles 99
end mouseUp

on singBottles howManyBottles
  put howManyBottles into bottles
  put howManyBottles into startBottles
  
  repeat until feelingSick
    countBottles
    makeSure
    drinkOne
    checkTheresSomeLeft
  end repeat
  
  put lyricSheet
end singBottles

on countBottles
  if bottles > 1 then
    put bottles && "bottles of beer on the wall, " after lyricSheet
  else if bottles = 1 then
    put bottles && "more bottle of beer on the wall, " after lyricSheet
  else
    put "No more bottles of beer on the wall, " after lyricSheet
  end if
end countBottles

on makeSure
  if bottles > 1 then
    put bottles && "bottles of beer." & cr after lyricSheet
  else if bottles = 1 then
    put bottles && "more bottle of beer." & cr after lyricSheet
  else
    put "No more bottles of beer." & cr after lyricSheet
  end if
end makeSure

on drinkOne
  if bottles > 1 then
    put "Take one down and pass it around, " after lyricSheet
  else if bottles = 1 then
    put "Take it down and pass it around, " after lyricSheet
  else
    put "Go to the shtore and buy shome more, " after lyricSheet
  end if
  subtract 1 from bottles
end drinkOne

on checkTheresSomeLeft
  if bottles > 1 then
    put bottles && "bottles of beer on the wall." & cr & cr after lyricSheet
  else if bottles = 1 then
    put bottles && "more bottle of beer on the wall." & cr & cr after lyricSheet
  else if bottles = 0 then
    put "No more bottles of beer on the wall." & cr & cr after lyricSheet
  else
    put startBottles into bottles
    put bottles && "bottlesh of beer on the wall!" after lyricSheet
    put true into feelingSick
  end if
end checkTheresSomeLeft

Download Source | Write Comment

Alternative Versions

Comments

>>  Eric Chatonet said on 12/28/05 13:21:40

Eric Chatonet From the cookbook shipped with Rev 2.0 and always accessible with Resources Picker, a plugin available on my website:

1. 99 bottles of Beer on the Wall (using repeat)
Index

Problem

You want to generate the lyrics to the traditional drinking song "99 bottles of Beer on the Wall".

Important! This example is included for comparison with the example in "Recipe for 99 bottles of Beer on the Wall (using send)". Both these examples accomplish the same task, but the method using the send command is more reliable, and that method is preferred for repetitive tasks. This example is included so that you can see how a conventional routine using a repeat loop compares to a message-based routine using the send command.

Code

on mouseUp
put 99 into bottlesLeft
repeat until the mouseClick -- stop song when the user clicks
-- show a verse, using the bottlePhrase function
-- do one verse on each iteration of the loop:
switch bottlesLeft
case zero -- last verse, zero bottles left
put bottlePhrase(bottlesLeft) && "on the wall," \
&& toLower(bottlePhrase(bottlesLeft)) & return \
& "Go to the store and buy some more," \
&& toLower(bottlePhrase(99)) \
&& "on the wall." into field "Song"
break
default -- all other verses
put bottlePhrase(bottlesLeft) && "on the wall," \
&& toLower(bottlePhrase(bottlesLeft)) & return \
& "Take one down and pass it around," \
&& toLower(bottlePhrase(bottlesLeft - 1)) \
&& "on the wall." into field "Song"
end switch
subtract 1 from bottlesLeft -- for the next verse
if bottlesLeft < zero then put 99 into bottlesLeft
wait for 1 second
end repeat
-- when the repeat loop ends with a click, the song is over:
put empty into field "Song"
end mouseUp

function bottlePhrase theNumber
-- generate the "base phrase" used to make a verse
switch theNumber
case zero
return "No more bottles of beer"
break
case one
return "One last bottle of beer"
break
default
return theNumber && "bottles of beer"
end switch
end bottlePhrase

Discussion

The mouseUp message is sent when the user clicks an object --in this case, a button. (It's possible to include this code in a different handler; putting it in a button's mouseUp handler is just convenient for this example.) When the mouseUp message is sent to the button, it triggers the mouseUp handler.

This handler displays the endless verses of the song "99 bottles of Beer on the Wall". In case you're not familiar with the song, it goes like this:

99 bottles of beer on the wall, 99 bottles of beer
You take one down and pass it around, 98 bottles of beer on the wall.

98 bottles of beer on the wall, 98 bottles of beer
You take one down and pass it around, 97 bottles of beer on the wall.

...and so on. The song continues, decreasing the number of bottles by one with each verse, until there's just one bottle left:

One more bottle of beer on the wall, one more bottle of beer
You take one down and pass it around, no more bottles of beer on the wall.

No more bottles of beer on the wall, no more bottles of beer
You go to the store and buy some more, 99 bottles of beer on the wall.

99 bottles of beer on the wall...

...and the song starts over from the beginning.

The example displays the song interactively, one verse at a time. (The handler assumes there is a field named "Song" to display successive verses.) When the user clicks, the handler starts a repeat loop to display each verse of the song from the beginning. The "bottlesLeft" variable keeps track of which verse is next: it starts out at 99, and each time through the loop, it's decreased by one. After a one-second delay imposed by the wait command, the handler returns to the top of the loop and displays the next verse. (You can change the delay time, depending on how long you think it will take to read one verse and how long you want the song to take.)

When the song finishes, and the number of bottles left is zero, the handler sets it back to 99 to start the song over from the beginning:

subtract 1 from bottlesLeft -- for the next verse
if bottlesLeft < zero then put 99 into bottlesLeft

The loop continues for all the verses, then starts over again, until the user clicks the button and stops the song. The repeat loop ends when the mouseClick function returns true, which happens if the mouse has been clicked.

Note: This example was inspired by a discussion on the Revolution mailing list with David Vaughan. The topic was in turn inspired by the "99 bottles of Beer" site at <http://99-bottles-of-beer.ls-la.net/>, featuring 99 bottles of Beer code in 454 programming languages (and counting).

Example stack: 99 bottles of Beer on the Wall (using repeat)


2. 99 bottles of Beer on the Wall (using send)
Index

Problem

You want to generate the lyrics to the traditional drinking song "99 bottles of Beer on the Wall".

Code

constant startbottles = 99
local bottlesLeft = 99
local currentVerseMessage -- stores message ID so we can cancel

on mouseUp
if currentVerseMessage is empty then -- song hasn't started
displayCurrentVerse -- start the song
else -- song is already going, so stop it:
cancel currentVerseMessage
put empty into currentVerseMessage
put empty into field "Song"
end if
end mouseUp

on displayCurrentVerse
-- show a verse, using the bottlePhrase function,
-- and set up the variable for the next verse
switch bottlesLeft
case zero -- last verse, zero bottles left
put bottlePhrase(bottlesLeft) && "on the wall," \
&& toLower(bottlePhrase(bottlesLeft)) & return \
& "You go to the store and buy some more," \
&& toLower(bottlePhrase(startbottles)) \
&& "on the wall!" into field "Song"
put startbottles into bottlesLeft -- start again
break
default -- all other verses
put bottlePhrase(bottlesLeft) && "on the wall," \
&& toLower(bottlePhrase(bottlesLeft)) & return \
& "You take one down and pass it around," \
&& toLower(bottlePhrase(bottlesLeft - 1)) \
&& "on the wall!" into field "Song"
subtract 1 from bottlesLeft -- for the next verse
end switch
send "displayCurrentVerse" to me in 1 second
put the result into currentVerseMessage
end displayCurrentVerse

function bottlePhrase theNumber
-- generate the "base phrase" used to make a verse
switch theNumber
case zero
return "No more bottles of beer"
break
case one
return "One last bottle of beer"
break
default
return theNumber && "bottles of beer"
end switch
end bottlePhrase

Discussion

This script uses three handlers to display the endless verses of the song "99 bottles of Beer on the Wall". In case you're not familiar with the song, it goes like this:

99 bottles of beer on the wall, 99 bottles of beer
You take one down and pass it around, 98 bottles of beer on the wall.

98 bottles of beer on the wall, 98 bottles of beer
You take one down and pass it around, 97 bottles of beer on the wall.

...and so on. The song continues, decreasing the number of bottles by one with each verse, until there's just one bottle left:

One more bottle of beer on the wall, one more bottle of beer
You take one down and pass it around, no more bottles of beer on the wall.

No more bottles of beer on the wall, no more bottles of beer
You go to the store and buy some more, 99 bottles of beer on the wall.

99 bottles of beer on the wall...

...and the song starts over from the beginning.

The mouseUp message is sent when the user clicks an object--in this case, a button. (It's possible to include this code in a different handler; putting it in a button's mouseUp handler is just convenient for this example.) This handler assumes there is a field named "Song" to display successive verses.

The example displays the song interactively, one verse at a time. When the user clicks, if the song is already going, the mouseUp handler stops it. Otherwise, it starts up the song from the beginning by sending a message called "displayBottleVerse" that shows the first verse of the song. The "displayBottleVerse" handler calls itself, after a one-second delay (to give the user time to read the verse). After the delay, the "displayBottleVerse handler" displays the next verse. The cycle continues for all the verses, then starts over again, until the user clicks the button and stops the song.

The constant declaration at the top of the script declares a constant value called "startbottles" which is equal to 99. This constant is declared for convenience. We could simply write "99" instead of "startbottles" in the two places where this constant is used, and the script would work the same way, but the use of a constant makes it easier to see how many bottles the song starts with when you're reading the script. It also makes it easier to change the starting verse, in case we ever decide to make this song "215 bottles of Beer on the Wall" instead.

Next, the script declares a script local variable called "bottlesLeft". This is the current number of bottles, and starts off at 99. Because this variable is declared outside any handler, it retains its value for the entire session. (If you declare a local variable inside a handler--or just use it without a local declaration--then the variable's value is lost when the handler finishes executing.) This is important, because the "displayCurrentVerse" handler is executed once for each verse. The "bottlesLeft" variable keeps track of which verse is next between executions.

The second local declaration creates a variable called "currentVerseMessage". Because it is a script local variable, it retains its value for the current session, and it's available to all handlers in this script. (We'll see in a moment how this variable is used to stop the song.)

The mouseUp handler checks the "currentVerseMessage" variable to see whether there's anything in it. We didn't specify a value when declaring this variable, so it starts out empty. If it's still empty, the handler sends the "displayCurrentVerse" message to show the first verse of the song. This handler, "displayCurrentVerse", uses the "bottlePhrase" function handler to construct the text of the first verse of the song, and puts it in the field named "Song". It subtracts 1 from the "bottlesLeft" variable. Then it sends a "displayCurrentVerse" message again after a one-second delay. (You can change the delay time, depending on how long you think it will take to read one verse and how long you want the song to take.)

(The send...in time form of the send command that's used here puts information about the message into a queue called the pendingMessages and assigns a unique number to the pending message. This number is returned in the result function, so our handler can retrieve it. A message waiting in the queue can be canceled later with the cancel command. Since we want to cancel the pending message if the user clicks the button, we need to store the message's number for later use. The next line of the handler stores the message's number in the script local variable "currentVerseMessage", which we declared at the top of the script.)

One second later, that pending message executes, instructing Revolution to execute the "displayCurrentVerse" handler again. The "displayCurrentVerse" handler shows the second verse, subtracts another bottle, and sends the message again after a one-second delay, and the process continues through all the verses of the song.

When the song reaches its end and the "bottlesLeft" is zero, the "displayCurrentVerse" handler sets the "bottlesLeft" variable back to the value of the "startbottles" constant we declared at the top of the script. The next time the "displayCurrentVerse" handler is executed, the song's first verse is displayed again.

When the user clicks the button, the mouseUp handler again checks the "currentVerseMessage" variable to see whether it's empty. If it's not, the song is currently playing and should be stopped. All we need to do to stop the verses is to cancel the pending "displayCurrentVerse" message that's waiting to be sent. To cancel a pending message, the mouseUp handler uses the cancel command:

cancel theMessageID

Here is where we use the script local variable "currentVerseMessage". This variable was declared at the top of the script, and in the "displayCurrentVerse" handler, we stored the message number of the pending message in the variable. The cancel command needs this number in order to figure out which pending message to cancel.

After canceling the pending message to break the cycle of verses, the mouseUp handler sets the "currentVerseMessage" back to empty (since the message is no longer pending). It also sets the "bottlesLeft" back to the "startbottles" number so that the next time the user clicks to start the song, it will start at the beginning.

Note: This example was inspired by a discussion on the Revolution mailing list with David Vaughan. The topic was in turn inspired by the "99 bottles of Beer" site at <http://99-bottles-of-beer.ls-la.net/>, featuring 99 bottles of Beer code in 454 programming languages (and counting).

Example stack: 99 bottles of Beer on the Wall (using send)

>>  Ken Ray said on 07/26/06 05:50:53

Ken Ray This is my version, just a bit shorter:

on mouseUp
put "" into tLyrics
put "Take one down and pass it around" into tPhrase
repeat with x = 99 down to 0
switch x
case 2
put "2 bottles" into tBot1
put "1 bottle" into tBot2
break
case 1
put "1 bottle" into tBot1
put "no more bottles" into tBot2
break
case 0
put "No more bottles" into tBot1
put "99 bottles" into tBot2
put "Go to the store and buy some more" into tPhrase
break
default
put x && "bottles" into tBot1
put tBot1 into tBot2
break
end switch
put tBot1 && "of beer on the wall," && tBot1 && "of beer." & cr & \
tPhrase & "," && tBot2 && "of beer on the wall." & cr & cr after tLyrics
end repeat
put tLyrics
end mouseUp

Download Source | Write Comment

Add Comment

Please provide a value for the fields Name, Comment and Security Code.
This is a gravatar-friendly website.
E-mail addresses will never be shown.
Enter your e-mail address to use your gravatar.

Please don't post large portions of code here! Use the form to submit new examples or updates instead!

Name:

eMail:

URL:

Security Code:
  
Comment: