1 | <?php |
||||
2 | require_once 'vendor/autoload.php'; |
||||
3 | |||||
4 | use Vctls\IntervalGraph\IntervalGraph; |
||||
5 | |||||
6 | /** |
||||
7 | * Generate random dates. |
||||
8 | * @param int $min |
||||
9 | * @param int $max |
||||
10 | * @return DateTime |
||||
11 | */ |
||||
12 | function rdm($min = 1514764800, $max = 1577750400) |
||||
13 | { |
||||
14 | return (new DateTime)->setTimestamp(mt_rand($min, $max)); |
||||
15 | } |
||||
16 | |||||
17 | $today = new DateTime('today'); |
||||
18 | |||||
19 | $base = [$today, new DateTime('today + 5 days')]; |
||||
20 | $date1 = [$today, new DateTime('today + 4 days'), 7 / 10]; |
||||
21 | $date2 = [new DateTime('today + 1 day'), new DateTime('today + 5 days'), 3 / 10]; |
||||
22 | $date3 = [new DateTime('today + 2 day'), new DateTime('today + 3 days'), 3 / 10]; |
||||
23 | $overlapped1 = new IntervalGraph([$base, $date1]); |
||||
24 | $overlapped2 = new IntervalGraph([$base, $date2]); |
||||
25 | $overlapped3 = new IntervalGraph([$base, $date3]); |
||||
26 | $overlapped = new IntervalGraph([$base, $date1, $date2, $date3]); |
||||
27 | |||||
28 | $withNull1 = new IntervalGraph([$base, [new DateTime('today'), new DateTime('today + 3 days'), 4 / 10],]); |
||||
29 | $withNull2 = new IntervalGraph([$base, [new DateTime('today + 1 day'), new DateTime('today + 2 days')],]); |
||||
30 | $withNull3 = new IntervalGraph([$base, [new DateTime('today + 2 day'), new DateTime('today + 3 days'), 4 / 10],]); |
||||
31 | $withNull4 = new IntervalGraph([$base, [new DateTime('today + 4 day'), new DateTime('today + 5 days'), 5 / 10],]); |
||||
32 | $withNullIntervals = new IntervalGraph([ |
||||
33 | [$today, new DateTime('today + 3 days'), 4 / 10], |
||||
34 | [new DateTime('today + 1 day'), new DateTime('today + 2 days')], |
||||
35 | [new DateTime('today + 2 day'), new DateTime('today + 3 days'), 4 / 10], |
||||
36 | [new DateTime('today + 4 day'), new DateTime('today + 5 days'), 5 / 10], |
||||
37 | ]); |
||||
38 | |||||
39 | $longIntervals = [ |
||||
40 | [$today, new DateTime('today + 3 days'), 2 / 10], |
||||
41 | [new DateTime('today + 1 day'), new DateTime('today + 4 days'), 2 / 10], |
||||
42 | [new DateTime('today + 2 day'), new DateTime('today + 5 days'), 3 / 10], |
||||
43 | [new DateTime('today + 3 day'), new DateTime('today + 6 days'), 5 / 10], |
||||
44 | [new DateTime('today + 4 day'), new DateTime('today + 7 days'), 4 / 10], |
||||
45 | [new DateTime('today + 5 day'), new DateTime('today + 8 days'), 2 / 10], |
||||
46 | [new DateTime('today + 6 day'), new DateTime('today + 9 days'), 2 / 10], |
||||
47 | ]; |
||||
48 | |||||
49 | $longDateFormat = function (\DateTime $bound){ |
||||
50 | return $bound->format('Y-m-d H:i:s'); |
||||
51 | }; |
||||
52 | |||||
53 | $long = (new IntervalGraph($longIntervals))->setBoundToStringFunction($longDateFormat); |
||||
54 | |||||
55 | /* |
||||
56 | * CUSTOM VALUE TYPES |
||||
57 | */ |
||||
58 | |||||
59 | // An aggregate function for arrays representing fractions with the same denominator. |
||||
60 | $agg = function ($a, $b) { |
||||
61 | if ($a === null && $b === null) return null; |
||||
62 | return [$a[0] + $b[0], $b[1]]; |
||||
63 | }; |
||||
64 | |||||
65 | // A toNumeric function… |
||||
66 | $toNumeric = function ($a) {return $a === null ? null : (int)($a[0] / $a[1] * 100);}; |
||||
67 | |||||
68 | // A toString function… |
||||
69 | $toString = function ($a) {return $a === null ? null : ($a[0] . '/' . $a[1]);}; |
||||
70 | |||||
71 | $fractions = [ |
||||
72 | [$today, new DateTime('today + 3 days'), [2, 10]], |
||||
73 | [new DateTime('today + 1 day'), new DateTime('today + 4 days'), [2, 10]], |
||||
74 | [new DateTime('today + 2 day'), new DateTime('today + 5 days'), [3, 10]], |
||||
75 | [new DateTime('today + 3 day'), new DateTime('today + 6 days'), [5, 10]], |
||||
76 | [new DateTime('today + 4 day'), new DateTime('today + 7 days'), [4, 10]], |
||||
77 | [new DateTime('today + 5 day'), new DateTime('today + 8 days'), [2, 10]], |
||||
78 | [new DateTime('today + 6 day'), new DateTime('today + 9 days'), [2, 10]], |
||||
79 | ]; |
||||
80 | $fractim = (new IntervalGraph($fractions))->setAggregateFunction($agg) |
||||
81 | ->setValueToNumericFunction($toNumeric) |
||||
82 | ->setValueToStringFunction($toString); |
||||
83 | $fract = $fractim->draw(); |
||||
84 | |||||
85 | /* /CUSTOM VALUE TYPES */ |
||||
86 | |||||
87 | /* |
||||
88 | * TRUNCATED INTERVALS |
||||
89 | */ |
||||
90 | try { |
||||
91 | $date1 = (clone $today)->add(new DateInterval('PT60H')); |
||||
92 | $date2 = (clone $today)->add(new DateInterval('PT108H')); |
||||
93 | $date3 = (clone $date2)->add(new DateInterval('PT60H')); |
||||
94 | } catch (Exception $e) { |
||||
0 ignored issues
–
show
Coding Style
Comprehensibility
introduced
by
![]() |
|||||
95 | } |
||||
96 | |||||
97 | $truncated = ($fractim->setIntervals(IntervalGraph::truncate($fractions, $date1, $date2))) |
||||
0 ignored issues
–
show
It seems like
$date2 can also be of type array<integer,integer|DateTime> ; however, parameter $end of Vctls\IntervalGraph\IntervalGraph::truncate() does only seem to accept null|DateTime , maybe add an additional type check?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
98 | ->setBoundToStringFunction($longDateFormat); |
||||
99 | /* /TRUNCATED INTERVALS */ |
||||
100 | |||||
101 | $withDates = new IntervalGraph([ |
||||
102 | [$date1, $date1], |
||||
103 | [$today, new DateTime('today + 4 days'), 7 / 10], |
||||
104 | [$date2, $date2], |
||||
105 | [new DateTime('today + 1 day'), new DateTime('today + 5 days'), 3 / 10], |
||||
106 | [new DateTime('today + 2 day'), new DateTime('today + 3 days'), 3 / 10], |
||||
107 | [$date3, $date3], |
||||
108 | ]); |
||||
109 | |||||
110 | $intvGraphs = []; |
||||
111 | foreach (range(0, 20) as $t) { |
||||
112 | $intervals = []; |
||||
113 | $j = (int)rand(3, 6); |
||||
114 | for ($i = 0; $i < $j; $i++) { |
||||
115 | $intervals[] = [rdm(), rdm(), rand(1, 9) / 10]; |
||||
116 | } |
||||
117 | $intvGraphs[] = new IntervalGraph($intervals); |
||||
118 | } |
||||
119 | |||||
120 | ?> |
||||
121 | <html> |
||||
122 | <head> |
||||
123 | <title>Php IntervalGraph demo</title> |
||||
124 | <link rel="stylesheet" href="styles.css"> |
||||
125 | <script type="application/javascript" src="app.js"></script> |
||||
126 | </head> |
||||
127 | <body style="font-family: sans-serif;"> |
||||
128 | <header> |
||||
129 | <h1>PHP Interval Graph demo</h1> |
||||
130 | </header> |
||||
131 | <p> |
||||
132 | PHP Interval Graph is a small utility to manipulate and |
||||
133 | display arrays of intervals. |
||||
134 | </p> |
||||
135 | <a href="https://github.com/vctls/php-interval-graph"> |
||||
136 | https://github.com/vctls/php-interval-graph |
||||
137 | </a> |
||||
138 | <h2>How it works</h2> |
||||
139 | <p> |
||||
140 | Here are three overlapping date intervals. |
||||
141 | Each one has a linked rate, displayed as a percentage when hovering it. |
||||
142 | <br>They are all displayed over the same period of time, which has no rate. |
||||
143 | </p> |
||||
144 | <div style="margin-bottom: 2px"><?= $overlapped1 ?></div> |
||||
145 | <div style="margin-bottom: 2px"><?= $overlapped2 ?></div> |
||||
146 | <div style="margin-bottom: 2px"><?= $overlapped3 ?></div> |
||||
147 | |||||
148 | <p> |
||||
149 | Gathered on the same graph, they are displayed as follows. |
||||
150 | </p> |
||||
151 | <?= $overlapped ?> |
||||
152 | |||||
153 | <h2>More examples</h2> |
||||
154 | <p> |
||||
155 | Overlapping intervals with a couple null intervals.<br> |
||||
156 | The first null interval overlaps a non null one. |
||||
157 | This cuts the non null interval, while the weight remains the same.<br> |
||||
158 | The second null interval is implicit. |
||||
159 | It is simply the gap between the two last intervals. |
||||
160 | </p> |
||||
161 | <div style="margin-bottom: 2px"><?= $withNull1 ?></div> |
||||
162 | <div style="margin-bottom: 2px"><?= $withNull2 ?></div> |
||||
163 | <div style="margin-bottom: 2px"><?= $withNull3 ?></div> |
||||
164 | <div style="margin-bottom: 2px"><?= $withNull4 ?></div> |
||||
165 | <br> |
||||
166 | <?= $withNullIntervals ?> |
||||
167 | |||||
168 | |||||
169 | <h2>Custom value types</h2> |
||||
170 | <p> |
||||
171 | The following graph takes arrays of two values |
||||
172 | and displays them as fractions.<br> |
||||
173 | In order to use custom value types, you need to set the custom functions |
||||
174 | that will aggregate the values, convert them to numeric values and strings. |
||||
175 | </p> |
||||
176 | <?= $fract ?> |
||||
177 | |||||
178 | <p> |
||||
179 | The same graph, truncated between <?= $date1->format('Y-m-d H:i:s') ?> |
||||
180 | and <?= $date2->format('Y-m-d H:i:s') ?>. |
||||
181 | <?= $truncated ?> |
||||
182 | </p> |
||||
183 | |||||
184 | <p> |
||||
185 | A graph with three isolated dates, shown as black bars. |
||||
186 | <br>One of the dates goes beyond all intervals. |
||||
187 | <?= $withDates ?> |
||||
188 | </p> |
||||
189 | <p> |
||||
190 | A bunch of random graphs, this time generated through JavaScript: |
||||
191 | <br> |
||||
192 | </p> |
||||
193 | <div id="random"></div> |
||||
194 | <script> |
||||
195 | 'use strict'; |
||||
196 | const graphs = JSON.parse('<?= json_encode($intvGraphs) ?>'); |
||||
197 | const el = document.getElementById('random'); |
||||
198 | |||||
199 | try { |
||||
200 | graphs.forEach(function (graph) { |
||||
201 | let html = document.createRange().createContextualFragment(intvg(graph)); |
||||
202 | el.appendChild(html); |
||||
203 | }); |
||||
204 | } catch (e) { |
||||
205 | el.innerHTML = 'The JavaScript function uses ES6 string literals. Sorry not sorry, IE.'; |
||||
206 | } |
||||
207 | </script> |
||||
208 | </body> |
||||
209 | </html> |