opr-calc 0.1.0 → 0.1.1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 434b7eba4789fd454564da8db982a45cbc31c5ce
4
- data.tar.gz: 71bbf74562b830a636202be0c0e100785c125b6a
3
+ metadata.gz: bc4b64c17002cc19c3c9ccda154fdeecd1a57043
4
+ data.tar.gz: e1aa8b1a9fd828b2d3a76fce85f3c0a7d961b2cb
5
5
  SHA512:
6
- metadata.gz: bc786e92a7d323d21ab2cacd40b7a05379453215b238754d45d2a490f17bb9473c1ea9067ad0d9140432c4c4e2737d600c55e3f96b78380ba7abe0a6939f6ab1
7
- data.tar.gz: 58a190ddaf8aa3b405b5e80127f66a28f1682f3df4cc907d7976bb9f05c9b1252e50b752538f61dab2a00e6a54a66fab70d676358de3a6c5a6e0da8c6b0ed133
6
+ metadata.gz: d1d6b5e73181e786af4e61bfa0c8f4976c0aa371daded216bd2306de6c2847984d01da721c4f82bad26c5a0995044c2c20bcc09306d7e65ec28305f5a0b0a2fb
7
+ data.tar.gz: a76ab942d81c005e258c71e7a0eb3e71fbee67836c430c055da23a724b63ece9e7faf7bd22e8c003ed67d9c7dd014982946f4591c3f275182b26a86f4acfe279
@@ -1,325 +1,20 @@
1
- #!/usr/bin/env ruby
2
-
3
1
  =begin
4
- opr-calc is a tool for calculating OPR and other scouting stats for FRC teams.
5
- Copyright (C) 2014 Kristofer Rye and Christopher Cooper
2
+ opr-calc is a tool for calculating OPR and other scouting stats for FRC teams.
3
+ Copyright (C) 2014 Kristofer Rye and Christopher Cooper
6
4
 
7
- This program is free software: you can redistribute it and/or modify
8
- it under the terms of the GNU General Public License as published by
9
- the Free Software Foundation, either version 3 of the License, or
10
- (at your option) any later version.
5
+ This program is free software: you can redistribute it and/or modify
6
+ it under the terms of the GNU General Public License as published by
7
+ the Free Software Foundation, either version 3 of the License, or
8
+ (at your option) any later version.
11
9
 
12
- This program is distributed in the hope that it will be useful,
13
- but WITHOUT ANY WARRANTY; without even the implied warranty of
14
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
- GNU General Public License for more details.
10
+ This program is distributed in the hope that it will be useful,
11
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ GNU General Public License for more details.
16
14
 
17
- You should have received a copy of the GNU General Public License
18
- along with this program. If not, see <http://www.gnu.org/licenses/>.
15
+ You should have received a copy of the GNU General Public License
16
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
19
17
  =end
20
18
 
