M-Script II


This is a sample M-Script II application. It allows users to indicate which Canadian political party they favor by selecting one and clicking the VOTE button. The current results of the poll are shown in the GIF image that is generated on the fly by another MS2 program.

NOTE: I am aware that this example allows the same person to vote more than once. This is not a mistake. The purpose of this example is to let people try it, multiple times if necessary. In "real life" I would set a cookie to indicate that the current browser has been here, then test for this cookie to see if they are allowed to vote again.

NOTE: Some browsers may not honor the "don't cache" information sent along with the bar chart. In this case you may have to clear your cache and reload the page to see an updated chart.

You may copy and modify this code as you see fit.


 Cast Your Vote

You need a graphical browser!


PC
BQ
Liberal
NDP
Reform
Other
None of the Above


 View the Source Code

There are two different MS2 programs in use here. The first one accepts the input from the form above and updates the counter values:

; POLLCAST.MS2
;
; This program is called via a form.  Based on the radio button selected
; by the user, it increments one of six values in a file.

; Lock the data file so nobody else can mess with it at the same time
lock( "ms2/poll.dat" )

; Read in the current counter values
if input = open( "ms2/poll.dat" )
   pccount = num( read( input ) )
   bqcount = num( read( input ) )
   libcount = num( read( input ) )
   ndpcount = num( read( input ) )
   refcount = num( read( input ) )
   othcount = num( read( input ) )
   close( input )
endif

; Test the form variable called "choice" and increment the appropriate
; value
choice = form( "choice" )
if choice == "PC"
   pccount = pccount + 1
elif choice == "BQ"
   bqcount = bqcount + 1
elif choice == "LIB"
   libcount = libcount + 1
elif choice == "NDP"
   ndpcount = ndpcount + 1
elif choice == "REF"
   refcount = refcount + 1
elif choice == "OTH"
   othcount = othcount + 1
endif

; Write the values to a new file and then rename it
if output = open( "ms2/poll.new", "w" )
   write( output, pccount, "\n" )
   write( output, bqcount, "\n" )
   write( output, libcount, "\n" )
   write( output, ndpcount, "\n" )
   write( output, refcount, "\n" )
   write( output, othcount, "\n" )
   close( output )
   move( "ms2/poll.new", "ms2/poll.dat" )
endif

; Unlock the data file
unlock( "ms2/poll.dat" )

; Redirect the user back to the poll page
redirect( "http://www.islandnet.com/mscript/poll.html" )

The second program reads in the data file and outputs a GIF image to display the results:

; POLLRESULTS.MS2
;
; This program takes the count values generated by the POLLCAST program
; and generates a bar graph image to show the results.


; First we read in the current counter values.  As we do so we want to
; figure out which of the six is largest so that we can scale the
; length of the bars accordingly.  We also sum up the values to get
; a total number of votes.

total = 0
max = 0
if input = open( "ms2/poll.dat" )
   pccount = num( read( input ) )
   total = total + pccount
   max = pccount
   bqcount = num( read( input ) )
   total = total + bqcount
   if bqcount > max
      max = bqcount
   endif
   libcount = num( read( input ) )
   total = total + libcount
   if libcount > max
      max = libcount
   endif
   ndpcount = num( read( input ) )
   total = total + ndpcount
   if ndpcount > max
      max = ndpcount
   endif
   refcount = num( read( input ) )
   total = total + refcount
   if refcount > max
      max = refcount
   endif
   othcount = num( read( input ) )
   total = total + othcount
   if othcount > max
      max = othcount
   endif
   close( input )
endif


; This is the width and height of the GIF image.  We store these values
; in variables so as to make future changes easier (we only have to change
; the value in one spot instead of several).

width = 400
height = 160


; This will be the title of our bar chart.  Note we embed the current date
; as well as the total number of votes cast to date.

title = "Poll Results as of " + time( "%b %d" ) + \
        " (" + str( total ) + " votes to date)" 


; Ok, here we go.  First we create a new image with a dark blue background
and a thin black outline.

image = newgif( width, height )
box( image, 0, 0, width - 1, height - 1, BLUE1 )
rectangle( image, 0, 0, width - 1, height - 1, BLACK )


; Next we draw the title and labels in white

text( image, 10, 10, title, FONT8x13B, WHITE )
text( image, 10, 38, "PC", FONT6x12, WHITE )
text( image, 10, 58, "BQ", FONT6x12, WHITE )
text( image, 10, 78, "LIB", FONT6x12, WHITE )
text( image, 10, 98, "NDP", FONT6x12, WHITE )
text( image, 10, 118, "REF", FONT6x12, WHITE )
text( image, 10, 138, "Oth", FONT6x12, WHITE )
line( image, 30, 35, 30, 150, WHITE )


; Assuming that at least one of the counter values is set we proceed to
; draw each bar.  We use a different color for each bar, then we draw
; the actual number of votes on top of the bar.  The bars are scaled
; such that the one with the largest number of votes will always have
; a maximally sized bar.

if max > 0
   box( image, 35, 35, 35 + pccount * (width - 55) / max, 50, RED3 )
   text( image, 40, 38, str( pccount ), FONT6x12, WHITE )

   box( image, 35, 55, 35 + bqcount * (width - 55) / max, 70, ORANGE3 )
   text( image, 40, 58, str( bqcount ), FONT6x12, WHITE )

   box( image, 35, 75, 35 + libcount * (width - 55) / max, 90, YELLOW3 )
   text( image, 40, 78, str( libcount ), FONT6x12, BLACK )

   box( image, 35, 95, 35 + ndpcount * (width - 55) / max, 110, GREEN3 )
   text( image, 40, 98, str( ndpcount ), FONT6x12, BLACK )

   box( image, 35, 115, 35 + refcount * (width - 55) / max, 130, CYAN2 )
   text( image, 40, 118, str( refcount ), FONT6x12, BLACK )

   box( image, 35, 135, 35 + othcount * (width - 55) / max, 150, BLUE3 )
   text( image, 40, 138, str( othcount ), FONT6x12, WHITE )
endif


; Since this image is going to be invoked via an <img> tag, the user's
; browser will cache it.  This is undesirable since we want the image
; that they see to be accurate based on the current data file.  That is,
; the image changes often so caching it will mean the user sees the wrong
; results.  To get around this we have to specify a few extra header
; values ourselves.  First we call mimetype() with no parameters, which
; causes the subsequent print() and writegif() calls to NOT output a
; Content-Type header automatically.  Then we write a special "Pragma"
; header with the direction to not cache the image.  Just to be sure
; we also set the image to expire yesterday.  In this case we also have
; to output our own Content-Type header.
;
; NOTE: Some browsers do not honor these headers.  In this case there is
; nothing that can be done except to reload the page with an empty cache.

mimetype()
print( "Pragma: no-cache\n" )
t = timeadd( time(), -1, "day" )
print( "Expires: ", time( "%A, %d-%a-%y %H:%M:%S GMT", t ), "\n" )
print( "Content-Type: image/gif\n\n" )


; Finally, we output the GIF data and close it.  We're done.

writegif( image )
closegif( image )