An Online Voting System

Description: This deliverable contains three files: login.php, joinAndVote.php, and voteProcess.php. "login.php" file loads a login form for user name and password. If either user name or password is entered incorrectly, user is redirected back to this login form. If user logs in successfully, he/she will get a voting form with group size field and join button enabled and all other controls disabled. This voting form is loaded by "joinAndVote.php" file. A session id will be used to represent a unique user and shown in the id field in the form. The voting form posts requests to itself.

When a user enters a group size and clicks on the join button, a join request is initiated and sent through an xmlhttp object to "voteProcess.php" script in the server. First voter will set the oveall group size. After enough users have joined the group successfully, vote field and vote button are enabled, and all other controls are disabled. When user enters a vote value of 0 or 1, and clicks on the vote button, a vote request is sent to the same script "voteProvess.php" in the server. If a response with proper majority and tally information is not ready, a "wait" message comes back instead, the client will continue polling the server for a proper response. User will not be able to vote in the next round until previous round is finished. And when an agreement is reached, "agreement reached!!" message will be shown and all controls are disabled. All the requests and responses are handled by xmlhttp object.

A login screen

1.In this example, four people try to log into the system.

Join a group

2.All four voters join the same group. And first voter gets the right to set the overall group size.

Wait for response

3.Three voters wait for the response before the fourth one casts a vote.

An agreement reached

4.An agreement has been reached. All voters cannot vote further.

Vote table enties in database

5.Here are the vote table entries after all the rounds.

login.php

<?php
/*
   login.php file presents user a login form.
   A user need to enter a vaid user name and password to
   be able to vote.

   Author: Chao Liang
   Date: 5/12/2006
*/
   session_start();  // Start a new session
?>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">

<head>
<title> User login form</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"/>
<script language="JavaScript" type="text/JavaScript">

   document.loginForm.reset();   // Clear the form data

</script>
</head>

<body>
<h1> User Log in </h1>

<?php
// Handle a situation that user name or password is wrong.
if (isset($_REQUEST['username']))
{
   echo "User name and password are wrong." . "<br/>";
   echo "Please re-enter." . "<br/>";
}
?>

<form method='get' action='joinAndVote.php'>
<table>
<tr>
   <td>
      User Name:
   </td>
   <td>
      <input type='text' name='username' id='username'/>
   </td>
</tr>
<tr>
   <td>
      Password:
   </td>
   <td>
      <input type='password' name='passwd' id='passwd'/>
   </td>
</tr>
<tr>
   <td>
      <input type = 'submit' name='login' value = 'login' />
   </td>
</tr>
</table>
</form>
</body>
</html>

joinAndVote.php

<?php

   /*
      Verify.php file verifies user name and password. It will
      redirect user back to the login form if either user name
      or password is wrong. If user logs in successfully, it will
      move onto a voting page.

      Author:  Chao Liang
      Date: 5/12/2006
   */

   // If user does not provide user name or password, it will
   // be redirect back to the login page.

   // First need to test out the join, wait and vote.

   session_start();

   if (!isset($_REQUEST['username']) || !isset($_REQUEST['passwd']))
   {
      die("Please enter user name and password");
      header("Location: http://localhost/voter/login.php");
   }

   $connection = mysql_connect("localhost","cs297", "cs297");
   mysql_select_db('users', $connection);

   $sql = "select * from user where username='" . $_REQUEST['username'] .
         "' and password = '" . $_REQUEST['passwd'] . "'";

   $resultSet = mysql_query($sql, $connection);

   // Check if the user name and password pair is in the database.
   // Redirect back to login page if they are not.
   if (mysql_num_rows($resultSet) != 1)
   {
      session_unset();
      session_destroy();
      header("Location: http://localhost/voter/login.php");
   }
   else
   {
      $fname = mysql_result($resultSet, 0, 'fname');
      echo "welcome! " .  $fname . "<br/>";
      echo "Please click on Join button to join " . "<br/>"
       . "then click on Vote button to vote";
   }
?>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title> Join and Vote</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"/>

