streak 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,18 @@
1
+ *.gem
2
+ *.rbc
3
+ *.rdb
4
+ .bundle
5
+ .config
6
+ .yardoc
7
+ Gemfile.lock
8
+ InstalledFiles
9
+ _yardoc
10
+ coverage
11
+ doc/
12
+ lib/bundler/man
13
+ pkg
14
+ rdoc
15
+ spec/reports
16
+ test/tmp
17
+ test/version_tmp
18
+ tmp
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format nested
data/.rvmrc ADDED
@@ -0,0 +1 @@
1
+ rvm use --create ruby-1.9.3-p125@streak_gem
@@ -0,0 +1,5 @@
1
+ # CHANGELOG
2
+
3
+ ## 0.0.1
4
+
5
+ * Initial release.
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in streak.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 David Czarnecki
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,69 @@
1
+ # streak
2
+
3
+ streak is a gem for calculating win/loss streaks. It uses Redis as its backend for collecting the data.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ ```ruby
10
+ gem 'streak'
11
+ ```
12
+
13
+ And then execute:
14
+
15
+ ```
16
+ $ bundle
17
+ ```
18
+
19
+ Or install it yourself as:
20
+
21
+ ```
22
+ $ gem install streak
23
+ ```
24
+
25
+ ## Usage
26
+
27
+ streak is configurable with respect to its keys to allow for tracking other positive/negative things in a game like wins and losses, kills and deaths, etc.
28
+
29
+ ```ruby
30
+ # Configuration
31
+ Streak.configure do |configuration|
32
+ configuration.redis = Redis.new
33
+ configuration.namespace = 'streak'
34
+ configuration.positive_key = 'wins'
35
+ configuration.positive_total_key = 'wins_total'
36
+ configuration.positive_streak_key = 'wins_streak'
37
+ configuration.negative_key = 'losses'
38
+ configuration.negative_total_key = 'losses_total'
39
+ configuration.negative_streak_key = 'losses_streak'
40
+ configuration.total_key = 'total'
41
+ end
42
+
43
+ Streak.aggregate('david', 3) # 3 wins
44
+ Streak.aggregate('david', -2) # 2 losses
45
+ Streak.aggregate('david', 5) # 5 wins
46
+ Streak.aggregate('david', -1) # 1 loss
47
+
48
+ Streak.statistics('david')
49
+ => {:wins=>0, :wins_total=>8, :wins_streak=>5, :losses=>1, :losses_total=>3, :losses_streak=>2, :total=>11}
50
+
51
+ Streak.statistics('david', [Streak.positive_streak_key, Streak.negative_streak_key])
52
+ => {:wins_streak=>5, :losses_streak=>2}
53
+
54
+ Streak.reset_statistics('david')
55
+ Streak.statistics('david')
56
+ => {:wins=>0, :wins_total=>0, :wins_streak=>0, :losses=>0, :losses_total=>0, :losses_streak=>0, :total=>0}
57
+ ```
58
+
59
+ ## Contributing
60
+
61
+ 1. Fork it
62
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
63
+ 3. Commit your changes (`git commit -am 'Added some feature'`)
64
+ 4. Push to the branch (`git push origin my-new-feature`)
65
+ 5. Create new Pull Request
66
+
67
+ ## Copyright
68
+
69
+ Copyright (c) 2012 David Czarnecki. See LICENSE for further details.
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
3
+ require 'rake'
4
+ require 'rspec/core/rake_task'
5
+
6
+ RSpec::Core::RakeTask.new(:spec) do |spec|
7
+ spec.pattern = 'spec/**/*_spec.rb'
8
+ spec.rspec_opts = ['--backtrace']
9
+ # spec.ruby_opts = ['-w']
10
+ end
11
+
12
+ task :default => :spec
@@ -0,0 +1,9 @@
1
+ require 'redis'
2
+ require 'streak/configuration'
3
+ require 'streak/collector'
4
+ require 'streak/version'
5
+
6
+ module Streak
7
+ extend Configuration
8
+ extend Collector
9
+ end
@@ -0,0 +1,82 @@
1
+ module Streak
2
+ module Collector
3
+ # Aggregate streaks for a given +id+. If +count+ is greater than 0, it will increment +Streak.positive_key+ and
4
+ # +Streak.positive_total_key+ by the absolute value of count. It will zero out +Streak.negative_key+. Finally, it
5
+ # will add the absolute value of count to +Streak.total_key+. If the current positive streak is greater than
6
+ # the value of +Streak.positive_streak_key+, its value will be replaced.
7
+ # If +count+ is less than than 0, it will increment +Streak.negative_key+ and
8
+ # +Streak.negative_total_key+ by the absolute value of count. It will zero out +Streak.positive_key+. Finally, it
9
+ # will add the absolute value of count to +Streak.total_key+. If the current negative streak is greater than
10
+ # the value of +Streak.negative_streak_key+, its value will be replaced.
11
+ #
12
+ # @param id [String] ID of the item being monitored for a streak.
13
+ # @param count [Integer] Streak count, which can be positive or negative.
14
+ def aggregate(id, count)
15
+ if count >= 0
16
+ previous_data = Streak.redis.multi do |transaction|
17
+ transaction.get("#{Streak::namespace}::#{Streak::positive_key}::#{id}")
18
+ transaction.get("#{Streak::namespace}::#{Streak::positive_streak_key}::#{id}")
19
+ end
20
+
21
+ previous_wins = previous_data[0].to_i
22
+ previous_streak = previous_data[1].to_i
23
+
24
+ Streak.redis.multi do |transaction|
25
+ transaction.set("#{Streak::namespace}::#{Streak::positive_streak_key}::#{id}", [previous_wins + count, previous_streak].max)
26
+ transaction.incrby("#{Streak::namespace}::#{Streak::positive_key}::#{id}", count.abs)
27
+ transaction.incrby("#{Streak::namespace}::#{Streak::positive_total_key}::#{id}", count.abs)
28
+ transaction.set("#{Streak::namespace}::#{Streak::negative_key}::#{id}", 0)
29
+ transaction.incrby("#{Streak::namespace}::#{Streak::total_key}::#{id}", count.abs)
30
+ end
31
+ else
32
+ previous_data = Streak.redis.multi do |transaction|
33
+ transaction.get("#{Streak::namespace}::#{Streak::negative_key}::#{id}")
34
+ transaction.get("#{Streak::namespace}::#{Streak::negative_streak_key}::#{id}")
35
+ end
36
+
37
+ previous_losses = previous_data[0].to_i
38
+ previous_streak = previous_data[1].to_i
39
+
40
+ Streak.redis.multi do |transaction|
41
+ transaction.set("#{Streak::namespace}::#{Streak::negative_streak_key}::#{id}", [previous_losses + count.abs, previous_streak].max)
42
+ transaction.incrby("#{Streak::namespace}::#{Streak::negative_key}::#{id}", count.abs)
43
+ transaction.incrby("#{Streak::namespace}::#{Streak::negative_total_key}::#{id}", count.abs)
44
+ transaction.set("#{Streak::namespace}::#{Streak::positive_key}::#{id}", 0)
45
+ transaction.incrby("#{Streak::namespace}::#{Streak::total_key}::#{id}", count.abs)
46
+ end
47
+ end
48
+ end
49
+
50
+ # Retrieve all (or some) of the streak statistics collected. By default, without a second parameter, this
51
+ # method will return a +Hash+ of: +Streak.positive_key+, +Streak.positive_total_key+, +Streak.positive_streak_key+,
52
+ # +Streak.negative_key+, +Streak.negative_total_key+, +Streak.negative_streak_key+, and +Streak.total_key+ with
53
+ # their corresponding values. If you want a subset of that list, pass in an array with the keys you want
54
+ # returned.
55
+ #
56
+ # @param id [String] ID.
57
+ # @param keys [Array, optional]. Optional list of streak statistic keys to be retrieved.
58
+ #
59
+ # @return +Hash+ of streak statistics and their corresponding values for a given +id+.
60
+ #
61
+ def statistics(id, keys = [Streak.positive_key, Streak.positive_total_key, Streak.positive_streak_key, Streak.negative_key, Streak.negative_total_key, Streak.negative_streak_key, Streak.total_key])
62
+ values = Streak.redis.multi do |transaction|
63
+ keys.each do |key|
64
+ transaction.get("#{Streak::namespace}::#{key}::#{id}")
65
+ end
66
+ end.map(&:to_i)
67
+
68
+ Hash[keys.map(&:to_sym).zip(values)]
69
+ end
70
+
71
+ # Reset all the statistics for a given +id+ to 0.
72
+ #
73
+ # @param id [String] ID.
74
+ def reset_statistics(id)
75
+ Streak.redis.multi do |transaction|
76
+ [Streak.positive_key, Streak.positive_total_key, Streak.positive_streak_key, Streak.negative_key, Streak.negative_total_key, Streak.negative_streak_key, Streak.total_key].each do |key|
77
+ transaction.set("#{Streak::namespace}::#{key}::#{id}", 0)
78
+ end
79
+ end
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,105 @@
1
+ module Streak
2
+ module Configuration
3
+ # Redis instance.
4
+ attr_accessor :redis
5
+
6
+ # streak namespace for Redis.
7
+ attr_writer :namespace
8
+
9
+ # Key used in Redis for tracking positive.
10
+ attr_writer :positive_key
11
+
12
+ # Key used in Redis for tracking positive total.
13
+ attr_writer :positive_total_key
14
+
15
+ # Key used in Redis for tracking positive streak.
16
+ attr_writer :positive_streak_key
17
+
18
+ # Key used in Redis for tracking negative.
19
+ attr_writer :negative_key
20
+
21
+ # Key used in Redis for tracking negative total.
22
+ attr_writer :negative_total_key
23
+
24
+ # Key used in Redis for tracking negative streak.
25
+ attr_writer :negative_streak_key
26
+
27
+ # Key used in Redis for tracking total.
28
+ attr_writer :total
29
+
30
+ # Yield self to be able to configure Streak with block-style configuration.
31
+ #
32
+ # Example:
33
+ #
34
+ # Streak.configure do |configuration|
35
+ # configuration.redis = Redis.new
36
+ # configuration.namespace = 'streak'
37
+ # configuration.positive_key = 'wins'
38
+ # configuration.positive_total_key = 'wins_total'
39
+ # configuration.positive_streak_key = 'wins_streak'
40
+ # configuration.negative_key = 'losses'
41
+ # configuration.negative_total_key = 'losses_total'
42
+ # configuration.negative_streak_key = 'losses_streak'
43
+ # configuration.total_key = 'total'
44
+ # end
45
+ def configure
46
+ yield self
47
+ end
48
+
49
+ # streak namespace for Redis.
50
+ #
51
+ # @return the streak namespace or the default of 'streak' if not set.
52
+ def namespace
53
+ @namespace ||= 'streak'
54
+ end
55
+
56
+ # Key used in Redis for tracking positive.
57
+ #
58
+ # @return the key used in Redis for tracking positive or the default of 'wins' if not set.
59
+ def positive_key
60
+ @positive_key ||= 'wins'
61
+ end
62
+
63
+ # Key used in Redis for tracking positive total.
64
+ #
65
+ # @return the key used in Redis for tracking positive total or the default of 'wins_total' if not set.
66
+ def positive_total_key
67
+ @positive_total_key ||= 'wins_total'
68
+ end
69
+
70
+ # Key used in Redis for tracking positive streak.
71
+ #
72
+ # @return the key used in Redis for tracking positive streak or the default of 'wins_streak' if not set.
73
+ def positive_streak_key
74
+ @positive_streak_key ||= 'wins_streak'
75
+ end
76
+
77
+ # Key used in Redis for tracking negative.
78
+ #
79
+ # @return the key used in Redis for tracking negative or the default of 'losses' if not set.
80
+ def negative_key
81
+ @negative_key ||= 'losses'
82
+ end
83
+
84
+ # Key used in Redis for tracking negative total.
85
+ #
86
+ # @return the key used in Redis for tracking negative total or the default of 'losses_total' if not set.
87
+ def negative_total_key
88
+ @negative_total_key ||= 'losses_total'
89
+ end
90
+
91
+ # Key used in Redis for tracking negative streak.
92
+ #
93
+ # @return the key used in Redis for tracking negative streak or the default of 'losses_streak' if not set.
94
+ def negative_streak_key
95
+ @negative_streak_key ||= 'losses_streak'
96
+ end
97
+
98
+ # Key used in Redis for tracking totals.
99
+ #
100
+ # @return the key used in Redis for tracking total or the default of 'total' if not set.
101
+ def total_key
102
+ @total ||= 'total'
103
+ end
104
+ end
105
+ end
@@ -0,0 +1,3 @@
1
+ module Streak
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,26 @@
1
+ require 'rspec'
2
+ require 'streak'
3
+
4
+ Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
5
+
6
+ RSpec.configure do |config|
7
+ config.before(:all) do
8
+ Streak.configure do |configuration|
9
+ redis = Redis.new(:db => 15)
10
+ configuration.redis = redis
11
+ end
12
+ end
13
+
14
+ config.before(:each) do
15
+ Streak.redis.flushdb
16
+ end
17
+
18
+ config.after(:all) do
19
+ Streak.redis.flushdb
20
+ Streak.redis.quit
21
+ end
22
+
23
+ def streak_value_for(key, id)
24
+ Streak.redis.get("#{Streak::namespace}::#{key}::#{id}").to_i
25
+ end
26
+ end
@@ -0,0 +1,69 @@
1
+ require 'spec_helper'
2
+
3
+ describe Streak::Collector do
4
+ describe '#aggregate' do
5
+ it 'should collect the right statistics' do
6
+ streak_value_for(Streak.positive_key, 'david').should == 0
7
+ streak_value_for(Streak.positive_streak_key, 'david').should == 0
8
+ streak_value_for(Streak.negative_key, 'david').should == 0
9
+ streak_value_for(Streak.negative_streak_key, 'david').should == 0
10
+ streak_value_for(Streak.total_key, 'david').should == 0
11
+ Streak.aggregate('david', 1)
12
+ streak_value_for(Streak.positive_key, 'david').should == 1
13
+ streak_value_for(Streak.positive_streak_key, 'david').should == 1
14
+ streak_value_for(Streak.negative_key, 'david').should == 0
15
+ streak_value_for(Streak.total_key, 'david').should == 1
16
+ Streak.aggregate('david', 1)
17
+ streak_value_for(Streak.positive_key, 'david').should == 2
18
+ streak_value_for(Streak.positive_streak_key, 'david').should == 2
19
+ streak_value_for(Streak.total_key, 'david').should == 2
20
+ Streak.aggregate('david', -1)
21
+ streak_value_for(Streak.positive_key, 'david').should == 0
22
+ streak_value_for(Streak.positive_streak_key, 'david').should == 2
23
+ streak_value_for(Streak.negative_key, 'david').should == 1
24
+ streak_value_for(Streak.negative_streak_key, 'david').should == 1
25
+ streak_value_for(Streak.total_key, 'david').should == 3
26
+ Streak.aggregate('david', 3)
27
+ streak_value_for(Streak.positive_key, 'david').should == 3
28
+ streak_value_for(Streak.positive_streak_key, 'david').should == 3
29
+ streak_value_for(Streak.negative_key, 'david').should == 0
30
+ streak_value_for(Streak.negative_streak_key, 'david').should == 1
31
+ streak_value_for(Streak.total_key, 'david').should == 6
32
+ end
33
+ end
34
+
35
+ describe '#statistics' do
36
+ it 'should return the default list of statistics if no keys list is provided' do
37
+ Streak.aggregate('david', 3)
38
+ Streak.aggregate('david', -2)
39
+ Streak.aggregate('david', 5)
40
+ Streak.aggregate('david', -1)
41
+
42
+ Streak.statistics('david').should == {:wins => 0, :wins_total => 8, :wins_streak => 5, :losses => 1, :losses_total => 3, :losses_streak => 2, :total => 11}
43
+ end
44
+
45
+ it 'should return the specified list of statistics if a keys list is provided' do
46
+ Streak.aggregate('david', 3)
47
+ Streak.aggregate('david', -2)
48
+ Streak.aggregate('david', 5)
49
+ Streak.aggregate('david', -1)
50
+
51
+ Streak.statistics('david', [Streak.positive_streak_key, Streak.negative_streak_key]).should == {:wins_streak => 5, :losses_streak => 2}
52
+ end
53
+ end
54
+
55
+ describe '#reset_statistics' do
56
+ it 'should reset all statistics' do
57
+ Streak.aggregate('david', 3)
58
+ Streak.aggregate('david', -2)
59
+ Streak.aggregate('david', 5)
60
+ Streak.aggregate('david', -1)
61
+
62
+ Streak.statistics('david').should == {:wins => 0, :wins_total => 8, :wins_streak => 5, :losses => 1, :losses_total => 3, :losses_streak => 2, :total => 11}
63
+
64
+ Streak.reset_statistics('david')
65
+
66
+ Streak.statistics('david').should == {:wins => 0, :wins_total => 0, :wins_streak => 0, :losses => 0, :losses_total => 0, :losses_streak => 0, :total => 0}
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,19 @@
1
+ require 'spec_helper'
2
+
3
+ describe Streak::Configuration do
4
+ describe '#configure' do
5
+ it 'should have default attributes' do
6
+ Streak.configure do |configuration|
7
+ configuration.redis.should_not be_nil
8
+ configuration.namespace.should eql('streak')
9
+ configuration.positive_key.should eql('wins')
10
+ configuration.positive_total_key.should eql('wins_total')
11
+ configuration.positive_streak_key.should eql('wins_streak')
12
+ configuration.negative_key.should eql('losses')
13
+ configuration.negative_total_key.should eql('losses_total')
14
+ configuration.negative_streak_key.should eql('losses_streak')
15
+ configuration.total_key.should eql('total')
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,24 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require 'streak/version'
4
+
5
+ # require File.expand_path('../lib/streak/version', __FILE__)
6
+
7
+ Gem::Specification.new do |gem|
8
+ gem.authors = ["David Czarnecki"]
9
+ gem.email = ["me@davidczarnecki.com"]
10
+ gem.description = %q{Streak is a gem for calculating win/loss streaks}
11
+ gem.summary = %q{Streak is a gem for calculating win/loss streaks}
12
+ gem.homepage = "https://github.com/czarneckid/streak"
13
+
14
+ gem.files = `git ls-files`.split($\)
15
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
16
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
17
+ gem.name = "streak"
18
+ gem.require_paths = ["lib"]
19
+ gem.version = Streak::VERSION
20
+
21
+ gem.add_dependency 'redis'
22
+ gem.add_development_dependency 'rspec'
23
+ gem.add_development_dependency 'rake'
24
+ end
metadata ADDED
@@ -0,0 +1,103 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: streak
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - David Czarnecki
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-04-18 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: redis
16
+ requirement: &70095633195380 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: *70095633195380
25
+ - !ruby/object:Gem::Dependency
26
+ name: rspec
27
+ requirement: &70095633194840 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ! '>='
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
33
+ type: :development
34
+ prerelease: false
35
+ version_requirements: *70095633194840
36
+ - !ruby/object:Gem::Dependency
37
+ name: rake
38
+ requirement: &70095633194140 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ! '>='
42
+ - !ruby/object:Gem::Version
43
+ version: '0'
44
+ type: :development
45
+ prerelease: false
46
+ version_requirements: *70095633194140
47
+ description: Streak is a gem for calculating win/loss streaks
48
+ email:
49
+ - me@davidczarnecki.com
50
+ executables: []
51
+ extensions: []
52
+ extra_rdoc_files: []
53
+ files:
54
+ - .gitignore
55
+ - .rspec
56
+ - .rvmrc
57
+ - CHANGELOG.md
58
+ - Gemfile
59
+ - LICENSE
60
+ - README.md
61
+ - Rakefile
62
+ - lib/streak.rb
63
+ - lib/streak/collector.rb
64
+ - lib/streak/configuration.rb
65
+ - lib/streak/version.rb
66
+ - spec/spec_helper.rb
67
+ - spec/streak/collector_spec.rb
68
+ - spec/streak/configuration_spec.rb
69
+ - streak.gemspec
70
+ homepage: https://github.com/czarneckid/streak
71
+ licenses: []
72
+ post_install_message:
73
+ rdoc_options: []
74
+ require_paths:
75
+ - lib
76
+ required_ruby_version: !ruby/object:Gem::Requirement
77
+ none: false
78
+ requirements:
79
+ - - ! '>='
80
+ - !ruby/object:Gem::Version
81
+ version: '0'
82
+ segments:
83
+ - 0
84
+ hash: -3298361675894523649
85
+ required_rubygems_version: !ruby/object:Gem::Requirement
86
+ none: false
87
+ requirements:
88
+ - - ! '>='
89
+ - !ruby/object:Gem::Version
90
+ version: '0'
91
+ segments:
92
+ - 0
93
+ hash: -3298361675894523649
94
+ requirements: []
95
+ rubyforge_project:
96
+ rubygems_version: 1.8.10
97
+ signing_key:
98
+ specification_version: 3
99
+ summary: Streak is a gem for calculating win/loss streaks
100
+ test_files:
101
+ - spec/spec_helper.rb
102
+ - spec/streak/collector_spec.rb
103
+ - spec/streak/configuration_spec.rb