was 0.7.0 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +84 -7
- data/lib/was/score.rb +20 -6
- data/lib/was/tree.rb +31 -0
- data/lib/was/version.rb +1 -1
- data/lib/was.rb +1 -0
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 974fa97c47b4fe794512983c75fa065b9bdd40370e5987b1e4523d01791bdd2a
|
4
|
+
data.tar.gz: 9f6e783dd2fbad215e8c2b16c820a1b8642b843efba424ed2d35e5aa1e7e2b92
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 43d1c61377ad1da1477d5edf911fd55b22acea765ffcf10e53c3cdc2c181e7968bd3bc02223721a82146c57b5186f79d25b75557026cedecb30dfc218a56e801
|
7
|
+
data.tar.gz: 6c09a8018b3d7fb5634985e3144d75adc942a21b3b6b459057192b1f0918bfee840b54a8897dc9ad25983623cbdf858b40c9e72f84ab073d3a891592998e5d41
|
data/README.md
CHANGED
@@ -14,8 +14,14 @@ Scenario:
|
|
14
14
|
* 'C' is 50%
|
15
15
|
* 'D' is 0%
|
16
16
|
* The practical is a simple mark out of 10.
|
17
|
-
* 4 out of 10 is 40%
|
18
|
-
* The person is given a final score out of 1000.
|
17
|
+
* 4 out of 10 is 40%
|
18
|
+
* The person is given a final score out of 1000.
|
19
|
+
|
20
|
+
### Install the RubyGem
|
21
|
+
|
22
|
+
```bash
|
23
|
+
gem install was
|
24
|
+
```
|
19
25
|
|
20
26
|
### Define score classes
|
21
27
|
|
@@ -25,8 +31,8 @@ require "was"
|
|
25
31
|
class ReportScore < WAS::Score
|
26
32
|
maximum_score 1000
|
27
33
|
|
28
|
-
with :exam,
|
29
|
-
with :practical class_name: "PracticalScore", weight: 0.25
|
34
|
+
with :exam, class_name: "ExamScore", weight: 0.75
|
35
|
+
with :practical, class_name: "PracticalScore", weight: 0.25
|
30
36
|
end
|
31
37
|
|
32
38
|
class ExamScore < WAS::Score
|
@@ -77,8 +83,8 @@ Omitting the `maximum_score` will return a composed percentage represented as a
|
|
77
83
|
```ruby
|
78
84
|
# report_score.rb
|
79
85
|
class ReportScore < WAS::Score
|
80
|
-
with :exam,
|
81
|
-
with :practical class_name: "PracticalScore", weight: 0.25
|
86
|
+
with :exam, class_name: "ExamScore", weight: 0.75
|
87
|
+
with :practical, class_name: "PracticalScore", weight: 0.25
|
82
88
|
end
|
83
89
|
```
|
84
90
|
|
@@ -91,9 +97,80 @@ ReportScore.new({
|
|
91
97
|
#> 0.875
|
92
98
|
```
|
93
99
|
|
100
|
+
### Working with a score tree
|
101
|
+
|
102
|
+
For more complex scenarios, we might need to know more about how the score was composed.
|
103
|
+
|
104
|
+
Using the example `ReportScore`, `ExamScore`, and `PracticalScore` classes as
|
105
|
+
an example, we can generate a tree of scores:
|
106
|
+
|
107
|
+
```ruby
|
108
|
+
tree = ReportScore.new({
|
109
|
+
exam: "A",
|
110
|
+
practical: 5
|
111
|
+
}).calculate(:tree)
|
112
|
+
|
113
|
+
#> tree
|
114
|
+
{
|
115
|
+
score: 875.0,
|
116
|
+
max: 1000,
|
117
|
+
deduction: -125.0,
|
118
|
+
with: {
|
119
|
+
exam: {
|
120
|
+
score: 750.0,
|
121
|
+
max: 750.0,
|
122
|
+
deduction: 0.0,
|
123
|
+
weight: 0.75
|
124
|
+
},
|
125
|
+
practical: {
|
126
|
+
score: 125.0,
|
127
|
+
max: 250.0,
|
128
|
+
deduction: -125.0,
|
129
|
+
weight: 0.25
|
130
|
+
}
|
131
|
+
}
|
132
|
+
}
|
133
|
+
```
|
134
|
+
|
135
|
+
This result is a `WAS::Tree` object. Basically a `Hash` with some extra
|
136
|
+
added to it.
|
137
|
+
|
138
|
+
#### Ordering by attribute
|
139
|
+
|
140
|
+
For each of the key attributes `:score`, `:max`, `:weight`, and
|
141
|
+
`:deduction`, we can order our tree interally by that key:
|
142
|
+
|
143
|
+
```ruby
|
144
|
+
#> tree.order(:deduction)
|
145
|
+
{
|
146
|
+
score: 875.0,
|
147
|
+
max: 1000,
|
148
|
+
deduction: -125.0
|
149
|
+
with: {
|
150
|
+
practical: {
|
151
|
+
score: 125.0,
|
152
|
+
max: 250.0,
|
153
|
+
deduction: -125.0,
|
154
|
+
weight: 0.25
|
155
|
+
},
|
156
|
+
exam: {
|
157
|
+
score: 750.0,
|
158
|
+
max: 750.0,
|
159
|
+
deduction: 0.0,
|
160
|
+
weight: 0.75
|
161
|
+
}
|
162
|
+
}
|
163
|
+
}
|
164
|
+
```
|
165
|
+
|
166
|
+
For `:deduction`, results adjacent to each other are ordered by the
|
167
|
+
_most negative_. For all other options, the values are ordered largest
|
168
|
+
value first.
|
169
|
+
|
94
170
|
### View all weights
|
95
171
|
|
96
|
-
If you want to see all of the weights that are used to compose the score,
|
172
|
+
If you want to see all of the weights that are used to compose the score,
|
173
|
+
there is a convenience method `.weights`:
|
97
174
|
|
98
175
|
```ruby
|
99
176
|
ReportScore.weights
|
data/lib/was/score.rb
CHANGED
@@ -45,9 +45,12 @@ module WAS
|
|
45
45
|
|
46
46
|
calc = calculation(:tree)
|
47
47
|
tree = if calc.is_a?(Hash)
|
48
|
-
calc.merge(
|
48
|
+
calc.merge(additional_score_attributes(calc[:score]))
|
49
49
|
else
|
50
|
-
{
|
50
|
+
{}.tap do |t|
|
51
|
+
t.merge!(score: calc)
|
52
|
+
t.merge!(additional_score_attributes(calc))
|
53
|
+
end
|
51
54
|
end
|
52
55
|
|
53
56
|
transform_scores_relative_to_max_score(tree)
|
@@ -63,6 +66,13 @@ module WAS
|
|
63
66
|
|
64
67
|
private
|
65
68
|
|
69
|
+
def additional_score_attributes(score_value)
|
70
|
+
{
|
71
|
+
max: self.class.max_score,
|
72
|
+
deduction: (score_value - self.class.max_score).round(8)
|
73
|
+
}
|
74
|
+
end
|
75
|
+
|
66
76
|
def transform_scores_relative_to_max_score(tree, max_score = nil)
|
67
77
|
max_score = max_score || self.class.max_score
|
68
78
|
return tree if self.class.max_score == 1
|
@@ -71,7 +81,7 @@ module WAS
|
|
71
81
|
next if key != :with
|
72
82
|
|
73
83
|
value.each do |scorer, branch|
|
74
|
-
|
84
|
+
adjust_values_relative_to_max_score(branch, max_score)
|
75
85
|
end
|
76
86
|
|
77
87
|
value.transform_values! do |nested_tree|
|
@@ -80,9 +90,10 @@ module WAS
|
|
80
90
|
end
|
81
91
|
end
|
82
92
|
|
83
|
-
def
|
84
|
-
branch[:max]
|
93
|
+
def adjust_values_relative_to_max_score(branch, max_score)
|
94
|
+
branch[:max] = branch[:max] * max_score * branch[:weight]
|
85
95
|
branch[:score] = branch[:score] * branch[:max]
|
96
|
+
branch[:deduction] = branch[:score] - branch[:max]
|
86
97
|
end
|
87
98
|
|
88
99
|
def contexts?
|
@@ -99,7 +110,10 @@ module WAS
|
|
99
110
|
|
100
111
|
def nested_score_calcuation(option)
|
101
112
|
if option == :tree
|
102
|
-
|
113
|
+
WAS::Tree.new.tap do |t|
|
114
|
+
t[:score] = sum
|
115
|
+
t[:with] = with_attribute
|
116
|
+
end
|
103
117
|
else
|
104
118
|
sum
|
105
119
|
end
|
data/lib/was/tree.rb
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
module WAS
|
2
|
+
class Tree < Hash
|
3
|
+
def order(order_key = :deduction)
|
4
|
+
self.dup.tap do |tree|
|
5
|
+
return tree if tree[:with].nil?
|
6
|
+
|
7
|
+
sort_with_by!(order_key, tree)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
private
|
12
|
+
|
13
|
+
def sort_with_by!(order_key, tree)
|
14
|
+
return tree if tree[:with].nil?
|
15
|
+
|
16
|
+
tree[:with].each do |_, subtree|
|
17
|
+
sort_with_by!(order_key, subtree)
|
18
|
+
end
|
19
|
+
|
20
|
+
array = tree[:with].sort_by do |_, subtree|
|
21
|
+
subtree[order_key]
|
22
|
+
end
|
23
|
+
|
24
|
+
tree[:with] = if order_key == :deduction
|
25
|
+
array.to_h
|
26
|
+
else
|
27
|
+
array.reverse.to_h
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
data/lib/was/version.rb
CHANGED
data/lib/was.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: was
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.8.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Mark Connell
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2025-02-
|
11
|
+
date: 2025-02-26 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: A simple gem/dsl for generating Weighted Average Score calculations.
|
14
14
|
email:
|
@@ -23,6 +23,7 @@ files:
|
|
23
23
|
- Rakefile
|
24
24
|
- lib/was.rb
|
25
25
|
- lib/was/score.rb
|
26
|
+
- lib/was/tree.rb
|
26
27
|
- lib/was/version.rb
|
27
28
|
- sig/was.rbs
|
28
29
|
- was.gemspec
|