Issues (65)

src/Display/TinyProgressBar.php (1 issue)

Labels
Severity
1
<?php
2
/**
3
 * This file is part of graze/parallel-process.
4
 *
5
 * Copyright © 2018 Nature Delivered Ltd. <https://www.graze.com>
6
 *
7
 * For the full copyright and license information, please view the LICENSE
8
 * file that was distributed with this source code.
9
 *
10
 * @license https://github.com/graze/parallel-process/blob/master/LICENSE.md
11
 * @link    https://github.com/graze/parallel-process
12
 */
13
14
namespace Graze\ParallelProcess\Display;
15
16
use InvalidArgumentException;
17
18
class TinyProgressBar
19
{
20
    /**
21
     * Format for a progress bar
22
     *
23
     * Options:
24
     *  - `{bar}` The actual bar
25
     *  - `{perc}` Display the percentage e.g 2%
26
     *  - `{position}` Display the current position e.g 1
27
     *  - `{max}` Display the maximum possible value e.g 100
28
     *
29
     * Example formats:
30
     *  - `{bar} {position}/{max} {perc}`
31
     */
32
    const FORMAT_DEFAULT         = '▕<comment>{bar}</comment>▏<info>{perc}</info> {position}/{max}';
33
    const FORMAT_SHORT           = '▕<comment>{bar}</comment>▏<info>{perc}</info>';
34
    const FORMAT_BAR_ONLY        = '{bar}';
35
    const FORMAT_COLOUR_BAR_ONLY = '<comment>{bar}</comment>';
36
37
    /** @var int */
38
    private $length;
39
    /** @var string */
40
    private $format;
41
    /** @var float */
42
    private $position;
43
    /** @var float */
44
    private $max;
45
    /** @var string[] */
46
    private $bar;
47
48
    /**
49
     * TinyProgressBar constructor.
50
     *
51
     * @param int    $numChars The number of characters to use for the bar
52
     * @param string $format   The format for the bar
53
     * @param float  $max      The maximum value for a bar
54
     */
55 38
    public function __construct($numChars, $format = self::FORMAT_DEFAULT, $max = 100.0)
56
    {
57 38
        $this->setLength($numChars);
58 35
        $this->setMax($max);
59 32
        $this->format = $format;
60 32
        $this->position = 0;
61 32
        $this->bar = [" ", "▏", "▎", "▍", "▌", "▋", "▊", "▉", "█"];
62 32
    }
63
64
    /**
65
     * Sets the characters to use for a bar. A bar is n chars long (defined in the constructor), each char will use
66
     * each character in the array once.
67
     *
68
     * The first character should always be blank
69
     *
70
     * Example:
71
     *
72
     *     ->setBarCharacters([" ","▄","█"]);
73
     *
74
     *     ▄
75
     *
76
     *     █
77
     *
78
     *     █▄
79
     *
80
     *     ██
81
     *
82
     *     ██▄
83
     *
84
     *     ███
85
     *
86
     * @param array $characters
87
     *
88
     * @return $this
89
     */
90 1
    public function setBarCharacters(array $characters)
91
    {
92 1
        $this->bar = $characters;
93 1
        return $this;
94
    }
95
96
    /**
97
     * @param float $step
98
     *
99
     * @return $this
100
     */
101 1
    public function advance($step = 1.0)
102
    {
103 1
        if ($this->position < $this->max) {
104 1
            $this->position = min($this->position + $step, $this->max);
105 1
        }
106
107 1
        return $this;
108
    }
109
110
    /**
111
     * @return string
112
     */
113 18
    public function render()
114
    {
115 18
        $percentage = round($this->position / $this->max, 2);
116
117
        // number of chars to display
118 18
        $displayChars = ceil($percentage * $this->length);
119 18
        if ($displayChars == 0) {
120 4
            $displayChars = 1;
121 4
        }
122
123
        // normalise the percentage to this character
124 18
        $percentageStep = 1 / $this->length;
125 18
        $minPercentage = $percentageStep * ($displayChars - 1);
126 18
        $maxPercentage = $minPercentage + $percentageStep;
127 18
        $charPercentage = ($percentage - $minPercentage) / ($maxPercentage - $minPercentage);
128 18
        if ($charPercentage == 0) {
129 4
            $charIndex = 0;
130 4
        } else {
131 16
            $charIndex = (int) (floor((count($this->bar) - 2) * $charPercentage) + 1);
132
        }
133 18
        $char = $this->bar[$charIndex];
134
135 18
        $bar = sprintf(
136 18
            '%s%s%s',
137 18
            str_repeat(end($this->bar), $displayChars - 1),
0 ignored issues
show
$displayChars - 1 of type double is incompatible with the type integer expected by parameter $multiplier of str_repeat(). ( Ignorable by Annotation )

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

137
            str_repeat(end($this->bar), /** @scrutinizer ignore-type */ $displayChars - 1),
Loading history...
138 18
            $char,
139 18
            str_repeat(' ', $this->length - $displayChars)
140 18
        );
141
142 18
        $percentageText = sprintf('%3d%%', $percentage * 100);
143
144 18
        return str_replace(
145 18
            ['{bar}', '{perc}', '{position}', '{max}'],
146 18
            [$bar, $percentageText, $this->position, $this->max],
147 18
            $this->format
148 18
        );
149
    }
150
151
    /**
152
     * @return int
153
     */
154 1
    public function getLength()
155
    {
156 1
        return $this->length;
157
    }
158
159
    /**
160
     * @param int $length
161
     *
162
     * @return $this
163
     */
164 38
    public function setLength($length)
165
    {
166 38
        if ($length <= 0) {
167 3
            throw new InvalidArgumentException(sprintf('Supplied bar length: %d must be greater than 0', $length));
168
        }
169 35
        $this->length = $length;
170 35
        return $this;
171
    }
172
173
    /**
174
     * @return float
175
     */
176 1
    public function getMax()
177
    {
178 1
        return $this->max;
179
    }
180
181
    /**
182
     * @param float $max
183
     *
184
     * @return $this
185
     */
186 35
    public function setMax($max)
187
    {
188 35
        if ($max <= 0) {
189 3
            throw new InvalidArgumentException(sprintf('Supplied max value: %d must be greater than 0', $max));
190
        }
191 32
        $this->max = $max;
192 32
        return $this;
193
    }
194
195
    /**
196
     * @return float
197
     */
198 2
    public function getPosition()
199
    {
200 2
        return $this->position;
201
    }
202
203
    /**
204
     * @return string
205
     */
206 1
    public function getFormat()
207
    {
208 1
        return $this->format;
209
    }
210
211
    /**
212
     * @param string $format
213
     *
214
     * @return $this
215
     */
216 1
    public function setFormat($format)
217
    {
218 1
        $this->format = $format;
219 1
        return $this;
220
    }
221
222
    /**
223
     * @param float $position
224
     *
225
     * @return TinyProgressBar
226
     */
227 19
    public function setPosition($position)
228
    {
229 19
        $this->position = max(min($position, $this->max), 0);
230 19
        return $this;
231
    }
232
}
233