21
- require 'matrix'
22
-
23
- # Props to http://rosettacode.org/wiki/Cholesky_decomposition#Ruby :L
24
- class Matrix
25
- # Returns whether or not the Matrix is symmetric (http://en.wikipedia.org/wiki/Symmetric_matrix)
26
- def symmetric?
27
-
28
- # Matrices can't be symmetric if they're not square.
29
- return false if not square?
30
-
31
- (0...row_size).each do |i|
32
- (0..i).each do |j|
33
- return false if self[i,j] != self[j,i]
34
- end
35
- end
36
-
37
- true
38
- end
39
-
40
- def cholesky_factor
41
- # We need a symmetric matrix for Cholesky.
42
- raise ArgumentError, "You must provide symmetric matrix" unless symmetric?
43
-
44
- # Make a new matrix to return
45
- l = Array.new(row_size) { Array.new(row_size, 0) }
46
-
47
- (0...row_size).each do |k|
48
- (0...row_size).each do |i|
49
- if i == k
50
- sum = (0..k-1).inject(0.0) {|sum, j| sum + l[k][j] ** 2}
51
- val = Math.sqrt(self[k,k] - sum)
52
- l[k][k] = val
53
- elsif i > k
54
- sum = (0..k-1).inject(0.0) {|sum, j| sum + l[i][j] * l[k][j]}
55
- val = (self[k,i] - sum) / l[k][k]
56
- l[i][k] = val
57
- end
58
- end
59
- end
60
-
61
- Matrix[*l]
62
- end
63
-
64
- # A helpful debug function for Matrices
65
- def output
66
- (0..self.row_size - 1).each do |row_number|
67
- (0..self.column_size - 1).each do |column_number|
68
- printf("%8.4f ", self[row_number, column_number])
69
- end
70
- printf("\n")
71
- end
72
- self
73
- end
74
- end
75
-
76
-
77
-
78
- class ScoreSet
79
- attr_reader :ared, :ablue, :scorered, :scoreblue
80
-
81
- def ared=(value)
82
- @ared = value
83
- @opr_recalc = @dpr_recalc = @ccwm_recalc = true
84
- end
85
- def ablue=(value)
86
- @ablue = value
87
- @opr_recalc = @dpr_recalc = @ccwm_recalc = true
88
- end
89
- def scorered=(value)
90
- @scorered = value
91
- @opr_recalc = @dpr_recalc = @ccwm_recalc = true
92
- end
93
- def scoreblue=(value)
94
- @scoreblue = value
95
- @opr_recalc = @dpr_recalc = @ccwm_recalc = true
96
- end
97
-
98
- def initialize(ared, ablue, scorered, scoreblue)
99
- @ared = ared
100
- @ablue = ablue
101
- @scorered = scorered
102
- @scoreblue = scoreblue
103
- end
104
-
105
- # A generic function for smooshing two matrices (one red, one blue).
106
- # Each should have the same dimensions.
107
- def alliance_smooshey(redmatrix, bluematrix)
108
- throw ArgumentError "Matrices must have same dimensions" unless (redmatrix.row_size == bluematrix.row_size) && (redmatrix.column_size == bluematrix.column_size)
109
-
110
- # Then we just pull the column and row size from the red matrix because we can.
111
- column_count = redmatrix.column_size
112
- row_count = redmatrix.row_size
113
-
114
- # Use a block function to generate the new matrix
115
- matrix = Matrix.build(row_count * 2, column_count) do
116
- |row, column|
117
-
118
- # note: no need to alternate, instead put all red, then all blue
119
- if row < row_count # first half = red
120
- redmatrix[row, column]
121
- else # second half = blue
122
- bluematrix[row - row_count, column]
123
- end
124
- end
125
- # This will end up looking like as follows:
126
-
127
- # [[red[0]],
128
- # [red[1]],
129
- # [red[2]],
130
- # ...
131
- # [red[n]],
132
- # [blue[0]],
133
- # [blue[1]],
134
- # [blue[2]],
135
- # ...
136
- # [blue[n]]]
137
- return matrix
138
- end
139
-
140
- private :alliance_smooshey
141
-
142
- # Solve equation of form [l][x] = [s] for [x]
143
- # l must be a lower triangular matrix.
144
- # Based off of algorithm given at http://en.wikipedia.org/wiki/Triangular_matrix#Forward_and_back_substitution
145
- def forward_substitute(l, s)
146
- raise "l must be a lower triangular matrix" unless l.lower_triangular?
147
-
148
- x = Array.new s.row_size
149
-
150
- x.size.times do |i|
151
- x[i] = s[i, 0]
152
- i.times do |j|
153
- x[i] -= l[i, j] * x[j]
154
- end
155
- x[i] /= l[i, i]
156
- end
157
-
158
- Matrix.column_vector x
159
- end
160
-
161
- # Solve equation of form [u][x] = [s] for [x]
162
- # u must be a upper triangular matrix.
163
- def back_substitute(u, s)
164
- raise "u must be an upper triangular matrix" unless u.upper_triangular?
165
-
166
- x = Array.new s.row_size
167
-
168
- (x.size - 1).downto 0 do |i|
169
- x[i] = s[i, 0]
170
- (i + 1).upto(x.size - 1) do |j|
171
- x[i] -= u[i, j] * x[j]
172
- end
173
- x[i] /= u[i, i]
174
- end
175
-
176
- Matrix.column_vector x
177
- end
178
-
179
- private :forward_substitute, :back_substitute
180
-
181
- =begin
182
- base matrix equation: [A][OPR] = [SCORE]
183
- define [A]^t to be [A] transpose
184
- define [P] to be [A]^t[A]
185
- define [S] to be [A]^t[SCORE]
186
- equation is now [P][OPR] = [S]
187
- refactor [P] as [L][L]^t using cholesky
188
- [L] is a lower triangular matrix and [L]^t an upper
189
- Therefore [L][L]^t[OPR] = [S]
190
- define [Y] = [L]^t[OPR]
191
- equation is now [L][Y] = [S]
192
- find [Y] through forward substitution
193
- find [OPR] through back substitution
194
- =end
195
-
196
- def opr_calculate(a, score)
197
- p = a.t * a
198
- s = a.t * score
199
-
200
- l = p.cholesky_factor
201
-
202
- # l.output
203
- # l.t.output
204
-
205
- y = forward_substitute l, s
206
- back_substitute l.t, y
207
- end
208
-
209
- # Offensive power rating: the average amount of points that a team contributes to their alliance's score
210
- # This is high for a good team
211
- def opr(recalc = false)
212
- if !@opr || recalc || @opr_recalc
213
- a = alliance_smooshey @ared, @ablue
214
- score = alliance_smooshey @scorered, @scoreblue
215
-
216
- @opr = opr_calculate a, score
217
- @opr_recalc = false
218
- end
219
- @opr
220
- end
221
-
222
- # Defensive power rating: the average amount of points that a team lets the other alliance score
223
- # This is low for a good team
224
- def dpr(recalc = false)
225
- if !@dpr || recalc || @dpr_recalc
226
- a = alliance_smooshey @ared, @ablue
227
- score = alliance_smooshey @scoreblue, @scorered # intentionally swapped, that's how dpr works
228
-
229
- @dpr = opr_calculate a, score
230
- @dpr_recalc = false
231
- end
232
- @dpr
233
- end
234
-
235
- # Calculated contribution to winning margin: the average amount of points that a team contributes to their alliance's winning margin
236
- # This is high for a good team
237
- def ccwm(recalc = false)
238
- if !@ccwm || recalc || @ccwm_recalc
239
- a = alliance_smooshey @ared, @ablue
240
-
241
- red_wm = Matrix.build(@scorered.row_size, @scorered.column_size) do |row, column|
242
- @scorered[row, column] - @scoreblue[row, column]
243
- end
244
- blue_wm = Matrix.build(@scoreblue.row_size, @scoreblue.column_size) do |row, column|
245
- @scoreblue[row, column] - @scorered[row, column]
246
- end
247
-
248
- score = alliance_smooshey red_wm, blue_wm
249
-
250
- @ccwm = opr_calculate a, score
251
- @ccwm_recalc = false
252
- end
253
- @ccwm
254
- end
255
-
256
- end
257
-
258
-
259
- def test_stuff
260
- # Team 0 opr: 0
261
- # Team 1 opr: 1
262
- # Team 2 opr: 2
263
- # ...
264
-
265
- # I don't think any team is every playing on both blue and red at the same time, but I might be wrong
266
-
267
- # 0 1 2 3 4 5 6 7 8 9
268
- test_ared = Matrix[[1, 0, 1, 0, 1, 0, 0, 0, 0, 0],
269
- [0, 1, 0, 1, 0, 1, 0, 0, 0, 0],
270
- [0, 0, 0, 0, 1, 1, 1, 0, 0, 0],
271
- [0, 0, 0, 0, 0, 0, 0, 1, 1, 1],
272
- [0, 1, 0, 0, 0, 1, 1, 0, 0, 0],
273
- [1, 0, 0, 1, 0, 0, 1, 0, 0, 0]]
274
-
275
- # 0 1 2 3 4 5 6 7 8 9
276
- test_ablue = Matrix[[0, 0, 1, 0, 0, 0, 0, 1, 0, 1],
277
- [1, 0, 0, 0, 1, 0, 0, 0, 1, 0],
278
- [1, 1, 1, 0, 0, 0, 0, 0, 0, 0],
279
- [0, 0, 1, 0, 0, 1, 1, 0, 0, 0],
280
- [0, 0, 0, 1, 0, 0, 0, 0, 1, 1],
281
- [0, 1, 0, 0, 1, 0, 0, 1, 0, 0]]
282
-
283
-
284
- test_scorered = Matrix[[6],
285
- [9],
286
- [15],
287
- [24],
288
- [12],
289
- [9]]
290
-
291
- test_scoreblue = Matrix[[18],
292
- [12],
293
- [3],
294
- [13],
295
- [20],
296
- [12]]
297
-
298
- test_expectedopr = Matrix[[0],
299
- [1],
300
- [2],
301
- [3],
302
- [4],
303
- [5],
304
- [6],
305
- [7],
306
- [8],
307
- [9]]
308
-
309
- test = ScoreSet.new test_ared, test_ablue, test_scorered, test_scoreblue
310
-
311
- puts "Expected OPR:"
312
- test_expectedopr.output
313
- puts "Actual OPR:"
314
- test.opr.output
315
-
316
- puts "DPR:"
317
- test.dpr.output
318
-
319
- puts "CCWM:"
320
- test.ccwm.output
321
- puts "CCWM by OPR - DPR:"
322
- (test.opr - test.dpr).output
323
-
324
- return true
325
- end
19
+ require "opr-calc/matrix.rb"
20
+ require "opr-calc/score_set.rb"
@@ -0,0 +1,75 @@
1
+ =begin
2
+ opr-calc is a tool for calculating OPR and other scouting stats for FRC teams.
3
+ Copyright (C) 2014 Kristofer Rye and Christopher Cooper
4
+
5
+ This program is free software: you can redistribute it and/or modify
6
+ it under the terms of the GNU General Public License as published by
7
+ the Free Software Foundation, either version 3 of the License, or
8
+ (at your option) any later version.
9
+
10
+ This program is distributed in the hope that it will be useful,
11
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ GNU General Public License for more details.
14
+
15
+ You should have received a copy of the GNU General Public License
16
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
17
+ =end
18
+
19
+ require "matrix"
20
+
21
+ # Props to http://rosettacode.org/wiki/Cholesky_decomposition#Ruby :L
22
+ class Matrix
23
+ # Returns whether or not the Matrix is symmetric (http://en.wikipedia.org/wiki/Symmetric_matrix).
24
+ def symmetric?
25
+ # Matrices can't be symmetric if they're not square.
26
+ return false unless square?
27
+
28
+ (0...row_size).each do |i|
29
+ (0..i).each do |j|
30
+ return false if self[i,j] != self[j,i]
31
+ end
32
+ end
33
+
34
+ true
35
+ end
36
+
37
+ # Determines the [L] matrix through Cholesky decomposition.
38
+ # To obtain [L]*, just transpose the matrix, it should work.
39
+ def cholesky_factor
40
+ # We need a symmetric matrix for Cholesky decomposition.
41
+ raise ArgumentError, "must provide a symmetric matrix" unless symmetric?
42
+
43
+ # Make a new matrix to return.
44
+ l = Array.new(row_size) { Array.new(row_size, 0) }
45
+
46
+ (0...row_size).each do |k|
47
+ (0...row_size).each do |i|
48
+ if i == k
49
+ sum = (0..k-1).inject(0.0) { |sum, j| sum + l[k][j] ** 2 }
50
+ val = Math.sqrt(self[k,k] - sum)
51
+ l[k][k] = val
52
+ elsif i > k
53
+ sum = (0..k-1).inject(0.0) { |sum, j| sum + l[i][j] * l[k][j] }
54
+ val = (self[k,i] - sum) / l[k][k]
55
+ l[i][k] = val
56
+ end
57
+ end
58
+ end
59
+
60
+ Matrix[*l]
61
+ end
62
+
63
+ # A helpful debug function for Matrices.
64
+ def output
65
+ (0..self.row_size - 1).each do |row_number|
66
+ (0..self.column_size - 1).each do |column_number|
67
+ printf("%8.4f ", self[row_number, column_number])
68
+ end
69
+
70
+ printf("\n")
71
+ end
72
+
73
+ self
74
+ end
75
+ end
@@ -0,0 +1,213 @@
1
+ =begin
2
+ opr-calc is a tool for calculating OPR and other scouting stats for FRC teams.
3
+ Copyright (C) 2014 Kristofer Rye and Christopher Cooper
4
+
5
+ This program is free software: you can redistribute it and/or modify
6
+ it under the terms of the GNU General Public License as published by
7
+ the Free Software Foundation, either version 3 of the License, or
8
+ (at your option) any later version.
9
+
10
+ This program is distributed in the hope that it will be useful,
11
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ GNU General Public License for more details.
14
+
15
+ You should have received a copy of the GNU General Public License
16
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
17
+ =end
18
+
19
+ module OPRCalc
20
+ class ScoreSet
21
+ attr_reader :ared, :ablue, :scorered, :scoreblue
22
+
23
+ def ared=(value)
24
+ @ared = value
25
+ @opr_recalc = @dpr_recalc = @ccwm_recalc = true
26
+ end
27
+
28
+ def ablue=(value)
29
+ @ablue = value
30
+ @opr_recalc = @dpr_recalc = @ccwm_recalc = true
31
+ end
32
+
33
+ def scorered=(value)
34
+ @scorered = value
35
+ @opr_recalc = @dpr_recalc = @ccwm_recalc = true
36
+ end
37
+
38
+ def scoreblue=(value)
39
+ @scoreblue = value
40
+ @opr_recalc = @dpr_recalc = @ccwm_recalc = true
41
+ end
42
+
43
+ def initialize(ared, ablue, scorered, scoreblue)
44
+ raise TypeError, "ared must be a Matrix" unless ared.is_a? Matrix
45
+ raise TypeError, "ablue must be a Matrix" unless ablue.is_a? Matrix
46
+ raise TypeError, "scorered must be a Matrix" unless scorered.is_a? Matrix
47
+ raise TypeError, "scoreblue must be a Matrix" unless scoreblue.is_a? Matrix
48
+
49
+ @ared = ared
50
+ @ablue = ablue
51
+ @scorered = scorered
52
+ @scoreblue = scoreblue
53
+ end
54
+
55
+ # A generic function for smooshing two matrices (one red, one blue).
56
+ # Each should have the same dimensions.
57
+ def alliance_smooshey(redmatrix, bluematrix)
58
+ throw ArgumentError "Matrices must have same dimensions" unless (redmatrix.row_size == bluematrix.row_size) && (redmatrix.column_size == bluematrix.column_size)
59
+
60
+ # Then we just pull the column and row size from the red matrix because we can.
61
+ column_count = redmatrix.column_size
62
+ row_count = redmatrix.row_size
63
+
64
+ # Use a block function to generate the new matrix.
65
+ matrix = Matrix.build(row_count * 2, column_count) do
66
+ |row, column|
67
+
68
+ # note: no need to alternate, instead put all red, then all blue.
69
+ if row < row_count # first half = red
70
+ redmatrix[row, column]
71
+ else # second half = blue
72
+ bluematrix[row - row_count, column]
73
+ end
74
+ end
75
+
76
+ # This will end up looking like as follows:
77
+
78
+ # [[red[0]],
79
+ # [red[1]],
80
+ # [red[2]],
81
+ # ...
82
+ # [red[n]],
83
+ # [blue[0]],
84
+ # [blue[1]],
85
+ # [blue[2]],
86
+ # ...
87
+ # [blue[n]]]
88
+ return matrix
89
+ end
90
+
91
+ private :alliance_smooshey
92
+
93
+ # Solve equation of form [l][x] = [s] for [x]
94
+ # l must be a lower triangular matrix.
95
+ # Based off of algorithm given at `http://en.wikipedia.org/wiki/Triangular_matrix#Forward_and_back_substitution`.
96
+ def forward_substitute(l, s)
97
+ raise "l must be a lower triangular matrix" unless l.lower_triangular?
98
+
99
+ x = Array.new s.row_size
100
+
101
+ x.size.times do |i|
102
+ x[i] = s[i, 0]
103
+
104
+ i.times do |j|
105
+ x[i] -= l[i, j] * x[j]
106
+ end
107
+
108
+ x[i] /= l[i, i]
109
+ end
110
+
111
+ Matrix.column_vector x
112
+ end
113
+
114
+ # Solve equation of form [u][x] = [s] for [x]
115
+ # u must be a upper triangular matrix.
116
+ def back_substitute(u, s)
117
+ raise "u must be an upper triangular matrix" unless u.upper_triangular?
118
+
119
+ x = Array.new s.row_size
120
+
121
+ (x.size - 1).downto 0 do |i|
122
+ x[i] = s[i, 0]
123
+
124
+ (i + 1).upto(x.size - 1) do |j|
125
+ x[i] -= u[i, j] * x[j]
126
+ end
127
+
128
+ x[i] /= u[i, i]
129
+ end
130
+
131
+ Matrix.column_vector x
132
+ end
133
+
134
+ private :forward_substitute, :back_substitute
135
+
136
+ # base matrix equation: [A][OPR] = [SCORE]
137
+ # define [A]^t to be [A] transpose
138
+ # define [P] to be [A]^t[A]
139
+ # define [S] to be [A]^t[SCORE]
140
+ # equation is now [P][OPR] = [S]
141
+ # refactor [P] as [L][L]^t using cholesky
142
+ # [L] is a lower triangular matrix and [L]^t an upper
143
+ # Therefore [L][L]^t[OPR] = [S]
144
+ # define [Y] = [L]^t[OPR]
145
+ # equation is now [L][Y] = [S]
146
+ # find [Y] through forward substitution
147
+ # find [OPR] through back substitution
148
+
149
+ def opr_calculate(a, score)
150
+ p = a.t * a
151
+ s = a.t * score
152
+
153
+ l = p.cholesky_factor
154
+
155
+ # l.output
156
+ # l.t.output
157
+
158
+ y = forward_substitute l, s
159
+ back_substitute l.t, y
160
+ end
161
+
162
+ # Offensive power rating: the average amount of points that a team contributes to their alliance's score.
163
+ # This is high for a good team.
164
+ def opr(recalc = false)
165
+ if !@opr || recalc || @opr_recalc
166
+ a = alliance_smooshey @ared, @ablue
167
+ score = alliance_smooshey @scorered, @scoreblue
168
+
169
+ @opr = opr_calculate a, score
170
+ @opr_recalc = false
171
+ end
172
+
173
+ @opr
174
+ end
175
+
176
+ # Defensive power rating: the average amount of points that a team lets the other alliance score.
177
+ # This is low for a good team.
178
+ def dpr(recalc = false)
179
+ if !@dpr || recalc || @dpr_recalc
180
+ a = alliance_smooshey @ared, @ablue
181
+ score = alliance_smooshey @scoreblue, @scorered # intentionally swapped, that's how dpr works.
182
+
183
+ @dpr = opr_calculate a, score
184
+ @dpr_recalc = false
185
+ end
186
+
187
+ @dpr
188
+ end
189
+
190
+ # Calculated contribution to winning margin: the average amount of points that a team contributes to their alliance's winning margin.
191
+ # This is high for a good team.
192
+ def ccwm(recalc = false)
193
+ if !@ccwm || recalc || @ccwm_recalc
194
+ a = alliance_smooshey @ared, @ablue
195
+
196
+ red_wm = Matrix.build(@scorered.row_size, @scorered.column_size) do |row, column|
197
+ @scorered[row, column] - @scoreblue[row, column]
198
+ end
199
+
200
+ blue_wm = Matrix.build(@scoreblue.row_size, @scoreblue.column_size) do |row, column|
201
+ @scoreblue[row, column] - @scorered[row, column]
202
+ end
203
+
204
+ score = alliance_smooshey red_wm, blue_wm
205
+
206
+ @ccwm = opr_calculate a, score
207
+ @ccwm_recalc = false
208
+ end
209
+
210
+ @ccwm
211
+ end
212
+ end
213
+ end
metadata CHANGED
@@ -1,16 +1,45 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: opr-calc
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kristofer Rye
8
8
  - Christopher Cooper
9
+ - Sam Craig
9
10
  autorequire:
10
11
  bindir: bin
11
12
  cert_chain: []
12
13
  date: 2014-01-25 00:00:00.000000000 Z
13
- dependencies: []
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: minitest
17
+ requirement: !ruby/object:Gem::Requirement
18
+ requirements:
19
+ - - '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ requirements:
26
+ - - '>='
27
+ - !ruby/object:Gem::Version
28
+ version: '0'
29
+ - !ruby/object:Gem::Dependency
30
+ name: rake
31
+ requirement: !ruby/object:Gem::Requirement
32
+ requirements:
33
+ - - '>='
34
+ - !ruby/object:Gem::Version
35
+ version: '0'
36
+ type: :development
37
+ prerelease: false
38
+ version_requirements: !ruby/object:Gem::Requirement
39
+ requirements:
40
+ - - '>='
41
+ - !ruby/object:Gem::Version
42
+ version: '0'
14
43
  description:
15
44
  email:
16
45
  executables: []
@@ -18,6 +47,8 @@ extensions: []
18
47
  extra_rdoc_files: []
19
48
  files:
20
49
  - lib/opr-calc.rb
50
+ - lib/opr-calc/matrix.rb
51
+ - lib/opr-calc/score_set.rb
21
52
  homepage: https://github.com/team461WBI/opr-calc
22
53
  licenses:
23
54
  - GPL-3.0
@@ -38,7 +69,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
38
69
  version: '0'
39
70
  requirements: []
40
71
  rubyforge_project:
41
- rubygems_version: 2.0.14
72
+ rubygems_version: 2.1.11
42
73
  signing_key:
43
74
  specification_version: 4
44
75
  summary: A tool for calculating OPR and other scouting stats for FRC teams.