<script language="JavaScript" type="text/JavaScript">
   var joinInterval;    // A global timer object for join.
   var voteInterval; // Another global timer object for vote.

   // Control for joining group or polling for current size
   var firstJoin;

   // A boolean for checking if user clicks on join or vote button.
   var join;

   var majority;     // Majority value comes from server.
   var tally;        // Tally value comes from server.
   var group;        // Group id of user.
   var vote;         // Vote from the previous round.
   var id;           // User id represented by session id.
   var round;        // Previous round number
   var agree;        // Agreement value start with -1.

   var size;         // Size of the group.
   var sentinel      // Threshold.
   var first         // Check if it is the first voter.
   var curSize       // Current size in the group.

   /*
      An event handler that will be called when user
      clicks on the vote button. It will connect to server
      every half second to request majority and tally
      information of previous round.
   */
   function voteToServer()
   {
      var voteComp = document.getElementById("vote");
      vote = voteComp.value;

      voteInterval = window.setInterval("requestInfo()",2000);
       requestInfo();

      // Always return false to mean do not move to other page.
      return false;
   }

   /*
      An event handler that will be called when user
      clicks on the join button. It will connect to server
      to join a group. After user clicks on the join button,
      vote field and vote button will be enabled, and join
      button will be disabled.
   */
   function connectToServer()
   {
      var joinButton = document.getElementById("join");

      joinButton.disabled = true;

      join = true;      // So join request will be constructed
      firstJoin = true; // So curSize request will be constructed

      joinInterval = window.setInterval("requestInfo()",500);

      // Always return false, so it does not move to other page.
      return false;
   }

   /*
      A function will be called to display all information from
      the server into the correct fields.
   */

   function displayInfo()
   {
      var idComp = document.getElementById("id");
      var majComp = document.getElementById("majority");
      var talComp = document.getElementById("tally");
      var roundComp = document.getElementById("round");
      var agreeComp = document.getElementById("agreement");
      var groupComp = document.getElementById("group");
      var voteComp = document.getElementById("vote");

      var sizeComp = document.getElementById("groupSize");
      var sentinelComp = document.getElementById("threshold");
      var firstComp = document.getElementById("first");
      var curComp = document.getElementById("curSize");

      idComp.value = id;
      majComp.value = majority;
      talComp.value = tally;
      roundComp.value = round;
      agreeComp.value = agree;
      groupComp.value = group;
      voteComp.value = vote;

      sizeComp.value = size;
      sentinelComp.value = sentinel;
      firstComp.value = first;
      curComp.value = curSize;
   }

   /*
      A function parses response. A response will contain just
      "wait" if others in the same group have not yet voted in
      the same round. If it is valid information, it will contains
      id, round, agreement, majority,tally, group, and vote separated
      with a ":". The timer will stop once valid information returned.
      A Message will be shown if an agreement is reached, and all the
      controls will be disabled.
   */

   function parseResponse(response)
   {
      var voteButton = document.getElementById('voteButton');
      var divComp = document.getElementById('respInfo');
      var voteElement = document.getElementById('vote');
      var firstIndex = response.indexOf("result:");

      if (firstIndex != -1)
      {
         var res = response.substring(firstIndex+7);

         if (res.indexOf("wait") != -1)
         {
            voteButton.disabled = true;
         }
         else if (res.indexOf("full") != -1)
         {
            voteButton.disabled = true;
            divComp = "A group is full!!"
            voteElement.disabled = true;
         }
         else
         {
            var resArray = res.split(":");

            id = resArray[0];
            agree = resArray[1];
            majority = resArray[2];
            tally = resArray[3];
            group = resArray[4];
            round = resArray[5];
            vote = resArray[6];

            size = resArray[7];
            sentinel = resArray[8];
            first = parseInt(resArray[9]);
            curSize = resArray[10];

            // -1 indicates that agreement is not reached
            if (resArray[1] != -1)
            {
               divComp.innerHTML = "Agreement reach!!";
               voteButton.disabled = true;
               voteElement.disabled = true;
               setIntervalOut();
            }
            // required number of people have joined
            else if (join == true && curSize == size)
            {
               var voteField = document.getElementById("vote");
               var voteButton = document.getElementById("voteButton");
               var joinButton = document.getElementById("join");
               var grSizeField = document.getElementById("groupSize");

               voteField.disabled = false;
               voteButton.disabled = false;
               joinButton.disabled = true;
               grSizeField.disabled = true;

               join = false;
               setIntervalOut();
            }
            else if (join == true && first)      // reset group size
            {
               var joinButton = document.getElementById("join");
               var sizeField = document.getElementById("groupSize");
               joinButton.disabled = false;
               sizeField.disable = false;
            }
            else if (join == true && !first)
            {
               var joinButton = document.getElementById("join");
               var sizeComp = document.getElementById("groupSize");
               sizeComp.disabled = true;
               joinButton.disabled = true;
            }
            else  // Just get the information of current round
            {
               setIntervalOut();
               voteButton.disabled = false;
               voteElement.disabled = false;
            }
         }
      }
      else
         return 0;
   }

   /*
      This function creates an xmlHttpRequest object
      according to the browser used.

      return:  created xmlHttpRequest object
   */

   function createXMLHttpRequest()
   {
      var transfer;
      if (window.ActiveXObject)
      {
         transfer = new ActiveXObject('Msxml2.XMLHTTP');
      }
      else if (window.XMLHttpRequest)
      {
         transfer = new XMLHttpRequest();
      }
      return transfer;
   }

   /*
      This function will clear the timer
   */

   function setIntervalOut()
   {
      if (joinInterval != null)
         clearInterval(joinInterval);
      if (voteInterval != null)
         clearInterval(voteInterval);
   }

   /*
      This function sends request to the server, and register
      the callback function to process the response when result
      comes back from the server. A random value parameter will
      be sent to the server to avoid use the cache url data.
   */
   function requestInfo()
   {
      var xmlHttpObject;
      var idValue;
      var idComp;
      var roundValue;
      var roundComp;
      var voteButton;

      xmlHttpObject = createXMLHttpRequest();
      idComp = document.getElementById('id');
      idValue = idComp.value;

      sizeComp = document.getElementById('groupSize');
      sizeValue = sizeComp.value;

      roundComp = document.getElementById('round');

      // Advance to the next round
      roundValue = parseInt(roundComp.value) + 1;

      if (join == true)  // click on the join button
      {
         if (firstJoin == true)  // Just join
         {
            xmlHttpObject.open("get", "voteProcess.php?join="
                               + 1 + "&size=" + sizeValue
                              + "&dummy=" + Math.random(), true);
            firstJoin = false;
         }
         else              // Request for current size
            xmlHttpObject.open("get", "voteProcess.php?firstJoin=" + 0
                           + "&dummy=" + Math.random(), true);
      }
      else          // click on the vote button
         xmlHttpObject.open("get", "voteProcess.php?vote=" + vote
                          + "&round=" + roundValue + "&size="
                          + sizeValue +
                          "&dummy=" + Math.random(), true);
      // callback function
      xmlHttpObject.onreadystatechange = function ()
      {
         // The response is stable for process when readyState
         // is 4
         if (xmlHttpObject.readyState == 4)
         {
            // check if upload is successful or not
            if (xmlHttpObject.status == 200)
            {
               var response = xmlHttpObject.responseText;
               var infoDiv = document.getElementById('respInfo');
               infoDiv.innerHTML = response;
               parseResponse(response);
               displayInfo();
               return true;
            }
            else
            {
               // Status will be shown when an error occurs
               displayInfo("An error occurred: " +
                                 xmlHttpObject.statusText);
               return false;
            }
         }
      };
      xmlHttpObject.send(null);  // A request is sent
   }

