debugMinor
Calculate grades based on pass/fail percentage
Viewed 0 times
gradespassfailcalculatebasedpercentage
Problem
Our school grading scale is from 1..10 with one decimal. If you do nothing you still get a grade of 1.0. A passing grade equals 5.5. A 'cesuur' percentage defines at what percentage of correct answers the 5.5 will be given to a student.
Examples:
Questions: how can I simplify the code? How can I make it more robust?
Examples:
- List item
- Grade(0,100,x) should always result in 1.0
- Grade(100,100,x) should always results in 10.0
- Grade(50,100,0.5) should result in 5.5
Questions: how can I simplify the code? How can I make it more robust?
Public Function Grade(Points As Integer, MaxPoints As Integer, Cesuur As Double) As Double
Dim passPoints As Integer
Dim maxGrade As Integer
Dim minGrade As Integer
Dim passGrade As Double
Dim base As Double
Dim restPoints As Integer
Dim restPass As Double
passPoints = Cesuur * MaxPoints
maxGrade = 10
minGrade = 1
passGrade = (maxGrade + minGrade) / 2
base = maxGrade - passGrade
If Points < passPoints Then
Grade = 1 + (passGrade - minGrade) * Points / passPoints
Else
restPoints = MaxPoints - Points
restPass = MaxPoints * (1 - Cesuur)
Grade = maxGrade - restPoints * base / restPass
End If
Grade = Round(Grade, 1)
End FunctionSolution
The function's parameters are implicitly passed by reference, which probably isn't the intent since none of the parameters are assigned/returned to the caller.
Signature should pass its parameters by value, like this:
I would suggest to declare variables closer to their usage, and perhaps only assign the function's return value in one place.
Variables
Signature should pass its parameters by value, like this:
Public Function Grade(ByVal Points As Integer, ByVal MaxByVal As Integer, ByVal Cesuur As Double) As DoublemaxGrade and minGrade are only ever assigned once - they're essentially constants and could be declared as such:Const MAXGRADE As Integer = 10
Const MINGRADE As Integer = 1I would suggest to declare variables closer to their usage, and perhaps only assign the function's return value in one place.
Variables
restPoints and restPass are only ever used with a passing grade, in that Else block. VBA doesn't scope variables at anything tighter than procedure scope, so you could extract a method to calculate a passing grade, but that's borderline overkill - here's what it would look like, with parameter casing to camelCase:Option Explicit
Private Const MAXGRADE As Integer = 10
Private Const MINGRADE As Integer = 1
Public Function Grade(ByVal points As Integer, ByVal maxPoints As Integer, ByVal cesuur As Double) As Double
Dim passPoints As Integer
passPoints = cesuur * maxPoints
Dim passGrade As Double
passGrade = (MAXGRADE + MINGRADE) / 2
Dim base As Double
base = MAXGRADE - passGrade
Dim result As Double
If points < passPoints Then
result = 1 + (passGrade - MINGRADE) * points / passPoints
Else
result = CalculatePassingGrade(MAXGRADE, base, points, maxPoints, cesuur)
End If
Grade = Round(result, 1)
End Function
Private Function CalculatePassingGrade(ByVal base As Double, ByVal points As Integer, ByVal maxPoints As Integer, ByVal cesuur As Double) As Double
Dim restPoints As Integer
restPoints = maxPoints - points
Dim restPass As Double
restPass = mxPoints * (1 - cesuur)
CalculatePassingGrade = MAXGRADE - restPoints * base / restPass
End FunctionCode Snippets
Public Function Grade(ByVal Points As Integer, ByVal MaxByVal As Integer, ByVal Cesuur As Double) As DoubleConst MAXGRADE As Integer = 10
Const MINGRADE As Integer = 1Option Explicit
Private Const MAXGRADE As Integer = 10
Private Const MINGRADE As Integer = 1
Public Function Grade(ByVal points As Integer, ByVal maxPoints As Integer, ByVal cesuur As Double) As Double
Dim passPoints As Integer
passPoints = cesuur * maxPoints
Dim passGrade As Double
passGrade = (MAXGRADE + MINGRADE) / 2
Dim base As Double
base = MAXGRADE - passGrade
Dim result As Double
If points < passPoints Then
result = 1 + (passGrade - MINGRADE) * points / passPoints
Else
result = CalculatePassingGrade(MAXGRADE, base, points, maxPoints, cesuur)
End If
Grade = Round(result, 1)
End Function
Private Function CalculatePassingGrade(ByVal base As Double, ByVal points As Integer, ByVal maxPoints As Integer, ByVal cesuur As Double) As Double
Dim restPoints As Integer
restPoints = maxPoints - points
Dim restPass As Double
restPass = mxPoints * (1 - cesuur)
CalculatePassingGrade = MAXGRADE - restPoints * base / restPass
End FunctionContext
StackExchange Code Review Q#91402, answer score: 4
Revisions (0)
No revisions yet.