<?php
// ----------------------------------------------------------------------------
//
// ccrotator.class.php - Concurrent Code Rotator class, ver.0.01 (May 17, 2005)
//
// Description:
// This class allows randomly select one of PHP, HTML or JavaScript code
// fragments that share same place on the page. It uses special random number
// generation algorithm which allows to control the frequency and probability
// of appearance per working cycle.
//
// Author:
// Vagharshak Tozalakyan <hide@address.com>
// This module was written by author on his free time.
//
// Warning:
// This class is non commercial, non professional work. It should not have
// unexpected results. However, if any damage is caused by this class the
// author can not be responsible. The use of this class is at the risk of
// the user.
//
// ----------------------------------------------------------------------------
define ( 'FROM_FILE', TRUE );
class CodeRotator
{
var $tracker_file; // The name of a file used to store display counters
var $codes; // Array of code fragments
var $debug_mode; // TRUE if the code runs in debug mode
/*
Description:
Class constructor.
Prototype:
void CodeRotator ( string tracker_file )
Parameters:
tracker_file - The name of a file used to store display counters.
*/
function CodeRotator ( $tracker_file )
{
$this->tracker_file = $tracker_file;
$this->codes = array ( );
$this->debug_mode = FALSE;
// Seed the better random number generator for PHP < 4.2.0
list ( $usec, $sec ) = explode ( ' ', microtime ( ) );
mt_srand ( ( float ) $sec + ( ( float ) $usec * 100000 ) );
}
/*
Description:
Adds a new code fragment.
Prototype:
void AddCode ( string id, string code, int vpc[, bool from_file] )
Parameters:
id - unique identifier of code fragment
code - code fragment or filename of it
vpc - max views number per working cycle
from_file - TRUE if filename specified instead of code
*/
function AddCode ( $id, $code, $vpc, $from_file = FALSE )
{
$this->codes[$id]['code'] = $code;
$this->codes[$id]['vpc'] = abs ( intval ( $vpc ) );
$this->codes[$id]['from_file'] = $from_file;
}
/*
Description:
Selects and shows a code fragment.
Prototype:
void ShowCode ( )
*/
function ShowCode ( )
{
$f = fopen ( $this->tracker_file, 'a+' );
if ( ! $f )
{
trigger_error ( 'Failed to open tracker file!', E_USER_WARNING );
return;
}
flock ( $f, LOCK_EX );
$fsz = filesize ( $this->tracker_file );
$counters = unserialize ( fread ( $f, $fsz + 10 ) );
if ( empty ( $counters ) )
$counters = array ( );
foreach ( $this->codes as $id => $code )
{
if ( ! isset ( $counters[$id] ) )
{
$counters[$id] = 0;
}
}
$tmp = array ( );
foreach ( $counters as $id => $count )
{
if ( $count < $this->codes[$id]['vpc'] )
{
$tmp[$id] = 0;
}
}
if ( count ( $tmp ) == 0 )
{
foreach ( $counters as $id => $count )
{
$counters[$id] = 0;
$tmp[$id] = 0;
}
}
$s = 0;
foreach ( $tmp as $id => $freq )
{
$s += $this->codes[$id]['vpc'];
}
foreach ( $tmp as $id => $freq )
{
$tmp[$id] = ceil ( ( $this->codes[$id]['vpc'] * 100 ) / $s );
}
$rand = mt_rand ( 0, 100 );
$s = 0;
foreach ( $tmp as $id => $freq )
{
$s += $freq;
if ( $rand < $s )
{
$code_id = $id;
break;
}
}
$counters[$code_id]++;
ftruncate ( $f, 0 );
fwrite ( $f, serialize ( $counters ) );
flock ( $f, LOCK_UN );
fclose ( $f );
if ( $this->debug_mode )
{
echo '<table align="center" width="60%" border="0" cellspacing="10" ';
echo 'cellpadding="0" bgcolor="#f0f0ff"><tr><td align="center">';
echo '<b>Rough probability:</b><br />';
foreach ( $tmp as $id => $freq )
{
echo "$id = $freq% <br />";
}
echo '<br /><b>Counters:</b><br />';
foreach ( $counters as $id => $count )
{
echo "$id = $count <br />";
}
echo '</td></tr></table>';
}
if ( $this->codes[$code_id]['from_file'] == TRUE )
{
include $this->codes[$code_id]['code'];
}
else
{
echo $this->codes[$code_id]['code'];
}
}
}
/*
$ccr = new CodeRotator ( 'tracker' );
$ccr->AddCode ( 'b1', 'code1', 2, FALSE );
$ccr->AddCode ( 'b2', 'code2', 5, FALSE );
$ccr->AddCode ( 'b3', 'code3', 7, FALSE );
$ccr->AddCode ( 'b4', 'code4', 3, FALSE );
$ccr->AddCode ( 'b5', 'includes/code5.txt', 3, TRUE );
$ccr->debug_mode = TRUE;
$ccr->ShowCode ( );
*/
?>