</script>
</head>
<body>
<form method="post" action="verify.php">
   <table summary="table used for formatting this form">
   <tr>
   <td>
      <label for="id">
      Id:
      </label>
   </td>
   <td>
      <input type="text" name="id" size="40"
         maxlength="60" id="id" value = "<?=session_id()?>" disabled/>
   </td>
   </tr>
   <tr>
   <td>
      <label for="agreement">
      Agreement:
      </label>
   </td>
   <td>
      <input type="text" name="agreement" size="20"
         maxlength="40" id="agreement" disabled/>
   </td>
   </tr>
   <tr>
   <td>
      <label for="majority">
      Majority:
      </label>
   </td>
   <td>
      <input type="text" name="majority" size="20"
         maxlength="40" id="majority" disabled/>
   </td>
   </tr>
   <tr>
   <td>
      <label for="tally">
      Tally:
      </label>
   </td>
   <td>
      <input type="text" name="tally" size="20"
         maxlength="40" id="tally" disabled/>
   </td>
   </tr>
   <tr>
   <td>
      <label for="group">
      Group:
      </label>
   </td>
   <td>
      <input type="text" name="group" size="20"
         maxlength="40" id="group" disabled />
   </td>
   </tr>
   <tr>
   <td>
      <label for="round">
      Round:
      </label>
   </td>
   <td>
      <input type="text" name="round" size="20"
         maxlength="40" id="round" disabled />
   </td>
   </tr>
   <tr>
   <td>
      <label for="vote">
      Vote:
      </label>
   </td>
   <td>
      <input type="text" name="vote" size="20"
         maxlength="40" id="vote" disabled/>
   </td>
   </tr>
   <tr>
   <td>
      <label for="groupSize">
      Group Size:
      </label>
   </td>
   <td>
      <input type="text" name="groupSize" size="20"
         maxlength="40" id="groupSize" />
   </td>
   </tr>
   <tr>
   <td>
      <label for="threshold">
      Threshold:
      </label>
   </td>
   <td>
      <input type="text" name="threshold" size="20"
         maxlength="40" id="threshold" disabled/>
   </td>
   </tr>
   <tr>
   <td>
      <label for="first">
      First Voter:
      </label>
   </td>
   <td>
      <input type="text" name="first" size="20"
         maxlength="40" id="first" disabled/>
   </td>
   </tr>
   <tr>
   <td>
      <label for="curSize">
      Current size:
      </label>
   </td>
   <td>
      <input type="text" name="curSize" size="20"
         maxlength="40" id="curSize" disabled/>
   </td>
   </tr>
   <tr>
   <td>
      <input type="submit" name="join" value="Join" id="join"
          onclick="return connectToServer();"/>
   </td>
   <td>
      <input type="submit" name="voteButton" value="Vote" id="voteButton"
      onclick="return voteToServer()" disabled />
   </td>
   </tr>
   </table>
