Skip to content
/ was Public

Weighted Average Score calculator

License

Notifications You must be signed in to change notification settings

mconnell/was

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

61 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

WAS: Weighted Average Score

A simple gem/dsl for generating Weighted Average Score calculations.

Example Usage

Scenario:

  • A person has a final report that is scored based on two parts:
    • A practical test score, worth 25% of the total
    • An Exam score, worth 75%
  • The exam is given a grade: A, B, C, F
    • 'A' is worth 100%
    • 'B' is 75%
    • 'C' is 50%
    • 'D' is 0%
  • The practical is a simple mark out of 10.
    • 4 out of 10 is 40%
  • The person is given a final score out of 1000.

Install the RubyGem

gem install was

Define score classes

require "was"

class ReportScore < WAS::Score
  maximum_score 1000

  with :exam,      class_name: "ExamScore",      weight: 0.75
  with :practical, class_name: "PracticalScore", weight: 0.25
end

class ExamScore < WAS::Score
  context :grade_a, score: 1 do |input|
    input == "A"
  end

  context :grade_b, score: 0.75 do |input|
    input == "B"
  end

  context :grade_c, score: 0.5 do |input|
    input == "C"
  end

  context :flunk do
    0
  end
end

class PracticalScore < WAS::Score
  context :score do |input|
    input / 10.0
  end
end

Generate a total score

ReportScore.new(
  exam: "A",
  practical: 10
).calculate
#> 1000

ReportScore.new(
  exam: "F",
  practical: 10
).calculate
#> 250

Compose without generating a total score

Omitting the maximum_score will return a composed percentage represented as a value between 0 and 1.

# report_score.rb
class ReportScore < WAS::Score
  with :exam,      class_name: "ExamScore",      weight: 0.75
  with :practical, class_name: "PracticalScore", weight: 0.25
end
# usage
ReportScore.new({
  exam: "A",
  practical: 5
}).calculate
#> 0.875

Working with a score tree

For more complex scenarios, we might need to know more about how the score was composed.

Using the example ReportScore, ExamScore, and PracticalScore classes as an example, we can generate a tree of scores:

tree = ReportScore.new({
  exam: "A",
  practical: 5
}).calculate(:tree)

#> tree
{
  score: 875.0,
  max: 1000,
  deduction: -125.0,
  with: {
    exam: {
      score: 750.0,
      max: 750.0,
      deduction: 0.0,
      weight: 0.75
    },
    practical: {
      score: 125.0,
      max: 250.0,
      deduction: -125.0,
      weight: 0.25
    }
  }
}

This result is a WAS::Tree object. Basically a Hash with some extra added to it.

Ordering by attribute

For each of the key attributes :score, :max, :weight, and :deduction, we can order our tree interally by that key:

#> tree.order(:deduction)
{
  score: 875.0,
  max: 1000,
  deduction: -125.0
  with: {
    practical: {
      score: 125.0,
      max: 250.0,
      deduction: -125.0,
      weight: 0.25
    },
    exam: {
      score: 750.0,
      max: 750.0,
      deduction: 0.0,
      weight: 0.75
    }
  }
}

For :deduction, results adjacent to each other are ordered by the most negative. For all other options, the values are ordered largest value first.

View all weights

If you want to see all of the weights that are used to compose the score, there is a convenience method .weights:

ReportScore.weights
#> {exam: {weight: 0.75}, practical: {weight: 0.25}}

About

Weighted Average Score calculator

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published