DIR : /home/kozerus/public_html/dgs/include/classlib_user.php
/home/kozerus/public_html/dgs/include
<?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';
/* Author: Jens-Uwe Gaspar */
/*!
* \file classlib_user.php
*
* \brief Functions to represent a DGS user: tables Players
*/
/*!
* \class User
*
* \brief Convenience Class to manage some parts of Players-table.
* Used as container to hold data to be able to create user-reference.
*/
class User
{
public $ID;
public $Name;
public $Handle;
public $Type;
public $Lastaccess;
public $Country;
public $Rating; // Players.Rating2
public $RatingStatus;
public $GamesRated;
public $GamesFinished;
public $AdminOptions;
public $AdminLevel;
// other DB-fields
public $urow = null;
/*! \brief Constructs a User with specified args. */
public function __construct( $id=0, $name='', $handle='', $type=0, $lastaccess=0, $country='', $rating=NULL,
$rating_status=RATING_NONE, $games_rated=0, $games_finished=0, $admin_opts=0,
$admin_level=0 )
{
$this->ID = (int)$id;
$this->Name = (string)$name;
$this->Handle = (string)$handle;
$this->Type = (int)$type;
$this->Lastaccess = (int)$lastaccess;
$this->Country = (string)$country;
$this->setRating( $rating );
$this->RatingStatus = $rating_status;
$this->GamesRated = (int)$games_rated;
$this->GamesFinished = (int)$games_finished;
$this->AdminOptions = (int)$admin_opts;
$this->AdminLevel = (int)$admin_level;
}//__construct
public function setRating( $rating )
{
if ( is_null($rating) || !is_numeric($rating) || abs($rating) >= OUT_OF_RATING )
$this->Rating = NO_RATING;
else
$this->Rating = limit( (double)$rating, MIN_RATING, OUT_OF_RATING-1, NO_RATING );
}
/*! \brief Returns true, if user set (id != 0). */
public function is_set()
{
return ( is_numeric($this->ID) && $this->ID > 0 );
}
/*! \brief Returns true, if user has set and valid rating. */
public function hasRating( $check_rating_status=true )
{
if ( $check_rating_status )
{
if ( $this->RatingStatus == RATING_INIT || $this->RatingStatus == RATING_RATED ) // user has rating
return ( abs($this->Rating) < OUT_OF_RATING ); // valid rating
else // user not rated ( RatingStatus == RATING_NONE )
return false;
}
else
return ( abs($this->Rating) < OUT_OF_RATING ); // valid rating
}//hasRating
/*!
* \brief Returns true, if user-rating falls inbetween given rating range (+/- 50%).
* \param $fix true = check users rating in range ($min <= rating < $max);
* false = check in range ($min-50 <= rating < $max+50)
*/
public function matchRating( $min, $max, $fix=false )
{
if ( !$fix )
{
$min = limit( $min - 50, MIN_RATING, OUT_OF_RATING-1, $min );
$max = limit( $max + 50, MIN_RATING, OUT_OF_RATING-1, $max );
}
return ( $this->Rating >= $min ) && ( $this->Rating < $max );
}//matchRating
/*! \brief Returns string-representation of this object (for debugging purposes). */
public function to_string()
{
return "User(ID={$this->ID}):"
. " Name=[{$this->Name}]"
. ", Handle=[{$this->Handle}]"
. sprintf( ", Type=[0x%x]", $this->Type )
. ", Lastaccess=[{$this->Lastaccess}]"
. ", Country=[{$this->Country}]"
. ", Rating=[{$this->Rating}]"
. ", RatingStatus=[{$this->RatingStatus}]"
. ", GamesRated=[{$this->GamesRated}]"
. ", GamesFinished=[{$this->GamesFinished}]"
. sprintf( ", AdminOptions=[0x%x]", $this->AdminOptions )
. sprintf( ", AdminLevel=[0x%x]", $this->AdminLevel )
. sprintf( ", urow={%s}", print_r($this->urow, true) )
;
}//to_string
/*! \brief Returns user_reference for user in this object. */
public function user_reference()
{
$name = ( (string)$this->Name != '' ) ? $this->Name : UNKNOWN_VALUE;
$handle = ( (string)$this->Handle != '' ) ? $this->Handle : UNKNOWN_VALUE;
return user_reference( REF_LINK, 1, '', $this->ID, $name, $handle );
}//user_reference
// ------------ static functions ----------------------------
/*! \brief Returns db-fields to be used for query of User-object. */
public static function build_query_sql()
{
// Players: ID,Name,Handle,Type,Lastaccess,LastQuickAccess,LastMove,Registerdate,Country,
// Rating2,RatingStatus,RatedGames,Finished,AdminOptions,Adminlevel
$qsql = new QuerySQL();
$qsql->add_part( SQLP_FIELDS,
'P.*',
'UNIX_TIMESTAMP(P.Lastaccess) AS X_Lastaccess',
'UNIX_TIMESTAMP(P.LastQuickAccess) AS X_LastQuickAccess',
'UNIX_TIMESTAMP(P.LastMove) AS X_LastMove',
'UNIX_TIMESTAMP(P.Registerdate) AS X_Registerdate' );
$qsql->add_part( SQLP_FROM, 'Players AS P' );
return $qsql;
}//build_query_sql
/*! \brief Returns User-object created from specified (db-)row and given table-prefix. */
public static function new_from_row( array $row, $prefix='', $urow_strip_prefix=false )
{
$user = new User(
// expected from Players-table
@$row[$prefix.'ID'],
@$row[$prefix.'Name'],
@$row[$prefix.'Handle'],
@$row[$prefix.'Type'],
@$row[$prefix.'X_Lastaccess'],
@$row[$prefix.'Country'],
@$row[$prefix.'Rating2'],
@$row[$prefix.'RatingStatus'],
@$row[$prefix.'RatedGames'],
@$row[$prefix.'Finished'],
@$row[$prefix.'AdminOptions'],
@$row[$prefix.'Adminlevel']
);
$user->urow = $row;
if ( $urow_strip_prefix && (string)$prefix != '' )
{
$prefixlen = strlen($prefix);
foreach ( $user->urow as $key => $val )
{
if ( strpos($key, $prefix) == 0 )
$user->urow[substr($key, $prefixlen)] = $val;
}
}
return $user;
}//new_from_row
/*! \brief Constructs a User for forum-users. */
public static function newForumUser( $id=0, $name='', $handle='', $admin_level=0, $rating=null )
{
$user = new User( $id, $name, $handle );
$user->AdminLevel = (int)$admin_level;
$user->setRating( $rating );
return $user;
}
/*! \brief Loads and returns User-object for given additional query; NULL if nothing found. */
public static function load_user_query( QuerySQL $query, $dbgmsg = null )
{
$qsql = self::build_query_sql();
$qsql->merge( $query );
$qsql->add_part( SQLP_LIMIT, '1' );
if ( is_null($dbgmsg) )
$dbgmsg = "User:load_user_query()";
$row = mysql_single_fetch( $dbgmsg, $qsql->get_select() );
return ($row) ? self::new_from_row( $row ) : null;
}//load_user_query
/*! \brief Loads and returns User-object for given user-ID; NULL if nothing found. */
public static function load_user( $uid )
{
$result = NULL;
if ( is_numeric($uid) && $uid > 0 )
{
$query_part = new QuerySQL( SQLP_WHERE, "P.ID=$uid" );
$result = self::load_user_query( $query_part, "User:load_user($uid)" );
}
return $result;
}//load_user
/*! \brief Loads and returns User-object for given user-Handle; NULL if nothing found. */
public static function load_user_by_handle( $handle )
{
$result = NULL;
if ( (string)$handle != '' )
{
$query_part = new QuerySQL( SQLP_WHERE, sprintf( "P.Handle='%s'", mysql_addslashes($handle) ));
$result = self::load_user_query( $query_part, "User:load_user_by_handle($handle)" );
}
return $result;
}//load_user_by_handle
/*!
* \brief Loads cached version and returns User-object for given user-Handle; NULL if nothing found.
* \see User::load_user_by_handle()
*/
public static function load_cache_user_by_handle( $xdbgmsg, $handle )
{
if ( (string)trim($handle) == '' )
error('invalid_args', "User:load_cache_user_by_handle.miss_handle($handle)");
$player_ref = strtolower($handle);
$dbgmsg = "User:load_cache_user_by_handle($player_ref).$xdbgmsg";
$key = "user_hdl.$player_ref";
$urow = DgsCache::fetch( $dbgmsg, CACHE_GRP_USER_HANDLE, $key );
if ( is_null($urow) )
{
$user = self::load_user_by_handle($handle);
if ( !is_null($user) )
DgsCache::store( $dbgmsg, CACHE_GRP_USER_HANDLE, $key, $user->urow, SECS_PER_HOUR );
}
else
$user = self::new_from_row($urow);
return $user;
}//load_cache_user_by_handle
public static function delete_cache_user_handle( $dbgmsg, $uhandle, $uhandle2=null )
{
DgsCache::delete( $dbgmsg, CACHE_GRP_USER_HANDLE, 'user_hdl.' . strtolower($uhandle) );
if ( !is_null($uhandle2) )
DgsCache::delete( $dbgmsg, CACHE_GRP_USER_HANDLE, 'user_hdl.' . strtolower($uhandle2) );
}
/*! \brief Returns non-null array( uid => { ID/Handle/Name/Rating2/Country => val }, ... ) for given users. */
public static function load_quick_userinfo( array $arr_uid )
{
$out = array();
$size = count($arr_uid);
if ( $size )
{
$users = implode(',', $arr_uid);
$result = db_query( "User.load_quick_userinfo($users)",
"SELECT ID, Handle, Name, Rating2, Country FROM Players WHERE ID IN ($users) LIMIT $size" );
while ( $row = mysql_fetch_assoc($result) )
$out[$row['ID']] = $row;
mysql_free_result($result);
}
return $out;
}//load_quick_userinfo
/*! \brief Calculates hero-ratio of user. */
public static function calculate_hero_ratio( $games_weaker, $games_finished, $rating, $rating_status )
{
return ( $rating_status != RATING_NONE && $rating >= MIN_RATING && $games_finished >= MIN_FIN_GAMES_HERO_AWARD )
? $games_weaker / $games_finished
: 0;
}
/*!
* \brief Returns number of games with weaker players required to reach next higher hero-level; 0 if end reached.
* \param $hero_ratio 0..1
* \param $cnt_finished number of finished games
* \param $cnt_weaker number of finished games with weaker players
* \return 0 = max hero-level reached; -1 = rating needed and min. 20 finished games
* else needed game-count with weaker players to reach next hero-level (>0 with rating, <0 miss rating)
*/
public static function determine_games_next_hero_level( $hero_ratio, $cnt_finished, $cnt_weaker, $rating_status )
{
static $ARR_NEXT_HERO_LEVEL = array( 0 => HERO_BRONZE, 1 => HERO_SILVER, 2 => HERO_GOLDEN );
if ( $rating_status != RATING_RATED || $cnt_finished < MIN_FIN_GAMES_HERO_AWARD )
return -1;
$hero_level = self::determine_hero_badge( $hero_ratio );
if ( $hero_level == 3 )
return 0;
$calc_hero_ratio = $ARR_NEXT_HERO_LEVEL[$hero_level] / 100;
return round( ($calc_hero_ratio * $cnt_finished - $cnt_weaker) / ( 1 - $calc_hero_ratio) + 0.5 );
}//determine_games_next_hero_level
/*! \brief Calculated hero-badge value-representation for hero-ratio: 0=none, 1=bronze, 2=silver, 3=gold. */
public static function determine_hero_badge( $hero_ratio )
{
$chk_hero_ratio = 100 * $hero_ratio;
if ( $chk_hero_ratio >= HERO_GOLDEN )
return 3;
elseif ( $chk_hero_ratio >= HERO_SILVER )
return 2;
elseif ( $chk_hero_ratio >= HERO_BRONZE )
return 1;
else
return 0;
}//determine_hero_badge
/*!
* \brief Loads GameStats about all games (without MP-games) for pair of players.
* \return map( Running/Finished => count )
*/
public static function load_game_stats_for_users( $dbgmsg, $uid, $oid )
{
static $ARR_NO_RESULT = array( 'Running' => 0, 'Finished' => 0 );
if ( $uid == $oid )
return $ARR_NO_RESULT;
elseif ( $uid > $oid )
swap($uid, $oid);
$row = mysql_single_fetch( $dbgmsg.".User:load_game_stats_for_users($uid,$oid)",
"SELECT Running, Finished FROM GameStats WHERE uid=$uid AND oid=$oid LIMIT 1" );
return ($row) ? $row : $ARR_NO_RESULT;
}//load_game_stats_for_users
/*!
* \brief Loads and calculates different-opponents of all games (without MP-games) for given user.
* \return map( count_diff_opps_all_games|count_all_games|ratio_all_games => value )
*/
public static function load_different_opponents_for_all_games( $dbgmsg, $uid )
{
$row = mysql_single_fetch( $dbgmsg.".User:load_different_opponents_for_all_games($uid)",
"SELECT SUM(Running + Finished) AS X_CNT_ALL_GAMES, COUNT(*) AS X_CNT_DIFF_OPPS_ALL_GAMES " .
"FROM GameStats WHERE (uid=$uid or oid=$uid) AND (Running + Finished > 0)" );
$count_all_games = $count_diff_opps_all_games = $ratio_all_games = 0;
if ( $row )
{
$count_all_games = $row['X_CNT_ALL_GAMES'];
if ( $count_all_games > 0 )
{
$count_diff_opps_all_games = $row['X_CNT_DIFF_OPPS_ALL_GAMES'];
$ratio_all_games = $count_diff_opps_all_games / $count_all_games;
}
}
return array(
'count_diff_opps_all_games' => $count_diff_opps_all_games,
'count_all_games' => $count_all_games,
'ratio_all_games' => $ratio_all_games,
);
}//load_different_opponents_for_all_games
} // end of 'User'
?>
//
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