Completed
Push — master ( 23d6c4...eb4d77 )
by Alec
06:36
created

Timer::format()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 3
dl 0
loc 4
ccs 2
cts 2
cp 1
crap 1
rs 10
c 0
b 0
f 0
1
<?php
2
/**
3
 * User: alec
4
 * Date: 14.10.18
5
 * Time: 2:19
6
 */
7
8
namespace AlecRabbit\Profiler;
9
10
class Timer implements Contracts\Timer
11
{
12
    /** @var string */
13
    private $name;
14
15
    /** @var float */
16
    private $previous;
17
18
    /** @var float */
19
    private $start;
20
21
    /** @var float */
22
    private $currentValue;
23
24
    /** @var float */
25
    private $avgValue;
26
27
    /** @var float */
28
    private $minValue;
29
30
    /** @var float */
31
    private $maxValue;
32
33
    /** @var int */
34
    private $count;
35
36
    /**
37
     * Timer constructor.
38
     * @param null|string $name
39
     */
40 14
    public function __construct(?string $name = null)
41
    {
42 14
        $this->name = $name ?? static::_DEFAULT;
43 14
    }
44
45
    /**
46
     * Starts the timer.
47
     * @return Timer
48
     */
49 2
    public function forceStart(): Timer
50
    {
51 2
        $this->start();
52 2
        return $this;
53
    }
54
55
    /**
56
     * Starts the timer.
57
     *
58
     * @return void
59
     */
60 8
    public function start(): void
61
    {
62 8
        $this->previous = $this->start = $this->current();
63 8
    }
64
65
    /**
66
     * @return float
67
     */
68 8
    private function current(): float
69
    {
70
        return
71 8
            microtime(true);
72
    }
73
74
    /**
75
     * @param bool $formatted
76
     * @return mixed
77
     */
78 4
    public function elapsed(bool $formatted = false)
79
    {
80 4
        if (!$this->start) {
81 1
            throw new \RuntimeException('Timer has not been started.');
82
        }
83 3
        $elapsed = $this->current() - $this->start;
84
85
        return
86 3
            $formatted ? $this->format($elapsed, static::UNIT_MILLISECONDS, 2) : $elapsed;
87
    }
88
89
    /**
90
     * @param float|null $value
91
     * @param int|null $units
92
     * @param int|null $precision
93
     * @return string
94
     */
95 5
    private function format(?float $value, ?int $units = null, int $precision = null): string
96
    {
97
        return
98 5
            format_time($value, $units, $precision ?? static::DEFAULT_PRECISION);
99
    }
100
101
    /**
102
     * @param bool|null $formatted
103
     * @param bool|null $extended
104
     * @param int|null $units
105
     * @param int|null $precision
106
     *
107
     * @return iterable
108
     */
109 3
    public function report(
110
        ?bool $formatted = null,
111
        ?bool $extended = null,
112
        ?int $units = null,
113
        ?int $precision = null
114
    ): iterable {
115 3
        if (!$this->count) {
116 1
            $this->check();
117
        }
118 3
        $formatted = $formatted ?? false;
119 3
        $current = $formatted ? $this->format($this->currentValue, $units, $precision) : $this->currentValue;
120 3
        $report = [];
121 3
        if ($current) {
122 2
            $name = $this->getName();
123
            $report = [
124 2
                static::_NAME => $name,
125 2
                static::_LAST => $current,
126 2
                static::_EXTENDED => $extended ? $this->getTimerValues($formatted) : null
127
            ];
128
        }
129 3
        return $report;
130
    }
131
132
    /**
133
     * Marks the elapsed time.
134
     * If timer was not started starts the timer.
135
     */
136 7
    public function check(): Timer
137
    {
138 7
        if (null !== $this->previous) {
139 6
            $this->mark();
140
        } else {
141 1
            $this->start();
142
        }
143 7
        return $this;
144
    }
145
146 6
    private function mark(): void
147
    {
148 6
        $current = $this->current();
149 6
        $this->currentValue = $current - $this->previous;
150 6
        $this->previous = $current;
151
152 6
        if ($this->count) {
153 4
            if ($this->currentValue < $this->minValue) {
154 2
                $this->minValue = $this->currentValue;
155
            }
156 4
            if ($this->currentValue > $this->maxValue) {
157 2
                $this->maxValue = $this->currentValue;
158
            }
159 4
            $this->avgValue = (($this->avgValue * $this->count) + $this->currentValue) / ++$this->count;
160
        } else {
161 6
            $this->count = 1;
162 6
            $this->maxValue = $this->currentValue;
163 6
            $this->minValue = $this->currentValue;
164 6
            $this->avgValue = $this->currentValue;
165
        }
166 6
    }
167
168
    /**
169
     * @return string
170
     */
171 6
    public function getName(): string
172
    {
173 6
        return $this->name;
174
    }
175
176
    /**
177
     * @param bool $formatted
178
     * @param int|null $units
179
     * @param int|null $precision
180
     * @return iterable
181
     */
182 4
    public function getTimerValues(bool $formatted = true, ?int $units = null, ?int $precision = null): iterable
183
    {
184 4
        if (!$count = $this->getCount()) {
185 1
            throw new \RuntimeException('Timer has not been started.');
186
        }
187 3
        $minValue = ($count === 1) ? $this->getCurrentValue() : $this->getMinValue();
188
        return
189 3
            $formatted ?
190
                [
191 2
                    static::_LAST => $this->format($this->getCurrentValue(), $units, $precision),
192 2
                    static::_AVG => $this->format($this->getAvgValue(), $units, $precision),
193 2
                    static::_MIN => $this->format($minValue, $units, $precision),
194 2
                    static::_MAX => $this->format($this->getMaxValue(), $units, $precision),
195 2
                    static::_COUNT => $count,
196
                ] :
197
                [
198 1
                    static::_LAST => $this->getCurrentValue(),
199 1
                    static::_AVG => $this->getAvgValue(),
200 1
                    static::_MIN => $minValue,
201 1
                    static::_MAX => $this->getMaxValue(),
202 3
                    static::_COUNT => $count,
203
                ];
204
    }
205
206
    /**
207
     * @return int|null
208
     */
209 5
    public function getCount(): ?int
210
    {
211 5
        return $this->count;
212
    }
213
214
    /**
215
     * @return float|null
216
     */
217 4
    public function getCurrentValue(): ?float
218
    {
219 4
        return $this->currentValue;
220
    }
221
222
    /**
223
     * @return float|null
224
     */
225 4
    public function getMinValue(): ?float
226
    {
227 4
        return $this->minValue;
228
    }
229
230
    /**
231
     * @return float|null
232
     */
233 4
    public function getAvgValue(): ?float
234
    {
235 4
        return $this->avgValue;
236
    }
237
238
    /**
239
     * @return float|null
240
     */
241 4
    public function getMaxValue(): ?float
242
    {
243 4
        return $this->maxValue;
244
    }
245
}
246