Passed
Push — master ( 344a76...0f8f50 )
by jean
02:53
created

ProgressBar::setOutput()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 1
dl 0
loc 3
ccs 2
cts 2
cp 1
crap 1
rs 10
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Darkilliant\ProcessBundle\Console;
6
7
use Symfony\Component\Console\Helper\Helper;
8
use Symfony\Component\Console\Helper\ProgressBar as SymfonyProgressBar;
9
use Symfony\Component\Console\Output\NullOutput;
10
use Symfony\Component\Console\Output\OutputInterface;
11
12
/**
13
 * @internal
14
 * Class ProgressBar
15
 */
16
class ProgressBar
17
{
18
    const INTERVAL_MONITORING = [1, 10, 20];
19
    /** @var OutputInterface */
20
    private $output;
21
    /** @var SymfonyProgressBar */
22
    private $progressBar;
23
24
    private $timelineMemory = [];
25
    private $intervalMemory = [-1, -1, -1];
26
    private $maxMemory;
27
28
    private $timelineItemPerSecond = [];
29
    private $intervalItemPerSecond = [-1, -1, -1];
30
    private $minItemPerSecond;
31
32
    private $lastTimeUpdated;
33
    private $timeElapsed = 0;
34
    private $previousItemCount = 0;
35
36 6
    public function setOutput($output)
37
    {
38 6
        $this->output = $output;
39 6
    }
40
41 5
    public function create($size, $title = 'Progression', $maxMemory = 30, $minItemPerSecond = 50)
42
    {
43 5
        $this->init();
44 5
        $this->maxMemory = $maxMemory;
45 5
        $this->minItemPerSecond = $minItemPerSecond;
46
47 5
        $this->progressBar =
48 5
            ($this->output->getVerbosity() > OutputInterface::VERBOSITY_NORMAL)
49 1
            ? new SymfonyProgressBar(new NullOutput(), $size)
50 4
            : new SymfonyProgressBar($this->output, $size);
51 5
        SymfonyProgressBar::setPlaceholderFormatterDefinition('memory', [$this, 'renderRightbar']);
52 5
        $this->progressBar->setFormat(" \033[44;37m %title:-37s% \033[0m\n %current%/%max% %bar% %percent:3s%%\n 🏁  %remaining:-10s% %memory:37s%");
53 5
        $this->progressBar->setBarCharacter($done = "\033[32m=\033[0m");
54 5
        $this->progressBar->setEmptyBarCharacter($empty = "\033[31m \033[0m");
55 5
        $this->progressBar->setProgressCharacter($progress = "\033[32m>\033[0m");
56 5
        $this->progressBar->setBarWidth(400);
57 5
        $this->progressBar->setMessage($title, 'title');
58 5
        $this->progressBar->start();
59 5
    }
60
61 4
    public function renderRightbar(SymfonyProgressBar $bar)
0 ignored issues
show
Unused Code introduced by
The parameter $bar is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

61
    public function renderRightbar(/** @scrutinizer ignore-unused */ SymfonyProgressBar $bar)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
62
    {
63 4
        return sprintf(
64 4
            'MEMORY %s / ITEMS %s',
65 4
            implode(' ', $this->intervalMemory),
66 4
            implode(' ', $this->intervalItemPerSecond)
67
        );
68
    }
69
70 4
    public function setProgress($progress)
71
    {
72 4
        if ($this->isUpdate()) {
73 2
            $this->updateMemory();
74 2
            $this->updateItemPerSecond();
75 2
            $this->progressBar->setProgress($progress);
76
        }
77 4
    }
78
79 1
    public function advance()
80
    {
81 1
        if ($this->isUpdate()) {
82 1
            $this->updateMemory();
83 1
            $this->updateItemPerSecond();
84 1
            $this->progressBar->advance();
85
        }
86 1
    }
87
88 1
    public function finish()
89
    {
90 1
        $this->progressBar->finish();
91
92 1
        $this->itemCount = [];
0 ignored issues
show
Bug Best Practice introduced by
The property itemCount does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
93 1
    }
94
95 5
    private function init()
96
    {
97 5
        $this->timelineMemory = [];
98 5
        $this->intervalMemory = [-1, -1, -1];
99
100 5
        $this->timelineItemPerSecond = [];
101 5
        $this->intervalItemPerSecond = [-1, -1, -1];
102
103 5
        $this->lastTimeUpdated = time();
104 5
        $this->previousItemCount = 0;
105 5
    }
106
107 4
    private function isUpdate()
108
    {
109 4
        if (null === $this->progressBar) {
110 1
            return;
111
        }
112
113 3
        $time = time();
114
115 3
        if ($time > $this->lastTimeUpdated) {
116 2
            $this->timeElapsed = $time - $this->lastTimeUpdated;
117 2
            $this->lastTimeUpdated = $time;
118
119 2
            return true;
120
        }
121
122 1
        return false;
123
    }
124
125 2
    private function updateMemory()
126
    {
127 2
        $time = time();
128
129 2
        if (count($this->timelineMemory) > self::INTERVAL_MONITORING[2]) {
130 1
            $this->timelineMemory = array_slice($this->timelineMemory, 1, null, true);
131
        }
132
133 2
        $this->timelineMemory[$time] = $now = memory_get_usage(true);
134
135 2
        $this->intervalMemory[0] = $this->formatMemory(
136 2
            $this->timelineMemory[$time - self::INTERVAL_MONITORING[0]] ?? $now,
137 2
            self::INTERVAL_MONITORING[0]
138
        );
139 2
        $this->intervalMemory[1] = $this->formatMemory(
140 2
            $this->timelineMemory[$time - self::INTERVAL_MONITORING[1]] ?? -1,
141 2
            self::INTERVAL_MONITORING[1]
142
        );
143 2
        $this->intervalMemory[2] = $this->formatMemory(
144 2
            $this->timelineMemory[$time - self::INTERVAL_MONITORING[2]] ?? -1,
145 2
            self::INTERVAL_MONITORING[2]
146
        );
147 2
    }
148
149 2
    private function updateItemPerSecond()
150
    {
151 2
        $time = time();
152
153 2
        if (count($this->timelineItemPerSecond) > self::INTERVAL_MONITORING[2]) {
154 1
            $this->timelineItemPerSecond = array_slice($this->timelineItemPerSecond, 1, null, true);
155
        }
156
157 2
        $this->timelineItemPerSecond[$time] = $now = ($this->progressBar->getProgress() - $this->previousItemCount) / $this->timeElapsed;
158 2
        $this->previousItemCount = $this->progressBar->getProgress();
159
160 2
        $this->intervalItemPerSecond[0] = $this->formatItemsCount(
161 2
            $this->timelineItemPerSecond[$time - self::INTERVAL_MONITORING[0]] ?? $now,
162 2
            self::INTERVAL_MONITORING[0]
163
        );
164 2
        $this->intervalItemPerSecond[1] = $this->formatItemsCount(
165 2
            $this->timelineItemPerSecond[$time - self::INTERVAL_MONITORING[1]] ?? -1,
166 2
            self::INTERVAL_MONITORING[1]
167
        );
168 2
        $this->intervalItemPerSecond[2] = $this->formatItemsCount(
169 2
            $this->timelineItemPerSecond[$time - self::INTERVAL_MONITORING[2]] ?? -1,
170 2
            self::INTERVAL_MONITORING[2]
171
        );
172 2
    }
173
174 2
    private function formatMemory($memory, $time)
175
    {
176 2
        $colors = (($memory / 1000) > $this->maxMemory * 1000) ? '41;37' : '44;37';
177 2
        $message = $time.'s = '.Helper::formatMemory($memory);
178
179 2
        return "\033[".$colors.'m '.$message." \033[0m";
180
    }
181
182 2
    private function formatItemsCount($itemsCount, $time)
183
    {
184 2
        $colors = ($itemsCount < $this->minItemPerSecond) ? '41;37' : '44;37';
185 2
        $message = $time.'s = '.$itemsCount;
186
187 2
        return "\033[".$colors.'m '.$message."/s \033[0m";
188
    }
189
}
190