Skip to content

Instantly share code, notes, and snippets.

@ModernTimes
Created August 16, 2012 07:28
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save ModernTimes/3368046 to your computer and use it in GitHub Desktop.
Save ModernTimes/3368046 to your computer and use it in GitHub Desktop.
Lottery: simulates unfair/weighted die rolls
/**
* Beware: Returns a winner even if the collective drop chance is below 100%.
* If that behavior is undesired, add some logic in getWinner to prevent it.
*/
class Lottery {
/**
* list of entries in the lottery. Elements are of the form
* array('participant' => (mixed),
* 'lots' => (float)),
*/
private $_entries = array();
/**
* total number of lots in the pool
* Lots can come in decimals as well, like 0.02
* @var float
*/
private $_lotsTotal = 0;
/**
* Adds a new entry to the lottery,
* i.e. a participant with a given number of lots
* @param mixed $participant
* @param float $lots
*/
public function addEntry($participant, $lots = 1) {
$this->_entries[] = array(
'participant' => $participant,
'lots' => $lots,
);
$this->_lotsTotal += $lots;
}
/**
* Determines the winner of the lottery based on the number of lots that
* each participant has. Lots and their owners are all lined up, then
* the RNG determines the position of the winning lot.
* @return mixed
*/
public function getWinner() {
if($this->_lotsTotal == 0) { return false; }
// * 1,000,000, to make sure that lots in decimal form are handled correctly
$rand = mt_rand(0, $this->_lotsTotal * 1000000);
$currentLot = 0;
foreach($this->_entries as as $entry) {
$currentLot += $entry['lots'] * 1000000;
if($currentLot >= $rand) {
return $entry['participant'];
}
}
return false; // should never happen
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment