2 /* Copyright 2006, 2007, 2008, 2009, 2010, 2011, 2012 Arun Persaud <arun@nubati.net>
4 * This file is part of e-DoKo.
6 * e-DoKo is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * e-DoKo is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with e-DoKo. If not, see <http://www.gnu.org/licenses/>.
21 /* make sure that we are not called from outside the scripts,
22 * use a variable defined in config.php to check this
27 function config_check()
29 global $EmailName,$EMAIL_REPLY,$ADMIN_NAME,$ADMIN_EMAIL,$DB_work;
31 /* check if some variables are set in the config file, else set defaults */
32 if(!isset($EmailName))
34 if(isset($EMAIL_REPLY))
36 ini_set('sendmail_from',$EMAIL_REPLY);
38 if(!isset($ADMIN_NAME))
41 echo '<h1>Setup not completed</h1>';
42 echo 'You need to set $ADMIN_NAME in config.php.';
46 if(!isset($ADMIN_EMAIL))
49 echo '<h1>Setup not completed</h1>';
50 echo 'You need to set $ADMIN_EMAIL in config.php. '.
51 'If something goes wrong an email will be send to this address.';
58 echo '<h1>Setup not completed</h1>';
59 echo 'You need to set $DB_work in config.php. '.
60 'If this is set to anything else than 0, the game will be suspended and one can work safely on the database. '.
61 'A message will be displayed that it will probably take about N minutes, with N being the number $DB_work is set to. '.
62 'The default should be 0 for the game to work.';
69 echo '<div class="WIP">'.
70 _("Working on some aspect of e-DoKo... This will probably take max. $DB_work minutes. It could be over in a few seconds too though ;)").
79 /* define possible status for email subsjects */
80 define("GAME_CANCELED", 0);
81 define("GAME_CANCELED_POVERTY", 1);
82 define("GAME_CANCELED_TIMEOUT", 2);
83 define("GAME_YOUR_TURN", 3);
84 define("GAME_READY", 4);
85 define("GAME_POVERTY", 5);
86 define("GAME_DPOVERTY", 6);
87 define("GAME_OVER", 7);
88 define("GAME_RECOVERY", 8);
89 define("GAME_REMINDER", 9);
90 define("GAME_NEW", 10);
92 /* define possible status for showing cards */
94 define("CARDS_EMPTY", 0); /* show player's hand*/
95 define("CARDS_SHOW", 1); /* show player's hand*/
96 define("CARDS_MYTURN", 2); /* show radiobuttons for cards that can be played*/
97 define("CARDS_EXCHANGE", 3); /* do we need to return cards to our partner in poverty?*/
98 define("CARDS_GAMEOVER_ME", 4); /* show all cards from everyone*/
99 define("CARDS_GAMEOVER", 5); /* show all cards from everyone (looking at someone else's game)*/
101 /* cards_status: SHOW show our hand
102 * MYTURN show radiobutton for cards that can be played
103 * EXCHANGE do we need to return cards to our partner in poverty?
104 * GAMEOVER show all cards from everyone
107 function mymail($uid,$gameid=0,$type,$message)
109 global $EmailName,$WIKI;
111 /* do we send the email right away or save it in the database? */
114 /* add standard header and footer */
115 $subject = "$EmailName ";
117 $game = DB_format_gameid($gameid);
124 $subject.=sprintf(_("Game %s canceled"),$game);
126 case GAME_CANCELED_POVERTY:
127 $subject.=sprintf(_("Game %s canceled (poverty not resolved)"),$game);
129 case GAME_CANCELED_TIMEOUT:
130 $subject.=sprintf(_("Game %s canceled (timed out)"),$game);
133 $subject.=sprintf(_("A card has been played in game %s"),$game);
136 $subject.=sprintf(_("Ready, set, go... (game %s)"),$game);
139 $subject.=sprintf(_("Poverty (game %s)"),$game);
142 $subject.=sprintf(_("Double poverty (game %s)"),$game);
145 $subject.=sprintf(_("Game over (game %s)"),$game);
148 $subject.=_("Recovery");
151 $subject.=sprintf(_("Reminder: game %s it's your turn"),$game);
154 $subject.=sprintf(_("You are invited to a game of DoKo (game %s)"),$game);
157 $subject.=sprintf(_("Problem with email, contact admin (errorcode %d)"),$gameid);
160 /* standard goodbye */
161 $footer = "\nHave a nice day\n".
162 " your E-Doko service department\n\n".
164 "You can change your mail delivery mode in the preference menu.\n".
165 'web: http://doko.nubati.net '.
166 "help, bugs, etc.: $WIKI";
170 /* send email to more than one person */
172 $header = "Hello all\n\n";
174 foreach($uid as $user)
176 $all[] = DB_get_email('userid',$user);
178 $To = implode(",",$all);
182 /* standard greeting */
183 $name = DB_get_name('userid',$uid);
184 $header = "Hello $name\n\n";
186 $To = DB_get_email('userid',$uid);
188 /* check if user wants email right away or if we should save it in
189 * the database for later delivery
192 $PREF = DB_get_PREF($uid);
193 if( $PREF['digest'] != 'digest-off' )
198 sendmail($To,$subject,$header.$message.$footer);
201 /* store email in database */
202 DB_digest_insert_email($To,$message,$type,$gameid);
206 function sendmail($To,$Subject,$message)
208 /* this function sends the mail or outputs to the screen in case of debugging */
209 global $debug,$EMAIL_REPLY;
213 if(isset($EMAIL_REPLY))
214 $header .= "From: e-DoKo daemon <$EMAIL_REPLY>\r\n";
218 /* display email on screen,
221 $message = str_replace("\n","<br />\n",$message);
222 $message = preg_replace("#(\w+://[^<>\s]+[\w/]*)#",
223 "<a href=\"$1\">$1</a>", $message);
225 echo "<br />To: $To<br />";
227 echo $header."<br />";
228 echo "Subject: $Subject <br />$message<br />\n";
232 mail($To,$Subject,$message,$header);
234 mail($To,$Subject,$message);
240 /* returns 1 if all names passed as args are defined by a GET or POST statement,
245 $args = func_get_args();
247 foreach($args as $arg)
249 $ok = $ok * isset($_REQUEST[$arg]);
250 /*echo "$arg: ok = $ok <br />";
256 function myerror($message)
258 echo "<span class=\"error\">".htmlspecialchars($message)."</span>\n";
259 sendmail($ADMIN_EMAIL,$EmailName." Error in Code",$message);
263 function pos_array($c,$arr)
280 function is_trump($c)
284 if(in_array($c,$CARDS["trump"]))
290 function is_same_suite($c1,$c2)
294 if(in_array($c1,$CARDS["trump"] ) && in_array($c2,$CARDS["trump"] ) ) return 1;
295 if(in_array($c1,$CARDS["clubs"] ) && in_array($c2,$CARDS["clubs"] ) ) return 1;
296 if(in_array($c1,$CARDS["hearts"] ) && in_array($c2,$CARDS["hearts"] ) ) return 1;
297 if(in_array($c1,$CARDS["spades"] ) && in_array($c2,$CARDS["spades"] ) ) return 1;
298 if(in_array($c1,$CARDS["diamonds"]) && in_array($c2,$CARDS["diamonds"]) ) return 1;
303 function compare_cards($a,$b,$game)
305 /* if "a" is higher than "b" return 1, else 0, "a" being the card first played */
311 /* first map all cards to the odd number,
312 * this insure that the first card wins the trick
313 * if they are the same card
315 if( $a/2 - (int)($a/2) != 0.5)
317 if( $b/2 - (int)($b/2) != 0.5)
320 /* check for schweinchen and ten of hearts*/
326 if($RULES['schweinchen']=='both' && $GAME['schweinchen-who'])
328 if($a == 19 || $a == 20 )
330 if($b == 19 || $b == 20 )
333 else if($RULES['schweinchen']=='second' && $GAME['schweinchen-second'])
335 if($a == 19 || $a == 20 )
337 if($b == 19 || $b == 20 )
340 else if($RULES['schweinchen']=='secondaftercall' && $GAME['schweinchen-who'] && $GAME['schweinchen-second'] )
342 /* check if a call was made either by the player or his partner. If so activate Schweinchen rule. */
343 if(DB_get_call_by_hash($GAME['schweinchen-who']) || DB_get_partner_call_by_hash($GAME['schweinchen-who']) )
345 if($a == 19 || $a == 20 )
347 if($b == 19 || $b == 20 )
350 /* if not, do nothing and the foxes are just handeled as normal trump */
356 /* check for ten of hearts rule */
357 if($RULES["dullen"]=="secondwins")
358 if($a==1 && $b==1) /* both 10 of hearts */
359 return 0; /* second one wins.*/
363 /* no special cases here */
367 if(is_trump($a) && is_trump($b) && $a<=$b)
369 else if(is_trump($a) && is_trump($b) )
372 { /*$a is not a trump */
376 { /* both no trump */
379 $posA = pos_array($a,$CARDS["clubs"]);
380 $posB = pos_array($b,$CARDS["clubs"]);
388 $posA = pos_array($a,$CARDS["spades"]);
389 $posB = pos_array($b,$CARDS["spades"]);
397 $posA = pos_array($a,$CARDS["hearts"]);
398 $posB = pos_array($b,$CARDS["hearts"]);
406 $posA = pos_array($a,$CARDS["diamonds"]);
407 $posB = pos_array($b,$CARDS["diamonds"]);
414 /* not the same suit and no trump: a wins */
420 function get_winner($p,$mode)
422 /* get all 4 cards played in a trick, in the order they are played */
425 $c1pos = $tmp["pos"];
429 $c2pos = $tmp["pos"];
433 $c3pos = $tmp["pos"];
437 $c4pos = $tmp["pos"];
439 /* first card is better than all the rest */
440 if( compare_cards($c1,$c2,$mode) && compare_cards($c1,$c3,$mode) && compare_cards($c1,$c4,$mode) )
443 /* second card is better than first and better than the rest */
444 if( !compare_cards($c1,$c2,$mode) && compare_cards($c2,$c3,$mode) && compare_cards($c2,$c4,$mode) )
447 /* third card is better than first card and better than last */
448 if( !compare_cards($c1,$c3,$mode) && compare_cards($c3,$c4,$mode) )
449 /* if second card is better than first, third card needs to be even better */
450 if( !compare_cards($c1,$c2,$mode) && !compare_cards($c2,$c3,$mode) )
452 /* second is worse than first, e.g. not following suite */
453 else if (compare_cards($c1,$c2,$mode) )
456 /* non of the above */
460 function count_nines($cards)
464 foreach($cards as $c)
466 if($c == "25" || $c == "26") $nines++;
467 else if($c == "33" || $c == "34") $nines++;
468 else if($c == "41" || $c == "42") $nines++;
469 else if($c == "47" || $c == "48") $nines++;
475 function check_wedding($cards)
478 if( in_array("3",$cards) && in_array("4",$cards) )
484 function count_trump($cards,$status='pregame')
490 /* count each trump, including the foxes, since this is used to determine poverty status */
491 foreach($cards as $c)
495 /* In case we really want to know the amount of trump, we can use the status variable.
496 * This is needed for example to figure out what icon to display on the table in case of
497 * trump given back in poverty */
498 if($status=='all') return $trump;
500 /* normally foxes don't count as trump, so we substract them here
501 * in case someone has schweinchen, one or two of them should count as trump
502 * though, so we need to add one trump for those cases */
505 if( in_array("19",$cards))
507 if( in_array("20",$cards) )
510 /* handle case where player has schweinchen */
511 if( in_array("19",$cards) && in_array("20",$cards) )
512 switch($RULES["schweinchen"])
515 /* add two, in case the player has both foxes (schweinchen) */
520 case "secondaftercall":
521 /* add one, in case the player has both foxes (schweinchen) */
531 function check_low_trump($cards)
535 if($RULES['lowtrump']=='none')
538 /* check if we have low trump */
541 foreach($cards as $card)
543 /* card a trump, but not a diamond? */
548 /* handle case where player has schweinchen */
549 if( in_array("19",$cards) && in_array("20",$cards) )
550 switch($RULES["schweinchen"])
554 case "secondaftercall":
564 function create_array_of_random_numbers($useridA,$useridB,$useridC,$useridD)
572 /* fix the hands; makes debugging easier; the following hands have lots of sicknesses,
573 * to make testing easier
575 $r[ 0]=1; $r[12]=47; $r[24]=13; $r[36]=37;
576 $r[ 1]=2; $r[13]=23; $r[25]=14; $r[37]=38;
577 $r[ 2]=3; $r[14]=27; $r[26]=15; $r[38]=39;
578 $r[ 3]=4; $r[15]=16; $r[27]=28; $r[39]=40;
579 $r[ 4]=5; $r[16]=17; $r[28]=29; $r[40]=21;
580 $r[ 5]=18; $r[17]=6; $r[29]=30; $r[41]=42;
581 $r[ 6]=41; $r[18]=7; $r[30]=31; $r[42]=43;
582 $r[ 7]=22; $r[19]=8; $r[31]=32; $r[43]=20;
583 $r[ 8]=45; $r[20]=9; $r[32]=33; $r[44]=19;
584 $r[ 9]=46; $r[21]=10; $r[33]=44; $r[45]=24;
585 $r[10]=35; $r[22]=11; $r[34]=48; $r[46]=25;
586 $r[11]=36; $r[23]=12; $r[35]=34; $r[47]=26;
590 /* check if we can find a game were non of the player was involved and return
593 $userstr = "'".implode("','",array($useridA,$useridB,$useridC,$useridD))."'";
594 $randomnumbers = DB_get_unused_randomnumbers($userstr);
595 $randomnumbers = explode(":",$randomnumbers);
597 if(sizeof($randomnumbers)==48)
598 return $randomnumbers;
600 /* need to create new numbers */
604 /* shuffle using a better random generator than the standard one */
605 for ($i = 0; $i <48; $i++)
607 $j = @mt_rand(0, $i);
617 function display_cards($me,$myturn)
622 function have_suit($cards,$c)
627 if(in_array($c,$CARDS["trump"]))
628 $suite = $CARDS["trump"];
629 else if(in_array($c,$CARDS["clubs"]))
630 $suite = $CARDS["clubs"];
631 else if(in_array($c,$CARDS["spades"]))
632 $suite = $CARDS["spades"];
633 else if(in_array($c,$CARDS["hearts"]))
634 $suite = $CARDS["hearts"];
635 else if(in_array($c,$CARDS["diamonds"]))
636 $suite = $CARDS["diamonds"];
638 foreach($cards as $card)
640 if(in_array($card,$suite))
647 function same_type($card,$c)
652 /* figure out what kind of card c is */
653 if(in_array($c,$CARDS["trump"]))
654 $suite = $CARDS["trump"];
655 else if(in_array($c,$CARDS["clubs"]))
656 $suite = $CARDS["clubs"];
657 else if(in_array($c,$CARDS["spades"]))
658 $suite = $CARDS["spades"];
659 else if(in_array($c,$CARDS["hearts"]))
660 $suite = $CARDS["hearts"];
661 else if(in_array($c,$CARDS["diamonds"]))
662 $suite = $CARDS["diamonds"];
664 /* card is the same suid return 1 */
665 if(in_array($card,$suite))
671 function set_gametype($gametype)
685 $CARDS["trump"] = array('1','2','3','4','5','6','7','8','9','10','11','12','13','14','15','16',
686 '17','18','19','20','21','22','23','24','25','26');
687 $CARDS["diamonds"] = array();
688 $CARDS["clubs"] = array('27','28','29','30','31','32','33','34');
689 $CARDS["spades"] = array('35','36','37','38','39','40','41','42');
690 $CARDS["hearts"] = array('43','44','45','46','47','48');
691 $CARDS["foxes"] = array('19','20');
692 if($RULES["dullen"]=='none')
694 $CARDS["trump"] = array('3','4','5','6','7','8','9','10','11','12','13','14','15','16',
695 '17','18','19','20','21','22','23','24','25','26');
696 $CARDS["hearts"] = array('43','44','1','2','45','46','47','48');
698 /* do we need to reorder for Schweinchen? need to search for it because of special case for dullen above*/
699 if($RULES['schweinchen']=='both'&& $GAME['schweinchen-who'])
701 /* find the fox and put them at the top of the stack */
702 foreach(array('19','20') as $fox)
705 $trump = $CARDS['trump'];
706 $key = array_keys($trump, $fox);
710 $foxa[]=$trump[$key[0]];
711 unset($trump[$key[0]]);
712 $trump = array_merge($foxa,$trump);
713 $CARDS['trump'] = $trump;
716 else if( ($RULES['schweinchen']=='second' || $RULES['schweinchen']=='secondaftercall')
717 && $GAME['schweinchen-who'])
719 /* find the fox and put them at the top of the stack */
720 $trump = $CARDS['trump'];
721 $key = array_keys($trump, '19');
725 $foxa[]=$trump[$key[0]];
726 unset($trump[$key[0]]);
727 $trump = array_merge($foxa,$trump);
728 $CARDS['trump'] = $trump;
732 $CARDS["trump"] = array('3','4','5','6','7','8','9','10');
733 $CARDS["clubs"] = array('27','28','29','30','31','32','11','12','33','34');
734 $CARDS["spades"] = array('35','36','37','38','39','40','13','14','41','42');
735 $CARDS["hearts"] = array('43','44', '1', '2','45','46','15','16','47','48');
736 $CARDS["diamonds"] = array('19','20','21','22','23','24','17','18','25','26');
737 $CARDS["foxes"] = array();
740 $CARDS["trump"] = array('11','12','13','14','15','16','17','18');
741 $CARDS["clubs"] = array('27','28','29','30','31','32','3', '4','33','34');
742 $CARDS["spades"] = array('35','36','37','38','39','40','5', '6','41','42');
743 $CARDS["hearts"] = array('43','44', '1', '2','45','46','7', '8','47','48');
744 $CARDS["diamonds"] = array('19','20','21','22','23','24','9','10','25','26');
745 $CARDS["foxes"] = array();
748 $CARDS["trump"] = array();
749 $CARDS["clubs"] = array('27','28','29','30','31','32','3', '4','11','12','33','34');
750 $CARDS["spades"] = array('35','36','37','38','39','40','5', '6','13','14','41','42');
751 $CARDS["hearts"] = array('43','44', '1', '2','45','46','7', '8','15','16','47','48');
752 $CARDS["diamonds"] = array('19','20','21','22','23','24','9','10','17','18','25','26');
753 $CARDS["foxes"] = array();
756 $CARDS["trump"] = array('1','2','3','4','5','6','7','8','9','10','11','12','13','14','15','16',
757 '17','18','27','28','29','30','31','32','33','34');
758 $CARDS["clubs"] = array();
759 $CARDS["spades"] = array('35','36','37','38','39','40','41','42');
760 $CARDS["hearts"] = array('43','44','45','46','47','48');
761 $CARDS["diamonds"] = array('19','20','21','22','23','24','25','26');
762 $CARDS["foxes"] = array();
763 if($RULES["dullen"]=='none')
765 $CARDS["trump"] = array('3','4','5','6','7','8','9','10','11','12','13','14','15','16',
766 '17','18','27','28','29','30','31','32','33','34');
767 $CARDS["hearts"] = array('43','44','1','2','45','46','47','48');
771 $CARDS["trump"] = array('1','2','3','4','5','6','7','8','9','10','11','12','13','14','15','16',
772 '17','18','35','36','37','38','39','40','41','42');
773 $CARDS["clubs"] = array('27','28','29','30','31','32','33','34');
774 $CARDS["spades"] = array();
775 $CARDS["hearts"] = array('43','44','45','46','47','48');
776 $CARDS["diamonds"] = array('19','20','21','22','23','24','25','26');
777 $CARDS["foxes"] = array();
778 if($RULES["dullen"]=='none')
780 $CARDS["trump"] = array('3','4','5','6','7','8','9','10','11','12','13','14','15','16',
781 '17','18','35','36','37','38','39','40','41','42');
782 $CARDS["hearts"] = array('43','44','1','2','45','46','47','48');
786 $CARDS["trump"] = array('1','2','3','4','5','6','7','8','9','10','11','12','13','14','15','16',
787 '17','18','43','44','45','46','47','48');
788 $CARDS["clubs"] = array('27','28','29','30','31','32','33','34');
789 $CARDS["spades"] = array('35','36','37','38','39','40','41','42');
790 $CARDS["hearts"] = array();
791 $CARDS["diamonds"] = array('19','20','21','22','23','24','25','26');
792 $CARDS["foxes"] = array();
793 if($RULES["dullen"]=='none')
795 $CARDS["trump"] = array('3','4','5','6','7','8','9','10','11','12','13','14','15','16',
796 '17','18','43','44','1','2','45','46','47','48');
802 function mysort($cards,$gametype)
805 if(isset($PREF['sorting']))
806 if($PREF['sorting']=='high-low')
807 usort ( $cards, 'sort_comp_high_low' );
809 usort ( $cards, 'sort_comp_low_high' );
811 usort ( $cards, 'sort_comp_high_low' );
815 function sort_comp_high_low($a,$b)
820 $ALL = array_merge($CARDS['trump'],$CARDS['diamonds'],$CARDS['clubs'],
821 $CARDS['hearts'],$CARDS['spades']);
823 return pos_array($a,$ALL)-pos_array($b,$ALL);
826 function sort_comp_low_high($a,$b)
831 $ALL = array_merge($CARDS['trump'],$CARDS['diamonds'],$CARDS['clubs'],
832 $CARDS['hearts'],$CARDS['spades']);
834 return -pos_array($a,$ALL)+pos_array($b,$ALL);
837 function can_call($what,$hash)
839 /* figure out if a person can make a call:
840 $what in 0,30,60,90,120 = points of the call
841 $hash = the hash of the person who wants to make the call
844 0 can't make that call
846 2 can make the call, but this is the last chance to do so...
851 /* get some information
853 $gameid = DB_get_gameid_by_hash($hash);
854 $gametype = DB_get_gametype_by_gameid($gameid);
855 $oldcall = DB_get_call_by_hash($hash); /* did the person already made a call? */
856 $pcall = DB_get_partner_call_by_hash($hash); /* did the partner already made a call */
859 /* you're call must be better than the one you or your partner already made
861 if( ($pcall!=NULL && ($what >= $pcall))
862 || ($oldcall!=NULL && ($what >=$oldcall)) )
867 /* for some rules we need to know how many cards people have
869 $NRcards = count(DB_get_hand($hash));
874 $user = DB_get_hash_from_game_and_pos($gameid,$i);
875 $NRallcards += count(DB_get_hand($user));
878 /* in case of a wedding, everything will be delayed by an offset
881 if($gametype=="wedding")
883 $offset = DB_get_sickness_by_gameid($gameid);
884 if ($offset <0) /* not resolved */
888 /* now check if the call is allowed depending on the rule set
890 switch ($RULES["call"])
893 /* calls can be made before/while you play your card...
894 * first card = 120, second card = 90, etc.
896 if( 4-($what/30) == 12 - ($NRcards + $offset))
898 if( 4-($what/30) > 12 - ($NRcards + $offset))
902 /* you can make the first call anytime during the first trick
904 if( 27+4*($what/30) == $NRallcards + $offset*4)
906 if( 27+4*($what/30) < $NRallcards + $offset*4)
910 /* you can call 120 with 12 cards, 90 with 9 or more cards, 60 with 6 or more, etc.
911 * you can't skip a call though
914 /* figure out last call
916 if($oldcall!=NULL && $pcall!=NULL)
917 $mincall = ($oldcall>$pcall) ? $pcall : $oldcall;
918 else if($oldcall!=NULL)
920 else if ($pcall!=NULL)
926 if( 12 == ($NRcards + $offset))
930 else if( 12 < ($NRcards + $offset))
934 else if ( 9 == ($NRcards + $offset))
936 if( ($mincall>=0 && $mincall<=120 && $what<=90 ) )
939 else if ( 9 < ($NRcards + $offset))
941 if( ($mincall>=0 && $mincall<=120 && $what<=90 ) )
944 else if ( 6 == ($NRcards + $offset))
946 if( ($mincall>=0 && $mincall<=90 && $what<=60 ) )
949 else if ( 6 < ($NRcards + $offset))
951 if( ($mincall>=0 && $mincall<=90 && $what<=60 ) )
954 else if ( 3 == ($NRcards + $offset))
956 if( ($mincall>=0 && $mincall<=60 && $what<=30 ) )
959 else if ( 3 < ($NRcards + $offset))
961 if( ($mincall>=0 && $mincall<=60 && $what<=30 ) )
964 else if ( 0 == ($NRcards + $offset))
966 if( ($mincall>=0 && $mincall<=30 && $what==0 ) )
969 else if ( 0 < ($NRcards + $offset))
971 if( ($mincall>=0 && $mincall<=30 && $what==0 ) )
980 function display_table_begin ()
982 global $gameid, $GT, $debug,$INDEX,$defaulttimezone,$session;
983 global $RULES,$GAME,$gametype;
985 $result = DB_query("SELECT User.fullname as name,".
986 " Hand.position as position, ".
988 " Hand.party as party, ".
989 " Hand.sickness as sickness, ".
990 " Hand.point_call, ".
991 " User.last_login, ".
996 "LEFT JOIN User ON User.id=Hand.user_id ".
997 "WHERE Hand.game_id='".$gameid."' ".
998 "ORDER BY position ASC");
1000 $row0 = DB_fetch_array($result);
1001 $row1 = DB_fetch_array($result);
1002 $row2 = DB_fetch_array($result);
1003 $row3 = DB_fetch_array($result);
1005 echo "<div class=\"table\">\n";
1006 display_single_user($row1);
1007 echo "\n<div class=\"middle\">\n";
1008 display_single_user($row0,1); /* mark starting player in case re/contra is not set yet */
1009 echo " <img class=\"table\" src=\"pics/table.png\" alt=\"table\" />\n";
1010 display_single_user($row2);
1014 function display_table_end ()
1016 global $gameid, $GT, $debug,$INDEX,$defaulttimezone,$session;
1017 global $RULES,$GAME,$gametype;
1019 $result = DB_query("SELECT User.fullname as name,".
1020 " Hand.position as position, ".
1022 " Hand.party as party, ".
1023 " Hand.sickness as sickness, ".
1024 " Hand.point_call, ".
1025 " User.last_login, ".
1030 "LEFT JOIN User ON User.id=Hand.user_id ".
1031 "WHERE Hand.game_id='".$gameid."' ".
1032 "ORDER BY position ASC");
1034 $row0 = DB_fetch_array($result);
1035 $row1 = DB_fetch_array($result);
1036 $row2 = DB_fetch_array($result);
1037 $row3 = DB_fetch_array($result);
1040 display_single_user($row3);
1046 function display_single_user($r,$start=0)
1048 /* start=1, mark starting player, default=0, so the player on the left is not marked */
1050 global $gameid, $GT, $debug,$INDEX,$defaulttimezone,$session;
1051 global $RULES,$GAME,$gametype;
1062 $wins = DB_get_number_of_tricks($gameid,$pos);
1063 date_default_timezone_set($defaulttimezone);
1064 $lastlogin = strtotime($r[6]);
1065 date_default_timezone_set($timezone);
1066 $timenow = strtotime(date("Y-m-d H:i:s"));
1067 $gravatar = "$name<br />\n <img class=\"gravatar\" title=\"$name\" src=\"http://www.gravatar.com/avatar/".
1068 md5(strtolower(trim($email)))."?d=identicon\" alt=\"$name's gravatar\" />";
1070 echo " <div class=\"table".($pos-1)."\">\n";
1072 /* mark starting player */
1073 if($start && ! ($party=="re" || $party=="contra"))
1074 echo ' <span class="start">'._('Starting Player')."</span> <br />\n";
1077 echo " <a href=\"".$INDEX."?action=game&me=".$hash."\">";
1078 if($vacation = check_vacation($user))
1080 $start = $vacation[0];
1081 $stop = substr($vacation[1],0,10);
1082 $comment = $vacation[2];
1084 $title = "begin: $start end: $stop $comment";
1085 echo " <span class=\"vacation\" title=\"$title\">$gravatar (on vacation until $stop)</span> \n";
1088 echo " $gravatar \n";
1092 /* add hints for poverty, wedding, solo, etc */
1093 if( $gametype != "solo")
1094 if( $RULES["schweinchen"]=="both" && $GAME["schweinchen-who"]==$hash )
1095 echo " Schweinchen. <br />";
1097 if($GT=="poverty" && $party=="re")
1098 if($sickness=="poverty" || ($RULES['lowtrump']=='poverty' && $sickness=='lowtrump'))
1100 $userhash = DB_get_hash_from_gameid_and_userid($gameid,$user);
1101 $cards = DB_get_all_hand($userhash);
1102 $trumpNR = count_trump($cards,'all');
1104 echo " <img src=\"pics/button/poverty_trump_button.png\" class=\"button\" ".
1105 "alt=\"poverty - trump back\" title=\"poverty - trump back\" />\n";
1107 echo " <img src=\"pics/button/poverty_notrump_button.png\" class=\"button\" ".
1108 "alt=\"poverty - no trump back\" title=\"poverty - no trump back\" />\n";
1111 echo " <img src=\"pics/button/poverty_partner_button.png\" class=\"button\" ".
1112 "alt=\"poverty partner\" title=\"poverty partner\" />\n";
1116 if($sickness=="poverty" || ($RULES['lowtrump']=='poverty' && $sickness=='lowtrump'))
1118 $userhash = DB_get_hash_from_gameid_and_userid($gameid,$user);
1119 $cards = DB_get_all_hand($userhash);
1120 $trumpNR = count_trump($cards,'all');
1122 echo " <img src=\"pics/button/poverty_trump_button.png\" class=\"button\" ".
1123 "alt=\"poverty < trump back\" title=\"poverty - trump back\" />\n";
1125 echo " <img src=\"pics/button/poverty_notrump_button.png\" class=\"button\" ".
1126 "alt=\"poverty <\" title=\"poverty - no trump back\" />\n";
1129 echo " <img src=\"pics/button/poverty_partner_button.png\" class=\"button\" ".
1130 "alt=\"poverty >\" title=\"poverty partner\" />\n";
1132 if($sickness=="poverty" || ($RULES['lowtrump']=='poverty' && $sickness=='lowtrump'))
1134 $userhash = DB_get_hash_from_gameid_and_userid($gameid,$user);
1135 $cards = DB_get_all_hand($userhash);
1136 $trumpNR = count_trump($cards,'all');
1138 echo " <img src=\"pics/button/poverty2_trump_button.png\" class=\"button\" ".
1139 "alt=\"poverty2 < trump back\" title=\"poverty2 - trump back\"/>\n";
1141 echo " <img src=\"pics/button/poverty2_notrump_button.png\" class=\"button\" ".
1142 "alt=\"poverty2 <\" title=\"poverty2 - no trump back\" />\n";
1145 echo " <img src=\"pics/button/poverty2_partner_button.png\" class=\"button\" ".
1146 "alt=\"poverty2 >\" title=\"poverty2 partner\" />\n";
1148 if($GT=="wedding" && $party=="re")
1149 if($sickness=="wedding")
1150 echo " <img src=\"pics/button/wedding_button.png\" class=\"button\" alt=\"wedding\" title=\"wedding\" />\n";
1152 echo " <img src=\"pics/button/wedding_partner_button.png\" class=\"button\" ".
1153 "alt=\"wedding partner\" title=\"wedding partner\" />\n";
1155 if( (strpos($GT,"solo")!==false) && $party=="re")
1157 if(strpos($GT,"queen")!==false)
1158 echo " <img src=\"pics/button/queensolo_button.png\" class=\"button\" alt=\"$GT\" title=\"Queen solo\" />\n";
1159 else if(strpos($GT,"jack")!==false)
1160 echo " <img src=\"pics/button/jacksolo_button.png\" class=\"button\" alt=\"$GT\" title=\"Jack solo\" />\n";
1161 else if(strpos($GT,"club")!==false)
1162 echo " <img src=\"pics/button/clubsolo_button.png\" class=\"button\" alt=\"$GT\" title=\"Club solo\" />\n";
1163 else if(strpos($GT,"spade")!==false)
1164 echo " <img src=\"pics/button/spadesolo_button.png\" class=\"button\" alt=\"$GT\" title=\"Spade solo\" />\n";
1165 else if(strpos($GT,"heart")!==false)
1166 echo " <img src=\"pics/button/heartsolo_button.png\" class=\"button\" alt=\"$GT\" title=\"Heart solo\" />\n";
1167 else if(strpos($GT,"trumpless")!==false)
1168 echo " <img src=\"pics/button/notrumpsolo_button.png\" class=\"button\" alt=\"$GT\" title=\"Trumpless solo\" />\n";
1169 else if(strpos($GT,"trump")!==false)
1170 echo " <img src=\"pics/button/trumpsolo_button.png\" class=\"button\" alt=\"$GT\" title=\"Trump solo\" />\n";
1173 /* add point calls */
1177 echo " <img src=\"pics/button/re_button.png\" class=\"button\" alt=\"re\" title=\"Re\" />\n";
1179 echo " <img src=\"pics/button/contra_button.png\" class=\"button\" alt=\"contra\" title=\"Contra\" />\n";
1183 echo " <img src=\"pics/button/0_button.png\" class=\"button\" alt=\"0\" title=\"Call 0\" />\n";
1186 echo " <img src=\"pics/button/30_button.png\" class=\"button\" alt=\"30\" title=\"Call 30\" />\n";
1189 echo " <img src=\"pics/button/60_button.png\" class=\"button\" alt=\"60\" title=\"Call 60\" />\n";
1192 echo " <img src=\"pics/button/90_button.png\" class=\"button\" alt=\"90\" title=\"Call 90\" />\n";
1197 echo " <img src=\"pics/button/time-info.png\" class=\"button\" alt=\"time info\" ".
1198 "title=\"local time: ".date("Y-m-d H:i:s",$timenow). " ".
1199 "last login: ".date("Y-m-d H:i:s",$lastlogin)."\" />";
1201 echo " <br /><span class=\"numberoftricks\">";
1202 /* show how many tricks the person made */
1206 echo "#tricks 0"; break;
1208 echo "#tricks 1"; break;
1212 echo "#tricks few"; break;
1214 echo "#tricks many"; break;
1221 function display_user_menu($id, $skiphash=NULL)
1223 global $WIKI,$INDEX;
1226 $result = DB_query("SELECT Hand.hash,Hand.game_id,Game.player from Hand".
1227 " LEFT JOIN Game On Hand.game_id=Game.id".
1228 " WHERE Hand.user_id='$id'".
1229 " AND Hand.hash!='$skiphash'".
1230 " AND ( Game.player='$id' OR ISNULL(Game.player) )".
1231 " AND ( Game.status='pre' OR Game.status='play' )".
1232 " ORDER BY Game.session" );
1234 $result = DB_query("SELECT Hand.hash,Hand.game_id,Game.player from Hand".
1235 " LEFT JOIN Game On Hand.game_id=Game.id".
1236 " WHERE Hand.user_id='$id'".
1237 " AND ( Game.player='$id' OR ISNULL(Game.player) )".
1238 " AND ( Game.status='pre' OR Game.status='play' )".
1239 " ORDER BY Game.session" );
1242 while( $r = DB_fetch_array($result))
1246 echo "\n<div class=\"usermenu\">\n ";
1247 echo _('It\'s your turn in these games').":\n";
1255 echo " <a href=\"".$INDEX."?action=game&me=".$r[0].
1256 "\"> ".DB_format_gameid($r[1])." </a>\n";
1269 function generate_score_table($session)
1271 /* returns an array with N entries
1272 * $score[$i]["gameid"] = gameid
1273 * $score[$i]["players"] = array (id=>total points)
1274 * $score[$i]["points"] = points for this game
1275 * $score[$i]["solo"] = 1 or 0
1280 /* get all ids, scores and gametypes */
1281 $gameids = DB_get_gameids_of_finished_games_by_session($session);
1283 if($gameids == NULL)
1287 $player_party = array();
1289 /* get player id from the first game */
1290 $result = DB_query("SELECT user_id from Hand".
1291 " WHERE Hand.game_id=".$gameids[0][0]);
1292 while( $r = DB_fetch_array($result))
1295 /* get party of players for each game in the session */
1296 foreach($player as $id=>$points)
1297 $player_party[$id]=DB_get_party_by_session_and_userid($session,$id);
1299 /* get points and generate table */
1300 foreach($gameids as $gameid)
1302 $re_score = $gameid[1];
1303 $gametype = $gameid[2];
1304 foreach($player as $id=>$points)
1306 $party = $player_party[$id][$i][0];
1308 if($gametype=="solo")
1309 $player[$id] += 3*$re_score;
1311 $player[$id] += $re_score;
1312 else if ($party == "contra")
1313 $player[$id] -= $re_score;
1315 $score[$i]['gameid'] = $gameid[0] ;
1316 $score[$i]['players'] = $player;
1317 $score[$i]['points'] = abs($re_score);
1318 $score[$i]['solo'] = ($gametype=="solo");
1326 function generate_global_score_table()
1330 /* get all ids, scores and gametypes */
1331 $gameids = DB_get_gameids_of_finished_games_by_session(0);
1333 if($gameids == NULL)
1337 /* get player id, names... from the User table */
1338 $result = DB_query('SELECT User.id, User.fullname FROM User');
1340 /* save information in an array */
1341 while( $r = DB_fetch_array($result))
1342 $player[$r[0]] = array('name'=> $r[1], 'points' => 0 , 'nr' => 0, 'active' => 0,
1343 'response' => 0 , 'solo' => 0, 'soloavg' => 0);
1345 /* get points and generate table */
1346 foreach($gameids as $gameid)
1348 $re_score = $gameid[1];
1349 $gametype = $gameid[2];
1351 /* get players involved in this game */
1352 $result = DB_query('SELECT user_id FROM Hand WHERE game_id='.DB_quote_smart($gameid[0]));
1353 while($r = DB_fetch_array($result))
1356 $party = DB_get_party_by_gameid_and_userid($gameid[0],$id);
1358 if($gametype=='solo')
1359 $player[$id]['points'] += 3*$re_score;
1361 $player[$id]['points'] += $re_score;
1362 else if ($party == 'contra')
1363 $player[$id]['points'] -= $re_score;
1365 $player[$id]['nr']+=1;
1369 /* add number of active games */
1370 $result = DB_query_array_all("SELECT user_id, COUNT(*) as c " .
1372 " LEFT JOIN Game ON Game.id=game_id".
1373 " WHERE Game.status IN ('pre','play')".
1374 " GROUP BY user_id");
1376 foreach($result as $res)
1378 $player[$res[0]]['active'] = $res[1];
1381 /* response time of users*/
1382 $result = DB_query_array_all("SELECT user_id,".
1383 "IFNULL(AVG(if(P1.sequence in (2,3,4),".
1384 "-timestampdiff(MINUTE,mod_date,(select mod_date from Play P2 where P1.trick_id=P2.trick_id and P2.sequence=P1.sequence-1)),NULL )),1e9) as a ".
1386 "LEFT JOIN Hand_Card ON P1.hand_card_id=Hand_Card.id ".
1387 "LEFT JOIN Hand ON Hand.id=Hand_Card.hand_id ".
1388 "GROUP BY user_id ");
1390 foreach($result as $res)
1392 $player[$res[0]]['response'] = $res[1];
1396 $result = DB_query_array_all("SELECT user_id as uid,".
1398 " COUNT(*)/(SELECT COUNT(*) FROM Hand LEFT JOIN User ON User.id=Hand.user_id WHERE User.id=uid) as c ".
1400 " LEFT JOIN Hand ON Hand.position=startplayer AND Game.id=Hand.game_id ".
1401 " WHERE type='solo' AND Game.status='gameover' ".
1402 " GROUP BY user_id ");
1404 foreach($result as $res)
1406 $player[$res[0]]['solo'] = $res[1];
1407 $player[$res[0]]['soloavg'] = $res[2];
1411 /* sort everything nicely */
1415 if($a['nr']==0) return 1;
1416 if($b['nr']==0) return 1;
1418 $a=$a['points']/$a['nr'];
1419 $b=$b['points']/$b['nr'];
1423 return ($a > $b) ? -1 : 1;
1425 usort($player,'cmp');
1428 foreach($player as $pl)
1430 /* limit to players with at least 10 games */
1432 $return[] = array( $pl['name'], round($pl['points']/$pl['nr'],3), $pl['points'],$pl['nr'],$pl['active'],
1433 $pl['response'],$pl['solo'],$pl['soloavg']);
1439 function format_score_table_ascii($score)
1442 if(sizeof($score)==0)
1445 /* truncate table if we have too many games */
1446 $max = sizeof($score);
1447 if($max>6) $output.=" (table truncated to last 6 games)\n";
1450 foreach($score[0]['players'] as $id=>$points)
1452 $name = DB_get_name('userid',$id); /*TODO*/
1453 $output.= " ".substr($name,0,2)." |";
1456 $output.= "------+------+------+------+------+\n";
1458 /* output score for each game */
1460 foreach($score as $game)
1463 if($i-1<$max-6) continue;
1465 foreach($game['players'] as $id=>$points)
1466 $output.=str_pad($points,6," ",STR_PAD_LEFT)."|";
1467 $output.=str_pad($game['points'],4," ",STR_PAD_LEFT);
1469 /* check for solo */
1480 function format_score_table_html($score,$userid)
1484 if(sizeof($score)==0)
1487 $output = "<div class=\"scoretable\">\n<table class=\"score\">\n";
1491 $header.= " <thead>\n <tr>\n";
1492 $header.= " <th> No </th>";
1493 foreach($score[0]['players'] as $id=>$points)
1495 $name = DB_get_name('userid',$id); /*TODO*/
1496 $header.= "<th> ".substr($name,0,2)." </th>";
1498 $header.="<th>P</th>\n </tr>\n </thead>\n";
1500 /* use the same as footer */
1502 $footer.= " <tfoot>\n <tr>\n";
1503 $footer.= " <td> No </td>";
1504 foreach($score[0]['players'] as $id=>$points)
1506 $name = DB_get_name('userid',$id); /*TODO*/
1507 $footer.= "<td> ".substr($name,0,2)." </td>";
1509 $footer.="<td>P</td>\n </tr>\n </tfoot>\n";
1513 $body.= " <tbody>\n";
1515 foreach($score as $game)
1519 $userhash = DB_get_hash_from_gameid_and_userid($game['gameid'],$userid);
1520 /* create link to old games only if you are logged in and its your game*/
1521 if(isset($_SESSION['id']) && $_SESSION['id']==$userid)
1522 $body.=" <td> <a href=\"".$INDEX."?action=game&me=".$userhash."\">$i</a></td>";
1524 $body.=" <td>$i</td>";
1526 foreach($game['players'] as $id=>$points)
1527 $body.="<td>".$points."</td>";
1528 $body.="<td>".$game['points'];
1530 /* check for solo */
1533 $body.="</td></tr>\n";
1541 $output.=" </tbody>\n</table>\n</div>\n";
1546 function createCache($content, $cacheFile)
1548 $fp = fopen($cacheFile,"w");
1551 fwrite($fp,$content);
1555 echo "WARNING: couldn't create cache file";
1560 function getCache($cacheFile, $expireTime)
1562 if( file_exists($cacheFile) &&
1563 filemtime($cacheFile )>( time() - $expireTime ) )
1565 return file_get_contents($cacheFile);
1571 function check_vacation($userid)
1573 /* get start date */
1574 $result = DB_query_array("SELECT value FROM User_Prefs".
1575 " WHERE user_id='$userid' AND pref_key='vacation start'" );
1577 $start = $result[0];
1582 $result = DB_query_array("SELECT value FROM User_Prefs".
1583 " WHERE user_id='$userid' AND pref_key='vacation stop'" );
1590 $result = DB_query_array("SELECT value FROM User_Prefs".
1591 " WHERE user_id='$userid' AND pref_key='vacation comment'" );
1593 $comment = $result[0];
1597 /* check if user is on vacation. TODO: use user's timezone */
1598 if( (time() - strtotime($start) >0) &&
1599 (strtotime($stop) - time() >0))
1600 return array ($start,$stop,$comment);
1605 function cancel_game($why,$gameid)
1607 $gameid = DB_quote_smart($gameid);
1609 /* update the game table */
1613 DB_query("UPDATE Game SET status='cancel-timedout' WHERE id=$gameid");
1616 DB_query("UPDATE Game SET status='cancel-nines' WHERE id=$gameid");
1619 DB_query("UPDATE Game SET status='cancel-trump' WHERE id=$gameid");
1622 DB_query("UPDATE Game SET status='cancel-noplay' WHERE id=$gameid");
1625 DB_query("UPDATE Game SET status='cancel-lowtrump' WHERE id=$gameid");
1628 /* set each player to gameover */
1629 $result = DB_query("SELECT id FROM Hand WHERE game_id=".DB_quote_smart($gameid));
1630 while($r = DB_fetch_array($result))
1633 DB_query("UPDATE Hand SET status='gameover' WHERE id=".DB_quote_smart($id));
1639 function get_user_token($userid)
1644 $date = DB_get_user_creation_date($userid);
1645 $name = DB_get_name('userid',$userid);
1648 $token = md5("token".$name.$date);
1653 function verify_password($email, $password)
1655 /* verify password, if old password has length 32 assume it's an old md5, else use new password scheme */
1656 /* return 0 if verified, else return error code
1657 * 1 can't find email
1658 * 2 can't calculate correct hash
1662 /* check user email by getting his id */
1663 $userid = DB_get_userid('email',$email);
1667 /* test for temporary passwords, only valid for one date (tested in the DB) */
1668 $tmppasswd = md5($password);
1669 if(DB_check_recovery_passwords($tmppasswd,$email))
1672 /* get saved password */
1673 $existingpassword = DB_get_passwd_by_userid($userid);
1675 if(strlen($existingpassword)==32) /* old password type */
1677 if ($existingpassword == md5($password))
1679 /* update password to new crypt version */
1680 // create a password hash using the crypt function, need php 5.3 for this
1681 // create and random salt
1682 $salt = substr(str_replace('+', '.', base64_encode(sha1(microtime(true), true))), 0, 22);
1683 // hash incoming password using 12 rounds of blowfish
1684 $hash = crypt($password, '$2y$12$' . $salt);
1685 if(strlen($hash)>13)
1686 DB_query("UPDATE User SET password='$hash' where id='$userid'");
1695 if ($existingpassword == crypt($password, $existingpassword))
1702 /* language functions */
1703 function detectlanguage()
1705 /* read out browser's prefered language, taken from php-manual*/
1706 $langcode = explode(";", $_SERVER['HTTP_ACCEPT_LANGUAGE']);
1707 $langcode = explode(",", $langcode['0']);
1708 return $langcode['0'];
1711 function set_language($language)
1716 putenv("LC_ALL=de_DE");
1717 setlocale(LC_ALL, "de_DE");
1718 // Specify location of translation tables
1719 bindtextdomain("edoko", "./locale");
1721 textdomain("edoko");