Passed
Push — master ( 54698d...36eab2 )
by Alec
02:14
created

AbstractTimer::setTimeFunction()   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 0
dl 0
loc 3
ccs 2
cts 2
cp 1
crap 1
rs 10
c 0
b 0
f 0
1
<?php declare(strict_types=1);
2
3
namespace AlecRabbit\Timers\Core;
4
5
use AlecRabbit\Reports\Contracts\ReportInterface;
6
use AlecRabbit\Reports\Core\Reportable;
7
use AlecRabbit\Reports\TimerReport;
8
use AlecRabbit\Timers\Contracts\TimerInterface;
9
use AlecRabbit\Timers\Core\Traits\TimerFields;
10
11
/**
12
 * Class AbstractTimer
13
 */
14
abstract class AbstractTimer extends Reportable implements TimerInterface
15
{
16
    use TimerFields;
17
18
    /**
19
     * Timer constructor.
20
     * @param null|string $name
21
     * @param bool $start
22
     * @throws \Exception
23
     */
24 40
    public function __construct(?string $name = null, bool $start = true)
25
    {
26 40
        $this->checkEnvironment();
27 40
        $this->name = $this->defaultName($name);
28 40
        $this->creationTime = new \DateTimeImmutable();
29 40
        $this->computeElapsed();
30 40
        $this->report = $this->createEmptyReport();
31 40
        if ($start) {
32 28
            $this->start();
33
        }
34 40
    }
35
36 19
    protected function checkEnvironment(): void
37
    {
38 19
    }
39
40
    /**
41
     * @throws \Exception
42
     */
43 40
    protected function computeElapsed(): void
44
    {
45 40
        $this->elapsed = (new \DateTimeImmutable())->diff($this->creationTime);
46 40
    }
47
48
    /**
49
     * Starts the timer.
50
     *
51
     * @return void
52
     */
53 33
    public function start(): void
54
    {
55 33
        if ($this->isNotStarted()) {
56 33
            $this->previous = $this->current();
57
        }
58 33
        $this->started = true;
59 33
    }
60
61
    abstract public function current();
62
63
    /**
64
     * Marks the time.
65
     * If timer was not started starts the timer.
66
     * @param int|null $iterationNumber
67
     * @return self
68
     */
69 7
    public function check(?int $iterationNumber = null): self
70
    {
71 7
        if ($this->isStopped()) {
72 1
            throw new \RuntimeException('Timer[' . $this->name . '] is already stopped.');
73
        }
74 7
        if ($this->isNotStarted()) {
75 2
            $this->start();
76
        } else {
77 7
            $this->mark($iterationNumber);
78
        }
79 7
        return $this;
80
    }
81
82
    /**
83
     * @param int|null $iterationNumber
84
     */
85 7
    protected function mark(?int $iterationNumber = null): void
86
    {
87 7
        $current = $this->current();
88 7
        $this->currentValue = $current - $this->previous;
89 7
        $this->previous = $current;
90
91 7
        $this->compute($iterationNumber);
92 7
    }
93
94
    /**
95
     * @param null|int $iterationNumber
96
     */
97 12
    protected function compute(?int $iterationNumber): void
98
    {
99 12
        if (0 !== $this->count) {
100 11
            ++$this->count;
101 11
            $this->checkMinValue($iterationNumber);
102 11
            $this->checkMaxValue($iterationNumber);
103 11
            $this->computeAverage();
104
        } else {
105 12
            $this->initValues();
106
        }
107 12
    }
108
109
    /**
110
     * @param null|int $iterationNumber
111
     */
112 11
    protected function checkMinValue(?int $iterationNumber): void
113
    {
114 11
        if ($this->currentValue < $this->minValue) {
115 5
            $this->minValue = $this->currentValue;
116 5
            $this->minValueIteration = $iterationNumber ?? $this->count;
117
        }
118 11
    }
119
120
    /**
121
     * @param null|int $iterationNumber
122
     */
123 11
    protected function checkMaxValue(?int $iterationNumber): void
124
    {
125 11
        if ($this->currentValue > $this->maxValue) {
126 8
            $this->maxValue = $this->currentValue;
127 8
            $this->maxValueIteration = $iterationNumber ?? $this->count;
128
        }
129 11
    }
130
131 11
    protected function computeAverage(): void
132
    {
133 11
        $this->avgValue = (($this->avgValue * ($this->count - 1)) + $this->currentValue) / $this->count;
134 11
    }
135
136 12
    protected function initValues(): void
137
    {
138 12
        $this->maxValueIteration = $this->minValueIteration = $this->count = 1;
139 12
        $this->maxValue = $this->currentValue;
140 12
        $this->minValue = $this->currentValue;
141 12
        $this->avgValue = $this->currentValue;
142 12
    }
143
144
    /**
145
     * Stops the timer and returns elapsed time string.
146
     * @return string
147
     * @throws \Exception
148
     */
149 5
    public function elapsed(): string
150
    {
151 5
        if ($this->isNotStopped()) {
152 5
            $this->stop();
153
        }
154
        return
155 5
            $this->formattedElapsed();
156
    }
157
158
    /**
159
     * Stops the timer.
160
     * @throws \Exception
161
     */
162 6
    public function stop(): void
163
    {
164 6
        $this->computeElapsed();
165 6
        $this->stopped = true;
166 6
    }
167
168
    /**
169
     * @return string
170
     * @throws \Exception
171
     */
172 5
    protected function formattedElapsed(): string
173
    {
174
        return
175 5
            TimerReport::getFormatter()::formatElapsed($this->elapsed);
176
    }
177
178
    /**
179
     * @return \DateInterval
180
     * @throws \Exception
181
     */
182 40
    public function getElapsed(): \DateInterval
183
    {
184 40
        if ($this->isNotStopped()) {
185 40
            $this->computeElapsed();
186
        }
187 40
        return $this->elapsed;
188
    }
189
190
    /**
191
     * @param int|float $start
192
     * @param int|float $stop
193
     * @param null|int $iterationNumber
194
     * @return self
195
     */
196 9
    public function bounds($start, $stop, ?int $iterationNumber = null): self
197
    {
198 9
        $this->assertStartAndStop($start, $stop);
199 5
        if ($this->isNotStarted()) {
200 1
            $this->start();
201
        }
202 5
        $this->updateCurrentAndPrevious($start, $stop);
203
204 5
        $this->compute($iterationNumber);
205 5
        return $this;
206
    }
207
208
    /**
209
     * @psalm-suppress MissingParamType
210
     */
211
    abstract protected function assertStartAndStop(/** @noinspection PhpDocSignatureInspection */ $start, $stop): void;
212
213
    /**
214
     * @param float $start
215
     * @param float $stop
216
     */
217 5
    protected function updateCurrentAndPrevious($start, $stop): void
218
    {
219 5
        $this->currentValue = $stop - $start;
220 5
        $this->previous = $stop;
221 5
    }
222
223 40
    protected function createEmptyReport(): ReportInterface
224
    {
225 40
        return (new TimerReport())->buildOn($this);
226
    }
227
}
228