You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
413 lines
11 KiB
413 lines
11 KiB
<?php
|
|
|
|
function &last(&$array) {
|
|
end($array);
|
|
return $array[key($array)];
|
|
}
|
|
|
|
class XoiPage extends Page {
|
|
public function addStats($stat1, $stat2)
|
|
{
|
|
$sum = $stat1;
|
|
$sum["average"][0] += $stat2["average"][0];
|
|
$sum["average"][1] += $stat2["average"][1];
|
|
$sum["first9"][0] += $stat2["first9"][0];
|
|
$sum["first9"][1] += $stat2["first9"][1];
|
|
$sum["checkouts"][0] += $stat2["checkouts"][0];
|
|
$sum["checkoutPoints"] = array_merge($sum["checkoutPoints"], $stat2["checkoutPoints"]);
|
|
$sum["checkouts"][1] += $stat2["checkouts"][1];
|
|
$sum["180"] += $stat2["180"];
|
|
$sum["140+"] += $stat2["140+"];
|
|
$sum["100+"] += $stat2["100+"];
|
|
$sum["60+"] += $stat2["60+"];
|
|
return $sum;
|
|
}
|
|
|
|
/**
|
|
* @kql-allowed
|
|
*/
|
|
public function tournamentStats() {
|
|
if (count($this->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)
|
|
]);
|
|
}
|
|
}
|
|
|