Created
December 18, 2012 21:13
-
-
Save kohenkatz/4332062 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php defined('SYSPATH') OR die('No direct access allowed.'); | |
class Model_ActionPlan extends Mongo_Document | |
{ | |
/** | |
* The name of the collection within the database. | |
* | |
* @var string | |
*/ | |
protected $name; | |
/** | |
* Use the after_load function to check for whether this AP has expired | |
*/ | |
protected function after_load() | |
{ | |
// If we don't have info needed to expire this AP, then don't try | |
if ( ! isset($this->game_id)) | |
return; | |
if ($this->is_expired()) | |
{ | |
$game = new Model_Game($this->game_id); | |
$user = Auth::current_user(); | |
$this->close($game, $user, 'failure'); | |
} | |
} | |
public function __construct($name = NULL, $id = NULL) | |
{ | |
if ($name !== NULL) | |
{ | |
$this->name = 'Stocks.'.$name.'.action_plans'; | |
} | |
if ($id !== NULL) | |
{ | |
parent::__construct($id); | |
} | |
} | |
public function is_expired() | |
{ | |
if (isset($this->expires)) | |
{ | |
$date = self::date_field($this->expires); | |
if ($date == null) | |
return false; | |
return ($date < time()); | |
} | |
return false; | |
} | |
public function close($game, $user, $close_type, $auto_close = false) | |
{ | |
// First, if this idea has not yet expired, that means it is being closed manually. In that case, | |
// make sure that this user is a gamemaster. Only gamemasters can close APs. | |
if ((! $auto_close) AND ($close_type !== 'failure') AND ( ! $this->is_expired()) AND ! $user->is_gamemaster_in_game($game->id)) | |
{ | |
return; | |
} | |
// Now do the payout | |
if ($game->config['prediction_market']['ActionPlan']) | |
{ | |
// For now, you can change a failed AP to success but you cannot change a | |
// successful one to a fail because it will be hard to remove the awarded points. | |
if (isset($this->status)) | |
{ | |
$status = $this->status; // This crashes | |
// $status = parent::__get('status'); // This works | |
if (($status === "closed") AND ($this->close_type != "failure")) | |
{ | |
return; | |
} | |
} | |
// Now, get all users who own stock in this AP | |
$owners = $this->owners; | |
// Can be 'implemented' or 'failed' | |
switch ($close_type) | |
{ | |
case 'successful': | |
// MAX[10, (c * question_score)] | |
$c = $game->config['prediction_market']['c']; | |
$payout_per_share = max(10, $c * $this->score); | |
foreach ($owners as $owner_id => $quantity) | |
{ | |
$owner = new Model_User(new MongoId($owner_id)); | |
if ($quantity > 0) | |
{ | |
$owner->inc('points', $payout_per_share * $quantity); | |
} | |
else | |
{ | |
// If this user short-sold shares (meaning that the quantity | |
// is negative), the spec says that the buyback price | |
// is always 10, no matter what the payback other users get is. | |
$owner->inc('points', 10 * $quantity); | |
} | |
$owner->save(); | |
} | |
break; | |
case 'failure': | |
// No payout, but we should keep this here for consistency. | |
break; | |
default: | |
throw new InvalidArgumentException("Invalid parameter to close action plan."); | |
} | |
} | |
$this->status = "closed"; | |
$this->close_type = $close_type; | |
$this->save(); | |
// If this is closed as a success, close it's parent question and all of its | |
// sibling action plans as failures. | |
if ($close_type == 'successful') | |
{ | |
$parent_question = new Model_Question($game->short_name, $this->parent_id); | |
$parent_question->close($game, $user, 'automatic'); | |
} | |
} | |
/** | |
* Mark an Action Plan as implemented | |
*/ | |
public function implement($game, $user) | |
{ | |
// First, stop if this idea has not yet expired or already been implemented. | |
// Also, only gamemasters can implement APs. | |
if ($this->is_expired() OR ($this->status == 'implemented') OR (! $user->is_gamemaster_in_game($game->id))) | |
{ | |
return false; | |
} | |
$this->status = "implemented"; | |
$this->save(); | |
return true; | |
} | |
private static function date_field($field) | |
{ | |
if (is_string($field) && strlen($field) > 0) | |
{ | |
return strtotime($field); | |
} | |
elseif ($field instanceof MongoDate) | |
{ | |
return $field->sec; // we don't care about anything more specific than the seconds. | |
} | |
return null; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment