<?
include ("settings.php");
/** set_exists()
* This function tests the existence of a card set,
* corresponding to the $setid in the config file
*/
function set_exists() {
global $setid;
return (file_exists("set.".$setid.".dat"));
}
/** card_number()
* This function returns the number of cards found in the card set
* user must verify that set exists before calling this function.
* This function will reload the set from the disk. Use
* count($set) if you already opened and loaded the set to fasten
* the process
*/
function card_number() {
$set=load_set();
if (is_array($set))
return count($set);
}
/** generate_cards()
* This function generate the appropriate number of cards
* All cards are randomly generated, and have a Free square
* in the center. The function saves the newly created set.
* This function will overwrite an existing set with the same
* setid.
*/
function generate_cards($numbercards) {
global $freesquare;
for ($cardnumber = 0; $cardnumber <$numbercards; $cardnumber++) {
// The next two variables are only used when freesquare == 2 (random location)
$randcolumn = rand(0,4);
$randrow = rand(0,4);
for ($column = 0; $column<5; $column++) {
for ($row = 0; $row<5; $row++) {
if (($column==2) && ($row == 2) && ($freesquare==1)) { //free
$set[$cardnumber][$column][$row]["number"] = "Free"; //free
$set[$cardnumber][$column][$row]["checked"] = true; //free
}
else if (($column==$randcolumn) && ($row==$randrow) && ($freesquare==2)){
$set[$cardnumber][$column][$row]["number"] = "Free"; //free
$set[$cardnumber][$column][$row]["checked"] = true; //free
}
else {
//to ensure we do not have the same number twice in one column
$numberexists = true; //loop entry
while ($numberexists) {
$random = rand(1+$column*15,($column+1)*15);
$numberexists =false; //assume it is not repeated until it is found
for ($checker=0; $checker<$row; $checker++)
if ($set[$cardnumber][$column][$checker]["number"] == $random) $numberexists=true;
}
$set[$cardnumber][$column][$row]["number"] = $random;
$set[$cardnumber][$column][$row]["checked"] = false;
}
} //row
} //column
} //cardnumbber
save_set($set);
}
/** display_card()
* This function draws an HTML table for one or four cards.
* By setting the $fourperpage parameter to 1, the tables
* are drawn smaller.
*/
function display_card ($cardnumber,$fourperpage=0) {
global $bingoletters, $setid;
$set = load_set(); //normal cards
if (is_array($set)) {
echo "<center><table width=".(($fourperpage)?"300":"75%")." border=1 cellpadding=".(($fourperpage)?"4":"20")." bgcolor=\"silver\" BORDERCOLOR=\"#FF0000\"><tr>";
//header
for ($column = 0; $column<5; $column++) {
echo '<td width="20%" align="center" bgcolor="#dd00dd"><b><font size=+'.(($fourperpage)?'2>':'7>').$bingoletters[$column].'</font></b></td>';
}
echo "</tr>";
//table
for ($row = 0; $row<5; $row++) {
echo "<tr>";
for ($column = 0; $column<5; $column++) { //column has to be inner loop due to HTML table
echo "\n<td align=center bgcolor=\"".($set[$cardnumber][$column][$row]["checked"]?"#eeee00":"silver")."\">";
if ($fourperpage) echo '<font size=+'.(($set[$cardnumber][$column][$row]["number"]=="Free")?'1':'3').'>';
else echo '<font size=+'.(($set[$cardnumber][$column][$row]["number"]=="Free")?'2':'5').'>';
echo $set[$cardnumber][$column][$row]["number"].'</font></td>';
}
echo "</tr>";
}
echo "</table><table width=".(($fourperpage)?"65%>":"75%>");
printf("<tr><td align=right colspan=5><font size=-2> Card Number: %s%'04s </font></td></tr>",$setid,$cardnumber+1);
echo "</table></center>";
}
else echo "set could not be opened";
}
/** random_number()
* This function generates a new random number.
* The number is unique: the function checks the draws.xx.dat file
* and loops until a new number randomly generated.
* The file draws.xx.dat is resorted and rewritten before the end of the function
* so it includes the new number.
* The function calls mark_cards() to have the new number set in all
* cards, and call check_bingo() to update the winners' list.
*/
function random_number($numberinplay) {
global $bingoletters;
$draws = load_draws();
if ($draws!=null){
$total=count($draws);
} else $total=0;
$samenumbertwice= true;
while ($samenumbertwice) {
$col = rand(0,4);
$row = rand(1,15);
$num = 15*$col+$row;
$samenumbertwice=false;
if ($total >0 ) //no need to check if we have no numbers yet
for ($i=0;$i < $total; $i++)
if ($num==$draws[$i]) $samenumbertwice=true;
}
$draws[$total]=$num;
save_draws($draws);
mark_cards($col,$num);
check_bingo($numberinplay);
return $bingoletters[$col].$num;
}
/** submit_number()
* This function is used in manual mode to enter a number into the draw list.
* The file draws.xx.dat is resorted and rewritten before the end of the function
* so it includes the new number.
* The function calls mark_cards() to have the new number set in all
* cards, and call check_bingo() to update the winners' list.
*/
function submit_number($number,$numberinplay) {
global $bingoletters;
$draws = load_draws();
if ($draws!=null){
$total=count($draws);
} else $total=0;
$samenumbertwice=false;
//extract the number out of the input string
$convert = intval(substr($number,1));
if ($total >0 ) //no need to check if we have no numbers yet
for ($i=0;$i < $total; $i++)
if ($convert==$draws[$i]) $samenumbertwice=true;
if (!$samenumbertwice) {
$draws[$total]=$convert;
save_draws($draws);
mark_cards(array_search(strtoupper(substr($number,0,1)),$bingoletters),$convert);
check_bingo($numberinplay);
} else echo '<font color="#ff3300"><b>This number has already been entered, please verify and enter a new number</b><br><hr></font>';
}
/** mark_cards()
* This function will "color" a given number on all cards
* that possess this number. The card set will be resaved
* before the end of the function.
* This function should be called before check_bingo() which
* determine winning cards.
*/
function mark_cards($col, $num) { //col provided here to speed up search in the right column only
$set = load_set();
$numcards=count($set);
for ($n=0; $n<$numcards;$n++) {
for ($r=0; $r<=4; $r++) { //go down the given column
if ($set[$n][$col][$r]["number"]==$num)
$set[$n][$col][$r]["checked"]=true;
}
}
save_set($set);
}
/** check_bingo()
* This function goes through the complete set and attempts to find
* winning cards.
* Winning cards are cards that match the current winning pattern.
* The winning cards are saved to the file winners.xx.dat and the file
* is re-written each time.
*/
function check_bingo ($numberinplay) {
global $winningpattern;
global $setid;
$set=load_set();
$numcards = count($set);
$currentwinners = load_winners();
//refresh the new winner list
@unlink("new_winners.".$setid.".dat");//erase the new winners file
//if a numberinplay is given, which is smaller than the the number
// of cards in the set, the rest of the cards are not verified.
for ($n=0; $n<min($numberinplay,$numcards);$n++) {
if (!(@in_array($n+1,$currentwinners))) { //avoids the warning if there are no winners yet
switch ($winningpattern) {
case 0: //normal bingo
$bingo=false;
for ($c=0; $c<5; $c++) {
$rowbingo=true; //assume there is bingo in rows and prove wrong
$colbingo=true; //assume there is bingo in columns and prove wrong
for ($r=0; $r<5; $r++) {
if (!$set[$n][$c][$r]["checked"]) $colbingo=false; //as soon as one is not checked
if (!$set[$n][$r][$c]["checked"]) $rowbingo=false; //as soon as one is not checked
} //end of that column/row, if we still have either bingo, we have a winner
if ($rowbingo||$colbingo){
$bingo=true;
break; //no need to keep checking
}
}
if (!$bingo) { //if it is not a winner already, will check the diagonals
$bingod1=true; //assume there is bingo in diagonals, prove wrong
$bingod2=true;
for ($d=0; $d<5 ; $d++) {
if (!$set[$n][$d][$d]["checked"]) $bingod1=false; //as soon as one item from diagonal is not checked
if (!$set[$n][$d][4-$d]["checked"]) $bingod2=false;
}
if ($bingod1||$bingod2) {
$bingo=true;
}
}
break; //from case 0
default:
//for any other case, check all the "winning squares" against the current card
//by loading the appropriate card of the "winningpatterns" set
//stop at the first unmatching square
$bingo=true; //assume true until one square not checked
$winningset = load_winning_patterns();
for ($c=0; $c<5; $c++) {
for ($r=0; $r<5; $r++) {
if ($winningset[$winningpattern-1][$c][$r]["checked"] && !$set[$n][$c][$r]["checked"]) {
$bingo=false; //as soon as one is not checked
break 3; //break from loop 1, loop 2 and default case
}
}
}
break; //from case else
} //end switch
if ($bingo){ //for the current card
$newwinners[count($newwinners)]=($n+1);
} //if bingo
}
} //for each card
if (count($newwinners)>0) {
save_new_winners($newwinners);
save_winners(array_merge($currentwinners,$newwinners));
}
}
/** restart()
* This function allows one to restart the game mode.
* Current list of winners will be erased, as well as all drawn numbers.
* The card set will remain untouched, but all "colours" will be reset, except
* for the free square. Very useful if you are using the same set of bingo cards for
* several games.
*/
function restart() { //erases winners, draws, and clears all cards but keeps numbers
global $setid;
@unlink ("winners.".$setid.".dat");
@unlink ("new_winners.".$setid.".dat");
@unlink("draws.".$setid.".dat");
if (set_exists()) {
$set = load_set();
$numcards=count($set);
for ($n=0; $n<$numcards;$n++) {
for ($c=0; $c<5; $c++) {
for ($r=0; $r<5; $r++) { //go down the column
$set[$n][$c][$r]["checked"]=($set[$n][$c][$r]["number"]=="Free"); //don't forget the free
}
}
}
save_set($set);
}
}
/** draws_table()
* This function generates an HTML table of all numbers drawn.
* It is used in game mode on the right side. The file containing the
* numbers drawn (draws.xx.dat) is already sorted.
*/
function draws_table() { //table of all numbers drawn
$draws = load_draws();
echo '<table width="100%" border=1 cols=5><tr>';
if ($draws!=null) {
$number = count($draws);
for ($i =0; $i<$number; $i++) {
echo '<td align=center width="20%">'.find_letter($draws[$i]).$draws[$i].'</td>';
if (($i+1)%5==0) echo "</tr><tr>";
}
} else echo "<td>No numbers drawn yet</td>";
echo '</tr></table>';
}
/** winners_table()
* This function generates an HTML table of all winning cards.
* It is used in game mode at the bottom.
* Each winning card number is displayed with its view link.
*/
function winners_table() {
$winners = load_winners();
$new_winners = load_new_winners(); //to be indicated in a different color
echo '<table width="100%" border=1><tr>';
if ($winners!=null) {
$number = count($winners);
for ($i =0; $i<$number; $i++) {
$color= ((@in_array($winners[$i],$new_winners))? "#ff0000" :"#ffffff");
echo '<td align=center width="20%"><a href="view.php?cardnumber='.$winners[$i].'" target=_blank><FONT color="'.$color.'">'.$winners[$i].'</font></a></td>';
if (($i+1)%5==0) echo "</tr><tr>";
}
}
else echo "<td>No winners yet!</td>";
echo '</tr></table>';
}
/** find_letter()
* This function returns the letter associated with the
* bingo number passed as a parameter (1 to 75): B, I, N, G or O
*/
function find_letter($num) {
global $bingoletters;
return $bingoletters[intval(($num-1) /15)];
}
/** load_set()
* This function attemps to load the card set
* from the file set.xx.dat where xx is the setid.
*/
function load_set() {
global $setid;
if (set_exists()) {
$filearray = file("set.".$setid.".dat");
for ($i=0; $i< $filearray[0]; $i++) { //first row is number of rows
$set[$i] = unserialize($filearray[$i+1]);
}
return $set;
} else {
echo "set could not be loaded";
return null;
}
}
/** save_set()
* This function attemps to save the card set
* to the file set.xx.dat where xx is the setid.
* Error msgs were removed because the demo
* on sourceforge.net cannot save files.
* The file is written by serializing each card onto a different line
* Serializing the whole set table also works, but the file
* is a lot more difficult to observe with a text editor.
*/
function save_set(&$set) {
global $setid;
$numcards = count($set);
if (@$fp = fopen("set.".$setid.".dat","w")) {
fwrite($fp,$numcards."\n");
for ($i =0; $i<$numcards; $i++) {
fwrite($fp, serialize($set[$i])."\n"); //one card per row
}
fclose($fp);
return true;
}
}
/** load_draws()
* This function attemps to load the series of numbers drawn
* from the file draws.xx.dat where xx is the setid.
*/
function load_draws() {
global $setid;
if (@file_exists("draws.".$setid.".dat")){
$filearray=file("draws.".$setid.".dat");
$draws = unserialize($filearray[0]);
return $draws;
} else return null;
}
/** save_draws()
* This function attemps to save the series of numbers drawn
* to the file draws.xx.dat where xx is the setid.
* Error msgs were removed because the demo
* on sourceforge.net cannot save files.
* The file is written by serializing the whole
* draws table, once sorted.
*/
function save_draws(&$draws) {
global $setid;
sort($draws);
if (@$fp=fopen("draws.".$setid.".dat","w")) {
fwrite($fp, serialize($draws));
fclose($fp);
}
}
/** load_winners()
* This function attemps to load the series of winning card numbers
* from the file winners.xx.dat where xx is the setid.
*/
function load_winners() {
global $setid;
if (@file_exists("winners.".$setid.".dat")){
$filearray=file("winners.".$setid.".dat");
$winners = unserialize($filearray[0]);
return $winners;
} else return null;
}
/** save_winners()
* This function attemps to save the series of winning cards
* to the file winners.xx.dat where xx is the setid.
* Error msgs were removed because the demo
* on sourceforge.net cannot save files.
* The file is written by serializing the whole
* winners table.
*/
function save_winners(&$winners) {
global $setid;
sort($winners);
if (@$fp=fopen("winners.".$setid.".dat","w")) {
fwrite($fp, serialize($winners));
fclose($fp);
}
}
/** load_new_winners()
* This function attemps to load the series of new winning card numbers
* from the file new_winners.xx.dat where xx is the setid.
*/
function load_new_winners() {
global $setid;
if (@file_exists("new_winners.".$setid.".dat")){
$filearray=file("new_winners.".$setid.".dat");
$new_winners = unserialize($filearray[0]);
return $new_winners;
} else return null;
}
/** save_new_winners()
* This function attemps to save the series of new winning cards
* to the file new_winners.xx.dat where xx is the setid.
* Error msgs were removed because the demo
* on sourceforge.net cannot save files.
* The file is written by serializing the table containing the new
* winners table.
*/
function save_new_winners(&$new_winners) {
global $setid;
if (@$fp=fopen("new_winners.".$setid.".dat","w")) {
fwrite($fp, serialize($new_winners));
fclose($fp);
}
}
/** load_winning_patterns()
* This function attemps to load the winning patterns set (winningpatterns.dat) which contains
* all winning patterns, with the exception of the normal winning pattern (pattern 0)
* (any row, any column, any diagonal). The set is loaded when the user wishes to preview
* customize a given winning pattern.
*/
function load_winning_patterns() {
if (file_exists("winningpatterns.dat")) {
$filearray = file("winningpatterns.dat");
for ($i=0; $i< $filearray[0]; $i++) { //first row is number of rows
$set[$i] = unserialize($filearray[$i+1]);
}
return $set;
} else {
echo "set could not be loaded";
return null;
}
}
/** update_winning_patterns()
* This function updates the given $cardnumber within the "winningp atterns" set based
* on the information graphically entered from the web page. The squares selected on the
* interactive web page are converted to a hidden string. The string is passed to this
* function as a parameter, along with the pattern number chosen. The set is updated
* to "check" all squares that were selected by the user.
* The functions saves the previewpatterns set prior to exiting.
*/
function update_winning_patterns($hiddenstring, $cardnumber) {
global $bingoletters;
@$winningset=load_winning_patterns();
if (is_array($winningset)) {
for ($row = 0; $row<5; $row++) {
for ($column = 0; $column<5; $column++) {
//eg. if B0 is in the string, then we must ensure that square becomes checked in
//the first card of the previewpattern set
if (ereg(($bingoletters[$column].$row),$hiddenstring)) {
$winningset[$cardnumber][$column][$row]["checked"]=true;
} else $winningset[$cardnumber][$column][$row]["checked"]=false;
}
}
save_winning_patterns($winningset);
}
}
/** save_winning_patterns()
* This function attemps to save the pattern preview set
* to the winningpatterns.dat file, a carefully crafted file that stores all winning patterns.
* with the exception of the normal winning pattern (pattern 0) which is not easily represented
* (any row, any column, any diagonal). This function is called once the user has selected
* the squares of the winning pattern from the GUI. The string of winning squares is converted
* from the interactive form with the function call update_winning_patterns() and then saved here
*/
function save_winning_patterns(&$set) {
if (file_exists("winningpatterns.dat")) {
//we must first open the file in reading to determine the number of rows
$filearray = file("winningpatterns.dat");
$numcards= trim($filearray[0]);
//then we write the appropriate number of cards in the previewpatterns set
if (@$fp=fopen("winningpatterns.dat","w")) {
fwrite($fp,$numcards."\n");
for ($i =0; $i<$numcards; $i++) {
fwrite($fp, serialize($set[$i])."\n"); //one card per row
}
fclose($fp);
}
}
}
/** display_interactive_card()
* function similar to display_card() that is called when the user wishes
* to preview or customize one of the "winning patterns". The technique
* used to customize the winning pattern involves Javascript and CSS components
* that are not supported by Netscape 4 (Opera 6 and IE 6 have been tested and
* are fully compatible. The card is an HTML table in which the cells react to mouse
* clicks. When the card is first loaded, the information is retreived from the
* winningpatterns.dat set and is represented visually on the screen. A string
* is generated from the "checked cell" and stored (hidden) in the form. When the user
* clicks a cell from the table, its color is reversed, and the hidden string is truncated
* or expanded with the name of the chosen cell. When the form is submitted, the
* updated winningpatterns.dat file is saved.
* This function returns a string composed of the names of the selected cell of the given
* card in the winningpatterns.dat file: eg. B0;I0;N0;N1;N2;N3;N4;G0;O0 would be returned
* if the T-shaped winning pattern was selected.
*/
function display_interactive_card($cardnumber) {
global $bingoletters;
@$winningset=load_winning_patterns(); //display a pattern preview
if (is_array($winningset)) {
echo '<center><table width="75%" border="1" cellpadding="20" bgcolor="silver" bordercolor="red"><tr>';
//header
for ($column = 0; $column<5; $column++) {
echo '<td width="20%" align="center" bgcolor="#dd00dd"><b><font size="+7">'.$bingoletters[$column].'</font></b></td>';
}
echo "</tr>";
//table
for ($row = 0; $row<5; $row++) {
echo "<tr>\n";
for ($column = 0; $column<5; $column++) { //column has to be inner loop due to HTML table
echo "\n<td align=\"center\" style=\"background:".($winningset[$cardnumber][$column][$row]["checked"]?"#eeee00;":"silver;")."\" onClick = \"this.style.background=clickcell(this.style.background,'".$bingoletters[$column].$row."')\">";
echo '<font size="+5">';
echo $winningset[$cardnumber][$column][$row]["number"].'</font></td>';
if ($winningset[$cardnumber][$column][$row]["checked"]) $hiddenstring.=($bingoletters[$column].$row.';');
}
echo "</tr>";
}
echo "</table></center>";
}
else echo "set could not be opened";
return $hiddenstring;
}
?>