Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
94.44% covered (success)
94.44%
85 / 90
78.57% covered (warning)
78.57%
11 / 14
CRAP
0.00% covered (danger)
0.00%
0 / 1
TsumegoButtons
94.32% covered (success)
94.32%
83 / 88
78.57% covered (warning)
78.57%
11 / 14
44.36
0.00% covered (danger)
0.00%
0 / 1
 __construct
84.21% covered (warning)
84.21%
16 / 19
0.00% covered (danger)
0.00%
0 / 1
9.32
 deriveFrom
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
1
 fill
100.00% covered (success)
100.00%
11 / 11
100.00% covered (success)
100.00%
1 / 1
4
 resetOrders
83.33% covered (warning)
83.33%
5 / 6
0.00% covered (danger)
0.00%
0 / 1
3.04
 filterByPartition
100.00% covered (success)
100.00%
10 / 10
100.00% covered (success)
100.00%
1 / 1
3
 partitionByParameter
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 partitionByCurrentOne
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
2
 deduceCurrentIndex
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 updateHighestTsumegoOrder
83.33% covered (warning)
83.33%
5 / 6
0.00% covered (danger)
0.00%
0 / 1
3.04
 getPartitionLinkSuffix
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
2
 getPartitionTitleSuffix
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
2
 exportCurrentAndPreviousLink
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
1 / 1
7
 getProblemsSolvedPercent
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
3
 getProblemsRating
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
3
1<?php
2
3App::uses('SgfParser', 'Utility');
4App::uses('TsumegoButtonsQueryBuilder', 'Utility');
5
6class TsumegoButtons extends ArrayObject
7{
8    public function __construct(?TsumegoFilters $tsumegoFilters = null, ?int $currentSetConnectionID = null, ?int $partition = null, string|int|null $id = null)
9    {
10        if (!$tsumegoFilters)
11            return; // Temporary until also the favorites are covered
12        $condition = "";
13        $this->fill($condition, $tsumegoFilters, $id);
14
15        // in topics we respect the orders specified by set connections, in other cases, it is kind of a
16        // 'virtual set' and we just order it from 1 to max
17        if ($tsumegoFilters->query != 'topics' && $tsumegoFilters->query != 'published')
18            $this->resetOrders();
19
20        if (!is_null($currentSetConnectionID))
21        {
22            $currentIndex = $this->deduceCurrentIndex($currentSetConnectionID);
23            if (is_null($currentIndex))
24                if ($tsumegoFilters->query == 'favorites')
25                {
26                    $tsumegoFilters->setQuery('topics');
27                    $this->fill($condition, $tsumegoFilters, $id);
28                    $currentIndex = $this->deduceCurrentIndex($currentSetConnectionID);
29                }
30            if (!is_null($currentIndex))
31            {
32                // mark the problem we are going to visit as the currently opened one
33                $this[$currentIndex]->isCurrentlyOpened = true;
34                $this->currentOrder = $this[$currentIndex]->order;
35            }
36            $this->partitionByCurrentOne($currentIndex, $tsumegoFilters->collectionSize);
37        }
38        elseif (!is_null($partition))
39            $this->partitionByParameter($partition, $tsumegoFilters->collectionSize);
40    }
41
42    public static function deriveFrom(TsumegoButtons $other)
43    {
44        $result = new TsumegoButtons();
45        $result->highestTsumegoOrder = $other->highestTsumegoOrder;
46        $result->partition = $other->partition;
47        $result->isPartitioned = $other->isPartitioned;
48        $result->currentOrder = $other->currentOrder;
49        return $result;
50    }
51
52    public function fill(string $condition, TsumegoFilters $tsumegoFilters, $id)
53    {
54        $queryBuilder = new TsumegoButtonsQueryBuilder($tsumegoFilters, $id);
55        $result = Util::query($queryBuilder->query->str());
56        $this->description = $queryBuilder->description;
57
58        foreach ($result as $index => $row)
59            $this [] = new TsumegoButton(
60                $row['tsumego_id'],
61                $row['set_connection_id'],
62                $row['num'],
63                Auth::isLoggedIn() ? ($row['status'] ?: 'N') : 'N',
64                $row['rating']);
65        $this->updateHighestTsumegoOrder();
66    }
67
68    public function resetOrders(): void
69    {
70        $this->currentOrder = -1;
71        foreach ($this as $key => $tsumegoButton)
72        {
73            $tsumegoButton->order = $key + 1;
74            if ($tsumegoButton->isCurrentlyOpened)
75                $this->currentOrder = $tsumegoButton->order;
76        }
77        $this->updateHighestTsumegoOrder();
78    }
79
80    private function filterByPartition($collectionSize): void
81    {
82        $from = $this->partition * $collectionSize;
83        $to = ($this->partition + 1) * $collectionSize - 1;
84        $this->isPartitioned = $from > 0 || $to + 1 < count($this);
85        $this->exchangeArray(array_values(array_filter(
86            (array) $this,
87            function ($tsumegoButton, $index) use ($from, $to): bool {
88                return $index >= $from && $index <= $to;
89            },
90            ARRAY_FILTER_USE_BOTH
91        )));
92    }
93
94    public function partitionByParameter($partition, $collectionSize): void
95    {
96        $this->partition = $partition;
97        $this->filterByPartition($collectionSize);
98    }
99
100    public function partitionByCurrentOne($currentIndex, $collectionSize): void
101    {
102        $this->partition = (int) floor($currentIndex / $collectionSize);
103
104        if ($collectionSize < count($this))
105            $this->filterByPartition($collectionSize);
106    }
107
108    private function deduceCurrentIndex($currentSetConnectionID): ?int
109    {
110        return array_find_key((array) $this, function ($tsumegoButton) use ($currentSetConnectionID) { return $tsumegoButton->setConnectionID === $currentSetConnectionID; });
111    }
112
113    private function updateHighestTsumegoOrder()
114    {
115        $this->highestTsumegoOrder = -1;
116        $this->currentOrder = -1;
117        foreach ($this as $tsumegoButton)
118        {
119            if ($tsumegoButton->isCurrentlyOpened)
120                $this->currentOrder = $tsumegoButton->order;
121            $this->highestTsumegoOrder = max($this->highestTsumegoOrder, $tsumegoButton->order);
122        }
123    }
124
125    public function getPartitionLinkSuffix(): string
126    {
127        if (!$this->isPartitioned)
128            return '';
129        return '/' . ($this->partition + 1);
130    }
131
132    public function getPartitionTitleSuffix(): string
133    {
134        if (!$this->isPartitioned)
135            return '';
136        return ' #' . ($this->partition + 1);
137    }
138
139    public function exportCurrentAndPreviousLink($setFunction, $tsumegoFilters, $setConnectionID, $set)
140    {
141        $indexOfCurrent = array_find_key((array) $this, function ($tsumegoButton) use ($setConnectionID) { return $tsumegoButton->setConnectionID == $setConnectionID; });
142
143        if (isset($indexOfCurrent) && $indexOfCurrent > 0)
144            $previousSetConnectionID = $this[$indexOfCurrent - 1]->setConnectionID;
145        $setFunction('previousLink', TsumegosController::tsumegoOrSetLink($tsumegoFilters, isset($previousSetConnectionID) ? $previousSetConnectionID : null, $tsumegoFilters->getSetID($set)));
146
147        if (isset($indexOfCurrent) && count($this) > $indexOfCurrent + 1)
148            $nextSetConnectionID = $this[$indexOfCurrent + 1]->setConnectionID;
149        $setFunction('nextLink', TsumegosController::tsumegoOrSetLink($tsumegoFilters, isset($nextSetConnectionID) ? $nextSetConnectionID : null, $tsumegoFilters->getSetID($set)));
150    }
151
152    public function getProblemsSolvedPercent(): float
153    {
154        $solvedCount = 0;
155        foreach ($this as $tsumegoButton)
156            if (TsumegoUtil::isSolvedStatus($tsumegoButton->status))
157                $solvedCount++;
158        return Util::getPercentButAvoid100UntilComplete($solvedCount, count($this));
159    }
160
161    public function getProblemsRating(): float
162    {
163        if (count($this) == 0)
164            return 0;
165        $ratingSum = 0;
166        foreach ($this as $tsumegoButton)
167            $ratingSum += $tsumegoButton->rating;
168        return $ratingSum / count($this);
169    }
170
171    public int $partition = 0;
172    public bool $isPartitioned = false;
173    public int $highestTsumegoOrder = -1;
174    public ?int $currentOrder = -1;
175    public ?string $description = null;
176}