Added: Student Ranking
This commit is contained in:
parent
0cc4ed243d
commit
70ea8899e2
2
.gitignore
vendored
2
.gitignore
vendored
@ -1,5 +1,5 @@
|
||||
# ---> ImGUI
|
||||
imgui.ini
|
||||
*.ini
|
||||
|
||||
# ---> Python
|
||||
# Byte-compiled / optimized / DLL files
|
||||
|
33
assets/Student_list.csv
Normal file
33
assets/Student_list.csv
Normal file
@ -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
|
|
BIN
assets/Student_list.xlsx
Normal file
BIN
assets/Student_list.xlsx
Normal file
Binary file not shown.
42
assets/convert.py
Normal file
42
assets/convert.py
Normal file
@ -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
|
||||
)
|
||||
|
BIN
assets/test.db
Normal file
BIN
assets/test.db
Normal file
Binary file not shown.
13
main_menu.py
13
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
|
||||
|
135
model.py
135
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")
|
||||
|
37
student_ranking.py
Normal file
37
student_ranking.py
Normal file
@ -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%}")
|
||||
|
5
view.py
5
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__()
|
||||
|
Loading…
Reference in New Issue
Block a user