Skip to content

Commit

Permalink
save replacement players to session state
Browse files Browse the repository at this point in the history
  • Loading branch information
ctizen committed Oct 4, 2024
1 parent 06a58c8 commit 94160fd
Show file tree
Hide file tree
Showing 8 changed files with 71 additions and 28 deletions.
23 changes: 23 additions & 0 deletions Mimir/src/helpers/SessionState.php
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,11 @@ class SessionState
* @var array
*/
protected $_yakitori = [];
/**
* Saved current replacements for proper recalculations
* @var array
*/
protected $_replacements = [];

/**
* SessionState constructor.
Expand Down Expand Up @@ -335,6 +340,24 @@ public function setScores(array $scores)
return $this;
}

/**
* @return array
*/
public function getReplacements()
{
return $this->_replacements;
}

/**
* @param array $replacements
* @return SessionState
*/
public function setReplacements(array $replacements)
{
$this->_replacements = $replacements;
return $this;
}

/**
* @return bool[]
*/
Expand Down
8 changes: 4 additions & 4 deletions Mimir/src/models/EventUserManagement.php
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ public function registerPlayer(int $playerId, int $eventId)
$nextLocalId = PlayerRegistrationPrimitive::findNextFreeLocalId($this->_ds, $eId);
}

$regItemOld = PlayerRegistrationPrimitive::findByPlayerAndEvent($this->_ds, $playerId, $eventId);
$regItemOld = PlayerRegistrationPrimitive::findByPlayerAndEvent($this->_ds, [$playerId], $eventId);
if (count($regItemOld) > 0) {
throw new InvalidParametersException('Player already registered to this event');
}
Expand All @@ -92,7 +92,7 @@ public function unregisterPlayer(int $playerId, int $eventId)
throw new AuthFailedException('Only administrators are allowed to unregister players to event');
}

$regItem = PlayerRegistrationPrimitive::findByPlayerAndEvent($this->_ds, $playerId, $eventId);
$regItem = PlayerRegistrationPrimitive::findByPlayerAndEvent($this->_ds, [$playerId], $eventId);
if (empty($regItem)) {
return false;
}
Expand All @@ -116,7 +116,7 @@ public function updateSeatingFlag(int $playerId, int $eventId, int $ignoreSeatin
throw new AuthFailedException('Only administrators are allowed to update player information');
}

$regItem = PlayerRegistrationPrimitive::findByPlayerAndEvent($this->_ds, $playerId, $eventId);
$regItem = PlayerRegistrationPrimitive::findByPlayerAndEvent($this->_ds, [$playerId], $eventId);
if (empty($regItem)) {
throw new EntityNotFoundException('Player is not registered for this event');
}
Expand All @@ -141,7 +141,7 @@ public function updateReplacement(int $playerId, int $eventId, int $replacementI
throw new AuthFailedException('Only administrators are allowed to update player information');
}

$regItem = PlayerRegistrationPrimitive::findByPlayerAndEvent($this->_ds, $playerId, $eventId);
$regItem = PlayerRegistrationPrimitive::findByPlayerAndEvent($this->_ds, [$playerId], $eventId);
if (empty($regItem)) {
throw new EntityNotFoundException('Player is not registered for this event');
}
Expand Down
8 changes: 4 additions & 4 deletions Mimir/src/primitives/PlayerRegistration.php
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ public function getTeamName()

/**
* @param DataSource $ds
* @param int $playerId
* @param int[] $playerIds
* @param int $eventId
*
* @return self[]
Expand All @@ -163,12 +163,12 @@ public function getTeamName()
*
* @psalm-return array<array-key, self>
*/
public static function findByPlayerAndEvent(DataSource $ds, int $playerId, int $eventId)
public static function findByPlayerAndEvent(DataSource $ds, $playerIds, int $eventId)
{
return self::_findBySeveral($ds, [
'player_id' => [$playerId],
'player_id' => $playerIds,
'event_id' => [$eventId]
], ['onlyLast' => true]);
]);
}

