mg-pso-gui 0.1.163__tar.gz → 0.1.165__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.
- {mg-pso-gui-0.1.163 → mg-pso-gui-0.1.165}/PKG-INFO +1 -1
- {mg-pso-gui-0.1.163 → mg-pso-gui-0.1.165}/mg_pso_gui.egg-info/PKG-INFO +1 -1
- {mg-pso-gui-0.1.163 → mg-pso-gui-0.1.165}/mgpsogui/gui/VisualizeTab/SideBar.py +65 -1
- {mg-pso-gui-0.1.163 → mg-pso-gui-0.1.165}/mgpsogui/gui/VisualizeTab/VisualizeTab.py +1 -1
- {mg-pso-gui-0.1.163 → mg-pso-gui-0.1.165}/mgpsogui/util/GraphGenerator.py +71 -0
- {mg-pso-gui-0.1.163 → mg-pso-gui-0.1.165}/mgpsogui/util/PSORunner.py +5 -2
- {mg-pso-gui-0.1.163 → mg-pso-gui-0.1.165}/setup.py +1 -1
- {mg-pso-gui-0.1.163 → mg-pso-gui-0.1.165}/mg_pso_gui.egg-info/SOURCES.txt +0 -0
- {mg-pso-gui-0.1.163 → mg-pso-gui-0.1.165}/mg_pso_gui.egg-info/dependency_links.txt +0 -0
- {mg-pso-gui-0.1.163 → mg-pso-gui-0.1.165}/mg_pso_gui.egg-info/entry_points.txt +0 -0
- {mg-pso-gui-0.1.163 → mg-pso-gui-0.1.165}/mg_pso_gui.egg-info/requires.txt +0 -0
- {mg-pso-gui-0.1.163 → mg-pso-gui-0.1.165}/mg_pso_gui.egg-info/top_level.txt +0 -0
- {mg-pso-gui-0.1.163 → mg-pso-gui-0.1.165}/mgpsogui/__init__.py +0 -0
- {mg-pso-gui-0.1.163 → mg-pso-gui-0.1.165}/mgpsogui/gui/HomePage.py +0 -0
- {mg-pso-gui-0.1.163 → mg-pso-gui-0.1.165}/mgpsogui/gui/OptionManager.py +0 -0
- {mg-pso-gui-0.1.163 → mg-pso-gui-0.1.165}/mgpsogui/gui/PlatformTab/PlatformTab.py +0 -0
- {mg-pso-gui-0.1.163 → mg-pso-gui-0.1.165}/mgpsogui/gui/PlatformTab/__init__.py +0 -0
- {mg-pso-gui-0.1.163 → mg-pso-gui-0.1.165}/mgpsogui/gui/RunTab/RunTab.py +0 -0
- {mg-pso-gui-0.1.163 → mg-pso-gui-0.1.165}/mgpsogui/gui/RunTab/__init__.py +0 -0
- {mg-pso-gui-0.1.163 → mg-pso-gui-0.1.165}/mgpsogui/gui/SetupTab/BoundsEditorWindow.py +0 -0
- {mg-pso-gui-0.1.163 → mg-pso-gui-0.1.165}/mgpsogui/gui/SetupTab/BoundsList.py +0 -0
- {mg-pso-gui-0.1.163 → mg-pso-gui-0.1.165}/mgpsogui/gui/SetupTab/CalibrationParametersView.py +0 -0
- {mg-pso-gui-0.1.163 → mg-pso-gui-0.1.165}/mgpsogui/gui/SetupTab/FunctionsList.py +0 -0
- {mg-pso-gui-0.1.163 → mg-pso-gui-0.1.165}/mgpsogui/gui/SetupTab/ListParametersView.py +0 -0
- {mg-pso-gui-0.1.163 → mg-pso-gui-0.1.165}/mgpsogui/gui/SetupTab/OptimalParameterView.py +0 -0
- {mg-pso-gui-0.1.163 → mg-pso-gui-0.1.165}/mgpsogui/gui/SetupTab/SetupTab.py +0 -0
- {mg-pso-gui-0.1.163 → mg-pso-gui-0.1.165}/mgpsogui/gui/SetupTab/StaticParameterView.py +0 -0
- {mg-pso-gui-0.1.163 → mg-pso-gui-0.1.165}/mgpsogui/gui/SetupTab/StepView.py +0 -0
- {mg-pso-gui-0.1.163 → mg-pso-gui-0.1.165}/mgpsogui/gui/SetupTab/__init__.py +0 -0
- {mg-pso-gui-0.1.163 → mg-pso-gui-0.1.165}/mgpsogui/gui/VisualizeTab/__init__.py +0 -0
- {mg-pso-gui-0.1.163 → mg-pso-gui-0.1.165}/mgpsogui/gui/__init__.py +0 -0
- {mg-pso-gui-0.1.163 → mg-pso-gui-0.1.165}/mgpsogui/gui/images/IGOW 4 Logo.png +0 -0
- {mg-pso-gui-0.1.163 → mg-pso-gui-0.1.165}/mgpsogui/gui/images/collapse.png +0 -0
- {mg-pso-gui-0.1.163 → mg-pso-gui-0.1.165}/mgpsogui/gui/images/down.png +0 -0
- {mg-pso-gui-0.1.163 → mg-pso-gui-0.1.165}/mgpsogui/gui/images/expand.png +0 -0
- {mg-pso-gui-0.1.163 → mg-pso-gui-0.1.165}/mgpsogui/gui/images/play.png +0 -0
- {mg-pso-gui-0.1.163 → mg-pso-gui-0.1.165}/mgpsogui/gui/images/refresh.png +0 -0
- {mg-pso-gui-0.1.163 → mg-pso-gui-0.1.165}/mgpsogui/gui/images/refresh_hd.png +0 -0
- {mg-pso-gui-0.1.163 → mg-pso-gui-0.1.165}/mgpsogui/gui/images/stop.png +0 -0
- {mg-pso-gui-0.1.163 → mg-pso-gui-0.1.165}/mgpsogui/gui/images/test.png +0 -0
- {mg-pso-gui-0.1.163 → mg-pso-gui-0.1.165}/mgpsogui/gui/images/trash.png +0 -0
- {mg-pso-gui-0.1.163 → mg-pso-gui-0.1.165}/mgpsogui/gui/images/up.png +0 -0
- {mg-pso-gui-0.1.163 → mg-pso-gui-0.1.165}/mgpsogui/mgpsogui.py +0 -0
- {mg-pso-gui-0.1.163 → mg-pso-gui-0.1.165}/mgpsogui/start.yaml +0 -0
- {mg-pso-gui-0.1.163 → mg-pso-gui-0.1.165}/mgpsogui/util/CTkToolTip/__init__.py +0 -0
- {mg-pso-gui-0.1.163 → mg-pso-gui-0.1.165}/mgpsogui/util/CTkToolTip/ctk_tooltip.py +0 -0
- {mg-pso-gui-0.1.163 → mg-pso-gui-0.1.165}/mgpsogui/util/__init__.py +0 -0
- {mg-pso-gui-0.1.163 → mg-pso-gui-0.1.165}/mgpsogui/util/debug.py +0 -0
- {mg-pso-gui-0.1.163 → mg-pso-gui-0.1.165}/mgpsogui/util/helpers.py +0 -0
- {mg-pso-gui-0.1.163 → mg-pso-gui-0.1.165}/mgpsogui/util/recosu/__init__.py +0 -0
- {mg-pso-gui-0.1.163 → mg-pso-gui-0.1.165}/mgpsogui/util/recosu/pso/__init__.py +0 -0
- {mg-pso-gui-0.1.163 → mg-pso-gui-0.1.165}/mgpsogui/util/recosu/pso/csip_access.py +0 -0
- {mg-pso-gui-0.1.163 → mg-pso-gui-0.1.165}/mgpsogui/util/recosu/pso/pso.py +0 -0
- {mg-pso-gui-0.1.163 → mg-pso-gui-0.1.165}/mgpsogui/util/recosu/sampling/__init__.py +0 -0
- {mg-pso-gui-0.1.163 → mg-pso-gui-0.1.165}/mgpsogui/util/recosu/sampling/halton/__init__.py +0 -0
- {mg-pso-gui-0.1.163 → mg-pso-gui-0.1.165}/mgpsogui/util/recosu/sampling/halton/halton.py +0 -0
- {mg-pso-gui-0.1.163 → mg-pso-gui-0.1.165}/mgpsogui/util/recosu/sampling/halton/prime.py +0 -0
- {mg-pso-gui-0.1.163 → mg-pso-gui-0.1.165}/mgpsogui/util/recosu/sampling/random/__init__.py +0 -0
- {mg-pso-gui-0.1.163 → mg-pso-gui-0.1.165}/mgpsogui/util/recosu/sampling/random/random_sampler.py +0 -0
- {mg-pso-gui-0.1.163 → mg-pso-gui-0.1.165}/mgpsogui/util/recosu/sampling/sample_trace_writer.py +0 -0
- {mg-pso-gui-0.1.163 → mg-pso-gui-0.1.165}/mgpsogui/util/recosu/sampling/sampler_task.py +0 -0
- {mg-pso-gui-0.1.163 → mg-pso-gui-0.1.165}/mgpsogui/util/recosu/sampling/sampling.py +0 -0
- {mg-pso-gui-0.1.163 → mg-pso-gui-0.1.165}/mgpsogui/util/recosu/utils/__init__.py +0 -0
- {mg-pso-gui-0.1.163 → mg-pso-gui-0.1.165}/mgpsogui/util/recosu/utils/plot/__init__.py +0 -0
- {mg-pso-gui-0.1.163 → mg-pso-gui-0.1.165}/mgpsogui/util/recosu/utils/plot/cost_steps.py +0 -0
- {mg-pso-gui-0.1.163 → mg-pso-gui-0.1.165}/mgpsogui/util/recosu/utils/trace_writer.py +0 -0
- {mg-pso-gui-0.1.163 → mg-pso-gui-0.1.165}/mgpsogui/util/recosu/utils/utils.py +0 -0
- {mg-pso-gui-0.1.163 → mg-pso-gui-0.1.165}/mgpsogui/util/sampler_test_driver.py +0 -0
- {mg-pso-gui-0.1.163 → mg-pso-gui-0.1.165}/setup.cfg +0 -0
|
@@ -198,7 +198,71 @@ class SideBar(CTkScrollableFrame):
|
|
|
198
198
|
if (self.home_page.csv_y2_selector.get() not in columns2):
|
|
199
199
|
self.home_page.csv_y2_selector.set(columns2[2])
|
|
200
200
|
|
|
201
|
-
|
|
201
|
+
elif (selected_graph == "Sampling CSV"):
|
|
202
|
+
|
|
203
|
+
info = self.option_manager.get_project_data()
|
|
204
|
+
folder = os.path.join(info['path'], info['name'])
|
|
205
|
+
if not os.path.exists(folder):
|
|
206
|
+
os.makedirs(folder)
|
|
207
|
+
|
|
208
|
+
# Get all CSV files in the folder and add their paths to a list
|
|
209
|
+
path_map = {}
|
|
210
|
+
name_list = []
|
|
211
|
+
for root, dirs, files in os.walk(folder):
|
|
212
|
+
for file in files:
|
|
213
|
+
if file.endswith(".csv"):
|
|
214
|
+
name = file.replace(".csv", "")
|
|
215
|
+
name_list.append(name)
|
|
216
|
+
path_map[name] = os.path.join(root, file)
|
|
217
|
+
|
|
218
|
+
if (len(name_list) == 0):
|
|
219
|
+
name_list.append("No files found...")
|
|
220
|
+
else:
|
|
221
|
+
if (self.home_page.selected_csv.get() not in name_list):
|
|
222
|
+
self.home_page.selected_csv.set(name_list[0])
|
|
223
|
+
|
|
224
|
+
file_label = CTkLabel(self.containerFrame, text="CSV File:")
|
|
225
|
+
file_label.grid(row=0, column=0, padx=(20, 20), pady=(20, 5), sticky="w")
|
|
226
|
+
|
|
227
|
+
self.home_page.csv_file_selector = CTkOptionMenu(self.containerFrame, values=name_list, variable=self.home_page.selected_csv, command=self.home_page.update_graph)
|
|
228
|
+
self.home_page.csv_file_selector.grid(row=1, column=0, padx=(20, 20), pady=(5, 5), sticky="ew")
|
|
229
|
+
|
|
230
|
+
selected_file = self.home_page.selected_csv.get()
|
|
231
|
+
if (selected_file in path_map and selected_file != self.home_page.open_file):
|
|
232
|
+
self.home_page.csv_data = pd.read_csv(path_map[selected_file])
|
|
233
|
+
print(self.home_page.csv_data)
|
|
234
|
+
self.home_page.open_file = selected_file
|
|
235
|
+
|
|
236
|
+
if (self.home_page.csv_data is not None):
|
|
237
|
+
# Get all column names of CSV
|
|
238
|
+
columns = self.home_page.csv_data.columns
|
|
239
|
+
|
|
240
|
+
x_axis_label = CTkLabel(self.containerFrame, text="X Axis:")
|
|
241
|
+
x_axis_label.grid(row=2, column=0, padx=(20, 20), pady=(40, 5), sticky="w")
|
|
242
|
+
|
|
243
|
+
self.home_page.csv_x_selector = CTkOptionMenu(self.containerFrame, values=columns, variable=self.home_page.selected_x, command=self.home_page.update_graph)
|
|
244
|
+
self.home_page.csv_x_selector.grid(row=3, column=0, padx=(20, 20), pady=(5, 5), sticky="ew")
|
|
245
|
+
|
|
246
|
+
if (self.home_page.csv_x_selector.get() not in columns):
|
|
247
|
+
self.home_page.csv_x_selector.set(columns[1])
|
|
248
|
+
|
|
249
|
+
y1_axis_label = CTkLabel(self.containerFrame, text="Y Axis:")
|
|
250
|
+
y1_axis_label.grid(row=4, column=0, padx=(20, 20), pady=(20, 5), sticky="w")
|
|
251
|
+
|
|
252
|
+
self.home_page.csv_y1_selector = CTkOptionMenu(self.containerFrame, values=columns, variable=self.home_page.selected_y1, command=self.home_page.update_graph)
|
|
253
|
+
self.home_page.csv_y1_selector.grid(row=5, column=0, padx=(20, 20), pady=(5, 5), sticky="ew")
|
|
254
|
+
|
|
255
|
+
if (self.home_page.csv_y1_selector.get() not in columns):
|
|
256
|
+
self.home_page.csv_y1_selector.set(columns[2])
|
|
257
|
+
|
|
258
|
+
y2_axis_label = CTkLabel(self.containerFrame, text="Secondary Y Axis:")
|
|
259
|
+
y2_axis_label.grid(row=6, column=0, padx=(20, 20), pady=(20, 5), sticky="w")
|
|
260
|
+
|
|
261
|
+
self.home_page.csv_y2_selector = CTkOptionMenu(self.containerFrame, values=columns, variable=self.home_page.selected_y2, command=self.home_page.update_graph)
|
|
262
|
+
self.home_page.csv_y2_selector.grid(row=7, column=0, padx=(20, 20), pady=(5, 5), sticky="ew")
|
|
263
|
+
|
|
264
|
+
if (self.home_page.csv_y2_selector.get() not in columns):
|
|
265
|
+
self.home_page.csv_y2_selector.set(columns[3])
|
|
202
266
|
|
|
203
267
|
def load_special_csv(self, file_path):
|
|
204
268
|
file_metadata = {}
|
|
@@ -61,7 +61,7 @@ def create_tab(self, tab):
|
|
|
61
61
|
self.graph_container.grid_columnconfigure(0, weight=1)
|
|
62
62
|
self.graph_container.grid_rowconfigure(0, weight=1)
|
|
63
63
|
|
|
64
|
-
self.graph_selector = customtkinter.CTkOptionMenu(self.graph_sidebar, values=["Best Cost Stacked", "Best Cost by Round", "Calibrated Parameters", "
|
|
64
|
+
self.graph_selector = customtkinter.CTkOptionMenu(self.graph_sidebar, values=["Best Cost Stacked", "Best Cost by Round", "Calibrated Parameters", "Custom CSV", "Compare CSV", "Sampling CSV"], variable=self.graph_selector_value, command=self.update_graph)
|
|
65
65
|
self.graph_selector.grid(row=0, column=0, padx=(20, 20), pady=(20, 20), sticky="nsew")
|
|
66
66
|
|
|
67
67
|
# Create SideBar
|
|
@@ -33,6 +33,9 @@ def generate_graphs(HomePage):
|
|
|
33
33
|
elif (selected_graph == "Compare CSV"):
|
|
34
34
|
HomePage.selected_graph_name = "compare_csv"
|
|
35
35
|
compare_csv(HomePage, HomePage.option_manager)
|
|
36
|
+
elif (selected_graph == "Sampling CSV"):
|
|
37
|
+
HomePage.selected_graph_name = "sampling_csv"
|
|
38
|
+
sampling_csv(HomePage, HomePage.option_manager)
|
|
36
39
|
|
|
37
40
|
image_path = os.path.join(folder, HomePage.selected_graph_name + ".png")
|
|
38
41
|
|
|
@@ -436,4 +439,72 @@ def compare_csv(homepage, option_manager):
|
|
|
436
439
|
with open(os.path.join(folder, "compare_csv.html"), "w") as f:
|
|
437
440
|
f.write(html)
|
|
438
441
|
|
|
442
|
+
return fig
|
|
443
|
+
|
|
444
|
+
def sampling_csv(homepage, option_manager):
|
|
445
|
+
fig = go.Figure()
|
|
446
|
+
|
|
447
|
+
data = homepage.csv_data
|
|
448
|
+
|
|
449
|
+
x = homepage.csv_x_selector.get()
|
|
450
|
+
val = homepage.csv_y1_selector.get()
|
|
451
|
+
val2 = homepage.csv_y2_selector.get()
|
|
452
|
+
|
|
453
|
+
xx = None
|
|
454
|
+
if x == "time":
|
|
455
|
+
xx = pd.to_datetime(data["time"], format='%Y-%m-%d', errors='coerce')
|
|
456
|
+
elif x == "date":
|
|
457
|
+
xx = pd.to_datetime(data["date"], format='%d-%m-%Y', errors='coerce')
|
|
458
|
+
else:
|
|
459
|
+
xx = pd.to_numeric(data[x], errors="coerce")
|
|
460
|
+
|
|
461
|
+
yy = pd.to_numeric(data[val], errors="coerce")
|
|
462
|
+
|
|
463
|
+
yy_unit = "-"
|
|
464
|
+
|
|
465
|
+
yy2 = pd.to_numeric(data[val2], errors="coerce")
|
|
466
|
+
|
|
467
|
+
yy2_unit = "-"
|
|
468
|
+
|
|
469
|
+
fig.add_trace(go.Scatter(x=xx, y=yy, name=val, mode='markers'))
|
|
470
|
+
fig.add_trace(go.Scatter(x=xx, y=yy2, name=val2, yaxis='y2', mode='markers'))
|
|
471
|
+
|
|
472
|
+
fig.update_layout(
|
|
473
|
+
title="",
|
|
474
|
+
xaxis_title=x,
|
|
475
|
+
yaxis_title=val,
|
|
476
|
+
font=dict(color='white'),
|
|
477
|
+
paper_bgcolor='rgba(42, 42, 42, 0)',
|
|
478
|
+
plot_bgcolor='rgb(62, 62, 62)',
|
|
479
|
+
xaxis=dict(
|
|
480
|
+
gridcolor='rgb(72, 72, 72)',
|
|
481
|
+
gridwidth=1
|
|
482
|
+
),
|
|
483
|
+
yaxis=dict(
|
|
484
|
+
title=val + " (" + str(yy_unit) + ")",
|
|
485
|
+
autorange=True,
|
|
486
|
+
gridcolor='rgb(72, 72, 72)',
|
|
487
|
+
gridwidth=0.1
|
|
488
|
+
),
|
|
489
|
+
yaxis2=dict(
|
|
490
|
+
title=val2 + " (" + str(yy2_unit) + ")",
|
|
491
|
+
overlaying='y',
|
|
492
|
+
side='right'
|
|
493
|
+
)
|
|
494
|
+
)
|
|
495
|
+
|
|
496
|
+
info = option_manager.get_project_data()
|
|
497
|
+
folder = os.path.join(info['path'], info['name'])
|
|
498
|
+
|
|
499
|
+
if not os.path.exists(folder):
|
|
500
|
+
os.makedirs(folder)
|
|
501
|
+
|
|
502
|
+
fig.write_image(os.path.join(folder, "sampling_csv.png"), width=1280, height=720)
|
|
503
|
+
fig.write_html(os.path.join(folder, "sampling_csv.html"), include_plotlyjs='cdn', auto_open=False)
|
|
504
|
+
with open(os.path.join(folder, "sampling_csv.html"), "r") as f:
|
|
505
|
+
html = f.read()
|
|
506
|
+
html = html.replace("<body>", "<body bgcolor='#2a2a2a'>")
|
|
507
|
+
with open(os.path.join(folder, "sampling_csv.html"), "w") as f:
|
|
508
|
+
f.write(html)
|
|
509
|
+
|
|
439
510
|
return fig
|
|
@@ -33,6 +33,9 @@ def run_process(stdout_queue, stderr_queue, results_queue, data, folder):
|
|
|
33
33
|
if not os.path.exists(folder):
|
|
34
34
|
os.makedirs(folder)
|
|
35
35
|
|
|
36
|
+
if not os.path.exists(os.path.join(folder, "results")):
|
|
37
|
+
os.makedirs(os.path.join(folder, "results"))
|
|
38
|
+
|
|
36
39
|
if (os.path.exists(os.path.join(folder, 'output.txt'))):
|
|
37
40
|
os.remove(os.path.join(folder, 'output.txt'))
|
|
38
41
|
|
|
@@ -112,7 +115,7 @@ def run_process(stdout_queue, stderr_queue, results_queue, data, folder):
|
|
|
112
115
|
int(calibration_map['num_threads']),
|
|
113
116
|
"halton",
|
|
114
117
|
conf=config,
|
|
115
|
-
trace_file=os.path.join(folder, 'halton_trace.
|
|
118
|
+
trace_file=os.path.join(folder, 'results', 'halton_trace.csv'),
|
|
116
119
|
offset=int(calibration_map['offset']))
|
|
117
120
|
results_queue.put(trace)
|
|
118
121
|
print(trace, flush=True)
|
|
@@ -125,7 +128,7 @@ def run_process(stdout_queue, stderr_queue, results_queue, data, folder):
|
|
|
125
128
|
int(calibration_map['num_threads']),
|
|
126
129
|
"random",
|
|
127
130
|
conf=config,
|
|
128
|
-
trace_file=os.path.join(folder, 'random_trace.
|
|
131
|
+
trace_file=os.path.join(folder, 'results', 'random_trace.csv'))
|
|
129
132
|
results_queue.put(trace)
|
|
130
133
|
print(trace, flush=True)
|
|
131
134
|
else:
|
|
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
|
{mg-pso-gui-0.1.163 → mg-pso-gui-0.1.165}/mgpsogui/gui/SetupTab/CalibrationParametersView.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
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mg-pso-gui-0.1.163 → mg-pso-gui-0.1.165}/mgpsogui/util/recosu/sampling/random/random_sampler.py
RENAMED
|
File without changes
|
{mg-pso-gui-0.1.163 → mg-pso-gui-0.1.165}/mgpsogui/util/recosu/sampling/sample_trace_writer.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
|