|
1
|
|
|
<?php declare(strict_types=1); |
|
2
|
|
|
|
|
3
|
|
|
namespace Smr; |
|
4
|
|
|
|
|
5
|
|
|
use SmrGame; |
|
6
|
|
|
use SmrPlayer; |
|
7
|
|
|
|
|
8
|
|
|
/** |
|
9
|
|
|
* Collection of functions to help with Lotto processing. |
|
10
|
|
|
*/ |
|
11
|
|
|
class Lotto { |
|
12
|
|
|
|
|
13
|
|
|
public const TICKET_COST = 1000000; // cost of 1 ticket |
|
14
|
|
|
public const WIN_FRAC = 0.9; // fraction of ticket sales returned to winner |
|
15
|
|
|
|
|
16
|
|
|
public static function checkForLottoWinner(int $gameID): void { |
|
17
|
|
|
|
|
18
|
|
|
// No more lotto winners after the game has ended |
|
19
|
|
|
if (SmrGame::getGame($gameID)->hasEnded()) { |
|
20
|
|
|
return; |
|
21
|
|
|
} |
|
22
|
|
|
|
|
23
|
|
|
// we check for a lotto winner... |
|
24
|
|
|
$db = Database::getInstance(); |
|
25
|
|
|
$db->lockTable('player_has_ticket'); |
|
26
|
|
|
$lottoInfo = self::getLottoInfo($gameID); |
|
27
|
|
|
|
|
28
|
|
|
if ($lottoInfo['TimeRemaining'] > 0) { |
|
29
|
|
|
// Drawing is not closed yet |
|
30
|
|
|
$db->unlock(); |
|
31
|
|
|
return; |
|
32
|
|
|
} |
|
33
|
|
|
|
|
34
|
|
|
//we need to pick a winner |
|
35
|
|
|
$dbResult = $db->read('SELECT * FROM player_has_ticket WHERE game_id = ' . $db->escapeNumber($gameID) . ' AND time > 0 ORDER BY rand() LIMIT 1'); |
|
36
|
|
|
$winner_id = $dbResult->record()->getInt('account_id'); |
|
37
|
|
|
|
|
38
|
|
|
// Any unclaimed prizes get merged into this prize |
|
39
|
|
|
$dbResult = $db->read('SELECT IFNULL(SUM(prize), 0) AS total_prize FROM player_has_ticket WHERE time = 0 AND game_id = ' . $db->escapeNumber($gameID)); |
|
40
|
|
|
$lottoInfo['Prize'] += $dbResult->record()->getInt('total_prize'); |
|
41
|
|
|
|
|
42
|
|
|
// Delete all tickets and re-insert the winning ticket |
|
43
|
|
|
$db->write('DELETE FROM player_has_ticket WHERE game_id = ' . $db->escapeNumber($gameID)); |
|
44
|
|
|
$db->insert('player_has_ticket', [ |
|
45
|
|
|
'game_id' => $db->escapeNumber($gameID), |
|
46
|
|
|
'account_id' => $db->escapeNumber($winner_id), |
|
47
|
|
|
'time' => 0, |
|
48
|
|
|
'prize' => $db->escapeNumber($lottoInfo['Prize']), |
|
49
|
|
|
]); |
|
50
|
|
|
$db->unlock(); |
|
51
|
|
|
|
|
52
|
|
|
// create news msg |
|
53
|
|
|
$winner = SmrPlayer::getPlayer($winner_id, $gameID); |
|
54
|
|
|
$winner->increaseHOF($lottoInfo['Prize'], ['Bar', 'Lotto', 'Money', 'Winnings'], HOF_PUBLIC); |
|
55
|
|
|
$winner->increaseHOF(1, ['Bar', 'Lotto', 'Results', 'Wins'], HOF_PUBLIC); |
|
56
|
|
|
$news_message = $winner->getBBLink() . ' has won the lotto! The jackpot was ' . number_format($lottoInfo['Prize']) . '. ' . $winner->getBBLink() . ' can report to any bar to claim their prize before the next drawing!'; |
|
57
|
|
|
// insert the news entry |
|
58
|
|
|
$db->write('DELETE FROM news WHERE type = \'lotto\' AND game_id = ' . $db->escapeNumber($gameID)); |
|
59
|
|
|
$db->insert('news', [ |
|
60
|
|
|
'game_id' => $db->escapeNumber($gameID), |
|
61
|
|
|
'time' => $db->escapeNumber(Epoch::time()), |
|
62
|
|
|
'news_message' => $db->escapeString($news_message), |
|
63
|
|
|
'type' => $db->escapeString('lotto'), |
|
64
|
|
|
'dead_id' => $db->escapeNumber($winner->getAccountID()), |
|
65
|
|
|
'dead_alliance' => $db->escapeNumber($winner->getAllianceID()), |
|
66
|
|
|
]); |
|
67
|
|
|
} |
|
68
|
|
|
|
|
69
|
|
|
/** |
|
70
|
|
|
* @return array<string, int> |
|
71
|
|
|
*/ |
|
72
|
|
|
public static function getLottoInfo(int $gameID): array { |
|
73
|
|
|
$amount = self::TICKET_COST; // pot starts with 1 ticket value |
|
74
|
|
|
$firstBuy = Epoch::time(); |
|
75
|
|
|
|
|
76
|
|
|
$db = Database::getInstance(); |
|
77
|
|
|
$dbResult = $db->read('SELECT count(*) as num, min(time) as time FROM player_has_ticket |
|
78
|
|
|
WHERE game_id = ' . $db->escapeNumber($gameID) . ' AND time > 0'); |
|
79
|
|
|
$dbRecord = $dbResult->record(); |
|
80
|
|
|
if ($dbRecord->getInt('num') > 0) { |
|
81
|
|
|
$amount += $dbRecord->getInt('num') * IFloor(self::TICKET_COST * self::WIN_FRAC); |
|
|
|
|
|
|
82
|
|
|
$firstBuy = $dbRecord->getInt('time'); |
|
83
|
|
|
} |
|
84
|
|
|
//find the time remaining in this jackpot. (which is 2 days from the first purchased ticket) |
|
85
|
|
|
return ['Prize' => $amount, 'TimeRemaining' => $firstBuy + TIME_LOTTO - Epoch::time()]; |
|
86
|
|
|
} |
|
87
|
|
|
|
|
88
|
|
|
} |
|
89
|
|
|
|