/**
Expand Down
28 changes: 24 additions & 4 deletions Mimir/src/primitives/Session.php
Original file line number Diff line number Diff line change
Expand Up @@ -921,12 +921,13 @@ public function updateScoresWithChipsBonus()

/**
* Generate session results
* @param bool $useSavedReplacements
* @throws \Exception
* @return bool
*/
protected function _finalizeGame()
protected function _finalizeGame($useSavedReplacements = false)
{
$sessionResults = $this->getSessionResults();
$sessionResults = $this->getSessionResults($useSavedReplacements);

return array_reduce($sessionResults, function ($acc, SessionResultsPrimitive $result) {
$playerHistoryItem = PlayerHistoryPrimitive::makeNewHistoryItem(
Expand All @@ -949,15 +950,16 @@ protected function _finalizeGame()
*/
public function recreateHistory()
{
$this->_finalizeGame();
$this->_finalizeGame(true);
}

/**
* Get a list on unsaved session results primitives
* @param bool $useSavedReplacements
* @throws \Exception
* @return SessionResultsPrimitive[]
*/
public function getSessionResults()
public function getSessionResults($useSavedReplacements = false)
{
if ($this->getEvent()->getRulesetConfig()->rules()->getRiichiGoesToWinner()) {
$placesMap = SessionResultsPrimitive::calcPlacesMap($this->getCurrentState()->getScores(), $this->getPlayersIds());
Expand Down Expand Up @@ -986,6 +988,24 @@ public function getSessionResults()
}
}

if (!$useSavedReplacements) {
// save replacements to session state for possible recalculations
$players = PlayerRegistrationPrimitive::findByPlayerAndEvent($this->_ds, $this->getPlayersIds(), $this->_eventId);
$replacements = array_reduce(
$players,
function ($acc, PlayerRegistrationPrimitive $reg) {
if ($reg->getReplacementPlayerId()) {
$acc[$reg->getPlayerId()] = $reg->getReplacementPlayerId();
}
return $acc;
},
[]
);

$this->getCurrentState()->setReplacements($replacements);
$this->save();
}

return array_map(function (PlayerPrimitive $player) {
return (new SessionResultsPrimitive($this->_ds))
->setPlayer($player)
Expand Down
16 changes: 5 additions & 11 deletions Mimir/src/primitives/SessionResults.php
Original file line number Diff line number Diff line change
Expand Up @@ -422,7 +422,7 @@ public function calc(\Common\Ruleset $rules, SessionState $results, array $playe
throw new InvalidParametersException('No player place found');
}

$this->_ratingDelta = $this->_calcRatingDelta($rules, $results->getScores());
$this->_ratingDelta = $this->_calcRatingDelta($rules, $results->getScores(), $results->getReplacements());

if ($withChips) {
$this->_ratingDelta += $this->_chips * $rules->rules()->getChipsValue();
Expand Down Expand Up @@ -507,23 +507,17 @@ public static function calcPlacesMap(array $scoreList, array $originalPlayersSeq
*
* @param \Common\Ruleset $rules
* @param int[] $allScores
* @param array $replacements
*
* @return float|int
* @throws InvalidParametersException
*/
protected function _calcRatingDelta(\Common\Ruleset $rules, array $allScores)
protected function _calcRatingDelta(\Common\Ruleset $rules, array $allScores, array $replacements)
{
$reg = PlayerRegistrationPrimitive::findByPlayerAndEvent($this->_ds, $this->_playerId, $this->_eventId);
if (empty($reg)) {
throw new InvalidParametersException('No player/event id pair found (' .
$this->_playerId . '/' . $this->_eventId . '), can\'t calculate delta');
}

$score = ($reg[0]->getReplacementPlayerId() && $rules->rules()->getReplacementPlayerFixedPoints() !== false)
$score = (!empty($replacements[$this->_playerId]) && $rules->rules()->getReplacementPlayerFixedPoints() !== false)
? $rules->rules()->getReplacementPlayerFixedPoints()
: $this->_score - $rules->rules()->getStartPoints();

$uma = ($reg[0]->getReplacementPlayerId() && $rules->rules()->getReplacementPlayerOverrideUma() !== false)
$uma = (!empty($replacements[$this->_playerId]) && $rules->rules()->getReplacementPlayerOverrideUma() !== false)
? $rules->rules()->getReplacementPlayerOverrideUma()
: $rules->uma($allScores)[$this->_place - 1];

Expand Down
8 changes: 4 additions & 4 deletions Mimir/tests/helpers/SessionStateTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -619,7 +619,7 @@ public function testSerialDraw()
public function testSessionStateToJson()
{
$this->assertEquals(
'{"_scores":{"1":30000,"2":30000,"3":30000,"4":30000},"_chombo":[],"_round":1,"_honba":0,"_riichiBets":0,"_prematurelyFinished":false,"_roundJustChanged":true,"_lastHandStarted":false,"_lastOutcome":null,"_yakitori":[],"_isFinished":false}',
'{"_scores":{"1":30000,"2":30000,"3":30000,"4":30000},"_chombo":[],"_round":1,"_honba":0,"_riichiBets":0,"_prematurelyFinished":false,"_roundJustChanged":true,"_lastHandStarted":false,"_lastOutcome":null,"_yakitori":[],"_replacements":[],"_isFinished":false}',
$this->_state->toJson()
);

Expand All @@ -631,14 +631,14 @@ public function testSessionStateToJson()
$this->_state->update($round);

$this->assertEquals(
'{"_scores":{"1":30000,"2":30000,"3":30000,"4":30000},"_chombo":[],"_round":2,"_honba":1,"_riichiBets":0,"_prematurelyFinished":false,"_roundJustChanged":true,"_lastHandStarted":false,"_lastOutcome":"draw","_yakitori":[],"_isFinished":false}',
'{"_scores":{"1":30000,"2":30000,"3":30000,"4":30000},"_chombo":[],"_round":2,"_honba":1,"_riichiBets":0,"_prematurelyFinished":false,"_roundJustChanged":true,"_lastHandStarted":false,"_lastOutcome":"draw","_yakitori":[],"_replacements":[],"_isFinished":false}',
$this->_state->toJson()
);
}

public function testSessionStateFromJson()
{
$json1 = '{"_scores":{"1":30000,"2":30000,"3":30000,"4":30000},"_chombo":[],"_round":1,"_honba":0,"_riichiBets":0,"_prematurelyFinished":false,"_roundJustChanged":true,"_lastHandStarted":false,"_lastOutcome":null,"_yakitori":[],"_isFinished":false}';
$json1 = '{"_scores":{"1":30000,"2":30000,"3":30000,"4":30000},"_chombo":[],"_round":1,"_honba":0,"_riichiBets":0,"_prematurelyFinished":false,"_roundJustChanged":true,"_lastHandStarted":false,"_lastOutcome":null,"_yakitori":[],"_replacements":[],"_isFinished":false}';

$state = SessionState::fromJson(
$this->_ruleset,
Expand All @@ -652,7 +652,7 @@ public function testSessionStateFromJson()
$this->assertEquals(1, $state->getRound());
$this->assertEquals(0, $state->getHonba());

$json2 = '{"_scores":{"1":30000,"2":30000,"3":30000,"4":30000},"_chombo":[],"_round":2,"_honba":1,"_riichiBets":0,"_prematurelyFinished":false,"_roundJustChanged":true,"_lastHandStarted":false,"_yakitori":[],"_lastOutcome":null}';
$json2 = '{"_scores":{"1":30000,"2":30000,"3":30000,"4":30000},"_chombo":[],"_round":2,"_honba":1,"_riichiBets":0,"_prematurelyFinished":false,"_roundJustChanged":true,"_lastHandStarted":false,"_yakitori":[],"_replacements":[],"_lastOutcome":null}';

$state = SessionState::fromJson(
$this->_ruleset,
Expand Down
2 changes: 1 addition & 1 deletion Mimir/tests/models/InteractiveSessionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -550,7 +550,7 @@ public function testRoundRollback()
/** @var SessionPrimitive $session */
list($session) = SessionPrimitive::findByRepresentationalHash($this->_ds, [$hash]);
$this->assertEquals(
'{"_scores":{"1":29400,"2":32800,"3":29900,"4":27900},"_chombo":[],"_round":2,"_honba":0,"_riichiBets":0,"_prematurelyFinished":false,"_roundJustChanged":true,"_lastHandStarted":false,"_lastOutcome":"tsumo","_yakitori":[],"_isFinished":false}',
'{"_scores":{"1":29400,"2":32800,"3":29900,"4":27900},"_chombo":[],"_round":2,"_honba":0,"_riichiBets":0,"_prematurelyFinished":false,"_roundJustChanged":true,"_lastHandStarted":false,"_lastOutcome":"tsumo","_yakitori":[],"_replacements":[],"_isFinished":false}',
$session->getCurrentState()->toJson()
);

Expand Down
6 changes: 6 additions & 0 deletions Mimir/tests/primitives/SessionResultsTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,8 @@ public function testReplacementPlayerRatingDelta()
$player = $this->_players[0];
$this->_regs[$player->getId()]->setReplacementPlayerId(true);
$this->_regs[$player->getId()]->save();
$this->_session->getCurrentState()->setReplacements([$player->getId() => true]);
$this->_session->save();

$result = (new SessionResultsPrimitive($this->_ds))
->setPlayer($player)
Expand All @@ -134,6 +136,10 @@ public function testReplacementPlayerRatingDelta()
$result->save();

$this->assertEquals(-30000, $result->getRatingDelta());

// cleanup for following tests
$this->_session->getCurrentState()->setReplacements([]);
$this->_session->save();
}

public function testUmaRule()
Expand Down

0 comments on commit 94160fd

Please sign in to comment.