githubstats 0.1.7
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 +7 -0
- data/.gitignore +3 -0
- data/.rspec +2 -0
- data/.rubocop.yml +2 -0
- data/.travis.yml +14 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +75 -0
- data/LICENSE +22 -0
- data/README.md +94 -0
- data/Rakefile +19 -0
- data/bin/githubstats +17 -0
- data/githubstats.gemspec +28 -0
- data/lib/githubstats.rb +241 -0
- data/spec/spec_helper.rb +10 -0
- data/vendor/cache/ast-1.1.0.gem +0 -0
- data/vendor/cache/coveralls-0.7.0.gem +0 -0
- data/vendor/cache/curb-0.8.5.gem +0 -0
- data/vendor/cache/diff-lcs-1.2.5.gem +0 -0
- data/vendor/cache/docile-1.1.0.gem +0 -0
- data/vendor/cache/fuubar-1.2.1.gem +0 -0
- data/vendor/cache/hashr-0.0.22.gem +0 -0
- data/vendor/cache/json-1.8.1.gem +0 -0
- data/vendor/cache/mime-types-2.0.gem +0 -0
- data/vendor/cache/multi_json-1.8.2.gem +0 -0
- data/vendor/cache/parser-2.1.0.pre1.gem +0 -0
- data/vendor/cache/powerpack-0.0.9.gem +0 -0
- data/vendor/cache/rainbow-1.1.4.gem +0 -0
- data/vendor/cache/rake-10.1.0.gem +0 -0
- data/vendor/cache/rest-client-1.6.7.gem +0 -0
- data/vendor/cache/rspec-2.14.1.gem +0 -0
- data/vendor/cache/rspec-core-2.14.7.gem +0 -0
- data/vendor/cache/rspec-expectations-2.14.4.gem +0 -0
- data/vendor/cache/rspec-instafail-0.2.4.gem +0 -0
- data/vendor/cache/rspec-mocks-2.14.4.gem +0 -0
- data/vendor/cache/rubocop-0.15.0.gem +0 -0
- data/vendor/cache/ruby-progressbar-1.2.0.gem +0 -0
- data/vendor/cache/simplecov-0.8.2.gem +0 -0
- data/vendor/cache/simplecov-html-0.8.0.gem +0 -0
- data/vendor/cache/slop-3.4.7.gem +0 -0
- data/vendor/cache/term-ansicolor-1.2.2.gem +0 -0
- data/vendor/cache/thor-0.18.1.gem +0 -0
- data/vendor/cache/tins-0.13.1.gem +0 -0
- data/vendor/cache/travis-lint-1.7.0.gem +0 -0
- metadata +214 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA1:
|
|
3
|
+
metadata.gz: 19948dcd258e9e6fe2c2dd1107f9865729580358
|
|
4
|
+
data.tar.gz: 8641305345c72fc7d9eb40bee86526a0879d1b93
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 1e090690830fff33cf761ac7c029fec813e4db023c3feb01e7f82a3a442527c17a09f9c8bd6893de0a4f882f1239442558018d19910b2eb76759a776d1383d46
|
|
7
|
+
data.tar.gz: b376c8553ea90afb5cb5374f8b4e702554d3ae165fe5d32b7fbb37a140b28b16859eb8f97c173e3185a3b18c6ccf3bf51fd45423362d0c2e2705996c824521ab
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.rubocop.yml
ADDED
data/.travis.yml
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
language: ruby
|
|
2
|
+
cache: bundler
|
|
3
|
+
rvm:
|
|
4
|
+
- ruby-head
|
|
5
|
+
- 2.0.0
|
|
6
|
+
- 1.9.3
|
|
7
|
+
notifications:
|
|
8
|
+
email: false
|
|
9
|
+
irc:
|
|
10
|
+
channels:
|
|
11
|
+
- ircs://irc.oftc.net:6697#akerl
|
|
12
|
+
channel_key: sekrit
|
|
13
|
+
template:
|
|
14
|
+
- '%{repository}/%{branch}/%{build_number}: %{message} -- %{build_url}'
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
PATH
|
|
2
|
+
remote: .
|
|
3
|
+
specs:
|
|
4
|
+
githubstats (0.1.7)
|
|
5
|
+
curb
|
|
6
|
+
json
|
|
7
|
+
|
|
8
|
+
GEM
|
|
9
|
+
remote: https://rubygems.org/
|
|
10
|
+
specs:
|
|
11
|
+
ast (1.1.0)
|
|
12
|
+
coveralls (0.7.0)
|
|
13
|
+
multi_json (~> 1.3)
|
|
14
|
+
rest-client
|
|
15
|
+
simplecov (>= 0.7)
|
|
16
|
+
term-ansicolor
|
|
17
|
+
thor
|
|
18
|
+
curb (0.8.5)
|
|
19
|
+
diff-lcs (1.2.5)
|
|
20
|
+
docile (1.1.0)
|
|
21
|
+
fuubar (1.2.1)
|
|
22
|
+
rspec (~> 2.0)
|
|
23
|
+
rspec-instafail (~> 0.2.0)
|
|
24
|
+
ruby-progressbar (~> 1.0)
|
|
25
|
+
hashr (0.0.22)
|
|
26
|
+
json (1.8.1)
|
|
27
|
+
mime-types (2.0)
|
|
28
|
+
multi_json (1.8.2)
|
|
29
|
+
parser (2.1.0.pre1)
|
|
30
|
+
ast (~> 1.1)
|
|
31
|
+
slop (~> 3.4, >= 3.4.5)
|
|
32
|
+
powerpack (0.0.9)
|
|
33
|
+
rainbow (1.1.4)
|
|
34
|
+
rake (10.1.0)
|
|
35
|
+
rest-client (1.6.7)
|
|
36
|
+
mime-types (>= 1.16)
|
|
37
|
+
rspec (2.14.1)
|
|
38
|
+
rspec-core (~> 2.14.0)
|
|
39
|
+
rspec-expectations (~> 2.14.0)
|
|
40
|
+
rspec-mocks (~> 2.14.0)
|
|
41
|
+
rspec-core (2.14.7)
|
|
42
|
+
rspec-expectations (2.14.4)
|
|
43
|
+
diff-lcs (>= 1.1.3, < 2.0)
|
|
44
|
+
rspec-instafail (0.2.4)
|
|
45
|
+
rspec-mocks (2.14.4)
|
|
46
|
+
rubocop (0.15.0)
|
|
47
|
+
parser (~> 2.0)
|
|
48
|
+
powerpack (~> 0.0.6)
|
|
49
|
+
rainbow (>= 1.1.4)
|
|
50
|
+
ruby-progressbar (1.2.0)
|
|
51
|
+
simplecov (0.8.2)
|
|
52
|
+
docile (~> 1.1.0)
|
|
53
|
+
multi_json
|
|
54
|
+
simplecov-html (~> 0.8.0)
|
|
55
|
+
simplecov-html (0.8.0)
|
|
56
|
+
slop (3.4.7)
|
|
57
|
+
term-ansicolor (1.2.2)
|
|
58
|
+
tins (~> 0.8)
|
|
59
|
+
thor (0.18.1)
|
|
60
|
+
tins (0.13.1)
|
|
61
|
+
travis-lint (1.7.0)
|
|
62
|
+
hashr (~> 0.0.22)
|
|
63
|
+
|
|
64
|
+
PLATFORMS
|
|
65
|
+
ruby
|
|
66
|
+
|
|
67
|
+
DEPENDENCIES
|
|
68
|
+
coveralls
|
|
69
|
+
fuubar
|
|
70
|
+
githubstats!
|
|
71
|
+
parser (~> 2.1.0.pre1)
|
|
72
|
+
rake
|
|
73
|
+
rspec
|
|
74
|
+
rubocop
|
|
75
|
+
travis-lint
|
data/LICENSE
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
The MIT License (MIT)
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2013 Les Aker
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
|
13
|
+
all copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
21
|
+
THE SOFTWARE.
|
|
22
|
+
|
data/README.md
ADDED
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
GithubStats
|
|
2
|
+
=========
|
|
3
|
+
|
|
4
|
+
[](http://badge.fury.io/rb/githubstats)
|
|
5
|
+
[](https://gemnasium.com/akerl/githubstats)
|
|
6
|
+
[](https://codeclimate.com/github/akerl/githubstats)
|
|
7
|
+
[](https://coveralls.io/r/akerl/githubstats?branch=master)
|
|
8
|
+
[](https://travis-ci.org/akerl/githubstats)
|
|
9
|
+
|
|
10
|
+
Grabs Github contribution statistics and presents it in an easily consumable format.
|
|
11
|
+
|
|
12
|
+
## Usage
|
|
13
|
+
|
|
14
|
+
A script is provided that uses the module to provide an overview of your contributions:
|
|
15
|
+
|
|
16
|
+
```
|
|
17
|
+
# githubstats
|
|
18
|
+
Contribution data for akerl:
|
|
19
|
+
Today's score: 9
|
|
20
|
+
Current streak: 32
|
|
21
|
+
Longest streak: 32
|
|
22
|
+
High score: 50 on 2013-07-14
|
|
23
|
+
Quartile boundaries: [0, 3, 8, 12, 50]
|
|
24
|
+
▁▁▁▆▁▂▁▁▅▄▁▃▂▁▁▃▁▁▁▁▄▁▂▃█▇▃▁▃▃▂▁▃▂▁▁▁▁▁▁▂▁▁▁▁▂▂▁▃▁▂▁▆▃▂▂▁▁▁▅
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
The graph is generated using spark (https://github.com/holman/spark) if you have it installed.
|
|
28
|
+
|
|
29
|
+
Initializing a new Contributions object can be done as so:
|
|
30
|
+
|
|
31
|
+
```
|
|
32
|
+
require 'githubstats'
|
|
33
|
+
stats = GithubStats.new('akerl')
|
|
34
|
+
puts stats.data.today # Prints today's current score
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
The username is taken from the argument passed to .new(). If no username is provided, it will try to use Rugged (https://github.com/libgit2/rugged) to load the Github username from your git configuration. If Rugged isn't installed or no Github username is set, it falls back to the current session's user, pulled via ENV.
|
|
38
|
+
|
|
39
|
+
```
|
|
40
|
+
# whoami
|
|
41
|
+
akerl
|
|
42
|
+
|
|
43
|
+
# head -2 .gitconfig
|
|
44
|
+
[github]
|
|
45
|
+
user = fly
|
|
46
|
+
|
|
47
|
+
# gem list | grep rugged
|
|
48
|
+
rugged (0.19.0)
|
|
49
|
+
|
|
50
|
+
# githubstats mikegrb
|
|
51
|
+
Contribution data for mikegrb:
|
|
52
|
+
Today's score: 0
|
|
53
|
+
Current streak: 0
|
|
54
|
+
Longest streak: 80
|
|
55
|
+
High score: 23 on 2013-09-08
|
|
56
|
+
Quartile boundaries: [0, 2, 5, 8, 23]
|
|
57
|
+
▁▁▂▂▂▁▁▁▁▃▁▁▄▁▁▁▄▂▁▂▄▁▁▂▄▃▂▁▁▁▁▁▄▃▁▁▁▁█▄▃▂▄▁▁▁▁▃▁▂▁▁▁▁▁▅▂▁▁▁
|
|
58
|
+
|
|
59
|
+
# githubstats
|
|
60
|
+
Contribution data for fly:
|
|
61
|
+
Today's score: 0
|
|
62
|
+
Current streak: 0
|
|
63
|
+
Longest streak: 37
|
|
64
|
+
High score: 28 on 2013-04-16
|
|
65
|
+
Quartile boundaries: [0, 3, 8, 12, 28]
|
|
66
|
+
▁▁▁▁▂▁▁▁▁▁▁▁▁▁▁▁▄▁▁▃▂▁▆▄▁▁▂▄▃▃▁▁▁▁▁▁▆▂▆▄▄▄▁▁▂█▁▄▆▂▁▄▄▄█▄▁▄▂▁
|
|
67
|
+
|
|
68
|
+
# gem uninstall rugged
|
|
69
|
+
Successfully uninstalled rugged-0.19.0
|
|
70
|
+
|
|
71
|
+
# githubstats
|
|
72
|
+
Contribution data for akerl:
|
|
73
|
+
Today's score: 9
|
|
74
|
+
Current streak: 32
|
|
75
|
+
Longest streak: 32
|
|
76
|
+
High score: 50 on 2013-07-14
|
|
77
|
+
Quartile boundaries: [0, 3, 8, 12, 50]
|
|
78
|
+
▁▁▁▆▁▂▁▁▅▄▁▃▂▁▁▃▁▁▁▁▄▁▂▃█▇▃▁▃▃▂▁▃▂▁▁▁▁▁▁▂▁▁▁▁▂▂▁▃▁▂▁▆▃▂▂▁▁▁▅
|
|
79
|
+
|
|
80
|
+
#
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
## Installation
|
|
84
|
+
|
|
85
|
+
gem install githubstats
|
|
86
|
+
|
|
87
|
+
## Contributors
|
|
88
|
+
|
|
89
|
+
* [Lee Matos](https://github.com/leematos) for help deconstructing Github's fancy Javascript math
|
|
90
|
+
* [Jon Chen](https://github.com/fly) for providing encouragement while borrowing my code
|
|
91
|
+
|
|
92
|
+
## License
|
|
93
|
+
GithubStats is released under the MIT License. See the bundled LICENSE file for details.
|
|
94
|
+
|
data/Rakefile
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
require 'bundler/gem_tasks'
|
|
2
|
+
require 'rspec/core/rake_task'
|
|
3
|
+
require 'rubocop/rake_task'
|
|
4
|
+
|
|
5
|
+
desc 'Run tests'
|
|
6
|
+
RSpec::Core::RakeTask.new(:spec)
|
|
7
|
+
|
|
8
|
+
desc 'Run Rubocop on the gem'
|
|
9
|
+
Rubocop::RakeTask.new(:rubocop) do |task|
|
|
10
|
+
task.patterns = ['lib/**/*.rb', 'spec/**/*.rb']
|
|
11
|
+
task.fail_on_error = true
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
desc 'Run travis-lint on .travis.yml'
|
|
15
|
+
task :travislint do
|
|
16
|
+
fail 'There is an issue with your .travis.yml' unless system('travis-lint')
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
task default: [:spec, :travislint, :rubocop, :build, :install]
|
data/bin/githubstats
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
|
|
3
|
+
require 'githubstats'
|
|
4
|
+
|
|
5
|
+
contrib = GithubStats.new ARGV.first
|
|
6
|
+
|
|
7
|
+
puts "Contribution data for #{contrib.user}:
|
|
8
|
+
Today's score: #{contrib.today}
|
|
9
|
+
Current streak: #{contrib.streak.length}
|
|
10
|
+
Longest streak: #{contrib.longest_streak.length}
|
|
11
|
+
High score: #{contrib.max.score} on #{contrib.max.date}
|
|
12
|
+
Quartile boundaries: #{contrib.quartile_boundaries(github = false).inspect}
|
|
13
|
+
Github-adjusted boundaries: #{contrib.quartile_boundaries(github = true).inspect}"
|
|
14
|
+
|
|
15
|
+
# Uses https://github.com/holman/spark
|
|
16
|
+
system('spark', *contrib.data.pop(60).map { |point| point.score.to_s })
|
|
17
|
+
|
data/githubstats.gemspec
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
Gem::Specification.new do |s|
|
|
2
|
+
s.name = 'githubstats'
|
|
3
|
+
s.version = '0.1.7'
|
|
4
|
+
s.date = Time.now.strftime("%Y-%m-%d")
|
|
5
|
+
|
|
6
|
+
s.summary = 'Present Github contributions stats in a consumable format'
|
|
7
|
+
s.description = "Pulls the statistics from Github's user contribution chart and provides an interface for analyzing that data"
|
|
8
|
+
s.authors = ['Les Aker']
|
|
9
|
+
s.email = 'me@lesaker.org'
|
|
10
|
+
s.homepage = 'https://github.com/akerl/githubstats'
|
|
11
|
+
s.license = 'MIT'
|
|
12
|
+
|
|
13
|
+
s.files = `git ls-files`.split
|
|
14
|
+
s.test_files = `git ls-files spec/*`.split
|
|
15
|
+
s.executables = ['githubstats']
|
|
16
|
+
|
|
17
|
+
s.add_runtime_dependency 'curb'
|
|
18
|
+
s.add_runtime_dependency 'json'
|
|
19
|
+
|
|
20
|
+
s.add_development_dependency 'rubocop'
|
|
21
|
+
s.add_development_dependency 'travis-lint'
|
|
22
|
+
s.add_development_dependency 'rake'
|
|
23
|
+
s.add_development_dependency 'coveralls'
|
|
24
|
+
s.add_development_dependency 'rspec'
|
|
25
|
+
s.add_development_dependency 'fuubar'
|
|
26
|
+
s.add_development_dependency 'parser', '~> 2.1.0.pre1'
|
|
27
|
+
end
|
|
28
|
+
|
data/lib/githubstats.rb
ADDED
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
require 'curb'
|
|
2
|
+
require 'json'
|
|
3
|
+
require 'date'
|
|
4
|
+
require 'version'
|
|
5
|
+
|
|
6
|
+
##
|
|
7
|
+
# Rugged is used to check git's configuration for a github user, if available
|
|
8
|
+
|
|
9
|
+
begin
|
|
10
|
+
require 'rugged'
|
|
11
|
+
USING_RUGGED = true
|
|
12
|
+
rescue LoadError
|
|
13
|
+
USING_RUGGED = false
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
##
|
|
17
|
+
# Basic_Cache is used to cache computation results, if available
|
|
18
|
+
|
|
19
|
+
begin
|
|
20
|
+
require 'basic_cache'
|
|
21
|
+
USING_CACHE = true
|
|
22
|
+
rescue LoadError
|
|
23
|
+
USING_CACHE = false
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
##
|
|
27
|
+
# This module provides a consumable object based on Github's contribution stats
|
|
28
|
+
|
|
29
|
+
module GithubStats
|
|
30
|
+
class << self
|
|
31
|
+
##
|
|
32
|
+
# Add .new() helper for creating a new Contributions object
|
|
33
|
+
|
|
34
|
+
def new(*args)
|
|
35
|
+
self::Contributions.new(*args)
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
##
|
|
40
|
+
# Datapoint objects provide a more sane date/time point interface
|
|
41
|
+
|
|
42
|
+
Datapoint = Struct.new(:date, :score)
|
|
43
|
+
|
|
44
|
+
##
|
|
45
|
+
# Contributions object holds and provides stats data for a user
|
|
46
|
+
|
|
47
|
+
class Contributions
|
|
48
|
+
attr_reader :user, :data, :last_updated
|
|
49
|
+
attr_accessor :url
|
|
50
|
+
|
|
51
|
+
GH_MAGIC = 3.77972616981
|
|
52
|
+
|
|
53
|
+
##
|
|
54
|
+
# Create a new object
|
|
55
|
+
# Guesses the user if one is not supplied
|
|
56
|
+
# Automatically updates if not disabled
|
|
57
|
+
# Creates a new cache object
|
|
58
|
+
|
|
59
|
+
def initialize(params = {})
|
|
60
|
+
@user = params[:user] || guess_user
|
|
61
|
+
@url = "https://github.com/users/#{@user}/contributions_calendar_data"
|
|
62
|
+
@data = []
|
|
63
|
+
@last_updated = nil
|
|
64
|
+
@cache = USING_CACHE ? BasicCache.new : GithubStats::NullCache.new
|
|
65
|
+
update unless params[:skip_load]
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
##
|
|
69
|
+
# Print human-readable string about object
|
|
70
|
+
|
|
71
|
+
def to_s
|
|
72
|
+
"Contributions from #{@user}"
|
|
73
|
+
end
|
|
74
|
+
alias_method :to_s, :inspect
|
|
75
|
+
|
|
76
|
+
##
|
|
77
|
+
# Return raw data directly
|
|
78
|
+
|
|
79
|
+
def to_a
|
|
80
|
+
@data
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
##
|
|
84
|
+
# Return Hash where keys are dates and values are scores
|
|
85
|
+
|
|
86
|
+
def to_h
|
|
87
|
+
@data.reduce(Hash.new(0)) { |a, e| a.merge('e.date' => e.score) }
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
##
|
|
91
|
+
# Try to guess username
|
|
92
|
+
# Checks Rugged if available, then ENV['USER']
|
|
93
|
+
|
|
94
|
+
def guess_user
|
|
95
|
+
names = []
|
|
96
|
+
names << Rugged::Config.global['github.user'] if USING_RUGGED
|
|
97
|
+
names << ENV['USER']
|
|
98
|
+
names.reject! { |name| name.nil? }
|
|
99
|
+
names.length ? names.first : (fail 'Failed to guess username')
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
##
|
|
103
|
+
# Download new data
|
|
104
|
+
|
|
105
|
+
def download
|
|
106
|
+
JSON.parse Curl::Easy.perform(@url).body_str
|
|
107
|
+
rescue
|
|
108
|
+
raise 'Unable to load data from Github'
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
##
|
|
112
|
+
# Parse the Github data into a pretty objects
|
|
113
|
+
|
|
114
|
+
def parse(raw_data)
|
|
115
|
+
raw_data.map { |d, s| Datapoint.new(Date.parse(d), s.to_i) }
|
|
116
|
+
rescue
|
|
117
|
+
raise 'Failed to parse data'
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
##
|
|
121
|
+
# Update the data based on Github
|
|
122
|
+
|
|
123
|
+
def update
|
|
124
|
+
@data = parse download
|
|
125
|
+
@last_updated = DateTime.now
|
|
126
|
+
@cache.clear
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
##
|
|
130
|
+
# Return today's score
|
|
131
|
+
|
|
132
|
+
def today
|
|
133
|
+
@cache.cache { to_h[Date.today] }
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
##
|
|
137
|
+
# Return the current streak
|
|
138
|
+
|
|
139
|
+
def streak
|
|
140
|
+
@cache.cache do
|
|
141
|
+
streak = @data.reverse.drop(1).take_while { |point| point.score > 0 }
|
|
142
|
+
streak.reverse!
|
|
143
|
+
streak << @data.last unless @data.last.score.zero?
|
|
144
|
+
streak
|
|
145
|
+
end
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
##
|
|
149
|
+
# Return the longest streak
|
|
150
|
+
|
|
151
|
+
def longest_streak
|
|
152
|
+
@cache.cache do
|
|
153
|
+
all_streaks = @data.reduce(Array.new(1, [])) do |streaks, point|
|
|
154
|
+
point.score == 0 ? streaks << [] : streaks.last << point
|
|
155
|
+
streaks
|
|
156
|
+
end
|
|
157
|
+
all_streaks.max { |a, b| a.length <=> b.length }
|
|
158
|
+
end
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
##
|
|
162
|
+
# Return the highest score in the dataset
|
|
163
|
+
|
|
164
|
+
def max
|
|
165
|
+
@cache.cache { @data.max { |a, b| a.score <=> b.score } }
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
##
|
|
169
|
+
# Return the mean score in the dataset
|
|
170
|
+
|
|
171
|
+
def mean
|
|
172
|
+
@cache.cache do
|
|
173
|
+
@data.reduce(0) { |a, e| e.score.to_f + a } / @data.size
|
|
174
|
+
end
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
##
|
|
178
|
+
# Return the break-points between the quartiles
|
|
179
|
+
|
|
180
|
+
def quartile_boundaries
|
|
181
|
+
@cache.cache do
|
|
182
|
+
variance = gh_quartile_magic
|
|
183
|
+
data = @data.select { |x| (mean - x.score).abs / variance <= GH_MAGIC }
|
|
184
|
+
range = data.map { |p| p.score }.uniq.sort.select { |s| !s.zero? }
|
|
185
|
+
bounds = (1..3).map { |q| range[(q * range.length / 4) - 2] }
|
|
186
|
+
bounds.unshift(0).push(max.score)
|
|
187
|
+
end
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
##
|
|
191
|
+
# Return the quartiles
|
|
192
|
+
|
|
193
|
+
def quartiles
|
|
194
|
+
@cache.cache do
|
|
195
|
+
bounds = quartile_boundaries
|
|
196
|
+
@data.reduce(Array.new(5) { Array.new }) do |acc, point|
|
|
197
|
+
acc[bounds.find_index { |i| point.score <= i }] << point
|
|
198
|
+
acc
|
|
199
|
+
end
|
|
200
|
+
end
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
##
|
|
204
|
+
# Return which quartile a score is in
|
|
205
|
+
|
|
206
|
+
def quartile
|
|
207
|
+
bounds = quartile_boundaries
|
|
208
|
+
return nil if score > bounds.last || score < 0
|
|
209
|
+
bounds.count { |bound| score > bound }
|
|
210
|
+
end
|
|
211
|
+
|
|
212
|
+
##
|
|
213
|
+
# Return Github's magic value (Used for calculating quartiles)
|
|
214
|
+
|
|
215
|
+
def gh_quartile_magic
|
|
216
|
+
@cache.cache do
|
|
217
|
+
magic = @data.reduce(0) { |a, e| (e.score.to_f - mean)**2 + a }
|
|
218
|
+
Math.sqrt(magic / (@data.size - 1))
|
|
219
|
+
end
|
|
220
|
+
end
|
|
221
|
+
end
|
|
222
|
+
|
|
223
|
+
##
|
|
224
|
+
# The Null_Cache is used if Basic_Cache is not available
|
|
225
|
+
# As per the name, it does not cache anything
|
|
226
|
+
|
|
227
|
+
class NullCache
|
|
228
|
+
##
|
|
229
|
+
# Clear is a no-op, since there is no cache
|
|
230
|
+
|
|
231
|
+
def clear
|
|
232
|
+
end
|
|
233
|
+
|
|
234
|
+
##
|
|
235
|
+
# Call the provided block and return its value
|
|
236
|
+
|
|
237
|
+
def cache(key = nil, &code)
|
|
238
|
+
code.call
|
|
239
|
+
end
|
|
240
|
+
end
|
|
241
|
+
end
|
data/spec/spec_helper.rb
ADDED
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
metadata
ADDED
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: githubstats
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.7
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Les Aker
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: bin
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2013-11-24 00:00:00.000000000 Z
|
|
12
|
+
dependencies:
|
|
13
|
+
- !ruby/object:Gem::Dependency
|
|
14
|
+
name: curb
|
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
|
16
|
+
requirements:
|
|
17
|
+
- - ">="
|
|
18
|
+
- !ruby/object:Gem::Version
|
|
19
|
+
version: '0'
|
|
20
|
+
type: :runtime
|
|
21
|
+
prerelease: false
|
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
23
|
+
requirements:
|
|
24
|
+
- - ">="
|
|
25
|
+
- !ruby/object:Gem::Version
|
|
26
|
+
version: '0'
|
|
27
|
+
- !ruby/object:Gem::Dependency
|
|
28
|
+
name: json
|
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
|
30
|
+
requirements:
|
|
31
|
+
- - ">="
|
|
32
|
+
- !ruby/object:Gem::Version
|
|
33
|
+
version: '0'
|
|
34
|
+
type: :runtime
|
|
35
|
+
prerelease: false
|
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
37
|
+
requirements:
|
|
38
|
+
- - ">="
|
|
39
|
+
- !ruby/object:Gem::Version
|
|
40
|
+
version: '0'
|
|
41
|
+
- !ruby/object:Gem::Dependency
|
|
42
|
+
name: rubocop
|
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
|
44
|
+
requirements:
|
|
45
|
+
- - ">="
|
|
46
|
+
- !ruby/object:Gem::Version
|
|
47
|
+
version: '0'
|
|
48
|
+
type: :development
|
|
49
|
+
prerelease: false
|
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
51
|
+
requirements:
|
|
52
|
+
- - ">="
|
|
53
|
+
- !ruby/object:Gem::Version
|
|
54
|
+
version: '0'
|
|
55
|
+
- !ruby/object:Gem::Dependency
|
|
56
|
+
name: travis-lint
|
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
|
58
|
+
requirements:
|
|
59
|
+
- - ">="
|
|
60
|
+
- !ruby/object:Gem::Version
|
|
61
|
+
version: '0'
|
|
62
|
+
type: :development
|
|
63
|
+
prerelease: false
|
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
65
|
+
requirements:
|
|
66
|
+
- - ">="
|
|
67
|
+
- !ruby/object:Gem::Version
|
|
68
|
+
version: '0'
|
|
69
|
+
- !ruby/object:Gem::Dependency
|
|
70
|
+
name: rake
|
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
|
72
|
+
requirements:
|
|
73
|
+
- - ">="
|
|
74
|
+
- !ruby/object:Gem::Version
|
|
75
|
+
version: '0'
|
|
76
|
+
type: :development
|
|
77
|
+
prerelease: false
|
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
79
|
+
requirements:
|
|
80
|
+
- - ">="
|
|
81
|
+
- !ruby/object:Gem::Version
|
|
82
|
+
version: '0'
|
|
83
|
+
- !ruby/object:Gem::Dependency
|
|
84
|
+
name: coveralls
|
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
|
86
|
+
requirements:
|
|
87
|
+
- - ">="
|
|
88
|
+
- !ruby/object:Gem::Version
|
|
89
|
+
version: '0'
|
|
90
|
+
type: :development
|
|
91
|
+
prerelease: false
|
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
93
|
+
requirements:
|
|
94
|
+
- - ">="
|
|
95
|
+
- !ruby/object:Gem::Version
|
|
96
|
+
version: '0'
|
|
97
|
+
- !ruby/object:Gem::Dependency
|
|
98
|
+
name: rspec
|
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
|
100
|
+
requirements:
|
|
101
|
+
- - ">="
|
|
102
|
+
- !ruby/object:Gem::Version
|
|
103
|
+
version: '0'
|
|
104
|
+
type: :development
|
|
105
|
+
prerelease: false
|
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
107
|
+
requirements:
|
|
108
|
+
- - ">="
|
|
109
|
+
- !ruby/object:Gem::Version
|
|
110
|
+
version: '0'
|
|
111
|
+
- !ruby/object:Gem::Dependency
|
|
112
|
+
name: fuubar
|
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
|
114
|
+
requirements:
|
|
115
|
+
- - ">="
|
|
116
|
+
- !ruby/object:Gem::Version
|
|
117
|
+
version: '0'
|
|
118
|
+
type: :development
|
|
119
|
+
prerelease: false
|
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
121
|
+
requirements:
|
|
122
|
+
- - ">="
|
|
123
|
+
- !ruby/object:Gem::Version
|
|
124
|
+
version: '0'
|
|
125
|
+
- !ruby/object:Gem::Dependency
|
|
126
|
+
name: parser
|
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
|
128
|
+
requirements:
|
|
129
|
+
- - "~>"
|
|
130
|
+
- !ruby/object:Gem::Version
|
|
131
|
+
version: 2.1.0.pre1
|
|
132
|
+
type: :development
|
|
133
|
+
prerelease: false
|
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
135
|
+
requirements:
|
|
136
|
+
- - "~>"
|
|
137
|
+
- !ruby/object:Gem::Version
|
|
138
|
+
version: 2.1.0.pre1
|
|
139
|
+
description: Pulls the statistics from Github's user contribution chart and provides
|
|
140
|
+
an interface for analyzing that data
|
|
141
|
+
email: me@lesaker.org
|
|
142
|
+
executables:
|
|
143
|
+
- githubstats
|
|
144
|
+
extensions: []
|
|
145
|
+
extra_rdoc_files: []
|
|
146
|
+
files:
|
|
147
|
+
- ".gitignore"
|
|
148
|
+
- ".rspec"
|
|
149
|
+
- ".rubocop.yml"
|
|
150
|
+
- ".travis.yml"
|
|
151
|
+
- Gemfile
|
|
152
|
+
- Gemfile.lock
|
|
153
|
+
- LICENSE
|
|
154
|
+
- README.md
|
|
155
|
+
- Rakefile
|
|
156
|
+
- bin/githubstats
|
|
157
|
+
- githubstats.gemspec
|
|
158
|
+
- lib/githubstats.rb
|
|
159
|
+
- spec/spec_helper.rb
|
|
160
|
+
- vendor/cache/ast-1.1.0.gem
|
|
161
|
+
- vendor/cache/coveralls-0.7.0.gem
|
|
162
|
+
- vendor/cache/curb-0.8.5.gem
|
|
163
|
+
- vendor/cache/diff-lcs-1.2.5.gem
|
|
164
|
+
- vendor/cache/docile-1.1.0.gem
|
|
165
|
+
- vendor/cache/fuubar-1.2.1.gem
|
|
166
|
+
- vendor/cache/hashr-0.0.22.gem
|
|
167
|
+
- vendor/cache/json-1.8.1.gem
|
|
168
|
+
- vendor/cache/mime-types-2.0.gem
|
|
169
|
+
- vendor/cache/multi_json-1.8.2.gem
|
|
170
|
+
- vendor/cache/parser-2.1.0.pre1.gem
|
|
171
|
+
- vendor/cache/powerpack-0.0.9.gem
|
|
172
|
+
- vendor/cache/rainbow-1.1.4.gem
|
|
173
|
+
- vendor/cache/rake-10.1.0.gem
|
|
174
|
+
- vendor/cache/rest-client-1.6.7.gem
|
|
175
|
+
- vendor/cache/rspec-2.14.1.gem
|
|
176
|
+
- vendor/cache/rspec-core-2.14.7.gem
|
|
177
|
+
- vendor/cache/rspec-expectations-2.14.4.gem
|
|
178
|
+
- vendor/cache/rspec-instafail-0.2.4.gem
|
|
179
|
+
- vendor/cache/rspec-mocks-2.14.4.gem
|
|
180
|
+
- vendor/cache/rubocop-0.15.0.gem
|
|
181
|
+
- vendor/cache/ruby-progressbar-1.2.0.gem
|
|
182
|
+
- vendor/cache/simplecov-0.8.2.gem
|
|
183
|
+
- vendor/cache/simplecov-html-0.8.0.gem
|
|
184
|
+
- vendor/cache/slop-3.4.7.gem
|
|
185
|
+
- vendor/cache/term-ansicolor-1.2.2.gem
|
|
186
|
+
- vendor/cache/thor-0.18.1.gem
|
|
187
|
+
- vendor/cache/tins-0.13.1.gem
|
|
188
|
+
- vendor/cache/travis-lint-1.7.0.gem
|
|
189
|
+
homepage: https://github.com/akerl/githubstats
|
|
190
|
+
licenses:
|
|
191
|
+
- MIT
|
|
192
|
+
metadata: {}
|
|
193
|
+
post_install_message:
|
|
194
|
+
rdoc_options: []
|
|
195
|
+
require_paths:
|
|
196
|
+
- lib
|
|
197
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
198
|
+
requirements:
|
|
199
|
+
- - ">="
|
|
200
|
+
- !ruby/object:Gem::Version
|
|
201
|
+
version: '0'
|
|
202
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
203
|
+
requirements:
|
|
204
|
+
- - ">="
|
|
205
|
+
- !ruby/object:Gem::Version
|
|
206
|
+
version: '0'
|
|
207
|
+
requirements: []
|
|
208
|
+
rubyforge_project:
|
|
209
|
+
rubygems_version: 2.0.3
|
|
210
|
+
signing_key:
|
|
211
|
+
specification_version: 4
|
|
212
|
+
summary: Present Github contributions stats in a consumable format
|
|
213
|
+
test_files:
|
|
214
|
+
- spec/spec_helper.rb
|