import imgui import glfw import OpenGL.GL as gl from imgui.integrations.glfw import GlfwRenderer from PIL import ImageColor from dataclasses import dataclass import numpy @dataclass class Lecture: name: str points: float max_points: int @dataclass class Student: name: str jupyter_id: str project: str lectures: list phil = Student( "Phil Keier", "772fb04b24caa68fd38a05ec2a22e62b", "Geomapping", [Lecture("1. Tutorial 1", 28.5, 31), Lecture("2. Tutorial 2", 4.5, 15), Lecture("3. Extended Application", 18, 18)] ) nova = Student( "Nova Eib", "772fb04b24caa68fd38a05ec2a22e62b", "Mapping Maps", [Lecture("1. Tutorial 1", 28.5, 31), Lecture("2. Tutorial 2", 4.5, 15), Lecture("3. Extended Application", 18, 18)] ) kathi = Student( "Katharina Walz", "772fb04b24caa68fd38a05ec2a22e62b", "Geomapping", [Lecture("1. Tutorial 1", 28.5, 31), Lecture("2. Tutorial 2", 4.5, 15), Lecture("3. Extended Application", 18, 18), Lecture("4. Numpy & MatPlotLib", 3, 30)] ) students = [phil, nova, kathi] # Global Color Pallet COLOR_BACKGROUND = tuple([e/255 for e in ImageColor.getcolor("#29132E","RGBA")]) COLOR_1 = tuple([e/255 for e in ImageColor.getcolor("#321450","RGBA")]) COLOR_2 = tuple([e/255 for e in ImageColor.getcolor("#860029","RGBA")]) COLOR_3 = tuple([e/255 for e in ImageColor.getcolor("#DE004E","RGBA")]) COLOR_TEXT = tuple([e/255 for e in ImageColor.getcolor("#F887FF","RGBA")]) COLOR_TEXT_PASSED = tuple([e/255 for e in ImageColor.getcolor("#1AFE49","RGBA")]) COLOR_TEXT_FAILED = tuple([e/255 for e in ImageColor.getcolor("#FF124F","RGBA")]) def impl_glfw_init(window_name="Grapher Tool", width=1280, height=720): if not glfw.init(): print("Could not initialize OpenGL context") exit(1) # OS X supports only forward-compatible core profiles from 3.2 glfw.window_hint(glfw.CONTEXT_VERSION_MAJOR, 3) glfw.window_hint(glfw.CONTEXT_VERSION_MINOR, 3) glfw.window_hint(glfw.OPENGL_PROFILE, glfw.OPENGL_CORE_PROFILE) glfw.window_hint(glfw.OPENGL_FORWARD_COMPAT, gl.GL_TRUE) # Create a windowed mode window and its OpenGL context window = glfw.create_window(int(width), int(height), window_name, None, None) glfw.make_context_current(window) if not window: glfw.terminate() print("Could not initialize Window") exit(1) return window class GUI(object): def __init__(self): super().__init__() self.backgroundColor = COLOR_BACKGROUND self.window = impl_glfw_init() gl.glClearColor(*self.backgroundColor) imgui.create_context() self.impl = GlfwRenderer(self.window) # App states self.select = 0 # Global GUI Setting '''win_w, win_h = glfw.get_window_size(self.window) fb_w, fb_h = glfw.get_framebuffer_size(self.window) font_scaling_factor = max(float(fb_w) / win_w, float(fb_h) / win_h) font_size_in_pixels = 30 io = imgui.get_io() io.fonts.add_font_from_file_ttf("assets/MPLUSRounded1c-Regular.ttf", font_size_in_pixels * font_scaling_factor) io.font_global_scale /= font_scaling_factor''' self.loop() def student_info(self, student: Student): # Window Position and Sizing io = imgui.get_io() imgui.set_next_window_size(io.display_size.x*0.3, io.display_size.y*0.4) imgui.set_next_window_position(io.display_size.x*0.7, io.display_size.y*0.05) # Student accumulated Info overall_points = sum([lecture.points for lecture in student.lectures]) if overall_points.is_integer(): overall_points = int(overall_points) overall_max = sum([lecture.max_points for lecture in student.lectures]) with imgui.begin("Student Info", False, imgui.WINDOW_NO_MOVE | imgui.WINDOW_NO_RESIZE | imgui.WINDOW_NO_COLLAPSE): if not student: imgui.text("No Student selected") return s = f"{overall_points}/{overall_max} | {round(overall_points/overall_max*100, 1)}%" imgui.text_colored(student.name, *COLOR_TEXT) w, h = imgui.get_window_size() imgui.progress_bar(overall_points/overall_max, (w*0.5, h*0.1), s) imgui.text("Jupyter ID:") imgui.text_colored(student.jupyter_id.rjust(4+len(student.jupyter_id), " "), *COLOR_TEXT) imgui.separator() imgui.text("Project:") imgui.text_colored(student.project.rjust(4+len(student.project), " "), *COLOR_TEXT) imgui.text("Lectures:") for lecture in student.lectures: COLOR = COLOR_TEXT_PASSED if lecture.points >= lecture.max_points/3 else COLOR_TEXT_FAILED s = f"{lecture.name}: {lecture.points}/{lecture.max_points}" imgui.text_colored(s.rjust(4+len(s), " "), *COLOR) def table(self, students: list): # Window Position and Sizing io = imgui.get_io() imgui.set_next_window_size(io.display_size.x*0.15, io.display_size.y*0.95) imgui.set_next_window_position(0, io.display_size.y*0.05) with imgui.begin("Student Table", False, imgui.WINDOW_NO_MOVE | imgui.WINDOW_NO_RESIZE | imgui.WINDOW_NO_COLLAPSE): if not students: imgui.text("No Dataset selected") return for n, student in enumerate(students): opened, _ = imgui.selectable(student.name, self.select == n) if opened: self.select = n def student_graph(self, student: Student): # Window Position and Sizing io = imgui.get_io() imgui.set_next_window_size(io.display_size.x*0.55, io.display_size.y*0.4) imgui.set_next_window_position(io.display_size.x*0.15, io.display_size.y*0.05) # Setup Data data = numpy.array([float(lecture.points) / float(lecture.max_points) * 100 for lecture in student.lectures], dtype=numpy.float32) with imgui.begin("Student Graph", False, imgui.WINDOW_NO_MOVE | imgui.WINDOW_NO_RESIZE | imgui.WINDOW_NO_COLLAPSE): if not students: imgui.text("No Dataset selected") return imgui.plot_histogram( "##Data", data, overlay_text="Performance per Lecture (in %)", scale_min=0.0, scale_max=100, graph_size=imgui.get_content_region_available() ) def header(self): # Window Position and Sizing io = imgui.get_io() imgui.set_next_window_size(io.display_size.x, io.display_size.y*0.05) imgui.set_next_window_position(0, 0) with imgui.begin("HEADER", False, imgui.WINDOW_NO_MOVE | imgui.WINDOW_NO_RESIZE | imgui.WINDOW_NO_COLLAPSE | imgui.WINDOW_NO_TITLE_BAR): imgui.set_window_font_scale(1.5) text = "Student Analyzer" ww = imgui.get_window_size().x tw = imgui.calc_text_size(text).x imgui.set_cursor_pos_x((ww - tw) * 0.5) imgui.text("Student Analyzer") def loop(self): while not glfw.window_should_close(self.window): glfw.poll_events() self.impl.process_inputs() imgui.new_frame() self.header() self.table(students) self.student_info(students[self.select]) self.student_graph(students[self.select]) #imgui.show_test_window() imgui.render() gl.glClearColor(*self.backgroundColor) gl.glClear(gl.GL_COLOR_BUFFER_BIT) self.impl.render(imgui.get_draw_data()) glfw.swap_buffers(self.window) self.impl.shutdown() glfw.terminate() if __name__ == "__main__": gui = GUI()