Last active
May 30, 2021 16:28
-
-
Save michalmonday/c58ab578be0d4ec9723c42c327fd6c87 to your computer and use it in GitHub Desktop.
Python3 program which calculates final mark based on previous and potential future marks.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Python3 program which calculates final mark based on previous and potential future marks. | |
# How to use this program: | |
# - modify "previous_marks" list (line 18) | |
# - run the program | |
# If the program fails to run because of missing libraries, you can run the following command: | |
# python3 -m pip install matplotlib tk numpy | |
import matplotlib | |
matplotlib.use('TkAgg') | |
import matplotlib.pyplot as plt | |
import numpy as np | |
SECOND_YEAR_WEIGHT = 40 | |
M_WEIGHT = 60 / 8 # single module weight (in 3rd year) | |
CE301_WEIGHT = M_WEIGHT * 3 | |
previous_marks = [ | |
# Format: (mark, weight) | |
# 2nd year overall mark | |
(70, SECOND_YEAR_WEIGHT), | |
# total module marks | |
(70, M_WEIGHT), # ce303 | |
(70, M_WEIGHT), # ce339 | |
(70, M_WEIGHT), # ce316 | |
# module marks with some assessments unmarked yet | |
(70, M_WEIGHT * 0.06), # ce324 logbook | |
(70, M_WEIGHT * 0.12), # ce324 progress test | |
(70, M_WEIGHT * 0.12), # ce324 progress test | |
(70, M_WEIGHT * 0.1), # ce314 assignment 1 | |
(70, M_WEIGHT * 0.2), # ce314 assignment 2 | |
(70, CE301_WEIGHT * 0.1), # ce301 interim interview | |
(70, CE301_WEIGHT * 0.05), # ce301 challenge week | |
(70, CE301_WEIGHT * 0.05) # ce301 poster | |
] | |
def stats_so_far(pm): | |
achieved = sum(w / 100.0 * m for m,w in pm) | |
optimal = sum(w for _,w in pm) | |
percentage = 100.0 / optimal * achieved | |
# print(f"So far {optimal:.1f}% was assessed, for which I got {percentage:.1f}%") | |
# print() | |
return achieved, optimal, percentage | |
def calculate_total_mark(exam_mark, pm): | |
achieved = sum(w / 100.0 * m for m,w in pm) | |
optimal = sum(w for _,w in pm) | |
remaining = 100 - optimal | |
return achieved + remaining / 100.0 * exam_mark | |
def plot_stats(achieved, optimal): | |
fig, (ax1, ax2) = plt.subplots(2, 1, sharex=False, sharey=False, gridspec_kw={'height_ratios': [1, 10]}) | |
ax1.set_xticks(range(0,101,10)) | |
ax1.set_xlim([0,100]) | |
ax1.set_ylim([0,1]) | |
ax1.tick_params(axis='y', left=False, labelleft=False, which='both') | |
ax1.fill_between(np.arange(0, int(achieved)+1, 1), 0, 1, facecolor='g', alpha=1) | |
ax1.fill_between(np.arange(int(achieved), int(optimal)+1, 1), 0, 1, facecolor='red', alpha=0.5) | |
ax1.fill_between(np.arange(int(optimal), 101, 1), 0, 1, facecolor='black', alpha=0.2) | |
ax1.set_title(f'Previous assessments ({achieved:.1f}% out of {optimal:.1f}%)') | |
ax2_min = 30 | |
total_x = range(ax2_min,101,1) | |
total_y = [calculate_total_mark(em, previous_marks) for em in total_x] | |
ax2.set_yticks(range(0,101,10)) | |
ax2.set_ylim([0,100]) | |
ax2.set_xticks(range(ax2_min,101,10)) | |
ax2.set_xlim([ax2_min,100]) | |
ax2.fill_between(total_x, total_y, 100, facecolor='red', alpha=0.5) | |
ax2.fill_between(total_x, 0, total_y, facecolor='green', alpha=1) | |
lw = 3 | |
ax2.axhline(y=70, color='cyan', linestyle='-', linewidth=lw) | |
ax2.axhline(y=60, color='yellow', linestyle='-', linewidth=lw) | |
ax2.axhline(y=50, color='orange', linestyle='-', linewidth=lw) | |
ax2.axhline(y=40, color='red', linestyle='-', linewidth=lw) | |
ax2.set_title("End mark prediction") | |
ax2.set_ylabel("End mark") | |
ax2.set_xlabel("Remaining assessments mark") | |
plt.subplots_adjust(hspace=0.5) | |
plt.show() | |
achieved, optimal, percentage = stats_so_far(previous_marks) | |
plot_stats(achieved, optimal) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I made repository with it, it contains examples of input/output and some other information:
https://github.com/michalmonday/marks.py