playerUUIDs()) == 2){ return [$this->parent()->getStats($this->playerUUIDs()[0]),$this->parent()->getStats($this->playerUUIDs()[1])]; } return []; } public function reorderPlayer($order){ kirby()->impersonate('kirby'); return $this->update([ "players" => $order ]); } public function playerUUIDs(){ $pp = $this->players()->toPages(); $players = []; foreach ($pp as $i => $p) { $players[] = $p->uuid()->toString(); } return $players; } public function getPlayerPos($playerUUIDs, $uuid) { $k = 0; foreach ($playerUUIDs as $i => $playeruuid) { if ($playeruuid == $uuid) { break; } $k++; } return $k; } // entity can be visit, leg or set public function nextPlayer($playerUUIDs, $uuid) { $k = $this->getPlayerPos($playerUUIDs, $uuid); return $playerUUIDs[($k+1)%count($playerUUIDs)]; } public function updateStats(&$stats, $visit){ $playerUUIDs = $this->playerUUIDs(); $k = $this->getPlayerPos($playerUUIDs, $visit["player"]); $todos = [&$stats["stats"][$k]]; $todos[] = &last($stats["sets"])["stats"][$k]; $todos[] = &last(last($stats["sets"])["legs"])["stats"][$k]; foreach ($todos as $i => $value) { $todos[$i]["average"][0] += $visit["sum"]; $todos[$i]["average"][1] += $visit["numDarts"]; if ($visit["visit"] < 4) { $todos[$i]["first9"][0] += $visit["sum"]; $todos[$i]["first9"][1] += $visit["numDarts"]; } if ($visit["toGo"][$k] == 0) { $todos[$i]["checkouts"][0] += 1; $todos[$i]["checkoutPoints"][] += $visit["sum"]; } $todos[$i]["checkouts"][1] += $visit["checkoutTries"]; if ($visit["sum"] == 180) { $todos[$i]["180"] += 1; } elseif ($visit["sum"] >= 140) { $todos[$i]["140+"] += 1; } elseif ($visit["sum"] >= 100) { $todos[$i]["100+"] += 1; } elseif ($visit["sum"] >= 60) { $todos[$i]["60+"] += 1; } } return $stats; } private function newVisit($player, $round) { return array( 'player' => $player, 'throws' => [], 'visit' => $round, 'checkoutTries' => 0, 'numDarts' => 0, ); } public function calcPoints($throw) { $throw = trim($throw); if ($throw == "") { return 0; } if ($throw == "SB"){ return 25; } if ($throw == "DB"){ return 50; } if ($throw[0] == "S" || $throw[0] == "O" || $throw[0] == "I"){ return intval(substr($throw, 1)); } if ($throw[0] == "D"){ return 2*intval(substr($throw, 1)); } if ($throw[0] == "T"){ return 3*intval(substr($throw, 1)); } if ($throw[0] == "M"){ return 0; } else { // TODO: Check for Na return intval($throw); } } public function sumPoints($throws) { $sum = 0; foreach ($throws as $i => $throw) { $points = $this->calcPoints($throw); $sum += $points; } return $sum; } public function getWinner($points, $mode) { $sum = 0; $k = 0; $max = -1; foreach ($points as $i => $point) { $sum += $point; if ($max < $point) { $max = $point; $maxidx = $k; } $k++; } if ($max > $mode/$k) { return $maxidx; } if ($sum == $mode) { return -2; } return -1; } public function clearLastVisit() { $game = $this->rounds()->parseJSON(); $set = &$game["sets"][count($game["sets"])-1]; $leg = &$set["legs"][count($set["legs"])-1]; $visit = &$leg["visits"][count($leg["visits"])-1]; $visit["throws"] = []; $visit["checkoutTries"] = 0; $visit["numDarts"] = 0; unset($visit["sum"]); unset($visit["toGo"]); return $this->storeGame($game); } public function addThrows($throws, $numDarts, $checkoutTries, $done=true) { $game = $this->rounds()->parseJSON(); $set = &$game["sets"][count($game["sets"])-1]; $leg = &$set["legs"][count($set["legs"])-1]; $visit = &$leg["visits"][count($leg["visits"])-1]; $current_throws = $visit['throws']; if (count($current_throws)+count($throws) > 3) { $error = "Two many throws given: ".count($current_throws)." + ".count($throws)." > 3"; throw new \Exception($error, 1); } $new_throws = array_merge($current_throws, $throws); $playerUUIDs = $this->playerUUIDs(); $k = $this->getPlayerPos($playerUUIDs, $visit["player"]); if (count($leg["visits"])-2 < 0) { $toGo = array_fill(0, count($playerUUIDs), $this->max()->toInt()); } else { $toGo = $leg["visits"][count($leg["visits"])-2]["toGo"]; } $visit["numDarts"] += $numDarts; $visit["throws"] = $new_throws; $visit["checkoutTries"] += $checkoutTries; $visit["sum"] = $this->sumPoints($visit["throws"]); $rest = $toGo[$k] - $visit["sum"]; if ($rest < 0 or ($this->out()->toString() == "Double" && $rest == 1)) { $visit["sum"] = 0; } else { $toGo[$k] = $rest; } $visit["toGo"] = $toGo; if (!$done) { $this->storeGame($game); return; } $stats = $this->stats()->parseJSON(); $page = $this->updateStats($stats, $visit); $update = []; if ($rest != 0) { // Normal case...next players turn $nextPlayer = $this->nextPlayer($playerUUIDs, $visit["player"]); $isNextRound = 0; if (last(last($game["sets"])["legs"])['visits'][0]["player"] == $nextPlayer) { $isNextRound = 1; } $newVisit = $this->newVisit($nextPlayer, $visit["visit"]+$isNextRound); last(last($game["sets"])["legs"])['visits'][] = $newVisit; } else { // rest == 0 leg finished // updates Stats...this is maybe the wrong place to store points $newlegp = $leg["points"]; $newlegp[$k] += 1; $winner = $this->getWinner($newlegp, $this->legs()->toInt()); if ($winner != -1) { $newsetp = $set["points"]; $newsetp[$k] += 1; $winner = $this->getWinner($newsetp, $this->sets()->toInt()); if ($winner != -1) { if ($winner == -2) { $stats["winner"] = "DRAW"; } else { $stats["winner"] = $visit["player"]; } // Game Over $update = [ "enddate" => date("Y-m-d H:i:s") ]; } else { // new Set $this->addNewSet($game, $newsetp); $stats = $this->addNewSetStats($stats); $stats = $this->addNewLegStats($stats); } } else { // new Leg $this->addNewLeg($game, $newlegp); $stats = $this->addNewLegStats($stats); } } $page = $this->storeGame($game); $page = $page->storeStats($stats); $page->update($update); } private function newSingleStats($player) { return array( "player" => $player, "average" => [0, 0], "first9" => [0, 0], "checkouts" => [0, 0], "checkoutPoints" => [], "60+" => 0, "100+" => 0, "140+" => 0, "180" => 0 ); } private function newStats(){ $playerUUIDs = $this->playerUUIDs(); $stats = array( // "winner" => "", "stats" => [] ); foreach ($playerUUIDs as $i => $player) { $n = $this->newSingleStats($player); $stats["stats"][] = $n; } return $stats; } private function addNewSet(&$game, $points){ $playerUUIDs = $this->playerUUIDs(); $set = &$game["sets"][count($game["sets"])-1]; $leg = &$set["legs"][count($set["legs"])-1]; $p = $this->nextPlayer($playerUUIDs, $set["legs"][0]["visits"][0]["player"]); $game["sets"][] = array( 'points' => $points, 'legs' => [ array( 'points' => array_fill(0, count($playerUUIDs), 0), 'visits' => [$this->newVisit($p, 1)] ) ] ); return $game; } private function addNewLeg(&$game, $points){ $playerUUIDs = $this->playerUUIDs(); $set = &$game["sets"][count($game["sets"])-1]; $leg = &$set["legs"][count($set["legs"])-1]; $p = $this->nextPlayer($playerUUIDs, $leg["visits"][0]["player"]); $set["legs"][] = array( 'points' => $points, 'visits' => [$this->newVisit($p, 1)] ); return $game; } private function addNewSetStats(&$stats){ $stats["sets"][] = $this->newStats(); $stats["sets"][0]["legs"] = []; return $stats; } private function addNewLegStats(&$stats){ last($stats["sets"])["legs"][] = $this->newStats(); return $stats; } public function recalcStats(){ $game = $this->rounds()->parseJSON(); $page = $this->initStats(); $stats = $page->stats()->parseJSON(); $lastset = count($game["sets"])-1; foreach ($game["sets"] as $i => $set) { $lastleg = count($set["legs"])-1; foreach ($set["legs"] as $j => $leg) { $lastvisit = count($leg["visits"])-1; foreach ($leg["visits"] as $k => $visit) { if (!($k == $lastvisit && $j == $lastleg && $i == $lastset)) { $this->updateStats($stats, $visit); } if ($k == $lastvisit && $j != $lastleg) { $this->addNewLegStats($stats); } } if ($j == $lastleg && $i != $lastset) { $this->addNewSetStats($stats); } } } return $this->storeStats($stats); } private function initStats() { $stats = $this->newStats(); $stats["sets"] = []; $this->addNewSetStats($stats); $this->addNewLegStats($stats); return $this->storeStats($stats); } public function initGame($startTime = true) { $playerUUIDs = $this->playerUUIDs(); $game = array('sets' => [array( 'points' => array_fill(0, count($playerUUIDs), 0), 'legs' => [ array( 'points' => array_fill(0, count($playerUUIDs), 0), 'visits' => [$this->newVisit($playerUUIDs[0], 1)] ) ] ) ]); $page = $this->initStats(); $update = [ 'rounds' => json_encode($game) ]; if ($startTime) { $update['startdate'] = date("Y-m-d H:i:s"); } kirby()->impersonate('kirby'); return $page->update($update); } public function storeStats($stats) { kirby()->impersonate('kirby'); return $this->update([ "stats" => json_encode($stats) ]); } public function storeGame($game) { kirby()->impersonate('kirby'); return $this->update([ "rounds" => json_encode($game) ]); } }