diff --git a/app/models/semester.rb b/app/models/semester.rb index 75c6925..d836c33 100644 --- a/app/models/semester.rb +++ b/app/models/semester.rb @@ -60,6 +60,18 @@ def achieved_score(user) total_weight.zero? ? 0 : (weighted_sum / total_weight) end + # Gets the highest possible percentage grade of the semester, if all uncompleted assessments were 100% + def highest_achievable_score(user) + return final_score if final_score.present? + return 0 if uni_modules.empty? + + total_credits = credits + return 0 if total_credits.zero? + + weighted_sum = uni_modules.sum { |m| m.highest_achievable_score(user) * m.credit_share } + (weighted_sum / total_credits).round(2) + end + def progress(user) return 100 if final_score.present? diff --git a/app/models/uni_module.rb b/app/models/uni_module.rb index 1aa8b87..07b1a00 100644 --- a/app/models/uni_module.rb +++ b/app/models/uni_module.rb @@ -70,9 +70,20 @@ def completion_percentage(user) exams_with_results(user).sum(:weight) end - + alias progress completion_percentage + # Gets the highest possible percentage grade of the module, if all uncompleted assessments were 100% + def highest_achievable_score(user) + return final_score if final_score.present? + + achieved = achieved_score(user) + done = completion_percentage(user) + return 100 if done.zero? && achieved.zero? + + (achieved + (100 - done)).clamp(0.0, 100.0) + end + def target(user) target = UniModuleTarget.find_by(user: user, uni_module: self) return nil if target.nil? || target.score.nil? diff --git a/app/models/user.rb b/app/models/user.rb index d22c6a1..8ec9e6c 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -74,14 +74,23 @@ def predicted_score total_weight = valid_years.sum(&:weighting_non_null) return 0 if total_weight.zero? - weighted_sum = valid_years.sum do |year| - year_score = year.predicted_score(self) - year_score * year.weighting_non_null - end + weighted_sum = valid_years.sum { |year| year.predicted_score(self) * year.weighting_non_null } weighted_sum / total_weight end + # Gets the highest possible percentage grade of the user, if all uncompleted assessments were 100% + def highest_achievable_score + valid_years = years.select { |year| year.weighting_non_null.positive? } + return 0 if valid_years.empty? + + total_weight = valid_years.sum(&:weighting_non_null) + return 0 if total_weight.zero? + + weighted_sum = valid_years.sum { |year| year.highest_achievable_score(self) * year.weighting_non_null } + (weighted_sum / total_weight).round(2) + end + def required_score_for_threshold(threshold) p = progress / 100.0 a = achieved_score diff --git a/app/models/year.rb b/app/models/year.rb index 47edf84..08fffb4 100644 --- a/app/models/year.rb +++ b/app/models/year.rb @@ -47,6 +47,18 @@ def weighting_non_null weighting end + # Gets the highest possible percentage grade of the year, if all uncompleted assessments were 100% + def highest_achievable_score(user) + return final_score if final_score.present? + return 0 if semesters.empty? + + total_credits = credits + return 0 if total_credits.zero? + + weighted_sum = semesters.sum { |s| s.highest_achievable_score(user) * s.credits } + (weighted_sum / total_credits).round(2) + end + def completed_credits(user) return 0 if uni_modules.empty? diff --git a/app/views/semesters/show.html.haml b/app/views/semesters/show.html.haml index 8bf7bb5..f742924 100644 --- a/app/views/semesters/show.html.haml +++ b/app/views/semesters/show.html.haml @@ -24,6 +24,9 @@ = link_to edit_semester_path(@semester, anchor: 'final_score') do Achieved Score .stat-content= number_to_percentage(@semester.achieved_score(current_user), precision: 2) + .stat + .stat-header Highest Achievable Score + .stat-content= number_to_percentage(@semester.highest_achievable_score(current_user), precision: 2) = turbo_frame_tag "modules" do .gt-empty-card diff --git a/app/views/shared/_dashboard_stats.html.haml b/app/views/shared/_dashboard_stats.html.haml index 971fb64..de00648 100644 --- a/app/views/shared/_dashboard_stats.html.haml +++ b/app/views/shared/_dashboard_stats.html.haml @@ -15,6 +15,9 @@ .stat .stat-header Achieved Score .stat-content= number_to_percentage(current_user.achieved_score, precision: 2) + .stat + .stat-header Highest Achievable Score + .stat-content= number_to_percentage(current_user.highest_achievable_score, precision: 2) .stat .stat-header Predicted .stat-content= number_to_percentage(current_user.predicted_score, precision: 2) \ No newline at end of file diff --git a/app/views/uni_modules/show.html.haml b/app/views/uni_modules/show.html.haml index a553405..563897f 100644 --- a/app/views/uni_modules/show.html.haml +++ b/app/views/uni_modules/show.html.haml @@ -29,6 +29,9 @@ = link_to edit_uni_module_path(@uni_module, anchor: 'final_score') do Achieved Score .stat-content= number_to_percentage(@uni_module.achieved_score(current_user), precision: 2) + .stat + .stat-header Highest Achievable Score + .stat-content= number_to_percentage(@uni_module.highest_achievable_score(current_user), precision: 2) .exams-container .exams diff --git a/app/views/users/show.html.haml b/app/views/users/show.html.haml index 5eebaa0..56a9b7a 100644 --- a/app/views/users/show.html.haml +++ b/app/views/users/show.html.haml @@ -28,6 +28,9 @@ .stat .stat-header Achieved Score .stat-content= number_to_percentage(@user.achieved_score, precision: 2) + .stat + .stat-header Highest Achievable Score + .stat-content= number_to_percentage(@user.highest_achievable_score, precision: 2) .stat .stat-header Predicted .stat-content= number_to_percentage(@user.predicted_score, precision: 2) diff --git a/app/views/years/show.html.haml b/app/views/years/show.html.haml index c6cc166..3d5f979 100644 --- a/app/views/years/show.html.haml +++ b/app/views/years/show.html.haml @@ -20,6 +20,9 @@ = link_to edit_year_path(@year, anchor: 'final_score') do Achieved Score .stat-content= number_to_percentage(@year.achieved_score(current_user), precision: 2) + .stat + .stat-header Highest Achievable Score + .stat-content= number_to_percentage(@year.highest_achievable_score(current_user), precision: 2) .stat .stat-header Predicted Score .stat-content= number_to_percentage(@year.predicted_score(current_user), precision: 2)