Files
SemesterapparatsManager/src/ui/widgets/graph.py

165 lines
5.4 KiB
Python

import random
import sys
from typing import Any, Union
import loguru
import pyqtgraph as pg
from PyQt6 import QtWidgets
from src import LOG_DIR
log = loguru.logger
log.remove()
log.add(sys.stdout, level="INFO")
log.add(f"{LOG_DIR}/application.log", rotation="1 MB", retention="10 days")
def mergedicts(d1: dict[str, Any], d2: dict[str, Any]):
res: dict[str, Any] = {}
d1_data = list(d1.items())
d2_data = list(d2.items())
for i in range(len(d1)):
# _data is a list of tuples
d1_data_slice = d1_data[i]
d2_data_slice = d2_data[i]
# convert the tuples to dicts
d1_dict = dict([d1_data_slice])
d2_dict = dict([d2_data_slice])
# merge the dicts
res.update(d1_dict) # type: ignore
res.update(d2_dict) # type: ignore
return res
class DataGraph(QtWidgets.QWidget):
def __init__(
self,
title: str,
data=Union[dict[list, list], dict[list[dict[str, list[Any]]]]],
generateMissing: bool = False,
label: str = None,
):
super().__init__()
log.debug(
"Initialized with options: {}, {}, {}, {}".format(
title, data, generateMissing, label
)
)
lst = []
if generateMissing:
x_data = data["x"]
y_data = data["y"]
if not isinstance(y_data, list):
for key in y_data:
data = {"x": x_data, "y": y_data[key]}
data = self.generateMissingSemesters(data)
data["y-label"] = key
lst.append(data)
else:
data = self.generateMissingSemesters(data)
lst.append(data)
else:
x_data = data["x"]
y_data = data["y"]
if not isinstance(y_data, list):
for key in y_data:
data = {"x": x_data, "y": y_data[key]}
data["y-label"] = key
lst.append(data)
else:
lst.append(data)
x_data = lst[0]["x"] #
xdict = dict(enumerate(x_data))
stringaxis_x = pg.AxisItem(orientation="bottom")
stringaxis_x.setTicks([xdict.items()])
graph = pg.PlotWidget(axisItems={"bottom": stringaxis_x})
graph.addLegend()
colors = ["b", "r", "c", "m", "y", "k", "w"]
symbols = [
"o",
"s",
"t",
"d",
"+",
"t1",
"t2",
"t3",
"p",
"h",
"star",
"x",
"arrow_up",
"arrow_down",
"arrow_left",
"arrow_right",
]
color_index = 0
index = 0
for data in lst:
symbol = symbols[random.randint(0, len(symbols) - 1)]
if color_index >= len(colors):
color_index = 0
# iterate over the list, use y-data and y-label to plot the graph
y_data = data["y"]
label = data["y-label"] if "y-label" in data else label
pen = pg.mkPen(color=colors[color_index], width=2)
if isinstance(y_data, list):
graph.plot(
list(xdict.keys()), y_data, pen=pen, symbol=symbol, name=label
)
color_index += 1
index += 1
else:
pass
graph.setBackground("#d3d3d3")
graph.setTitle(title)
layout = QtWidgets.QVBoxLayout()
layout.addWidget(graph)
self.setLayout(layout)
def generateMissingSemesters(self, data: dict[list]):
# join the data into a single dict with x values as key and y values as value
tmp_data = dict(zip(data["x"], data["y"], strict=False))
# split into dicts based on SoSe and WiSe
SoSe_data = {k: v for k, v in tmp_data.items() if "SoSe" in k}
WiSe_data = {k: v for k, v in tmp_data.items() if "WiSe" in k}
SoSe_years = [int(sose.split("SoSe")[1]) for sose in SoSe_data]
WiSe_years = [int(wise.split("WiSe")[1].split("/")[0]) for wise in WiSe_data]
years = SoSe_years + WiSe_years
years = [
year for year in range(min(list(set(years))), max(list(set(years))) + 1)
]
years.sort()
for year in years:
SoSe_year = f"SoSe{year}"
WiSe_year = f"WiSe{year}/{year + 1}"
if SoSe_year not in SoSe_data.keys():
SoSe_data[SoSe_year] = 0
if WiSe_year not in WiSe_data.keys():
WiSe_data[WiSe_year] = 0
# sort WiSe_data to have same order as SoSe_data
WiSe_data = dict(sorted(WiSe_data.items(), key=lambda x: x[0]))
SoSe_data = dict(sorted(SoSe_data.items(), key=lambda x: x[0]))
data = mergedicts(SoSe_data, WiSe_data)
# split the data back into x and y
data = {"x": list(data.keys()), "y": list(data.values())}
return data
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
graph_data = {"x": ["WiSe 25/26", "WiSe 24/25", "SoSe 25"], "y": [1, 2, 1]}
widget = DataGraph(
"ELSA Apparate pro Semester", graph_data, True, "Anzahl der Apparate"
)
widget.show()
sys.exit(app.exec())