Completed
Push — develop ( a410d7...efad38 )
by Alec
04:48 queued 01:47
created

AbstractTimer::checkEnvironment()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 2
Code Lines 0

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 1
CRAP Score 1

Importance

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