DIR : /home/kozerus/public_html/dgs/clock_tick.php
/home/kozerus/public_html/dgs
<?php
/*
Dragon Go Server
Copyright (C) 2001- Erik Ouchterlony, Rod Ival, Jens-Uwe Gaspar
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
require_once 'include/std_functions.php';
require_once 'include/rating.php';
require_once 'include/game_functions.php';
require_once 'include/cache_clock.php';
$TheErrors->set_mode(ERROR_MODE_COLLECT);
if ( !$is_down )
{
$tick_diff = floor(SECS_PER_HOUR / TICK_FREQUENCY); // called every 5 minutes (300s)
if ( $chained )
$chained = $tick_diff;
else
connect2mysql();
$tick_diff -= 10;
$max_run_time = $NOW + $tick_diff;
set_time_limit(0); // don't want script-break during "transaction" with multi-db-queries
// Check that ticks are not too frequent
$row = mysql_single_fetch( 'clock_tick.check_frequency',
"SELECT ($NOW-UNIX_TIMESTAMP(Lastchanged)) AS timediff"
." FROM Clock WHERE ID=".CLOCK_CRON_TICK." LIMIT 1" );
if ( !$row )
$TheErrors->dump_exit('clock_tick');
if ( $row['timediff'] < $tick_diff )
$TheErrors->dump_exit('clock_tick');
db_query( 'clock_tick.set_lastchanged',
"UPDATE Clock SET Ticks=1, Lastchanged=FROM_UNIXTIME($NOW) WHERE ID=".CLOCK_CRON_TICK." LIMIT 1" )
or $TheErrors->dump_exit('clock_tick');
// ---------- BEGIN ------------------------------
// Handle game timeouts
if ( !$clocks_stopped )
handle_game_timeouts();
// ---------- END --------------------------------
db_query( 'clock_tick.reset_tick',
"UPDATE Clock SET Ticks=0, Finished=FROM_UNIXTIME(".time().") WHERE ID=".CLOCK_CRON_TICK." LIMIT 1" );
if ( !$chained )
$TheErrors->dump_exit('clock_tick');
}//$is_down
//end main
function handle_game_timeouts()
{
global $NOW, $max_run_time;
// $NOW is time in UTC
$hour = gmdate('G', $NOW);
$day_of_week = gmdate('w', $NOW);
// Increase running clocks
// - NOTE: ClockUsed is the GMT hour for game clocks (GAME_CLOCK=0: std-clock, GAME_WEEKEND_CLOCK: weekend)
$clocks_modified = array( GAME_CLOCK );
if ( $day_of_week > 0 && $day_of_week < 6 )
$clocks_modified[] = GAME_WEEKEND_CLOCK;
$game_clocks_modified = sprintf('Clock.ID IN (%s)', join(',', $clocks_modified));
$clocks_modified[] = CLOCK_TIMELEFT; // clock for remaining-time ordering
db_query( 'clock_tick.increase_clocks',
"UPDATE Clock SET Ticks=Ticks+1, Lastchanged=FROM_UNIXTIME($NOW) "
. "WHERE Clock.ID IN (".join(',', $clocks_modified).") ");
ClockCache::delete_cache_clocks();
// Check if any game has timed out
/* TODO(keep as note) BUG in old & new version:
if maintenance spans more than a whole hour and graces the non-running-clocks,
the time-window has passed to detect time-outs within that hour.
So time-outs are delayed by a full day till the games with the respective clock is checked again!
=> keep Clock.ID>=0 (as safety for clones; else join with Games would be empty anyway
as there is no Clock.ID<0 any more)
=> remove Clock.Lastchanged=$NOW to match all clock-timeouts
*/
/*
In a first approximation, as $has_moved==false (see time_remaining()),
$main>$hours will just produce $main-=$hours which will never
activate $time_is_up and so, will produce nothing here...
So the "find_timeout_games" query may be restricted with:
- given IF(ToMove_ID=Black_ID, Black_Maintime, White_Maintime) AS ToMove_Maintime
- WHERE ToMove_Maintime <= $hours
because $hours is always < $ticks/TICK_FREQUENCY (see ticks_to_hours())
- Clock.ticks is always > Games.LastTicks
- given ((ticks-LastTicks) / TICK_FREQUENCY) AS Upper_Ellapsed
- WHERE ToMove_Maintime < Upper_Ellapsed
which is:
- WHERE IF(ToMove_ID=Black_ID, Black_Maintime, White_Maintime)
< ((Clock.Ticks-Games.LastTicks) / TICK_FREQUENCY)
During a test, this lowered the number of returned rows from 10,960 to 675.
This is a table scan, but indeed reduces the number of affected rows.
*/
$result = db_query( 'clock_tick.find_timeout_games',
"SELECT Games.*, Games.ID as gid, Clock.Ticks as ticks"
." FROM Games"
." INNER JOIN Clock ON Clock.ID=Games.ClockUsed AND ($game_clocks_modified)"
." WHERE Clock.ID >= 0 AND" // older DGS-clones may still have clocks<0
." IF(ToMove_ID=Black_ID, Black_Maintime, White_Maintime) * ".TICK_FREQUENCY." < Clock.Ticks - Games.LastTicks "
." AND Status" . IS_STARTED_GAME
);
/* TODO: The following UPDATE should be optimized, splited in smaller chunk?
use TEMPORARY TABLEs for generated UPDATEs ??? */
while ($row = mysql_fetch_assoc($result))
{
if ( time() > $max_run_time ) break; // stop script if running too long to avoid concurrent runs
extract($row);
//$game_clause (lock) needed. See *** HOT_SECTION *** in GameActionHelper.init_query()
$game_clause = " WHERE ID=$gid AND Status".IS_STARTED_GAME." AND Moves=$Moves LIMIT 1";
$hours = ticks_to_hours($ticks - $LastTicks);
if ( $ToMove_ID == $Black_ID )
{
time_remaining( $hours, $Black_Maintime, $Black_Byotime, $Black_Byoperiods,
$Maintime, $Byotype, $Byotime, $Byoperiods, false);
$time_is_up = ( $Black_Maintime == 0 && $Black_Byotime == 0 );
}
else if ( $ToMove_ID == $White_ID )
{
time_remaining( $hours, $White_Maintime, $White_Byotime, $White_Byoperiods,
$Maintime, $Byotype, $Byotime, $Byoperiods, false);
$time_is_up = ( $White_Maintime == 0 && $White_Byotime == 0 );
}
else
continue;
if ( $time_is_up )
{
//TODO(feature): Delete games with too few moves ??? (if so -> send delete-game-msg)
$score = ( $ToMove_ID == $Black_ID ) ? SCORE_TIME : -SCORE_TIME;
$game_finalizer = new GameFinalizer( ACTBY_CRON, /*cron*/0, $gid, $tid,
$Status, $GameType, $GamePlayers, $Flags, $Black_ID, $White_ID, $Moves, ($Rated != 'N'),
$Black_Start_Rating, $White_Start_Rating );
ta_begin();
{//HOT-section to save game-timeout
// send message to my opponent / all-players / observers about the result
$game_finalizer->finish_game( "clock_tick.time_is_up", /*del*/false, $score, null, '' );
}
ta_end();
}//time-out
}
mysql_free_result($result);
}//handle_game_timeouts
?>
//
koh5_pano
Drag mouse to navigate.
Navigation
- Left/Right Mouse drag: Changes camera heading.
- Up/Sown Mouse drag: Changes camera pitch.
- Scroll wheel: Changes camera field of view.
- I-Key: Displays Info panel with canvas size, image size and FPS.
17.Aug.2010, Martin Wengenmayer