HiveBrain v1.2.0
Get Started
← Back to all entries
debugMinor

Calculate grades based on pass/fail percentage

Submitted by: @import:stackexchange-codereview··
0
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:

  • 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 Function

Solution

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:

Public Function Grade(ByVal Points As Integer, ByVal MaxByVal As Integer, ByVal Cesuur As Double) As Double


maxGrade 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 = 1


I 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 Function

Code Snippets

Public Function Grade(ByVal Points As Integer, ByVal MaxByVal As Integer, ByVal Cesuur As Double) As Double
Const MAXGRADE As Integer = 10
Const MINGRADE As Integer = 1
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 Function

Context

StackExchange Code Review Q#91402, answer score: 4

Revisions (0)

No revisions yet.