Passed
Pull Request — master (#1887)
by Janko
53:41
created

EndLotteryPeriod   A

Complexity

Total Complexity 17

Size/Duplication

Total Lines 184
Duplicated Lines 0 %

Test Coverage

Coverage 0%

Importance

Changes 0
Metric Value
eloc 98
dl 0
loc 184
ccs 0
cts 110
cp 0
rs 10
c 0
b 0
f 0
wmc 17

5 Methods

Rating   Name   Duplication   Size   Complexity  
A payOutLatinum() 0 18 1
B handle() 0 85 11
A createAwardAndPrestige() 0 18 2
A transmitShip() 0 36 2
A __construct() 0 15 1
1
<?php
2
3
namespace Stu\Module\Maintenance;
4
5
use Override;
0 ignored issues
show
Bug introduced by
The type Override was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
6
use RuntimeException;
7
use Stu\Component\Player\UserAwardEnum;
0 ignored issues
show
Bug introduced by
The type Stu\Component\Player\UserAwardEnum was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
8
use Stu\Component\Trade\TradeEnum;
0 ignored issues
show
Bug introduced by
The type Stu\Component\Trade\TradeEnum was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
9
use Stu\Module\Award\Lib\CreateUserAwardInterface;
10
use Stu\Module\Commodity\CommodityTypeEnum;
0 ignored issues
show
Bug introduced by
The type Stu\Module\Commodity\CommodityTypeEnum was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
11
use Stu\Module\Control\StuRandom;
12
use Stu\Module\Control\StuTime;
13
use Stu\Module\Message\Lib\PrivateMessageFolderTypeEnum;
14
use Stu\Module\Message\Lib\PrivateMessageSenderInterface;
15
use Stu\Module\PlayerSetting\Lib\UserEnum;
0 ignored issues
show
Bug introduced by
The type Stu\Module\PlayerSetting\Lib\UserEnum was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
16
use Stu\Module\Prestige\Lib\CreatePrestigeLogInterface;
17
use Stu\Module\Ship\Lib\ShipCreatorInterface;
18
use Stu\Module\Trade\Lib\LotteryFacadeInterface;
19
use Stu\Module\Trade\Lib\TradeLibFactoryInterface;
20
use Stu\Orm\Entity\LotteryWinnerBuildplanInterface;
21
use Stu\Orm\Entity\TradePostInterface;
22
use Stu\Orm\Entity\UserInterface;
23
use Stu\Orm\Repository\AwardRepositoryInterface;
24
use Stu\Orm\Repository\LotteryTicketRepositoryInterface;
25
use Stu\Orm\Repository\LotteryWinnerBuildplanRepositoryInterface;
26
use Stu\Orm\Repository\TradePostRepositoryInterface;
27
use Stu\Orm\Repository\UserRepositoryInterface;
28
29
final class EndLotteryPeriod implements MaintenanceHandlerInterface
30
{
31
    public function __construct(
32
        private LotteryTicketRepositoryInterface $lotteryTicketRepository,
33
        private TradePostRepositoryInterface $tradepostRepository,
34
        private AwardRepositoryInterface $awardRepository,
35
        private LotteryWinnerBuildplanRepositoryInterface $lotteryWinnerBuildplanRepository,
36
        private UserRepositoryInterface $userRepository,
37
        private LotteryFacadeInterface $lotteryFacade,
38
        private TradeLibFactoryInterface $tradeLibFactory,
39
        private CreateUserAwardInterface $createUserAward,
40
        private ShipCreatorInterface $shipCreator,
41
        private CreatePrestigeLogInterface $createPrestigeLog,
42
        private PrivateMessageSenderInterface $privateMessageSender,
43
        private StuTime $stuTime,
44
        private StuRandom $stuRandom
45
    ) {}
46
47
    #[Override]
48
    public function handle(): void
49
    {
50
        $time = $this->stuTime->time();
51
        $day = (int)date("j", $time);
52
53
        if ($day !== 1) {
54
            return;
55
        }
56
57
        $tickets = $this->lotteryFacade->getTicketsOfLastPeriod();
58
        $ticketCount = count($tickets);
59
60
        if ($ticketCount === 0) {
61
            return;
62
        }
63
64
        $tradePost = $this->tradepostRepository->getFergTradePost(TradeEnum::DEALS_FERG_TRADEPOST_ID);
65
        if ($tradePost === null) {
66
            throw new RuntimeException('no deals ferg tradepost found');
67
        }
68
69
        $jackpot = (int)ceil($ticketCount / 100 * 80);
70
71
        $winnerIndex = random_int(0, $ticketCount - 1);
72
        $losers = [];
73
        $winner = null;
74
75
        //set winner and loser
76
        for ($i = 0; $i < $ticketCount; $i++) {
77
            $ticket = $tickets[$i];
78
            $user = $ticket->getUser();
79
80
            if ($i === $winnerIndex) {
81
                $ticket->setIsWinner(true);
82
                $winner = $user;
83
84
                //jackpot to winner
85
                $this->createAwardAndPrestige($winner, $time);
86
                $this->payOutLatinum($winner, $jackpot, $ticketCount, $tradePost);
87
                $this->transmitShip($winner, $tradePost);
88
            } else {
89
                $ticket->setIsWinner(false);
90
91
                $losers[$user->getId()] = $user;
92
            }
93
94
            $this->lotteryTicketRepository->save($ticket);
95
        }
96
97
        if ($winner === null) {
98
            return;
99
        }
100
101
        //PM to all losers
102
        foreach ($losers as $loserId => $user) {
103
            //skip winner if he had more than one ticket
104
            if ($user === $winner) {
105
                continue;
106
            }
107
108
            $this->privateMessageSender->send(
109
                $tradePost->getUserId(),
110
                $loserId,
111
                sprintf(
112
                    "%s hat %d Latinum in der Lotterie gewonnen.\nEs waren %d Lose im Topf.\nViel Glück beim nächsten Mal!",
113
                    $winner->getName(),
114
                    $jackpot,
115
                    $ticketCount
116
                ),
117
                PrivateMessageFolderTypeEnum::SPECIAL_TRADE
118
            );
119
        }
120
121
        $userCount = $this->userRepository->getActiveAmount();
122
123
        //give random users a ticket
124
        foreach ($this->userRepository->getNonNpcList() as $user) {
125
            $winRateInPercent = 10 * ($user->getId() - UserEnum::USER_FIRST_ID) / $userCount;
126
127
            if (random_int(1, 100) > $winRateInPercent) {
128
                continue;
129
            }
130
131
            $this->lotteryFacade->createLotteryTicket($user, true);
132
        }
133
    }
134
135
    private function createAwardAndPrestige(UserInterface $user, int $time): void
136
    {
137
        $award = $this->awardRepository->find(UserAwardEnum::LOTTERY_WINNER);
138
139
        if ($award !== null) {
140
            $this->createUserAward->createAwardForUser(
141
                $user,
142
                $award
143
            );
144
        }
145
146
        $amount = $this->lotteryFacade->getTicketAmountByUser($user->getId(), true);
147
148
        $this->createPrestigeLog->createLog(
149
            $amount,
150
            sprintf('%1$d Prestige erhalten für den Erwerb von %1$d Losen in der letzten Lotterieziehung', $amount),
151
            $user,
152
            $time
153
        );
154
    }
155
156
    private function payOutLatinum(UserInterface $winner, int $jackpot, int $ticketCount, TradePostInterface $tradePost): void
157
    {
158
        $storageManagerUser = $this->tradeLibFactory->createTradePostStorageManager($tradePost, $winner);
159
160
        $storageManagerUser->upperStorage(
161
            CommodityTypeEnum::COMMODITY_LATINUM,
162
            $jackpot
163
        );
164
165
        $this->privateMessageSender->send(
166
            $tradePost->getUserId(),
167
            $winner->getId(),
168
            sprintf(
169
                "Du hast %d Latinum in der Lotterie gewonnen.\nEs waren %d Lose im Topf.\nDer Gewinn wartet auf dich am Handelsposten 'Zur goldenen Kugel'",
170
                $jackpot,
171
                $ticketCount
172
            ),
173
            PrivateMessageFolderTypeEnum::SPECIAL_TRADE
174
        );
175
    }
176
177
    private function transmitShip(UserInterface $winner, TradePostInterface $tradePost): void
178
    {
179
        /** @var array<int, LotteryWinnerBuildplanInterface> */
180
        $winnerBuildplans = $this->lotteryWinnerBuildplanRepository->findAll();
181
        if (empty($winnerBuildplans)) {
182
            return;
183
        }
184
185
        $chances = array_map(fn(LotteryWinnerBuildplanInterface $winnerBuildplan) => $winnerBuildplan->getChance(), $winnerBuildplans);
186
187
        $randomKey = $this->stuRandom->randomKeyOfProbabilities($chances);
188
        $buildplan = $winnerBuildplans[$randomKey]->getBuildplan();
189
190
        $wrapper = $this->shipCreator
191
            ->createBy(
192
                $winner->getId(),
193
                $buildplan->getRumpId(),
194
                $buildplan->getId()
195
            )->setLocation($tradePost->getShip()->getLocation())
196
            ->setShipName(sprintf(
197
                'Lotteriegewinn (%s)',
198
                $this->stuTime->transformToStuDate(time())
199
            ))
200
            ->finishConfiguration();
201
202
        $ship = $wrapper->get();
203
204
        $this->privateMessageSender->send(
205
            $tradePost->getUserId(),
206
            $winner->getId(),
207
            sprintf(
208
                "Als zusätzlicher Lotteriegewinn wurde dir ein Schiff der %s-Klasse zu den Koordinaten %s am Handelsposten 'Zur goldenen Kugel' überstellt.",
209
                $ship->getRumpName(),
210
                $ship->getSectorString()
211
            ),
212
            PrivateMessageFolderTypeEnum::SPECIAL_SHIP
213
        );
214
    }
215
}
216