</form>
<div id="respInfo"></div>
</body>
</html>

voteProcess.php

<?php

   /*
      Vote.php file will process the vote from user. All the
      the voting information stored in "vote" table of "users"
      database. When a vote comes from a user, all available
      information will be drawn from the database to calcualte
      majority and tally for user. A "wait" message will be
      sent if not all users in the same group voted at current
      round.
   */

   // Starts different sessions for different user.
   session_start();

?>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Process a vote</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"/>
</head>
<body>

<?php
   /*
      A class manages votes from users and updates the
      database if necessary. It also constructs response
      each round.
   */
   class ElectionManager
   {
      public static $groupSize = 4; // Maximum group size

      private $connection;       // Database connection

      /*
         A function opens a database connection and
         selects a database.
      */

      public function openDatabase()
      {
         $connection = mysql_connect("localhost","cs297", "cs297");
         @mysql_select_db("users");
      }

      /*
         A function to get a random value of 0 or 1.

         Return:     ramdomized 0 or 1
      */

      public static function flip ()
      {
         srand();
         $result = rand(0,1);
         return $result;
      }


      /*
         A function constructs proper response. It will contain
         all the needed fields separated by a ":".

         Return:     A constructed response.
      */

      public function constructResponse($id, $agree, $maj, $tally,$group,
      $round, $vote, $size, $sentinel, $first, $curSize)
      {

         $result = $id . ":";
         $result = $result  . $agree . ":";
         $result = $result  . $maj .   ":";
         $result = $result  . $tally . ":";
         $result = $result  . $group . ":";
         $result = $result  . $round . ":";
         $result = $result  . $vote  . ":";
         $result = $result  . $size  . ":";
         $result = $result  . $sentinel . ":";
         $result = $result  . $first  . ":";
         $result = $result  . $curSize  . ":";
         return $result;
      }

      /*
         A function is used to check if the id given represents
         the first voter in the group.

         Parameter:     $id - voter id
         Return:        array of (1 or 0, size), where size
                     is the size of the group. 1 for first
                     voter and 0 for other voter
      */

      public function checkFirstVoter($id)
      {
         // First time comes in and "vote" table is empty
         $firstVoter = false;
         $size;
         $sql = "select * from vote";
         $sqlResult = mysql_query($sql) or die(mysql_error());
         $resultRows = mysql_num_rows($sqlResult);

         // Get the size from database if it is not first voter
         while ($rowArr = mysql_fetch_array($sqlResult))
         {
            $size = $rowArr[7];
            break;
         }

         // First voter can change the group size
         $voterSql = "select * from vote where id='" . $id . "'";
         $voterSqlResult = mysql_query($voterSql) or die(mysql_error());

         while ($arr = mysql_fetch_array($voterSqlResult))
         {
            $firstVoter = $arr[9];
            break;
         }
         // first voter just join or first voter want to reset size
         if ($resultRows == 0 || $firstVoter)
         {
            // Make sure voter enter group size when joining.
            if (isset($_REQUEST['size']) && $_REQUEST['size'] == null)
               die("Enter group size before click on join button!");
            $size = $_REQUEST['size'];
            return array(1, $size);
         }
         else
            return array(0, $size);
      }

      /*
         A main function processes 'join' and 'vote' request.
         It will insert an entry into the database once a user
         joins. When a user votes, it inputs the vote into database
         and calculate majority and tally information and puts the
         updated information back to the database.

         Return:     a "wait" message or a proper majority and tally
                  information.
      */


      // The layout of the table vote is as following:
      // id, agreement, majority, tally, group, round, vote,
      // groupSize, threshold, firstVoter, curSize.

      public function main()
      {
         // Open a database connection first
         $this->openDatabase();
         $id = session_id();
         $groupNum = 0;

         // The join round's round value is -1
         if (isset($_REQUEST['join']))
         {
            $curSize = 0;
            $result;

            $voterSizePair = $this->checkFirstVoter($id);

            $firstVoter = $voterSizePair[0];
            $size = $voterSizePair[1];

            $selectSql =
            "select * from vote where groupNum='" . $groupNum . "'";
            $selectResult = mysql_query($selectSql) or die(mysql_error());
            $rows = mysql_num_rows($selectResult);

            // Get current size from database
            while ($arr = mysql_fetch_array($selectResult))
            {
               $curSize = $arr[10];
               break;
            }
            // Current size will increase by one after insertion
            $curSize = $curSize + 1;

            if ($rows == $size)
            {
               return "full";       // A group is full
            }

            $sql = "insert into vote values('$id', -1, -1, 0, $groupNum,
                  -1, -1, $size, -1, $firstVoter, $curSize)";
            $insertResult = mysql_query($sql) or die(mysql_error());

            // Update current size of all other voters to increase by one.
            $updateSql = "update vote set curSize = '" . $curSize .
                     "', groupSize='" . $size . "'";
            $updateResult = mysql_query($updateSql) or die(mysql_error());


            $this->closeDatabase();    // close database connection


            $result  = $this->constructResponse
                        ($id, -1, -1, 0, $groupNum, -1,
                           -1, $size, -1, $firstVoter, $curSize);

            return $result;
         }
         // Handle request after join, but before vote
         // Vote is happening only when current size
         // is equal to group size.
         else if (isset($_REQUEST['firstJoin']))
         {
            $sql = "select * from vote where groupNum='" . $groupNum . "'" .
                  " and id='" . $id . "'";
            $sqlResult = mysql_query($sql) or die(mysql_error());
            $result = "";
            while ($arr = mysql_fetch_array($sqlResult))
            {
               $eachRow = $this->constructResponse
                    ($arr['id'], $arr['agreement'],
                     $arr['majority'], $arr['tally'],
                     $arr['groupNum'], $arr['round'],
                     $arr['vote'], $arr['groupSize'],
                     $arr['threshold'], $arr['firstVoter'],
                     $arr['curSize']);
               $result = $eachRow;
            }
            $this->closeDatabase();    // close database
            return $result;

         }
         else  // user clicks on vote
         {
            $size = $_REQUEST['size'];

            // id is not in the group
            if ( $groupNum === false)
            {
               // groupNum is -1 to indicate id has not join
               $result = $this->constructResponse
               ($id, -1, -1, 0, -1, -1, -1, -1, -1, 0, 0);
               return $result;
            }
            if (isset($_REQUEST['vote']) &&
            $_REQUEST['vote'] == null)
               die("Enter a vote value before click on vote button!");
            $round = $_REQUEST['round'];
            $vote = $_REQUEST['vote'];

            $dupSql = "select * from vote where id='" . $id .
                    "' and round='" . $round . "'";
            $dupResult = mysql_query($dupSql)
                        or die(mysql_error());
            $existRows = mysql_num_rows($dupResult);

            // Avoid duplicated insertion
            if ($existRows != 1)
            {
               $curSize;
               $first;
               $previousSql = "select * from vote where id='" . $id .
                    "' and round='" . ($round - 1) . "'";
               $previousResult = mysql_query($previousSql)
                           or die(mysql_error());

               // Get curSize, firstVoter information from database
               while ($arr = mysql_fetch_array($previousResult))
               {
                  $curSize = $arr['curSize'];
                  $first = $arr['firstVoter'];
                  break;
               }
               $sql = "insert into vote values('$id', -1, " .
                           "-1, 0, 0, $round,".
                      "$vote,$size, -1,$first,$curSize)";
               mysql_query($sql) or die(mysql_error());
            }

            $result = "";

            // Make sure majority and tally won't be delivered util
            // all users in the same group voted.
            // A "wait" message as an indicator that shows not all users
            // have been voted.

            if (!$this->getReady($round, 0, $size))
               return "wait";
            $result = $this->retrieveInfo($round, 0, $id);
            $this->closeDatabase();       // close database connection
            return $result;
         }
      }

      /*
         A function checks if all the users in the same group have
         been voted.

         Return:     True for all users vote in the same round,
                  otherwise false.
      */

      public function getReady($round, $groupId, $size)
      {
         $sql = "select * from vote where round ='" . $round .
                "' and groupNum ='" . $groupId . "'";
         $result = mysql_query($sql) or die(mysql_error());
         $rows = mysql_num_rows($result);
         if ($rows < $size)
            return false;
         else
            return true;
      }

      /*
         A function calcualtes majority, tally and agreement information
         based on combinations of $round, $groupNum, and $id. It updates
         the corresponding fields in database. And it constructed proper
         response message.

         Return:     A proper message contains $id,
                     $agreement, $majority,
                     $tally, $group, $round, and $vote
                     separated by ":".
      */

      public function retrieveInfo($round, $groupId, $id)
      {
         $majority;
         $tally;
         $threshold;
         $agreement = -1;
         $numHeads = 0;
         $numTails = 0;
         $arr;
         $size = -1;

         $selectSql = "select * from vote where round >= '"
                   . 0 . "' and groupNum = '" . $groupId . "'";
         $selectResult = mysql_query($selectSql)
                  or die(mysql_error());

         while ($arr = mysql_fetch_array($selectResult))
         {
            if ($arr['vote'] == 1)
               $numHeads++;
            else
               $numTails++;
            if ($size == -1)
               $size = $arr['groupSize'];

         }

         $majority = ($numHeads > $numTails)? 1 : 0;
         $tally = ($majority == 1)? $numHeads : $numTails;
         if($numHeads >= ((7.0 / 8.0) * $size))
         {
            $agreement = 1;
         }
         else if($numTails >= ((7.0 / 8.0) * $size))
         {
            $agreement = 0;
         }

         $retFlip = ElectionManager::flip();

         if ($retFlip)
            $threshold = (int)((5.0 / 8.0) * $size + 1);
         else
            $threshold = (int)((3.0 / 4.0) * $size + 1);

         // An sql string updates the database
         $updateSql = "update vote set majority = '" . $majority
                    . "', tally ='" . $tally . "'" . ", agreement='"
                    . $agreement . "', threshold='" . $threshold
                    . "' where round = '" . $round
                    . "' and groupNum = '" . $groupId . "' and id='"
                    . $id . "'";
         $updateResult = mysql_query($updateSql) or die(mysql_error());

         // An sql string select a row according to groupNum and id
         $selectSql = "select * from vote where round = '" . $round
                      . "' and groupNum = '" . $groupId . "'"
                  . " and id='" . $id . "'";
         $afterUpdate = mysql_query($selectSql) or die(mysql_error());

         $result = "";

         while ($arr = mysql_fetch_array($afterUpdate))
         {
            $eachRow = $this->constructResponse
                     ($arr['id'], $arr['agreement'],
                      $arr['majority'], $arr['tally'],
                      $arr['groupNum'], $arr['round'],
                      $arr['vote'], $arr['groupSize'],
                      $arr['threshold'], $arr['firstVoter'],
                      $arr['curSize']);
            $result = $eachRow;
         }
         return $result;
      }

      /*
         A function closes database connection.
      */
      public function closeDatabase()
      {
         mysql_close();
      }
   }

   // Construct an ElectionManager object
   $manager = new ElectionManager();
   $result = $manager->main();
   echo "result:" . $result;
?>
</body>
</html>