Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
0.00% |
0 / 113 |
|
0.00% |
0 / 17 |
CRAP | |
0.00% |
0 / 1 |
TransportSuggestion | |
0.00% |
0 / 113 |
|
0.00% |
0 / 17 |
812 | |
0.00% |
0 / 1 |
getFieldValue | |
0.00% |
0 / 11 |
|
0.00% |
0 / 1 |
2 | |||
fromFieldValue | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
2 | |||
populateFromFieldValue | |
0.00% |
0 / 9 |
|
0.00% |
0 / 1 |
2 | |||
getPrettyPrint | |
0.00% |
0 / 37 |
|
0.00% |
0 / 1 |
72 | |||
getMainConnection | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
setMainConnection | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
getSideConnections | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
addSideConnection | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
getOriginInfo | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
setOriginInfo | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
getDebug | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
addDebug | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
generateOriginInfo | |
0.00% |
0 / 23 |
|
0.00% |
0 / 1 |
6 | |||
getDestinationHalt | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
getHaltAtStation | |
0.00% |
0 / 11 |
|
0.00% |
0 / 1 |
6 | |||
getFlatHalts | |
0.00% |
0 / 6 |
|
0.00% |
0 / 1 |
2 | |||
getRatingForHalt | |
0.00% |
0 / 4 |
|
0.00% |
0 / 1 |
12 |
1 | <?php |
2 | |
3 | namespace Olz\Apps\Oev\Utils; |
4 | |
5 | use Olz\Utils\WithUtilsTrait; |
6 | |
7 | class TransportSuggestion { |
8 | use WithUtilsTrait; |
9 | |
10 | protected TransportConnection $mainConnection; |
11 | /** @var array<array{connection: TransportConnection, joiningStationId: string}> */ |
12 | protected array $sideConnections = []; |
13 | /** @var array<mixed> */ |
14 | protected array $originInfo = []; |
15 | /** @var array<string> */ |
16 | protected array $debug = []; |
17 | |
18 | /** @return array<string, mixed> */ |
19 | public function getFieldValue(): array { |
20 | return [ |
21 | 'mainConnection' => $this->mainConnection->getFieldValue(), |
22 | 'sideConnections' => array_map(function ($side_connection) { |
23 | return [ |
24 | 'connection' => $side_connection['connection']->getFieldValue(), |
25 | 'joiningStationId' => $side_connection['joiningStationId'], |
26 | ]; |
27 | }, $this->sideConnections), |
28 | 'originInfo' => $this->originInfo, |
29 | 'debug' => implode("\n", $this->debug), |
30 | ]; |
31 | } |
32 | |
33 | /** @param array<string, mixed> $value */ |
34 | public static function fromFieldValue(array $value): self { |
35 | $instance = new self(); |
36 | $instance->populateFromFieldValue($value); |
37 | return $instance; |
38 | } |
39 | |
40 | /** @param array<string, mixed> $value */ |
41 | protected function populateFromFieldValue(array $value): void { |
42 | $this->mainConnection = TransportConnection::fromFieldValue($value['mainConnection']); |
43 | $this->sideConnections = array_map(function ($side_connection) { |
44 | return [ |
45 | 'connection' => TransportConnection::fromFieldValue($side_connection['connection']), |
46 | 'joiningStationId' => $side_connection['joiningStationId'], |
47 | ]; |
48 | }, $value['sideConnections']); |
49 | $this->originInfo = $value['originInfo']; |
50 | $this->debug = explode("\n", $value['debug']); |
51 | } |
52 | |
53 | public function getPrettyPrint(): string { |
54 | $all_entries = []; |
55 | foreach ($this->mainConnection->getFlatHalts() as $halt) { |
56 | $all_entries[] = [ |
57 | 'halt' => $halt, |
58 | 'connection_index' => 0, |
59 | 'is_joining_halt' => false, |
60 | ]; |
61 | } |
62 | $side_connection_index = 1; |
63 | foreach ($this->sideConnections as $side_connection) { |
64 | $has_joined = false; |
65 | foreach ($side_connection['connection']->getFlatHalts() as $halt) { |
66 | $is_joining_halt = $side_connection['joiningStationId'] == $halt->getStationId(); |
67 | if (!$has_joined) { |
68 | $all_entries[] = [ |
69 | 'halt' => $halt, |
70 | 'connection_index' => $side_connection_index, |
71 | 'is_joining_halt' => $is_joining_halt, |
72 | ]; |
73 | } |
74 | if ($is_joining_halt) { |
75 | $has_joined = true; |
76 | } |
77 | } |
78 | $side_connection_index++; |
79 | } |
80 | usort( |
81 | $all_entries, |
82 | function ($entry_a, $entry_b) { |
83 | $entry_a_value = $entry_a['halt']->getTimeSeconds(); |
84 | $entry_b_value = $entry_b['halt']->getTimeSeconds(); |
85 | return $entry_a_value < $entry_b_value ? -1 : 1; |
86 | } |
87 | ); |
88 | $num_connections = count($this->sideConnections) + 1; |
89 | return implode("\n", array_map(function ($entry) use ($num_connections) { |
90 | $before_dot = str_repeat(' ', $entry['connection_index']); |
91 | $after_dot = str_repeat(' ', $num_connections - $entry['connection_index'] - 1); |
92 | $dot = $entry['is_joining_halt'] ? '<' : 'O'; |
93 | $halt = $entry['halt']; |
94 | return "{$before_dot}{$dot}{$after_dot} {$halt->getTimeString()} {$halt->getStationName()}"; |
95 | }, $all_entries)); |
96 | } |
97 | |
98 | public function getMainConnection(): TransportConnection { |
99 | return $this->mainConnection; |
100 | } |
101 | |
102 | public function setMainConnection(TransportConnection $new_main_connection): void { |
103 | $this->mainConnection = $new_main_connection; |
104 | } |
105 | |
106 | /** @return array<array{connection: TransportConnection, joiningStationId: string}> */ |
107 | public function getSideConnections(): array { |
108 | return $this->sideConnections; |
109 | } |
110 | |
111 | /** @param array{connection: TransportConnection, joiningStationId: string} $new_side_connection */ |
112 | public function addSideConnection(array $new_side_connection): void { |
113 | $this->sideConnections[] = $new_side_connection; |
114 | } |
115 | |
116 | /** @return array<mixed> */ |
117 | public function getOriginInfo(): array { |
118 | return $this->originInfo; |
119 | } |
120 | |
121 | /** @param array<mixed> $new_origin_info */ |
122 | public function setOriginInfo(array $new_origin_info): void { |
123 | $this->originInfo = $new_origin_info; |
124 | } |
125 | |
126 | /** @return array<string> */ |
127 | public function getDebug(): array { |
128 | return $this->debug; |
129 | } |
130 | |
131 | public function addDebug(string $line): void { |
132 | $this->debug[] = $line; |
133 | } |
134 | |
135 | /** |
136 | * @param array<mixed> $origin_stations |
137 | * |
138 | * @return array<mixed> |
139 | */ |
140 | public function generateOriginInfo(array $origin_stations): array { |
141 | $most_important_stations = array_slice($origin_stations, 0); |
142 | usort( |
143 | $most_important_stations, |
144 | function ($station_a, $station_b) { |
145 | $station_a_weight = $station_a['weight'] ?? 0; |
146 | $station_b_weight = $station_b['weight'] ?? 0; |
147 | return $station_a_weight < $station_b_weight ? 1 : -1; |
148 | } |
149 | ); |
150 | $destination_halt = $this->getDestinationHalt(); |
151 | return array_map(function ($station) use ($destination_halt) { |
152 | $station_id = $station['id']; |
153 | $halt_at_station = $this->getHaltAtStation($station_id); |
154 | return [ |
155 | 'halt' => [ |
156 | 'stationId' => $station_id, |
157 | 'stationName' => $station['name'], |
158 | 'time' => $halt_at_station?->getTimeString() ?? '', |
159 | ], |
160 | 'isSkipped' => $halt_at_station === null, |
161 | 'rating' => $this->getRatingForHalt($halt_at_station, $destination_halt), |
162 | ]; |
163 | }, $most_important_stations); |
164 | } |
165 | |
166 | public function getDestinationHalt(): TransportHalt { |
167 | return $this->mainConnection->getDestinationHalt(); |
168 | } |
169 | |
170 | public function getHaltAtStation(string $station_id): ?TransportHalt { |
171 | $halts = $this->getFlatHalts(); |
172 | $halts_at_station = array_values(array_filter( |
173 | $halts, |
174 | function ($halt) use ($station_id) { |
175 | return $halt->getStationId() === $station_id; |
176 | } |
177 | )); |
178 | $last_index = count($halts_at_station) - 1; |
179 | if ($last_index === -1) { |
180 | return null; |
181 | } |
182 | return $halts_at_station[$last_index]; |
183 | } |
184 | |
185 | /** @return array<TransportHalt> */ |
186 | public function getFlatHalts(): array { |
187 | return array_merge( |
188 | $this->mainConnection->getFlatHalts(), |
189 | ...array_map(function ($side_connection) { |
190 | return $side_connection['connection']->getFlatHalts(); |
191 | }, $this->sideConnections), |
192 | ); |
193 | } |
194 | |
195 | public function getRatingForHalt(?TransportHalt $halt, ?TransportHalt $destination_halt): float { |
196 | if (!$halt || !$destination_halt) { |
197 | return 0; |
198 | } |
199 | $duration_seconds = $destination_halt->getTimeSeconds() - $halt->getTimeSeconds(); |
200 | return 1 / max(1, log($duration_seconds)); |
201 | } |
202 | } |