#!/usr/bin/perl
# ================================================================================
# $Rev: 263 $ $URL: svn://localhost/PlayChess/trunk/cgi/prv-challenge.cgi $
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Author: $Author: epts $
# Modified: $Date: 2006-11-26 18:28:58 +0100 (So, 26 Nov 2006) $
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Copyright at playchess.de - all rights reserved
# ================================================================================
use lib "../cgi-bin";
use CGI qw( :standard );
use CGI::Carp qw(fatalsToBrowser);
use PCSession;
use Template;
use Util;
use DB_Tour;
use MyDbi;
local $cgi = CGI->new();
local $sobj = PCSession->new( $cgi );
local $name = $sobj->getValue( 'name' );
local $spid = $sobj->getValue( 'pid' );
local $action = $cgi->param( 'action' ) || '';
local $mode = $cgi->param( 'mode' ) || '';
local $pname = $cgi->param( 'pname' );
local $clock_min = 0+$cgi->param( 'clock_min' ) || 5;
local $clock_inc = 0+$cgi->param( 'clock_inc' ) || 24;
local $clock_max = 0+$cgi->param( 'clock_max' ) || 30;
local $color = $cgi->param( 'color' );
local $usecomp = $cgi->param( 'usecomp' ) || 'no';
local $publish = $cgi->param( 'publish' );
local $pcr_min = 0+$cgi->param( 'pcr_min' );
local $pcr_max = 0+$cgi->param( 'pcr_max' );
local $cid = $cgi->param( 'cid' );
local $config = getConfig();
local $dbh;
# print "$action
\n";
# Page requires login
# ~~~~~~~~~~~~~~~~~~~
$sobj->assertLogged();
# Page member only ?
# ~~~~~~~~~~~~~~~~~~
$sobj->assertMember() if( $mode eq 'friend' );
# a challenge has been issued
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~
if( $action eq 'challenge' )
{
# action requires membership
# ~~~~~~~~~~~~~~~~~~~~~~~~~~
# $sobj->assertMember();
# check input data
# ~~~~~~~~~~~~~~~~
ShowPage( 'challenge', 'Player name is missing, enter '*' to challenge anybody' ) unless($pname);
ShowPage( 'challenge', 'You cannot challenge yourself' ) if($pname eq $name);
ShowPage( 'challenge', 'Initial time out of range' ) unless($clock_min>=1 && $clock_min<=60);
ShowPage( 'challenge', 'Increment out of range' ) unless($clock_inc>=0 && $clock_inc<=120);
ShowPage( 'challenge', 'Increment must be integer' ) if($clock_inc!=int($clock_inc));
ShowPage( 'challenge', 'Max clock must be larger than initial time' )
if($clock_max>0 && $clock_max<$clock_min);
# Following actions require database access
#------------------------------------------
$dbh = MyDbi::dbiConnect() or exit(1);
# Read the game status of this player
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
my $result = DB_Tour::readGameLimit( $spid );
# Membership dependent parameters
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
($GAME_OFFSET, $GAME_LIMIT) = $sobj->getGamelimitParms();
$plannedgames = $result->{planned};
$runninggames = $result->{running};
$validgames = $result->{valid};
$plannedgames = $result->{planned};
$plannedArray = $result->{plannedArray};
$allowedgames = $GAME_OFFSET + $validgames;
$allowedgames = $GAME_LIMIT if $allowedgames > $GAME_LIMIT;
$newGames = $allowedgames-($plannedgames+$runninggames);
$newGames = 0 if $newGames < 0;
# check game limit of this player
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
ShowPage( 'challenge', 'Your game limit is reached' ) if($newGames<=0);
# print "RG = $runninggames
\n";
# print "PG = $plannedgames
\n";
# print "VG = $validgames
\n";
# print "GA = $allowedgames
\n";
# print "new allowed=$newGames
\n";
# exit(0);
my ($gpid, $nopriv);
unless( $pname eq '*' )
{
# does challenged player exist and accept challenges?
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
my $stmt = "
select p.pid, o.value
from tbl_player p
left outer join tbl_options o on p.pid=o.pid
and o.choice = 'nopriv'
where p.name = ?
";
($gpid, $nopriv) = @{ MyDbi::getRow( $stmt, $pname ) };
# Player is not possible
# ~~~~~~~~~~~~~~~~~~~~~~
ShowPage( 'challenge', "Player '$pname' does not exist" ) unless($gpid);
ShowPage( 'challenge', "Player '$pname' does not accept challenges" ) if($nopriv);
}
# Everything OK => issue challenge
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
$stmt = '
insert into tbl_challenge
(hpid,gpid,color,ctime,clockmin,clockinc,clockmax,publish,usecomp,pcr_min,pcr_max)
values(?,?,?,?,?,?,?,?,?,?,?)
';
# print join( "
\n", $rc, $stmt, $spid, $gpid, $color, time(), $clock_min, $clock_inc, $clock_max );
$rc = MyDbi::doStmt( $stmt, $spid, 0+$gpid, $color, time(),
$clock_min, $clock_inc, $clock_max, $publish, $usecomp, $pcr_min, $pcr_max );
# print join( "
\n", $rc, $stmt, $spid, $gpid, $color, time(), $clock_min, $clock_inc, $clock_max );
ShowPage( 'challenge', "Error: challenge could not be issued ($rc)" ) unless($rc==1);
# public challenge: show directory of challenges
$sobj->redirectKeepSession( 'prv-publist.cgi', 0 ) if( $pname eq '*' );
# private challenge: show dialog with success message
ShowPage( 'challenge', "Player '$pname' has been challenged" );
# ShowPage( 'challenge', "All players have been challenged" ) if $pname eq '*';
# ShowPage( 'challenge' );
}
# a challenge is accepted
# ~~~~~~~~~~~~~~~~~~~~~~~
elsif( $action eq 'accept' )
{
# Following actions require database access
#------------------------------------------
$dbh = MyDbi::dbiConnect() or exit(1);
# Read the game status of this player
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
my $result = DB_Tour::readGameLimit( $spid );
# Membership dependent parameters
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
($GAME_OFFSET, $GAME_LIMIT) = $sobj->getGamelimitParms();
$plannedgames = $result->{planned};
$runninggames = $result->{running};
$validgames = $result->{valid};
$plannedgames = $result->{planned};
$plannedArray = $result->{plannedArray};
$allowedgames = $GAME_OFFSET + $validgames;
$allowedgames = $GAME_LIMIT if $allowedgames > $GAME_LIMIT;
$newGames = $allowedgames-($plannedgames+$runninggames-1);
$newGames = 0 if $newGames < 0;
# check game limit of this player
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
ShowPage( 'accept', "Your game limit ($allowedgames) is reached" ) if($newGames<=0);
# Load challenge
# ~~~~~~~~~~~~~~
$stmt = "
select
c.hpid, c.gpid, c.ctime, c.clockmin, c.clockinc, c.clockmax,
c.color, c.publish, c.state, c.pcr_min, c.pcr_max, c.usecomp
from tbl_challenge c
where c.cid=?
";
my( $hpid, $gpid, $ctime, $cmin, $cinc, $cmax, $color, $publish, $state, $pcr_min, $pcr_max, $usecomp ) =
@{ MyDbi::getRow( $stmt, $cid ) };
die( "Challenge $cid not found" ) unless $hpid;
# check if challenge can be accepted
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
ShowPage( 'accept', "Challenge already taken by you." ) if($state eq 'accepted' && gpid==spid);
ShowPage( 'accept', "Challenge already taken by another player." ) if($state eq 'accepted');
ShowPage( 'accept', "Challenge withdrawn by player." ) if($state ne 'pending');
# check if rating is in range
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~
my $pcr = ($usecomp eq 'yes') ? $sobj->getValue('aclelo') : $sobj->getValue('hclelo');
ShowPage( 'accept', "Your rating $pcr is not in the range ($pcr_min-$pcr_max)." )
if( $pcr_min && $pcr<$pcr_min || $pcr_max && $pcr>$pcr_max );
# anonymous challenge
$gpid = $spid unless( $gpid > 0 );
ShowPage( 'accept', 'You cannot challenge yourself' ) if($hpid == $gpid);
ShowPage( 'accept', 'You are not the challenged player' ) if($gpid>0 and $gpid != $spid);
# Randomly select colors if neccessary
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# print "1: color=$color
\n";
$color = 'w' if($color eq 'White');
$color = 'b' if($color eq 'Black');
$color = (rand() > 0.5) ? 'w' : 'b' if($color eq 'Random');
# Create new private game
#------------------------
my $clock = $cmin * 86400;
$stmt = "
insert into tbl_game
(tid,bd,currpos,tomove,castling,epfield,fullmove,name,lastmove,result,publish,wpid,bpid,wclock,bclock)
values (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)
";
$sth_g = $dbh->prepare( $stmt );
$stmt = "
insert into tbl_player_game
(color,gid,pid,clock)
values (?,?,?,?)
";
$sth_pg = $dbh->prepare( $stmt );
my $pos = 'rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR';
if( $color eq 'w' )
{
$wpid = $hpid;
$bpid = $gpid;
}
else
{
$wpid = $gpid;
$bpid = $hpid;
}
# create new game (gid is automatically created)
#-----------------------------------------------
$gamename = sprintf( "PRV-%06d", $cid );
$sth_g->execute( 0, $cid, $pos, 'w', 'KQkq', '-', 1, $gamename, time(), '', $publish, $wpid, $bpid, $clock, $clock );
$gid = $sth_g->{mysql_insertid};
# connect both players to the new game
#-------------------------------------
$rv = $sth_pg->execute( $color, $gid, $hpid, $clock );
$rv = $sth_pg->execute( ($color eq 'w' ? 'b' : 'w'), $gid, $gpid, $clock );
# mark challenge as accepted
# ~~~~~~~~~~~~~~~~~~~~~~~~~~
$stmt = "update tbl_challenge set state='accepted', gpid=? where cid=?";
$rc = MyDbi::doStmt( $stmt, $gpid, $cid );
# Notify old players about new player
#------------------------------------
#$game->Message( 'startgame' );
ShowPage( 'accept' );
}
# a challenge has been cancelled
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
elsif( $action eq 'cancel' )
{
# Following actions require database access
#------------------------------------------
$dbh = MyDbi::dbiConnect() or exit(1);
# mark challenge as declined
# ~~~~~~~~~~~~~~~~~~~~~~~~~~
$stmt = "update tbl_challenge set state='done' where cid=? and hpid=?";
$rc = MyDbi::doStmt( $stmt, $cid, $spid );
# Notify old players about new player
#------------------------------------
#$game->Message( 'startgame' );
$sobj->redirectKeepSession( '/prv-publist.cgi' );
ShowPage( 'decline' );
}
# a challenge has been declined
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
elsif( $action eq 'decline' )
{
# Following actions require database access
#------------------------------------------
$dbh = MyDbi::dbiConnect() or exit(1);
# mark challenge as declined
# ~~~~~~~~~~~~~~~~~~~~~~~~~~
$stmt = "update tbl_challenge set state='declined' where cid=?";
$rc = MyDbi::doStmt( $stmt, $cid );
# Notify old players about new player
#------------------------------------
#$game->Message( 'startgame' );
ShowPage( 'decline' );
}
# default action
# ~~~~~~~~~~~~~~
else
{
ShowPage( "challenge" );
}
#------------------------------------
sub ShowPage
#------------------------------------
{
# End of data retrieval. Now generating output
#---------------------------------------------
$dbh->disconnect() if($dbh);
my( $action, $errstr ) = @_;
my $tplfile = ($action eq 'challenge' && $mode eq 'friend') ? 'prv-friend.tpl' : "prv-$action.tpl";
my $tpl = Template->new( $tplfile );
my $isengine = $sobj->getValue('isengine');
my $mypcr = $sobj->getValue( $isengine ? 'cclelo' : 'hclelo' );
my $mypcr_min = 200 * int( ($mypcr - 200)/200 );
my $mypcr_max = 200 * int( ($mypcr + 400)/200 );
# print "ie=$isengine
\n";
$sobj->addMakros( $tpl );
$tpl->addMakro( "ERR", $errstr );
$tpl->addMakro( "PNAME", $pname );
$tpl->addMakro( "GAME", $gamename );
$tpl->addMakro( "CLOCK_MIN", $clock_min );
$tpl->addMakro( "CLOCK_INC", $clock_inc );
$tpl->addMakro( "CLOCK_MAX", $clock_max );
$tpl->addMakro( "PCR_MIN", $pcr_min || $mypcr_min );
$tpl->addMakro( "PCR_MAX", $pcr_max || $mypcr_max );
$tpl->addMakro( "HUMAN", !$isengine);
$tpl->addMakro( "mode", $mode );
$tpl->addRadioMakro( "usecomp", $usecomp );
$tpl->addSelectMakro( "pcr_min", $pcr_min || $mypcr_min );
$tpl->addSelectMakro( "pcr_max", $pcr_max || $mypcr_max );
$tpl->addSelectMakro( "color", $color );
$tpl->addSelectMakro( "publish", $publish );
# $tpl->addRadioMakro( "usecomp", ($isengine) ? 'yes' : 'no' );
print $tpl->Expand( $sobj );
if(0)
{
my @attribs = keys %$sobj;
my $attr;
foreach $attr (@attribs)
{
printf "%20s = %-20s
\n", $attr, $sobj->getValue( $attr );
}
}
exit(0);
}