eflips-depot 4.15.0__tar.gz → 4.15.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of eflips-depot might be problematic. Click here for more details.
- {eflips_depot-4.15.0 → eflips_depot-4.15.2}/PKG-INFO +1 -1
- {eflips_depot-4.15.0 → eflips_depot-4.15.2}/eflips/depot/api/private/consumption.py +46 -23
- {eflips_depot-4.15.0 → eflips_depot-4.15.2}/eflips/depot/api/private/depot.py +11 -10
- {eflips_depot-4.15.0 → eflips_depot-4.15.2}/eflips/depot/api/private/results_to_database.py +6 -1
- {eflips_depot-4.15.0 → eflips_depot-4.15.2}/eflips/depot/api/private/util.py +19 -6
- {eflips_depot-4.15.0 → eflips_depot-4.15.2}/eflips/depot/processes.py +19 -3
- {eflips_depot-4.15.0 → eflips_depot-4.15.2}/eflips/depot/rating.py +1 -1
- {eflips_depot-4.15.0 → eflips_depot-4.15.2}/eflips/depot/simple_vehicle.py +12 -1
- {eflips_depot-4.15.0 → eflips_depot-4.15.2}/pyproject.toml +1 -1
- {eflips_depot-4.15.0 → eflips_depot-4.15.2}/LICENSE.md +0 -0
- {eflips_depot-4.15.0 → eflips_depot-4.15.2}/README.md +0 -0
- {eflips_depot-4.15.0 → eflips_depot-4.15.2}/eflips/depot/__init__.py +0 -0
- {eflips_depot-4.15.0 → eflips_depot-4.15.2}/eflips/depot/api/__init__.py +0 -0
- {eflips_depot-4.15.0 → eflips_depot-4.15.2}/eflips/depot/api/defaults/default_settings.json +0 -0
- {eflips_depot-4.15.0 → eflips_depot-4.15.2}/eflips/depot/api/private/__init__.py +0 -0
- {eflips_depot-4.15.0 → eflips_depot-4.15.2}/eflips/depot/configuration.py +0 -0
- {eflips_depot-4.15.0 → eflips_depot-4.15.2}/eflips/depot/depot.py +0 -0
- {eflips_depot-4.15.0 → eflips_depot-4.15.2}/eflips/depot/evaluation.py +0 -0
- {eflips_depot-4.15.0 → eflips_depot-4.15.2}/eflips/depot/filters.py +0 -0
- {eflips_depot-4.15.0 → eflips_depot-4.15.2}/eflips/depot/input_epex_power_price.py +0 -0
- {eflips_depot-4.15.0 → eflips_depot-4.15.2}/eflips/depot/layout_opt/__init__.py +0 -0
- {eflips_depot-4.15.0 → eflips_depot-4.15.2}/eflips/depot/layout_opt/doc/__init__.py +0 -0
- {eflips_depot-4.15.0 → eflips_depot-4.15.2}/eflips/depot/layout_opt/doc/direct_details.pdf +0 -0
- {eflips_depot-4.15.0 → eflips_depot-4.15.2}/eflips/depot/layout_opt/evaluation.py +0 -0
- {eflips_depot-4.15.0 → eflips_depot-4.15.2}/eflips/depot/layout_opt/opt_tools/__init__.py +0 -0
- {eflips_depot-4.15.0 → eflips_depot-4.15.2}/eflips/depot/layout_opt/opt_tools/crossover.py +0 -0
- {eflips_depot-4.15.0 → eflips_depot-4.15.2}/eflips/depot/layout_opt/opt_tools/fitness_c_urfd.py +0 -0
- {eflips_depot-4.15.0 → eflips_depot-4.15.2}/eflips/depot/layout_opt/opt_tools/fitness_util.py +0 -0
- {eflips_depot-4.15.0 → eflips_depot-4.15.2}/eflips/depot/layout_opt/opt_tools/init.py +0 -0
- {eflips_depot-4.15.0 → eflips_depot-4.15.2}/eflips/depot/layout_opt/opt_tools/mutation.py +0 -0
- {eflips_depot-4.15.0 → eflips_depot-4.15.2}/eflips/depot/layout_opt/optimize_c_urfd.py +0 -0
- {eflips_depot-4.15.0 → eflips_depot-4.15.2}/eflips/depot/layout_opt/packing.py +0 -0
- {eflips_depot-4.15.0 → eflips_depot-4.15.2}/eflips/depot/layout_opt/settings.py +0 -0
- {eflips_depot-4.15.0 → eflips_depot-4.15.2}/eflips/depot/layout_opt/template_creation.py +0 -0
- {eflips_depot-4.15.0 → eflips_depot-4.15.2}/eflips/depot/layout_opt/util.py +0 -0
- {eflips_depot-4.15.0 → eflips_depot-4.15.2}/eflips/depot/plots.py +0 -0
- {eflips_depot-4.15.0 → eflips_depot-4.15.2}/eflips/depot/resources.py +0 -0
- {eflips_depot-4.15.0 → eflips_depot-4.15.2}/eflips/depot/settings_config.py +0 -0
- {eflips_depot-4.15.0 → eflips_depot-4.15.2}/eflips/depot/simulation.py +0 -0
- {eflips_depot-4.15.0 → eflips_depot-4.15.2}/eflips/depot/smart_charging.py +0 -0
- {eflips_depot-4.15.0 → eflips_depot-4.15.2}/eflips/depot/standalone.py +0 -0
- {eflips_depot-4.15.0 → eflips_depot-4.15.2}/eflips/depot/validation.py +0 -0
|
@@ -286,20 +286,6 @@ def extract_trip_information(
|
|
|
286
286
|
)
|
|
287
287
|
.one()
|
|
288
288
|
)
|
|
289
|
-
# Check exactly one of the vehicle classes has a consumption LUT
|
|
290
|
-
all_consumption_luts = [
|
|
291
|
-
vehicle_class.consumption_lut
|
|
292
|
-
for vehicle_class in trip.rotation.vehicle_type.vehicle_classes
|
|
293
|
-
]
|
|
294
|
-
all_consumption_luts = [x for x in all_consumption_luts if x is not None]
|
|
295
|
-
if len(all_consumption_luts) != 1:
|
|
296
|
-
raise ValueError(
|
|
297
|
-
f"Expected exactly one consumption LUT, got {len(all_consumption_luts)}"
|
|
298
|
-
)
|
|
299
|
-
consumption_lut = all_consumption_luts[0]
|
|
300
|
-
# Disconnect the consumption LUT from the session to avoid loading the whole table
|
|
301
|
-
|
|
302
|
-
del all_consumption_luts
|
|
303
289
|
|
|
304
290
|
total_distance = trip.route.distance / 1000 # km
|
|
305
291
|
total_duration = (
|
|
@@ -307,6 +293,13 @@ def extract_trip_information(
|
|
|
307
293
|
).total_seconds() / 3600
|
|
308
294
|
average_speed = total_distance / total_duration # km/h
|
|
309
295
|
|
|
296
|
+
# Check exactly one of the vehicle classes has a consumption LUT
|
|
297
|
+
all_consumption_luts = [
|
|
298
|
+
vehicle_class.consumption_lut
|
|
299
|
+
for vehicle_class in trip.rotation.vehicle_type.vehicle_classes
|
|
300
|
+
]
|
|
301
|
+
all_consumption_luts = [x for x in all_consumption_luts if x is not None]
|
|
302
|
+
|
|
310
303
|
temperature = temperature_for_trip(trip_id, session)
|
|
311
304
|
|
|
312
305
|
payload_mass = passenger_mass * passenger_count
|
|
@@ -324,16 +317,46 @@ def extract_trip_information(
|
|
|
324
317
|
)
|
|
325
318
|
level_of_loading = payload_mass / full_payload
|
|
326
319
|
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
320
|
+
if len(all_consumption_luts) == 1:
|
|
321
|
+
consumption_lut = all_consumption_luts[0]
|
|
322
|
+
# Disconnect the consumption LUT from the session to avoid loading the whole table
|
|
323
|
+
|
|
324
|
+
del all_consumption_luts
|
|
325
|
+
|
|
326
|
+
info = ConsumptionInformation(
|
|
327
|
+
trip_id=trip.id,
|
|
328
|
+
consumption_lut=consumption_lut,
|
|
329
|
+
average_speed=average_speed,
|
|
330
|
+
distance=total_distance,
|
|
331
|
+
temperature=temperature,
|
|
332
|
+
level_of_loading=level_of_loading,
|
|
333
|
+
)
|
|
334
|
+
info.calculate()
|
|
335
|
+
elif len(all_consumption_luts) == 0:
|
|
336
|
+
warnings.warn(
|
|
337
|
+
f"No consumption LUT found for vehicle type {trip.rotation.vehicle_type}.",
|
|
338
|
+
ConsistencyWarning,
|
|
339
|
+
)
|
|
340
|
+
# Here, we fill out the condumption information without the LUT and LUT data, but with `consumption_per_km`
|
|
341
|
+
# set to the vehicle's `consumption` value.
|
|
342
|
+
assert (
|
|
343
|
+
VehicleType.consumption is not None
|
|
344
|
+
), f"Vehicle type {trip.rotation.vehicle_type} must have a consumption value set if no consumption LUT is available."
|
|
345
|
+
info = ConsumptionInformation(
|
|
346
|
+
trip_id=trip.id,
|
|
347
|
+
average_speed=average_speed,
|
|
348
|
+
distance=total_distance,
|
|
349
|
+
consumption_per_km=trip.rotation.vehicle_type.consumption,
|
|
350
|
+
consumption=trip.rotation.vehicle_type.consumption * total_distance,
|
|
351
|
+
consumption_lut=None,
|
|
352
|
+
temperature=temperature,
|
|
353
|
+
level_of_loading=level_of_loading,
|
|
354
|
+
)
|
|
355
|
+
else:
|
|
356
|
+
raise ValueError(
|
|
357
|
+
f"Expected exactly one consumption LUT, got {len(all_consumption_luts)}"
|
|
358
|
+
)
|
|
335
359
|
|
|
336
|
-
info.calculate()
|
|
337
360
|
return info
|
|
338
361
|
|
|
339
362
|
|
|
@@ -230,7 +230,7 @@ def depot_to_template(depot: Depot) -> Dict[str, str | Dict[str, str | int]]:
|
|
|
230
230
|
if process_type(processes_in_area) == ProcessType.CHARGING:
|
|
231
231
|
# Add the charging process for this vehicle type
|
|
232
232
|
template["areas"][area_name]["available_processes"].append(
|
|
233
|
-
str(processes_in_area.id) + str(area.vehicle_type_id)
|
|
233
|
+
str(processes_in_area.id) + "vt" + str(area.vehicle_type_id)
|
|
234
234
|
)
|
|
235
235
|
# Delete the original charging process
|
|
236
236
|
template["areas"][area_name]["available_processes"].remove(
|
|
@@ -253,7 +253,7 @@ def depot_to_template(depot: Depot) -> Dict[str, str | Dict[str, str | int]]:
|
|
|
253
253
|
# Add the charging process for this vehicle type
|
|
254
254
|
for vt in scenario.vehicle_types:
|
|
255
255
|
template["areas"][area_name]["available_processes"].append(
|
|
256
|
-
str(processes_in_area.id) + str(vt.id)
|
|
256
|
+
str(processes_in_area.id) + "vt" + str(vt.id)
|
|
257
257
|
)
|
|
258
258
|
# Delete the original charging process
|
|
259
259
|
template["areas"][area_name]["available_processes"].remove(
|
|
@@ -386,30 +386,31 @@ def depot_to_template(depot: Depot) -> Dict[str, str | Dict[str, str | int]]:
|
|
|
386
386
|
|
|
387
387
|
for vt in all_vehicle_types:
|
|
388
388
|
charging_curve = vt.charging_curve
|
|
389
|
-
|
|
389
|
+
|
|
390
|
+
charging_process_name = process_name + "vt" + str(vt.id)
|
|
391
|
+
template["processes"][charging_process_name] = template[
|
|
390
392
|
"processes"
|
|
391
393
|
][process_name].copy()
|
|
392
|
-
template["processes"][
|
|
394
|
+
template["processes"][charging_process_name][
|
|
393
395
|
"typename"
|
|
394
396
|
] = "ChargeEquationSteps"
|
|
395
|
-
template["processes"][
|
|
396
|
-
"vehicle_filter"
|
|
397
|
-
] = {
|
|
397
|
+
template["processes"][charging_process_name]["vehicle_filter"] = {
|
|
398
398
|
"filter_names": ["vehicle_type"],
|
|
399
399
|
"vehicle_types": [str(vt.id)],
|
|
400
400
|
}
|
|
401
401
|
|
|
402
|
-
template["processes"][
|
|
402
|
+
template["processes"][charging_process_name][
|
|
403
403
|
"peq_name"
|
|
404
404
|
] = "charging_curve_power"
|
|
405
|
-
template["processes"][
|
|
405
|
+
template["processes"][charging_process_name]["peq_params"] = {
|
|
406
406
|
"soc": [soc_power_pair[0] for soc_power_pair in charging_curve],
|
|
407
407
|
"power": [
|
|
408
408
|
soc_power_pair[1] for soc_power_pair in charging_curve
|
|
409
409
|
],
|
|
410
|
+
"precision": 0.01,
|
|
410
411
|
}
|
|
411
412
|
|
|
412
|
-
del template["processes"][
|
|
413
|
+
del template["processes"][charging_process_name]["dur"]
|
|
413
414
|
|
|
414
415
|
# delete the original process
|
|
415
416
|
del template["processes"][process_name]
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import datetime
|
|
2
2
|
import itertools
|
|
3
3
|
import logging
|
|
4
|
+
import math
|
|
4
5
|
import warnings
|
|
5
6
|
from datetime import timedelta
|
|
6
7
|
from typing import List, Dict
|
|
@@ -398,6 +399,10 @@ def add_soc_to_events(dict_of_events, battery_log) -> None:
|
|
|
398
399
|
"""
|
|
399
400
|
battery_log_list = []
|
|
400
401
|
for log in battery_log:
|
|
402
|
+
# TODO this is a bypass of update events having lower energy_real than the event before. It happens in processes L 1304
|
|
403
|
+
if log.event_name == "update":
|
|
404
|
+
continue
|
|
405
|
+
|
|
401
406
|
battery_log_list.append((log.t, round(log.energy / log.energy_real, 4)))
|
|
402
407
|
|
|
403
408
|
time_keys = sorted(dict_of_events.keys())
|
|
@@ -522,7 +527,7 @@ def add_events_into_database(
|
|
|
522
527
|
if "timeseries" in process_dict.keys():
|
|
523
528
|
# Convert "time" in timeseries to timedelta
|
|
524
529
|
timeseries["time"] = [
|
|
525
|
-
(timedelta(seconds=t) + simulation_start_time).isoformat()
|
|
530
|
+
(timedelta(seconds=math.ceil(t)) + simulation_start_time).isoformat()
|
|
526
531
|
for t in process_dict["timeseries"]["time"]
|
|
527
532
|
]
|
|
528
533
|
timeseries["soc"] = process_dict["timeseries"]["soc"]
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"""This module contains miscellaneous utility functions for the eflips-depot API."""
|
|
2
2
|
import logging
|
|
3
3
|
import os
|
|
4
|
+
import warnings
|
|
4
5
|
from contextlib import contextmanager
|
|
5
6
|
from dataclasses import dataclass
|
|
6
7
|
from datetime import timedelta, datetime
|
|
@@ -17,9 +18,11 @@ from eflips.model import (
|
|
|
17
18
|
Trip,
|
|
18
19
|
Depot,
|
|
19
20
|
Temperatures,
|
|
21
|
+
ConsistencyWarning,
|
|
20
22
|
)
|
|
21
23
|
from eflips.model import create_engine
|
|
22
24
|
from sqlalchemy import inspect
|
|
25
|
+
from sqlalchemy.exc import NoResultFound
|
|
23
26
|
from sqlalchemy.orm import Session
|
|
24
27
|
|
|
25
28
|
from eflips.depot import SimpleTrip, Timetable as EflipsTimeTable
|
|
@@ -99,6 +102,7 @@ def vehicle_type_to_global_constants_dict(vt: VehicleType) -> Dict[str, float]:
|
|
|
99
102
|
"soc_max": 1.0,
|
|
100
103
|
"soc_init": 1.0,
|
|
101
104
|
"soh": 1.0,
|
|
105
|
+
"charging_efficiency": vt.charging_efficiency,
|
|
102
106
|
}
|
|
103
107
|
return the_dict
|
|
104
108
|
|
|
@@ -204,7 +208,9 @@ def check_depot_validity(depot: Depot) -> None:
|
|
|
204
208
|
|
|
205
209
|
def temperature_for_trip(trip_id: int, session: Session) -> float:
|
|
206
210
|
"""
|
|
207
|
-
Returns the temperature for a trip.
|
|
211
|
+
Returns the temperature for a trip.
|
|
212
|
+
|
|
213
|
+
Finds the temperature for the mid-point of the trip.
|
|
208
214
|
|
|
209
215
|
:param trip_id: The ID of the trip
|
|
210
216
|
:param session: The SQLAlchemy session
|
|
@@ -212,11 +218,18 @@ def temperature_for_trip(trip_id: int, session: Session) -> float:
|
|
|
212
218
|
"""
|
|
213
219
|
|
|
214
220
|
trip = session.query(Trip).filter(Trip.id == trip_id).one()
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
221
|
+
try:
|
|
222
|
+
temperatures = (
|
|
223
|
+
session.query(Temperatures)
|
|
224
|
+
.filter(Temperatures.scenario_id == trip.scenario_id)
|
|
225
|
+
.one()
|
|
226
|
+
)
|
|
227
|
+
except NoResultFound:
|
|
228
|
+
warnings.warn(
|
|
229
|
+
f"No temperatures found for scenario {trip.scenario_id}.",
|
|
230
|
+
ConsistencyWarning,
|
|
231
|
+
)
|
|
232
|
+
return None
|
|
220
233
|
|
|
221
234
|
# Find the mid-point of the trip
|
|
222
235
|
mid_time = trip.departure_time + (trip.arrival_time - trip.departure_time) / 2
|
|
@@ -840,6 +840,7 @@ class Charge(ChargeAbstract):
|
|
|
840
840
|
|
|
841
841
|
@property
|
|
842
842
|
def power(self):
|
|
843
|
+
# TODO this doesn't consider vehicle charging power
|
|
843
844
|
return self.charging_interface.max_power
|
|
844
845
|
|
|
845
846
|
def _action(self, *args, **kwargs):
|
|
@@ -1240,6 +1241,8 @@ class ChargeEquationSteps(ChargeAbstract):
|
|
|
1240
1241
|
self.precision = precision
|
|
1241
1242
|
Charge.check_soc_target(soc_target, vehicle_filter)
|
|
1242
1243
|
self.soc_target = soc_target
|
|
1244
|
+
if "precision" in self.peq_params:
|
|
1245
|
+
self.precision = self.peq_params["precision"]
|
|
1243
1246
|
|
|
1244
1247
|
@property
|
|
1245
1248
|
def power(self):
|
|
@@ -1271,8 +1274,12 @@ class ChargeEquationSteps(ChargeAbstract):
|
|
|
1271
1274
|
)
|
|
1272
1275
|
soc_target_step = self.vehicle.battery.soc + soc_interval
|
|
1273
1276
|
amount = self.vehicle.battery.energy_real * soc_interval
|
|
1274
|
-
effective_power =
|
|
1275
|
-
|
|
1277
|
+
effective_power = (
|
|
1278
|
+
self.power
|
|
1279
|
+
* self.efficiency
|
|
1280
|
+
* self.vehicle.vehicle_type.charging_efficiency
|
|
1281
|
+
)
|
|
1282
|
+
self.dur = round(amount / effective_power * 3600, 12)
|
|
1276
1283
|
|
|
1277
1284
|
if self.dur == 0:
|
|
1278
1285
|
# amount is so small that dur is <1s. Reduce the precision
|
|
@@ -1295,6 +1302,7 @@ class ChargeEquationSteps(ChargeAbstract):
|
|
|
1295
1302
|
yield self.env.timeout(self.dur)
|
|
1296
1303
|
|
|
1297
1304
|
if soc_target_step < self.soc_target:
|
|
1305
|
+
# TODO why here we have energy higher than the step_soc_target?
|
|
1298
1306
|
# recalculate amount because update_battery may have been
|
|
1299
1307
|
# called in the meantime
|
|
1300
1308
|
amount_step = (
|
|
@@ -1438,13 +1446,21 @@ def charging_curve_power(vehicle, charging_interface, peq_params):
|
|
|
1438
1446
|
:return: charging power in float for given SimpleVehicle
|
|
1439
1447
|
"""
|
|
1440
1448
|
|
|
1449
|
+
precision = peq_params.get("precision", 0.01)
|
|
1441
1450
|
current_soc = vehicle.battery.soc
|
|
1442
1451
|
p_max = charging_interface.max_power
|
|
1452
|
+
target_step_soc = min(vehicle.battery.soc + precision, vehicle.battery.soc_max)
|
|
1443
1453
|
|
|
1444
|
-
|
|
1454
|
+
power_current_soc = min(
|
|
1445
1455
|
p_max, np.interp(current_soc, peq_params["soc"], peq_params["power"])
|
|
1446
1456
|
)
|
|
1447
1457
|
|
|
1458
|
+
power_target_soc = min(
|
|
1459
|
+
p_max, np.interp(target_step_soc, peq_params["soc"], peq_params["power"])
|
|
1460
|
+
)
|
|
1461
|
+
|
|
1462
|
+
current_power = min(power_current_soc, power_target_soc)
|
|
1463
|
+
|
|
1448
1464
|
return float(current_power)
|
|
1449
1465
|
|
|
1450
1466
|
|
|
@@ -422,7 +422,7 @@ class RfdDiffDispatch:
|
|
|
422
422
|
diffs = []
|
|
423
423
|
for vehicle in area.vehicles:
|
|
424
424
|
etc = vehicle.dwd.etc_processes
|
|
425
|
-
if isinstance(etc, int):
|
|
425
|
+
if isinstance(etc, int) or isinstance(etc, float):
|
|
426
426
|
diff = etc - slot[0].env.now
|
|
427
427
|
diffs.append(diff)
|
|
428
428
|
# Convert EstimateValue to numerical rfddiff
|
|
@@ -36,7 +36,17 @@ class VehicleType:
|
|
|
36
36
|
|
|
37
37
|
"""
|
|
38
38
|
|
|
39
|
-
def __init__(
|
|
39
|
+
def __init__(
|
|
40
|
+
self,
|
|
41
|
+
ID,
|
|
42
|
+
battery_capacity,
|
|
43
|
+
soc_min,
|
|
44
|
+
soc_max,
|
|
45
|
+
soc_init,
|
|
46
|
+
soh,
|
|
47
|
+
charging_efficiency=1.0,
|
|
48
|
+
CR=None,
|
|
49
|
+
):
|
|
40
50
|
self.ID = ID
|
|
41
51
|
self.battery_capacity = battery_capacity
|
|
42
52
|
self.soc_min = soc_min
|
|
@@ -45,6 +55,7 @@ class VehicleType:
|
|
|
45
55
|
self.soh = soh
|
|
46
56
|
self.CR = CR
|
|
47
57
|
self.group = None
|
|
58
|
+
self.charging_efficiency = charging_efficiency
|
|
48
59
|
|
|
49
60
|
self.count = {}
|
|
50
61
|
self.share = {}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{eflips_depot-4.15.0 → eflips_depot-4.15.2}/eflips/depot/layout_opt/opt_tools/fitness_c_urfd.py
RENAMED
|
File without changes
|
{eflips_depot-4.15.0 → eflips_depot-4.15.2}/eflips/depot/layout_opt/opt_tools/fitness_util.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|