Skip to content

Instantly share code, notes, and snippets.

@Friedjof
Last active August 4, 2023 10:47
Show Gist options
  • Save Friedjof/cedb9cad54b4ba172a7af182afc48bb9 to your computer and use it in GitHub Desktop.
Save Friedjof/cedb9cad54b4ba172a7af182afc48bb9 to your computer and use it in GitHub Desktop.
"""
EIST 2023 Grading
Versions:
- GOE 1: grade + (1.0 + (.25 * hw_points / 90.0))
Since: beginning of the first lecture
- GOE 2: grade + (1.0 + (.25 * hw_points / 101.0))
Since: slack message from 2023-07-22 23:47:27
- GOE 3: grade + (1.0 + (.35 * hw_points / 101.0))
Since: since mail from 2023-08-02 14:48
- GOE 4.1: grade * 1.1 + .25 * (hw_points / 101.0) * 100
Since: since mail from 2023-08-03 11:19 - option 1
- GOE 4.2: Register for the GORE exam
Since: since mail from 2023-08-03 11:19 - option 2
- GOE 4.3: Register for the GORE exam
Since: since mail from 2023-08-03 11:19 - default
- GOE 5: grade * 1.1 + .25 * (hw_points / 101.0) * 100
Since: since mail from 2023-08-04 09:38
- GORE 1: Your homework does not count anymore.
Since: since mail from 2023-08-03 11:19 - default
"""
class Model:
def __init__(self, grade: float, hw_points: float):
self.grade = grade
self.hw_points = hw_points
class Controller:
def __init__(self, model: Model, view: 'View'):
self.model = model
self.view = view
self.can_talk = True
def run(self):
self.view.run(self)
def valid_hw_points_v1(self) -> bool:
return .0 <= self.model.hw_points <= 90.0
def valid_hw_points_v2(self) -> bool:
return .0 <= self.model.hw_points <= 101.0
def will_pass_v1(self) -> bool:
return self.model.hw_points >= 50.0
def will_pass_v2(self) -> bool:
return self.model.hw_points >= 45.0
def will_pass_v3(self) -> bool:
return self.model.hw_points >= 30.0
def say(self, message: str, spaces: int = 4) -> None:
if self.can_talk:
print((" " * spaces) + str(message))
def get_best_grade(self) -> float or None:
self.can_talk = False
grade_v1: float or None = self.goe_grading_v1()
grade_v2: float or None = self.goe_grading_v2()
grade_v3: float or None = self.goe_grading_v3()
grade_v4_option_1: float or None = self.goe_grading_v4_option_1()
grade_v5: float or None = self.goe_grading_v5()
self.can_talk = True
max_grade: dict = {"grade": .0, "version": ""}
for grade, v in [(grade_v1, "v1"), (grade_v2, "v2"), (grade_v3, "v3"),
(grade_v4_option_1, "v4.1"), (grade_v5, "v5")]:
if grade is not None and grade >= max_grade["grade"]:
max_grade["grade"] = grade
max_grade["version"] = v
if max_grade["grade"] == .0:
self.say(Msg.GORE_REGISTER, 0)
else:
self.say(Msg.BEST_GRADE.format(
grade=round(max_grade["grade"], 3),
score=self.calc_score(max_grade["grade"]),
version=max_grade["version"],
), 0)
def goe_grading_v1(self) -> float or None:
self.say(Msg.AUTOMATED_GRADING.format(1), 0)
if not self.valid_hw_points_v1():
self.say(Msg.ERROR_INVALID_HW_POINTS_V1)
elif not self.will_pass_v1():
self.say(Msg.ERROR_WILL_NOT_PASS_V1)
else:
return self.model.grade + (1.0 + (.25 * self.model.hw_points / 90.0))
def goe_grading_v2(self) -> float or None:
self.say(Msg.AUTOMATED_GRADING.format(2), 0)
if not self.valid_hw_points_v2():
self.say(Msg.ERROR_INVALID_HW_POINTS_V2)
elif not self.will_pass_v1():
self.say(Msg.ERROR_WILL_NOT_PASS_V2)
else:
return self.model.grade + (1.0 + (.25 * self.model.hw_points / 101.0))
def goe_grading_v3(self) -> float or None:
self.say(Msg.AUTOMATED_GRADING.format(3), 0)
if not self.valid_hw_points_v2():
self.say(Msg.ERROR_INVALID_HW_POINTS_V2)
else:
return self.model.grade + (1.0 + (.35 * self.model.hw_points / 101.0))
def goe_grading_v4_option_1(self) -> float or None:
self.say(Msg.AUTOMATED_GRADING.format(4.1), 0)
if not self.valid_hw_points_v2():
self.say(Msg.ERROR_INVALID_HW_POINTS_V2)
elif not self.will_pass_v2():
self.say(Msg.ERROR_WILL_NOT_PASS_V2)
else:
return self.model.grade * 1.1 + .25 * (self.model.hw_points / 101.0) * 100.0
def goe_grading_v4_option_2(self) -> None:
self.say(Msg.AUTOMATED_GRADING.format(4.2), 0)
self.say(Msg.GORE_REGISTER)
self.say(Msg.GORE_REGISTER_HW_POINTS.format(self.model.hw_points))
self.say(Msg.GORE_REGISTER_GRADE.format(self.model.grade))
def goe_grading_v4_default(self) -> None:
self.say(Msg.AUTOMATED_GRADING.format(4.3), 0)
self.say(Msg.GORE_REGISTER)
self.say(Msg.GORE_REGISTER_GRADE_HW_POINTS.format(self.model.hw_points, self.model.grade))
def goe_grading_v5(self) -> float or None:
self.say(Msg.AUTOMATED_GRADING.format(5), 0)
if not self.valid_hw_points_v2():
self.say(Msg.ERROR_INVALID_HW_POINTS_V2)
elif not self.will_pass_v3():
self.say(Msg.ERROR_WILL_NOT_PASS_V3)
else:
return self.model.grade * 1.1 + .25 * (self.model.hw_points / 101.0) * 100.0
def get_model(self) -> Model:
return self.model
def set_model(self, model: Model) -> None:
self.model = model
@staticmethod
def calc_score(grade: float) -> float:
if grade < 20.0:
return 5.0
elif grade < 25.0:
return 4.7
elif grade < 30.0:
return 4.3
elif grade < 40.0:
return 4.0
elif grade < 45.0:
return 3.7
elif grade < 50.0:
return 3.3
elif grade < 55.0:
return 3.0
elif grade < 60.0:
return 2.7
elif grade < 65.0:
return 2.3
elif grade < 70.0:
return 2.0
elif grade < 78.0:
return 1.7
elif grade < 86.0:
return 1.3
else:
return 1.0
def __repr__(self) -> str:
return Msg.STUDENT_LOOK.format(grade=self.model.grade, hw_points=self.model.hw_points)
def __eq__(self, other: 'Controller') -> bool:
return self.model.grade == other.model.grade and self.model.hw_points == other.model.hw_points
class View:
def __init__(self) -> None:
print(Msg.WELCOME)
def run(self, controller: Controller) -> None:
model = controller.get_model()
self.show_help()
self.show_model(model=model)
while True:
try:
option: str = input(Msg.INPUT_OPTION).lower()
except KeyboardInterrupt:
break
if option == "h":
self.show_help()
print(Msg.SEPERATOR)
elif option == "c":
print(Msg.SEPERATOR)
controller.set_model(self.get_student())
model = controller.get_model()
self.show_model(model=model)
elif option == "1":
print(Msg.SEPERATOR)
r: float or None = controller.goe_grading_v1()
if r is not None:
controller.say(Msg.GRADE_OUTPUT.format(
grade=round(r, 3), score=Controller.calc_score(r)))
print(Msg.SEPERATOR)
elif option == "2":
print(Msg.SEPERATOR)
r: float or None = controller.goe_grading_v2()
if r is not None:
controller.say(Msg.GRADE_OUTPUT.format(
grade=round(r, 3), score=Controller.calc_score(r)))
print(Msg.SEPERATOR)
elif option == "3":
print(Msg.SEPERATOR)
r: float or None = controller.goe_grading_v3()
if r is not None:
controller.say(Msg.GRADE_OUTPUT.format(
grade=round(r, 3), score=Controller.calc_score(r)))
print(Msg.SEPERATOR)
elif option == "4":
print(Msg.SEPERATOR)
r: float or None = controller.goe_grading_v4_option_1()
if r is not None:
controller.say(Msg.GRADE_OUTPUT.format(
grade=round(r, 3), score=Controller.calc_score(r)))
else:
controller.goe_grading_v4_option_2()
print(Msg.SEPERATOR)
elif option == "5":
print(Msg.SEPERATOR)
r: float or None = controller.goe_grading_v5()
if r is not None:
controller.say(Msg.GRADE_OUTPUT.format(
grade=round(r, 3), score=Controller.calc_score(r)))
else:
controller.goe_grading_v4_default()
print(Msg.SEPERATOR)
elif option == "s":
self.show_model(model=model)
elif option == "g":
print(Msg.SEPERATOR)
controller.get_best_grade()
print(Msg.SEPERATOR)
elif option == "q":
break
else:
print(Msg.INVALID_OPTION)
print(Msg.GOODBYE)
@staticmethod
def show_model(model: Model) -> None:
print(Msg.SEPERATOR)
print(Msg.SHOW_STUDENT.format(grade=model.grade, hw_points=model.hw_points))
print(Msg.SEPERATOR)
@staticmethod
def get_student() -> Model:
while True:
try:
hw_points: float = float(input(Msg.INPUT_HW_POINTS).replace(",", "."))
grade: float = float(input(Msg.INPUT_GRADE).replace(",", "."))
break
except ValueError:
print(Msg.INVALID_NUMBER)
return Model(grade=grade, hw_points=hw_points)
@staticmethod
def show_help() -> None:
print(Msg.SEPERATOR)
print("""Options:
[H]elp
[C]hange student grade and homework points
[1] to [4] - Run the grading algorithm
[G]et the best grade
[S]how the current student
[Q]uit""")
class Msg:
ERROR_INVALID_HW_POINTS_V1 = "Invalid HW points. Must be between 0 and 90."
ERROR_INVALID_HW_POINTS_V2 = "Invalid HW points. Must be between 0 and 101."
ERROR_WILL_NOT_PASS_V1 = "You need at least a 50% to pass the course. Register for the GORE exam."
ERROR_WILL_NOT_PASS_V2 = "You need at least a 45% to pass the course. Register for the GORE exam."
ERROR_WILL_NOT_PASS_V3 = "You need at least a 30% to pass the course. Register for the GORE exam."
GORE_REGISTER = "You need to register for the GORE exam."
GORE_REGISTER_HW_POINTS = "You can take the Homework points ({}) with you."
GORE_REGISTER_GRADE = "But do not forget to throw your grade ({}) in the rubbish."
GORE_REGISTER_GRADE_HW_POINTS = "You can take the Homework points ({}) with you. But do not forget to throw your " \
"grade ({}) in the rubbish."
BEST_GRADE = "Best grade is {grade} (Points) [score: {score}] for version {version}"
AUTOMATED_GRADING = "Automated grading for version {}"
STUDENT_LOOK = "Student(grade={grade}, hw_points={hw_points})"
INPUT_OPTION = ">> "
INPUT_GRADE = " Enter your grade: "
INPUT_HW_POINTS = "Enter your homework points: "
INVALID_NUMBER = "Invalid number. Please try again."
INVALID_OPTION = "Invalid option. Please try again."
GRADE_OUTPUT = "{grade} (Points) this is a score of {score}"
SHOW_STUDENT = "Student(grade={grade}, hw_points={hw_points})"
GOODBYE = "Goodbye."
SEPERATOR = "-----------------------------------------"
WELCOME = "Welcome to the GORE grading system EIST23 (v1.0)"
if __name__ == '__main__':
m: Model = Model(0.0, 0.0)
v: View = View()
c: Controller = Controller(m, v)
c.run()
@CommanderStorm
Copy link

CommanderStorm commented Aug 3, 2023

I am missing at least one strategy pattern in this codebase.

@Friedjof
Copy link
Author

Friedjof commented Aug 3, 2023

fixed

@CommanderStorm
Copy link

WTF happened here?
This looks straight up mental. I don't think MVC is a good pattern for text based input-output. Are you okay?

@Friedjof
Copy link
Author

Friedjof commented Aug 4, 2023

You wanted a pattern, then you get some patterns. Feel free to add a graphical interface to the whole thing. You just need to customize the view.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment