Code Coverage
 
Lines
Branches
Paths
Functions and Methods
Classes and Traits
Total
79.17% covered (warning)
79.17%
38 / 48
4.55% covered (danger)
4.55%
1 / 22
4.35% covered (danger)
4.35%
1 / 23
50.00% covered (danger)
50.00%
1 / 2
CRAP
0.00% covered (danger)
0.00%
0 / 1
GenerateNicksCommand
79.17% covered (warning)
79.17%
38 / 48
4.55% covered (danger)
4.55%
1 / 22
4.35% covered (danger)
4.35%
1 / 23
50.00% covered (danger)
50.00%
1 / 2
116.89
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 __invoke
78.72% covered (warning)
78.72%
37 / 47
0.00% covered (danger)
0.00%
0 / 21
0.00% covered (danger)
0.00%
0 / 22
0.00% covered (danger)
0.00%
0 / 1
10.96
1<?php
2
3namespace App\Command;
4
5use App\Application\UseCase\GenerateNickInterface;
6use App\Dto\Command\GenerateNickCommand;
7use App\Enum\Lang;
8use App\Enum\OffenseLevel;
9use App\Enum\WordGender;
10use Symfony\Component\Console\Attribute\AsCommand;
11use Symfony\Component\Console\Attribute\Option;
12use Symfony\Component\Console\Command\Command;
13use Symfony\Component\Console\Input\InputInterface;
14use Symfony\Component\Console\Output\OutputInterface;
15use Symfony\Component\Console\Style\SymfonyStyle;
16use Symfony\Component\Stopwatch\Stopwatch;
17
18/**
19 * @author Wilhelm Zwertvaegher
20 */
21#[AsCommand(name: 'app:generate-nicks')]
22class GenerateNicksCommand extends Command
23{
24    public function __construct(
25        private readonly GenerateNickInterface $generateNick,
26        private readonly Stopwatch $stopwatch,
27    ) {
28        parent::__construct();
29    }
30
31    public function __invoke(
32        InputInterface $input,
33        OutputInterface $output,
34        #[Option('Number of nicks to generate', 'number')] string $numberOfNicksToGenerateStr = '10',
35        #[Option('Target lang.')] string $targetLangStr = 'fr',
36        #[Option('Target offense level.', 'offense-level')] ?string $offenseLevelStr = null,
37        #[Option('Target gender.')] ?string $targetGenderStr = null,
38    ): int {
39        $offenseLevel = $targetGender = null;
40
41        if (!filter_var($numberOfNicksToGenerateStr, FILTER_VALIDATE_INT)) {
42            throw new \InvalidArgumentException('Number of nicks to generate must be an integer');
43        }
44        if (null !== $offenseLevelStr && !filter_var($offenseLevelStr, FILTER_VALIDATE_INT)) {
45            throw new \InvalidArgumentException('Offense level must be a known value of OffenseLevel enum');
46        }
47
48        if (null !== $offenseLevelStr) {
49            try {
50                $offenseLevel = OffenseLevel::from((int) $offenseLevelStr);
51            } catch (\ValueError $exception) {
52                throw new \InvalidArgumentException('Offense level must be a known value of OffenseLevel enum');
53            }
54        }
55
56        if (null !== $targetGenderStr) {
57            try {
58                $targetGender = WordGender::from($targetGenderStr);
59            } catch (\ValueError $exception) {
60                throw new \InvalidArgumentException('Gender must be a known value of WordGender enum');
61            }
62        }
63
64        try {
65            $targetLang = Lang::from($targetLangStr);
66        } catch (\ValueError $exception) {
67            throw new \InvalidArgumentException('Target lang must be a known value of Lang enum');
68        }
69
70        $io = new SymfonyStyle($input, $output);
71
72        $numberOfNicksToGenerate = (int) $numberOfNicksToGenerateStr;
73
74        $output->writeln("Generating {$numberOfNicksToGenerate} nicks");
75        $io->section('Nicks generation');
76        $io->comment('Warming up services...');
77
78        // first generation to warm up services and DI
79        ($this->generateNick)(new GenerateNickCommand($targetLang, $targetGender, $offenseLevel));
80
81        $this->stopwatch->start('global');
82        $this->stopwatch->start('nick');
83
84        for ($i = 0; $i < $numberOfNicksToGenerate; ++$i) {
85            $nickData = ($this->generateNick)(
86                new GenerateNickCommand($targetLang, $targetGender, $offenseLevel)
87            );
88
89            $event = $this->stopwatch->lap('nick');
90            $lastPeriod = $event->getPeriods()[array_key_last($event->getPeriods())];
91
92            $io->text(sprintf(
93                '<info>%d</info> →  %s <comment>%.2f ms</comment>',
94                $i + 1,
95                $nickData->getNick()->getLabel(),
96                $lastPeriod->getDuration()
97            ));
98        }
99
100        $globalEvent = $this->stopwatch->stop('global');
101        $nickEvent = $this->stopwatch->getEvent('nick');
102        $durations = array_map(fn ($p) => $p->getDuration(), $nickEvent->getPeriods());
103
104        $io->section('Summary');
105        $io->definitionList(
106            ['Total nicks' => count($durations)],
107            ['Total duration' => sprintf('%.2f ms', $globalEvent->getDuration())],
108            ['Min duration' => sprintf('%.2f ms', min($durations))],
109            ['Max duration' => sprintf('%.2f ms', max($durations))],
110        );
111
112        return Command::SUCCESS;
113    }
114}