diff --git a/.gitignore b/.gitignore index 0d1eaa6..0f4c902 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,5 @@ # ---> ImGUI -imgui.ini +*.ini # ---> Python # Byte-compiled / optimized / DLL files diff --git a/assets/Student_list.csv b/assets/Student_list.csv new file mode 100644 index 0000000..e05d8f5 --- /dev/null +++ b/assets/Student_list.csv @@ -0,0 +1,33 @@ +First Name,Last Name,Sex,Tutorial 1,Tutorial 2,Extended Applications,Numpy & MatPlotLib,SciPy,Monte Carlo,Pandas & Seaborn,Folium +Abdalaziz,Abunjaila,Male,30.5,15,18,28,17,17,17,22 +Marleen,Adolphi,Female,29.5,15,18,32,19,0,17,24 +Aurela,Brahimi,Female,17.5,15,15.5,26,16,17,19,16 +Cam Thu,Do,Female,31,15,18,34,19,20,21.5,22 +Nova,Eib,Female,31,15,15,34,20,20,21,27 +Nele,Grundke,Female,23.5,13,16,28,20,17,21,18 +Anna,Grünewald,Female,12,14,16,29,16,15,19,9 +Yannik,Haupt,Male,18,6,14,21,13,2,9,0 +Janna,Heiny,Female,30,15,18,33,18,20,22,25 +Milena,Krieger,Female,30,15,18,33,20,20,21.5,26 +Julia,Limbach,Female,27.5,12,18,29,11,19,17.5,26 +Viktoria,Litza,Female,21.5,15,18,27,13,20,22,21 +Manthey,Leonie,Female,28.5,14,18,29,20,10,18,23 +Izabel,Mike,Female,29.5,15,15,35,11,4,19,21 +Lea,Noglik,Female,22.5,15,17,34,13,10,20,0 +Donika,Nuhiu,Female,31,13.5,18,35,14,10,17,18 +Julia,Renner,Female,27.5,10,14,0,20,17,11,20 +Fabian,Rothberger,Male,30.5,15,18,34,17,17,19,22 +Natascha,Rott,Female,29.5,12,18,32,19,20,21,26 +Isabel,Rudolf,Female,27.5,9,17,34,16,19,19,21 +Melina,Sablotny,Female,31,15,18,33,20,20,21,19 +Alea,Schleier,Female,27,14,18,34,16,18,21.5,22 +Flemming,Schur,Male,29.5,15,17,34,19,20,19,22 +Marie,Seeger,Female,27.5,15,18,32,14,9,17,22 +Lucy,Thiele,Female,27.5,15,18,27,20,17,19,18 +Lara,Troschke,Female,28.5,14,17,28,13,19,21,25 +Inga-Brit,Turschner,Female,25.5,14,18,34,20,16,19,22 +Alea,Unger,Female,30,12,18,31,20,20,21,22 +Marie,Wallbaum,Female,28.5,14,18,34,17,20,19,24 +Katharina,Walz,Female,31,15,18,31,19,19,17,24 +Xiaowei,Wang,Male,30.5,14,18,26,19,17,0,0 +Lilly-Lu,Warnken,Female,30,15,18,30,14,17,19,14 diff --git a/assets/Student_list.xlsx b/assets/Student_list.xlsx new file mode 100644 index 0000000..403425c Binary files /dev/null and b/assets/Student_list.xlsx differ diff --git a/assets/convert.py b/assets/convert.py new file mode 100644 index 0000000..4ce3dd4 --- /dev/null +++ b/assets/convert.py @@ -0,0 +1,42 @@ +import pandas as pd +import pprint +import sys +sys.path.append('..') +from model import * + +df = pd.read_csv("Student_list.csv") +courses = { + 'Tutorial 1': 31, + 'Tutorial 2': 15, + 'Extended Applications': 18, + 'Numpy & MatPlotLib': 35, + 'SciPy': 20, + 'Monte Carlo': 20, + 'Pandas & Seaborn': 22, + 'Folium': 27 + } + +# Create Class +clas = Class.create(name='WiSe 24/25') +#print(clas.id) + +# Create Courses +for k, v in courses.items(): + Lecture.create(title=k, points=v, class_id=clas.id) + #print(l.title, l.points, l.class_id, l.id) + +for index, row in df.iterrows(): + s = Student.create( + prename=row["First Name"], + surname=row["Last Name"], + sex=row["Sex"], + class_id=clas.id + ) + + for title, points in list(row.to_dict().items())[3:]: + Submission.create( + student_id=s.id, + lecture_id=Lecture.select().where(Lecture.title == title), + points=points + ) + diff --git a/assets/test.db b/assets/test.db new file mode 100644 index 0000000..b29087f Binary files /dev/null and b/assets/test.db differ diff --git a/main_menu.py b/main_menu.py index a9a4e19..4a1f8f2 100644 --- a/main_menu.py +++ b/main_menu.py @@ -6,12 +6,20 @@ class MainMenu: def __init__(self): super().__init__() + self.new = False + self.new_text = str() + def __call__(self): + if self.new: + self.create_new_file() + with imgui.begin_main_menu_bar() as main_menu_bar: if main_menu_bar: with imgui.begin_menu("File", True) as file_menu: if file_menu.opened: - imgui.menu_item("New", " ", False, True) + new, _ = imgui.menu_item("New", " ", False, True) + if new: + self.new = True imgui.menu_item("Open", " ", False, True) imgui.menu_item("Save", " ", False, True) imgui.menu_item("Save as", " ", False, True) @@ -24,3 +32,6 @@ class MainMenu: clicked, _ = imgui.menu_item(l.name.title(), None, False, True) if clicked: return l + + def create_new_file(self): + pass diff --git a/model.py b/model.py index 4040768..56aa96d 100644 --- a/model.py +++ b/model.py @@ -1,7 +1,11 @@ from peewee import * from datetime import datetime -db = SqliteDatabase('test.db') +import json +from typing import TextIO +from pathlib import Path + +db = SqliteDatabase(None, autoconnect=False) class BaseModel(Model): class Meta: @@ -30,39 +34,59 @@ class Submission(BaseModel): points = FloatField() created_at = DateTimeField(default=datetime.now) -db.connect() -db.create_tables([Class, Student, Lecture, Submission]) - -if __name__ == "__main__": - '''import random - # Generate Test Data - class1 = Class.create(name="WiSe 22/23") - class2 = Class.create(name="WiSe 23/24") - class3 = Class.create(name="WiSe 24/25") - - phil = Student.create(prename="Phil", surname="Keier", sex="Male", class_id=class1.id) - calvin = Student.create(prename="Calvin", surname="Brandt", sex="Male", class_id=class2.id) - nova = Student.create(prename="Nova", surname="Eib", sex="Female", class_id=class1.id) - kathi = Student.create(prename="Katharina", surname="Walz", sex="Female", class_id=class3.id) - victoria = Student.create(prename="Victoria", surname="Möller", sex="Female", class_id=class3.id) - - lec1 = Lecture.create(title="Tutorial 1", points=30, class_id=class1.id) - lec2 = Lecture.create(title="Tutorial 1", points=30, class_id=class3.id) - lec3 = Lecture.create(title="Tutorial 2", points=20, class_id=class1.id) - lec4 = Lecture.create(title="Tutorial 2", points=20, class_id=class2.id) - lec5 = Lecture.create(title="Extended Applications", points=44, class_id=class1.id) - - sub1_phil = Submission.create(student_id=phil.id, lecture_id=lec1.id, points=random.randint(0, lec1.points)) - sub2_phil = Submission.create(student_id=phil.id, lecture_id=lec3.id, points=random.randint(0, lec3.points)) - sub3_phil = Submission.create(student_id=phil.id, lecture_id=lec5.id, points=random.randint(0, lec5.points)) - sub1_nova = Submission.create(student_id=nova.id, lecture_id=lec1.id, points=random.randint(0, lec1.points)) - sub2_nova = Submission.create(student_id=nova.id, lecture_id=lec3.id, points=random.randint(0, lec3.points)) - sub1_kathi = Submission.create(student_id=kathi.id, lecture_id=lec3.id, points=random.randint(0, lec3.points)) - sub1_vici = Submission.create(student_id=victoria.id, lecture_id=lec2.id, points=random.randint(0, lec2.points))''' +def load_from_json(fp: Path) -> None: + ''' + Rebuilding Database from a given json + ''' + with open(fp, "r") as file: + data = json.load(file) + for c_k, c_v in data.items(): + Class.create( + name=c_k, + id=c_v["DB ID"], + created_at=c_v["Date"] + ) + #print(f"KLASSE = {c.id} {c.name} ({c.created_at})") + + for student in c_v["Students"]: + Student.create( + id=student["DB ID"], + created_at=student["Date"], + prename=student["First Name"], + surname=student["Last Name"], + sex=student["Sex"], + class_id=c_v["DB ID"] + ) + #print(f"STUDENT = {s.id}. {s.prename} {s.surname} {s.sex} ({s.created_at}) Klasse: {s.class_id}") + + for submission in student["Submissions"]: + Submission.create( + id=submission["DB ID"], + created_at=submission["Date"], + points=submission["Points"], + lecture_id=submission["Lecture ID"], + student_id=student["DB ID"] + ) + #print(f"SUBMISSION = {sub.id}. {sub.points} Lecture: {sub.lecture_id} Student: {sub.student_id} ({sub.created_at})") + + for lecture in c_v["Lectures"]: + Lecture.create( + id=lecture["DB ID"], + created_at=lecture["Date"], + title=lecture["Title"], + points=lecture["Points"], + class_id=c_v["DB ID"] + ) + #print(f"LECTURE = {l.id}. {l.title} {l.points} ({l.created_at}) Klasse: {l.class_id}") + +def dump_to_json(fp: Path, indent=None) -> None: + ''' + Dump existing Database to Json + ''' classes = Class.select() d = {c.name: { - "DB ID": c.id, + "DB ID": int(c.id), "Date": c.created_at.isoformat(), "Students": [ { @@ -96,5 +120,50 @@ if __name__ == "__main__": for c in classes } - import json - print(json.dumps(d)) + with open(fp, "w") as file: + json.dump(d, file, indent=indent) + +db.init('test.db') +db.connect() +db.create_tables([Class, Student, Lecture, Submission]) + +def main(): + import random + # Generate Test Data + class1 = Class.create(name="WiSe 22/23") + class2 = Class.create(name="WiSe 23/24") + class3 = Class.create(name="WiSe 24/25") + + phil = Student.create(prename="Phil", surname="Keier", sex="Male", class_id=class1.id) + calvin = Student.create(prename="Calvin", surname="Brandt", sex="Male", class_id=class2.id) + nova = Student.create(prename="Nova", surname="Eib", sex="Female", class_id=class1.id) + kathi = Student.create(prename="Katharina", surname="Walz", sex="Female", class_id=class3.id) + victoria = Student.create(prename="Victoria", surname="Möller", sex="Female", class_id=class3.id) + + lec1 = Lecture.create(title="Tutorial 1", points=30, class_id=class1.id) + lec2 = Lecture.create(title="Tutorial 1", points=30, class_id=class3.id) + lec3 = Lecture.create(title="Tutorial 2", points=20, class_id=class1.id) + lec4 = Lecture.create(title="Tutorial 2", points=20, class_id=class2.id) + lec5 = Lecture.create(title="Extended Applications", points=44, class_id=class1.id) + + sub1_phil = Submission.create(student_id=phil.id, lecture_id=lec1.id, points=random.randint(0, lec1.points)) + sub2_phil = Submission.create(student_id=phil.id, lecture_id=lec3.id, points=random.randint(0, lec3.points)) + sub3_phil = Submission.create(student_id=phil.id, lecture_id=lec5.id, points=random.randint(0, lec5.points)) + sub1_nova = Submission.create(student_id=nova.id, lecture_id=lec1.id, points=random.randint(0, lec1.points)) + sub2_nova = Submission.create(student_id=nova.id, lecture_id=lec3.id, points=random.randint(0, lec3.points)) + sub1_kathi = Submission.create(student_id=kathi.id, lecture_id=lec3.id, points=random.randint(0, lec3.points)) + sub1_vici = Submission.create(student_id=victoria.id, lecture_id=lec2.id, points=random.randint(0, lec2.points)) + + return + fp = Path().cwd()/"Test.json" + dump_to_json(fp) + db.close() + db.init("Test.db") + db.connect() + db.create_tables([Class, Student, Lecture, Submission]) + load_from_json(fp) + + +if __name__ == "__main__": + # main() + dump_to_json(Path().cwd()/"TEST.json") diff --git a/student_ranking.py b/student_ranking.py new file mode 100644 index 0000000..e8e9e1a --- /dev/null +++ b/student_ranking.py @@ -0,0 +1,37 @@ +import imgui +import numpy as np + +from model import * + +class StudentRanking: + def __init__(self): + super().__init__() + + def __call__(self): + students = Student.select().where(Student.class_id == 1) + lectures = Lecture.select().where(Lecture.class_id == 1) + + overall_points = sum([l.points for l in lectures]) + + ranking = list() + avg = list() + for s in students: + rank = sum([sub.points for sub in Submission.select().where(Submission.student_id == s.id)])/overall_points + ranking.append((f"{s.prename} {s.surname}", rank)) + avg.append(rank) + ranking = sorted(ranking, key=lambda x: x[1], reverse=True) + avg = sum(avg)/len(avg) + + flag = True + + with imgui.begin("Student Ranking", False, imgui.WINDOW_NO_MOVE | imgui.WINDOW_NO_RESIZE | imgui.WINDOW_NO_COLLAPSE): + for n, rank in enumerate(ranking, start=1): + if rank[1] < avg and flag: + imgui.separator() + flag = False + + imgui.text(f"{n}. {rank[0]} {rank[1]:.1%}") + + imgui.separator() + imgui.text(f"Average: {avg:.1%}") + diff --git a/test.db b/test.db index f80bd51..b29087f 100644 Binary files a/test.db and b/test.db differ diff --git a/view.py b/view.py index 499c6a5..79e22cd 100644 --- a/view.py +++ b/view.py @@ -12,6 +12,7 @@ from lecture_editor import LectureEditor from submission_editor import SubmissionEditor from student_graph import StudentGraph +from student_ranking import StudentRanking def set_layout(size: tuple, pos: tuple) -> None: io = imgui.get_io() @@ -29,11 +30,15 @@ class GrapherLayout: super().__init__() self.student_graph = StudentGraph() + self.student_ranking = StudentRanking() def __call__(self): set_layout((1, 0.4), (0, 0.02)) self.student_graph() + set_layout((0.3, 0.6), (0, 0.42)) + self.student_ranking() + class EditorLayout: def __init__(self): super().__init__()