Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
| Total | |
95.77% |
136 / 142 |
|
72.73% |
8 / 11 |
CRAP | |
0.00% |
0 / 1 |
| CronController | |
95.74% |
135 / 141 |
|
72.73% |
8 / 11 |
39 | |
0.00% |
0 / 1 |
| daily | |
100.00% |
13 / 13 |
|
100.00% |
1 / 1 |
2 | |||
| dailyUsersReset | |
100.00% |
13 / 13 |
|
100.00% |
1 / 1 |
1 | |||
| dailyTsumegoStatusReset | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
1 | |||
| dailyStalingSolvedTsumegoStatuses | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
1 | |||
| deduceUserOfTheDay | |
77.78% |
7 / 9 |
|
0.00% |
0 / 1 |
6.40 | |||
| deduceQuoteToUse | |
83.33% |
10 / 12 |
|
0.00% |
0 / 1 |
6.17 | |||
| createDayRecord | |
100.00% |
59 / 59 |
|
100.00% |
1 / 1 |
14 | |||
| publish | |
100.00% |
6 / 6 |
|
100.00% |
1 / 1 |
3 | |||
| publishSingle | |
90.00% |
18 / 20 |
|
0.00% |
0 / 1 |
3.01 | |||
| updatePopularTags | |
100.00% |
3 / 3 |
|
100.00% |
1 / 1 |
1 | |||
| updateSolvedCounts | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
1 | |||
| 1 | <?php |
| 2 | |
| 3 | App::uses('TsumegoUtil', 'Util'); |
| 4 | |
| 5 | class CronController extends AppController |
| 6 | { |
| 7 | /* Supposed to be ran daily to reset hearts and hero powers */ |
| 8 | public function daily($secret) |
| 9 | { |
| 10 | if ($secret != CRON_SECRET) |
| 11 | { |
| 12 | $this->response->statusCode(403); |
| 13 | $this->response->body('Wrong cron secret.'); |
| 14 | return $this->response; |
| 15 | } |
| 16 | $this->dailyTsumegoStatusReset(); |
| 17 | $this->dailyStalingSolvedTsumegoStatuses(); |
| 18 | self::createDayRecord(); |
| 19 | self::publish(); |
| 20 | $this->dailyUsersReset(); |
| 21 | $this->updatePopularTags(); |
| 22 | $this->updateSolvedCounts(); |
| 23 | |
| 24 | $this->response->statusCode(200); |
| 25 | return $this->response; |
| 26 | } |
| 27 | |
| 28 | private function dailyUsersReset() |
| 29 | { |
| 30 | $query = 'UPDATE user SET'; |
| 31 | $query .= ' used_refinement=0'; |
| 32 | $query .= ',used_sprint=0'; |
| 33 | $query .= ',used_rejuvenation=0'; |
| 34 | $query .= ',used_potion=0'; |
| 35 | $query .= ',used_intuition=0'; |
| 36 | $query .= ',used_revelation=0'; |
| 37 | $query .= ',damage=0'; |
| 38 | $query .= ',daily_xp=0'; |
| 39 | $query .= ',daily_solved=0'; |
| 40 | $query .= ',readingTrial=30'; |
| 41 | $query .= ',reuse4=0'; |
| 42 | ClassRegistry::init('User')->query($query); |
| 43 | } |
| 44 | |
| 45 | private function dailyTsumegoStatusReset() |
| 46 | { |
| 47 | ClassRegistry::init('TsumegoStatus')->query("UPDATE tsumego_status SET status='V' where status='F'"); |
| 48 | ClassRegistry::init('TsumegoStatus')->query("UPDATE tsumego_status SET status='W' where status='X'"); |
| 49 | } |
| 50 | |
| 51 | private function dailyStalingSolvedTsumegoStatuses() |
| 52 | { |
| 53 | ClassRegistry::init('TsumegoStatus')->query(" |
| 54 | UPDATE tsumego_status |
| 55 | SET status='W' |
| 56 | WHERE |
| 57 | status='S' AND |
| 58 | tsumego_status.updated < '" . date('Y-m-d H:i:s', strtotime('-7 days')) . "'"); |
| 59 | } |
| 60 | |
| 61 | private static function deduceUserOfTheDay(): ?array |
| 62 | { |
| 63 | $lastDayRecords = ClassRegistry::init('DayRecord')->find('all', ['limit' => '7', 'order' => 'date DESC']) ?: []; |
| 64 | |
| 65 | $excludedUsers = []; |
| 66 | foreach ($lastDayRecords as $lastDayRecord) |
| 67 | $excludedUsers[$lastDayRecord['DayRecord']['user_id']] = true; |
| 68 | |
| 69 | $topUsers = ClassRegistry::init('User')->find('all', ['limit' => '8', 'order' => 'daily_xp DESC']) ?: []; |
| 70 | foreach ($topUsers as $user) |
| 71 | if (!isset($excludedUsers[$user['User']['id']])) |
| 72 | return $user; |
| 73 | return null; |
| 74 | } |
| 75 | |
| 76 | private static function deduceQuoteToUse(): string |
| 77 | { |
| 78 | $latestDayRecords = ClassRegistry::init('DayRecord')->find('all', ['conditions' => ['date' => date('Y-m-d', strtotime('-10 days'))]]) ?: []; |
| 79 | $usedQuotes = []; |
| 80 | foreach ($latestDayRecords as $latestDayRecord) |
| 81 | $usedQuotes[$latestDayRecord['DayRecord']['quote']] = true; |
| 82 | |
| 83 | $allQuotes = []; |
| 84 | for ($i = 1; $i < 13; $i++) |
| 85 | $allQuotes[] = sprintf('q%02d', $i); |
| 86 | shuffle($allQuotes); |
| 87 | foreach ($allQuotes as $quote) |
| 88 | if (!isset($usedQuotes[$quote])) |
| 89 | return $quote; |
| 90 | throw new Exception("Quote couldn't be generated"); |
| 91 | } |
| 92 | |
| 93 | private function createDayRecord() |
| 94 | { |
| 95 | $userOfTheDay = self::deduceUserOfTheDay(); |
| 96 | $currentQuote = self::deduceQuoteToUse(); |
| 97 | $today = date('Y-m-d'); |
| 98 | $activity = $this->TsumegoAttempt->find('all', ['limit' => 40000, 'conditions' => ['created' => date('Y-m-d', strtotime('yesterday'))]]) ?: []; |
| 99 | $visitedProblems = count($activity); |
| 100 | |
| 101 | //how many users today |
| 102 | $usersNum = []; |
| 103 | $activities = $this->User->find('all', ['limit' => 400, 'order' => 'created DESC']) ?: []; |
| 104 | foreach ($activities as $activity) |
| 105 | { |
| 106 | $a = new DateTime($activity['User']['created']); |
| 107 | if ($a->format('Y-m-d') == $today) |
| 108 | array_push($usersNum, $activity['User']); |
| 109 | } |
| 110 | $gemRand1 = rand(0, 2); |
| 111 | $gemRand2 = rand(0, 2); |
| 112 | $gemRand3 = rand(0, 2); |
| 113 | |
| 114 | $arch1 = ClassRegistry::init('Achievement')->findById(111); |
| 115 | if ($gemRand1 == 0) |
| 116 | $arch1['Achievement']['description'] = 'Has a chance to trigger once a day on an easy ddk problem.'; |
| 117 | elseif ($gemRand1 == 1) |
| 118 | $arch1['Achievement']['description'] = 'Has a chance to trigger once a day on a regular ddk problem.'; |
| 119 | elseif ($gemRand1 == 2) |
| 120 | $arch1['Achievement']['description'] = 'Has a chance to trigger once a day on a difficult ddk problem.'; |
| 121 | ClassRegistry::init('Achievement')->save($arch1); |
| 122 | $arch2 = ClassRegistry::init('Achievement')->findById(112); |
| 123 | if ($gemRand2 == 0) |
| 124 | $arch2['Achievement']['description'] = 'Has a chance to trigger once a day on an easy sdk problem.'; |
| 125 | elseif ($gemRand2 == 1) |
| 126 | $arch2['Achievement']['description'] = 'Has a chance to trigger once a day on a regular sdk problem.'; |
| 127 | elseif ($gemRand2 == 2) |
| 128 | $arch2['Achievement']['description'] = 'Has a chance to trigger once a day on a difficult sdk problem.'; |
| 129 | ClassRegistry::init('Achievement')->save($arch2); |
| 130 | $arch3 = ClassRegistry::init('Achievement')->findById(113); |
| 131 | if ($gemRand3 == 0) |
| 132 | $arch3['Achievement']['description'] = 'Has a chance to trigger once a day on an easy dan problem.'; |
| 133 | elseif ($gemRand3 == 1) |
| 134 | $arch3['Achievement']['description'] = 'Has a chance to trigger once a day on a regular dan problem.'; |
| 135 | elseif ($gemRand3 == 2) |
| 136 | $arch3['Achievement']['description'] = 'Has a chance to trigger once a day on a difficult dan problem.'; |
| 137 | ClassRegistry::init('Achievement')->save($arch3); |
| 138 | |
| 139 | ClassRegistry::init('DayRecord')->create(); |
| 140 | $dayRecord = []; |
| 141 | $dayRecord['DayRecord']['user_id'] = $userOfTheDay['User']['id']; |
| 142 | $dayRecord['DayRecord']['date'] = $today; |
| 143 | $dayRecord['DayRecord']['solved'] = $userOfTheDay['User']['daily_solved']; |
| 144 | $dayRecord['DayRecord']['quote'] = $currentQuote; |
| 145 | $dayRecord['DayRecord']['usercount'] = count($usersNum); |
| 146 | $dayRecord['DayRecord']['visitedproblems'] = $visitedProblems; |
| 147 | $dayRecord['DayRecord']['gems'] = $gemRand1 . '-' . $gemRand2 . '-' . $gemRand3; |
| 148 | $dayRecord['DayRecord']['gemCounter1'] = 0; |
| 149 | $dayRecord['DayRecord']['gemCounter2'] = 0; |
| 150 | $dayRecord['DayRecord']['gemCounter3'] = 0; |
| 151 | $dayRecord['DayRecord']['tsumego_count'] = TsumegoUtil::currentTsumegoCount(); |
| 152 | ClassRegistry::init('DayRecord')->save($dayRecord); |
| 153 | |
| 154 | ClassRegistry::init('AchievementCondition')->create(); |
| 155 | $achievementCondition = []; |
| 156 | $achievementCondition['AchievementCondition']['user_id'] = $userOfTheDay['User']['id']; |
| 157 | $achievementCondition['AchievementCondition']['set_id'] = null; |
| 158 | $achievementCondition['AchievementCondition']['category'] = 'uotd'; |
| 159 | $achievementCondition['AchievementCondition']['value'] = 1; |
| 160 | ClassRegistry::init('AchievementCondition')->save($achievementCondition); |
| 161 | } |
| 162 | |
| 163 | public static function publish() |
| 164 | { |
| 165 | $date = date('Y-m-d', strtotime('today')); |
| 166 | $todaysSchedule = ClassRegistry::init('Schedule')->find('all', ['conditions' => ['date' => $date]]) ?: []; |
| 167 | foreach ($todaysSchedule as $item) |
| 168 | { |
| 169 | self::publishSingle($item['Schedule']['tsumego_id'], $item['Schedule']['set_id'], $item['Schedule']['date']); |
| 170 | $item['Schedule']['published'] = 1; |
| 171 | ClassRegistry::init('Schedule')->save($item); |
| 172 | } |
| 173 | } |
| 174 | |
| 175 | protected static function publishSingle($tsumegoID = null, $to = null, $date = null): void |
| 176 | { |
| 177 | $tsumego = ClassRegistry::init('Tsumego')->findById($tsumegoID); |
| 178 | if (!$tsumego) |
| 179 | return; |
| 180 | $setConnection = ClassRegistry::init('SetConnection')->find('first', ['conditions' => ['tsumego_id' => $tsumegoID]]); |
| 181 | if (!$setConnection) |
| 182 | return; |
| 183 | $setConnection['SetConnection']['set_id'] = $to; |
| 184 | ClassRegistry::init('SetConnection')->save($setConnection); |
| 185 | |
| 186 | // delete tsumego stats |
| 187 | $tsumego['Tsumego']['created'] = $date . ' 22:00:00'; |
| 188 | $tsumego['Tsumego']['solved'] = 0; |
| 189 | $tsumego['Tsumego']['failed'] = 0; |
| 190 | $tsumego['Tsumego']['userWin'] = 0; |
| 191 | $tsumego['Tsumego']['userLoss'] = 0; |
| 192 | ClassRegistry::init('Tsumego')->save($tsumego); |
| 193 | |
| 194 | // delete any status made on the tsumego when it was in the sandbox |
| 195 | ClassRegistry::init('TsumegoStatus')->deleteAll(['tsumego_id' => $tsumego['Tsumego']['id']]); |
| 196 | |
| 197 | $x = []; |
| 198 | $x['PublishDate']['date'] = $date . ' 22:00:00'; |
| 199 | $x['PublishDate']['tsumego_id'] = $tsumegoID; |
| 200 | ClassRegistry::init('PublishDate')->create(); |
| 201 | ClassRegistry::init('PublishDate')->save($x); |
| 202 | } |
| 203 | |
| 204 | private static function updatePopularTags() |
| 205 | { |
| 206 | ClassRegistry::init('Tag')->query(" |
| 207 | UPDATE tag |
| 208 | JOIN ( |
| 209 | SELECT tag_id |
| 210 | FROM tag_connection |
| 211 | GROUP BY tag_id |
| 212 | ORDER BY COUNT(*) DESC |
| 213 | LIMIT " . Tag::$POPULAR_COUNT . " |
| 214 | ) AS top_tags ON tag.id = top_tags.tag_id |
| 215 | SET tag.popular = 1;"); |
| 216 | } |
| 217 | |
| 218 | private static function updateSolvedCounts() |
| 219 | { |
| 220 | Util::query("UPDATE user u |
| 221 | LEFT JOIN ( |
| 222 | SELECT user_id, COUNT(*) AS cnt |
| 223 | FROM tsumego_status |
| 224 | WHERE status IN ('S', 'W', 'C', 'X') |
| 225 | GROUP BY user_id |
| 226 | ) ts ON ts.user_id = u.id |
| 227 | SET u.solved = COALESCE(ts.cnt, 0)"); |
| 228 | } |
| 229 | } |