Skip to content

Commit

Permalink
Initial commit of Reliability Rating changes
Browse files Browse the repository at this point in the history
  • Loading branch information
kestasjk authored and TimothyJones committed Dec 5, 2014
1 parent 21a0bd1 commit 5250d15
Show file tree
Hide file tree
Showing 5 changed files with 129 additions and 13 deletions.
7 changes: 6 additions & 1 deletion gamemaster.php
Expand Up @@ -167,8 +167,13 @@
header('refresh: 4; url=gamemaster.php');
print '<p class="notice">'.l_t('Timed-out; re-running').'</p>';
}
else
{
// Finished all remaining games with time to spare; update the civil disorder and NMR counts
//libGameMaster::updateCDNMRCounts();
}

print '</div>';
libHTML::footer();

?>
?>
37 changes: 36 additions & 1 deletion gamemaster/game.php
Expand Up @@ -406,6 +406,38 @@ public function resetMinimumBet()
}
}

/**
* Record NMRs by entering any NMRs into wD_NMRs, and also increment the phaseCount for all users in the game.
*/
private function recordNMRs()
{
global $DB;

/*
* Make a note of NMRs. An NMR is where a member's orderStatus does not contain "Saved", but there are orders to
* be submitted and the user is playing. (Note this could be changed to require orderStatus is "Completed", if
* incomplete orders don't count as moves.)
*/
$DB->sql_put("INSERT INTO wD_NMRs (gameID, userID, countryID, turn, bet, SCCount)
SELECT m.gameID, m.userID, m.countryID, ".$this->turn." as turn, m.bet, m.supplyCenterNo
FROM wD_Members m
WHERE m.gameID = ".$this->id."
AND m.status='Playing'
AND EXISTS(SELECT o.id FROM wD_Orders o WHERE o.gameID = m.gameID AND o.countryID = m.countryID)
AND NOT m.orderStatus LIKE '%Saved%'");

/*
* Increment the moves received counter for users who could have submitted moves. This is a counter because it's a large number
* users are unlikely to question, and calculating it from stored data is very involved.
*/
$DB->sql_put("UPDATE wD_Users u
INNER JOIN wD_Members m ON m.userID = u.id
SET u.phaseCount = u.phaseCount + 1
WHERE m.gameID = ".$this->id."
AND m.status='Playing'
AND EXISTS(SELECT o.id FROM wD_Orders o WHERE o.gameID = m.gameID AND o.countryID = m.countryID)");
}

/**
* Process; the main gamemaster function for managing games; processes orders, adjudicates them,
* applies the results, creates new orders, updates supply center/army numbers, and moves the
Expand All @@ -430,6 +462,7 @@ function process()
/*
* Process the game. In a nutshell:
*
* - Make a note of any NMRs, increment phases played
* - Adjudicate
* - Save the current state of the game (Units,Orders,TerrStatus) to the archives if we have entered a new turn
* - Wipe the game's orders
Expand All @@ -439,6 +472,8 @@ function process()
* - Create new orders for the current phase
* - Set the next date for game processing
*/

$this->recordNMRs();

/*
* Except for wiping redundant TerrStatus data after a new turn and generating new orders
Expand Down Expand Up @@ -541,7 +576,7 @@ function process()
SET m.orderStatus=IF(o.id IS NULL, 'None',''),
missedPhases=IF(m.status='Playing' AND NOT o.id IS NULL, missedPhases + 1, missedPhases)
WHERE m.gameID = ".$this->id);

$this->processTime = time() + $this->phaseMinutes*60;

$DB->sql_put("UPDATE wD_Games SET processTime = ".$this->processTime." WHERE id = ".$this->id);
Expand Down
55 changes: 55 additions & 0 deletions gamemaster/gamemaster.php
Expand Up @@ -83,6 +83,61 @@ static public function updateSessionTable()

}

$DB->sql_put("COMMIT");
}

/**
* Update the reliability ratings by taking count of the number of civil disorders, NMRs, and civil disorders taken over for each
* user. Uses the wD_CivilDisorders and wD_NMRs tables and recalculates for all users that have logged in the last two weeks.
*
* This is a relatively DB intensive query since it needs to check over three tables for all the users it includes, but it does
* ensure the way the numbers are calculated can be tracked back to the specific games involved and tweaked down the or by other
* installations (e.g. whether games just joined should be counted, etc).
*
* This could be optimized by making it recalculate only for users who are members / who were members in games that have just been
* processed.
*
* @param $recalculateAll If true don't filter on active users, but recalculate for all users, which takes longer
*/
static public function updateReliabilityRating($recalculateAll = false)
{
global $DB, $Misc;

/*
* CDs and NMRs are straightforward counts.
*
* GameCount is the number of memberships the user has, plus the number of civil disorders which the user didn't rejoin
*
* CTTakenCount is calculated by taking all of a user's memberships to games, linking them
* to civil disorders in that game (other than the user's civil disorders), and making sure that only the latest civil disorder
* is counted (so that the user isn't said to have taken over from two civil disorders if a certain country went into civil
* disorder twice)
*
* Then the reliabilityRating is calculated based on the formula considered most appropriate. However the
*/
$DB->sql_put("UPDATE wD_Users u
SET u.cdCount = (SELECT COUNT(c.userID) FROM wD_CivilDisorders c WHERE c.userID = u.id),
u.nmrCount = (SELECT COUNT(n.userID) FROM wD_NMRs n WHERE n.userID = u.id),
u.gameCount = (
SELECT COUNT(*)
FROM wD_Members m
WHERE m.userID = u.id) + (
SELECT COUNT(*)
FROM wD_CivilDisorders c LEFT JOIN wD_Members m ON c.gameID = m.gameID AND c.userID = m.userID AND c.countryID = m.countryID
WHERE m.id IS NULL AND c.userID = u.id),
u.cdTakenCount = (
SELECT COUNT(*)
FROM wD_Members ct
INNER JOIN wD_CivilDisorders c ON c.gameID = ct.gameID AND c.countryID = ct.countryID AND NOT c.userID = ct.userID
WHERE ct.userID = u.id AND c.turn = (
SELECT MAX(sc.turn)
FROM wD_CivilDisorders sc
WHERE sc.gameID = c.gameID AND sc.countryID = c.countryID
)
),
u.reliabilityRating = ( 1.0 - (u.cdCount / (u.gameCount+1) ))
".($recalculateAll ? "" : "WHERE u.timeLastSessionEnded+(14*24*60*60) > ".$Misc->LastProcessTime));

$DB->sql_put("COMMIT");
}
}
Expand Down
29 changes: 23 additions & 6 deletions objects/user.php
Expand Up @@ -182,6 +182,15 @@ public function getActiveSilence() {
* @var string
*/
public $muteReports;

/**
* The users reliability stats; civil disorders, nmrs, civil disorders taken over, phases where moves could have been submitted, games, reliability rating.
*
* Generated in libGameMaster
*
* @var int/double
*/
public $cdCount, $nmrCount, $cdTakenCount, $phaseCount, $gameCount, $reliabilityRating;

/**
* Give this user a supplement of points
Expand Down Expand Up @@ -428,6 +437,12 @@ function load($username=false)
u.muteReports,
u.silenceID,
u.notifications,
u.cdCount,
u.nmrCount,
u.cdTakenCount,
u.phaseCount,
u.gameCount,
u.reliabilityRating,
IF(s.userID IS NULL,0,1) as online
FROM wD_Users u
LEFT JOIN wD_Sessions s ON ( u.id = s.userID )
Expand Down Expand Up @@ -538,19 +553,19 @@ function sendPM(User $FromUser, $message)
require_once(l_r('lib/message.php'));
$message = message::linkify($message);

if( $FromUser->isSilenced() )
if( $FromUser->isSilenced() )
{
notice::send($FromUser->id, $this->id, 'PM', 'No', 'Yes',
l_t('Could not deliver message, you are currently silenced.') .'('. $FromUser->getActiveSilence()->reason .')', l_t('To:') .' '. $this->username,
$this->id);
return false;
}
else if( $this->isUserMuted($FromUser->id) )
else if( $this->isUserMuted($FromUser->id) )
{
notice::send($FromUser->id, $this->id, 'PM', 'No', 'Yes',
l_t('Could not deliver message, user has muted you.'), l_t('To:').' '.$this->username,
$this->id);
return false;
$this->id);
return false;
}
else
{
Expand All @@ -561,8 +576,8 @@ function sendPM(User $FromUser, $message)

notice::send($FromUser->id, $this->id, 'PM', 'No', 'Yes',
l_t('You sent:').' <em>'.$message.'</em>', l_t('To:').' '.$this->username,
$this->id);
return true;
$this->id);
return true;
}
}

Expand Down Expand Up @@ -731,6 +746,8 @@ public function rankingDetails()
{
$rankingDetails['stats'][$status] = $number;
}
$rankingDetails['stats']['Civil disorder'] = $this->cdCount;
$rankingDetails['stats']['Civil disorders taken over'] = $this->cdTakenCount;

$tabl = $DB->sql_tabl( "SELECT COUNT(m.id), m.status, SUM(m.bet) FROM wD_Members AS m
INNER JOIN wD_Games AS g ON m.gameID = g.id
Expand Down
14 changes: 9 additions & 5 deletions profile.php
Expand Up @@ -338,8 +338,6 @@
print '</li>';
}

print '<li>'.l_t('Total (finished): <strong>%s</strong>',$total).'</li>';

foreach($rankingDetails['stats'] as $name => $status)
{
if ( in_array($name, $includeStatus) ) continue;
Expand All @@ -349,6 +347,11 @@
print '<li>'.l_t($name.': <strong>%s</strong>',$status).'</li>';
}

print '<li>'.l_t('No moves received / received:').' <strong>'.$UserProfile->nmrCount.'/'.$UserProfile->phaseCount.'</strong></li>';
print '<li>'.l_t('Reliability rating:').' <strong>'.round(100*$UserProfile->reliabilityRating).'%</strong></li>';

print '<li>'.l_t('Total (finished): <strong>%s</strong>',$total).'</li>';

if ( $rankingDetails['takenOver'] )
print '<li>'.l_t('Left and taken over: <strong>%s</strong>',$rankingDetails['takenOver']).
'(<a href="profile.php?detail=civilDisorders&userID='.$UserProfile->id.'">'.l_t('View details').'</a>)</li>';
Expand Down Expand Up @@ -553,14 +556,15 @@
}
else
{
if ( $UserProfile->sendPM($User, $_REQUEST['message']) )
if ( $UserProfile->sendPM($User, $_REQUEST['message']) )
{
print '<p class="notice">'.l_t('Private message sent successfully.').'</p>';
}
else
}
else
{
print '<p class="notice">'.l_t('Private message could not be sent. You may be silenced or muted.').'</p>';
}

}
}

Expand Down

0 comments on commit 5250d15

Please sign in to comment.