Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Determine how many stars to give from a portion of a score

Tags:

c#

Math isn't one of my strong points, and I would like to know how to do this properly (I could hack somthing together, but it would be a mess):

  • We score modules and give the user their score as a percentage
  • We want to reward these scores with a star rating, but only if they achieve a score greater than the module pass mark
  • The pass mark is variable
  • For future proofing, lets say the number of stars to be awarded is also variable
  • If they pass, I want them to always get at least 1 star

Example figures:

  • Max Stars : 3
  • Pass mark : 75 %
  • User scores 75%, minimum passmark, so award 1 star
  • User scores 90%, would this be 2 stars ??

Thanks guys.


Integrated solution

this is what I went with :

private const int NUMSTARS = 3;

public int starsFor(int pScore, int pPassMark)
{
    if(pScore < pPassMark)
    {
        return 0;
    }
    else if (pScore == pPassMark)
    {
        return 1;
    }
    else
    {           
        return (int)Math.Ceiling(NUMSTARS * ((pScore - pPassMark) / (double)(100 - pPassMark))); 
    }
}
like image 872
Keeno Avatar asked Dec 28 '22 08:12

Keeno


2 Answers

This is a Java implementation; C# translation should be straightforward. This assumes linear interpolation:

    public static int starsFor(int mark, int passMark, int numStars) {
            if (mark < passMark) 
                    return 0;
            else if (mark == passMark)
                    return 1;
            else 
                    return (int) Math.ceil(
                            numStars * (
                                    (mark - passMark) / (double) (100 - passMark)
                            )
                    );
    }

Then we have (as seen on ideone.com):

System.out.println(starsFor(70, 75, 5)); // 0
System.out.println(starsFor(75, 75, 5)); // 1
System.out.println(starsFor(80, 75, 5)); // 1
System.out.println(starsFor(81, 75, 5)); // 2
System.out.println(starsFor(93, 75, 5)); // 4
System.out.println(starsFor(99, 75, 5)); // 5
System.out.println(starsFor(100, 75, 5)); // 5

C#/Variation

Here's a slight variation that handles extra points as well. It uses integer division, without requiring double cast and Math.ceil. Ternary/conditional ?: operator is used (for style!).

  static int starsFor(int mark, int passMark, int maxMark, int numStars) {
    return
      (mark >= maxMark) ?
         numStars
         :
      (mark < passMark) ?
         0 
         :
      1 + numStars * (mark - passMark) / (maxMark - passMark);
  }

Then we have (as seen on ideone.com):

Console.WriteLine(starsFor(50, 75, 100, 5)); // 0
Console.WriteLine(starsFor(75, 75, 100, 5)); // 1
Console.WriteLine(starsFor(79, 75, 100, 5)); // 1
Console.WriteLine(starsFor(80, 75, 100, 5)); // 2
Console.WriteLine(starsFor(93, 75, 100, 5)); // 4
Console.WriteLine(starsFor(100, 75, 100, 5)); // 5
Console.WriteLine(starsFor(110, 75, 100, 5)); // 5 no extra stars!
like image 165
polygenelubricants Avatar answered Jan 19 '23 00:01

polygenelubricants


Following function may give you the expected result.
Logic I used:
- If passing marks are 75%, then 75%=1 star
- and you want to give max 5 stars to the user
- then divide remaining marks into 5 equal parts (75 to 80, 81 to 85, 86 to 90, 91 to 95 and 96 100)
- Apply the stars depending on this range.

public int RateMyUser(int MaxStars, int MinThreshold, int MarksObtained)
    {
        int division = 0;
        int stars = 0;
        // this will give division of remaining score greater than passing percentage<br>
        division = (100 - MinThreshold) / MaxStars;
        if (MarksObtained >= MinThreshold)
        {
            // obtain the stars to be given
            stars = (MarksObtained - MinThreshold) / division; // integer representing stars
            return stars + 1;
        }
        return stars;
    }
like image 31
Anil Soman Avatar answered Jan 18 '23 23:01

Anil Soman