firebase-stats 0.1.0 → 1.0.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/bin/firebase-stats +56 -15
- data/lib/device_utils.rb +24 -0
- data/lib/firebase-stats.rb +2 -0
- data/lib/reader.rb +2 -2
- data/lib/version.rb +5 -0
- data/lib/wrapper.rb +110 -71
- metadata +67 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4c0052a1fd763bfd20e4561f5381098bc8436252f25ca478a51f152d9c9edc1f
|
4
|
+
data.tar.gz: 5057c8cf57c562d489d60ecf7d35fa4172ad025937da9b7fd3ddd72b09e8b86c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2e36f05b2e942c81ebd86db0ddaff06aecca5e8167bf233591a32df06489b31b52985d6636d00dfcedd2c82ff914430c03d220297f3d93456b658c012b8240be
|
7
|
+
data.tar.gz: f74f39bd93fcfc0fc0c93ed6f11d9485d1635cbcbb64c0ca046cd91eb5f0828f8acaa9c3e3c2640cec4c62f00ef4cadf4f92dbe5e9b1dbe5d9c7ea07b5bba498
|
data/bin/firebase-stats
CHANGED
@@ -6,11 +6,11 @@ require 'commander/import'
|
|
6
6
|
require 'firebase-stats'
|
7
7
|
require 'table_print'
|
8
8
|
|
9
|
-
program :name, '
|
10
|
-
program :version,
|
11
|
-
program :description, 'CLI to
|
9
|
+
program :name, 'firebase-stats'
|
10
|
+
program :version, FirebaseStats::VERSION
|
11
|
+
program :description, 'A CLI tool to get different stats out of the huge Firebase Analytics CSV'
|
12
|
+
program :help_formatter, Commander::HelpFormatter::TerminalCompact
|
12
13
|
|
13
|
-
global_option('--platform STRING', String, 'Show only stats for this OS. Either ios, android or all (default)')
|
14
14
|
|
15
15
|
def map_platform(options)
|
16
16
|
raw_platform = options.platform ||= 'all'
|
@@ -21,10 +21,12 @@ def map_platform(options)
|
|
21
21
|
end
|
22
22
|
|
23
23
|
command :devices do |c|
|
24
|
-
c.syntax = '
|
24
|
+
c.syntax = 'devices <path to csv> [options]'
|
25
25
|
c.summary = 'Prints out device stats'
|
26
|
-
c.description = ''
|
27
|
-
c.option '--friendly', '
|
26
|
+
c.description = 'Prints out a table with all of the devices, optionally filtered by OS'
|
27
|
+
c.option '--friendly', 'Prints out Android device models with their human readable name (this is slow)'
|
28
|
+
c.option '--limit NUMBER', Integer, 'Limits number of devices output'
|
29
|
+
c.option '--platform STRING', String, 'Show only stats for this OS. Either ios, android or all (default)'
|
28
30
|
|
29
31
|
c.action do |args, options|
|
30
32
|
stats = FirebaseStats::Reader.new
|
@@ -32,16 +34,18 @@ command :devices do |c|
|
|
32
34
|
|
33
35
|
platform = map_platform(options)
|
34
36
|
|
35
|
-
wrapper = FirebaseStats::Wrapper.new(stats
|
36
|
-
tp wrapper.devices(friendly: options.friendly)
|
37
|
+
wrapper = FirebaseStats::Wrapper.new(stats)
|
38
|
+
tp wrapper.devices(friendly: options.friendly, limit: options.limit, platform: platform)
|
37
39
|
end
|
38
40
|
end
|
39
41
|
|
40
42
|
command :os do |c|
|
41
|
-
c.syntax = '
|
42
|
-
c.summary = 'Prints out
|
43
|
-
c.description = ''
|
44
|
-
c.option '--grouped', 'Groups OS versions together'
|
43
|
+
c.syntax = 'os <path to csv> [options]'
|
44
|
+
c.summary = 'Prints out OS stats'
|
45
|
+
c.description = 'Prints out the number of devices per OS version, optionally filtered by OS and grouped by major version'
|
46
|
+
c.option '--grouped', 'Groups minor OS versions together'
|
47
|
+
c.option '--version-sorted', 'Sorts by OS version instead of percentage'
|
48
|
+
c.option '--platform STRING', String, 'Show only stats for this OS. Either ios, android or all (default)'
|
45
49
|
|
46
50
|
c.action do |args, options|
|
47
51
|
stats = FirebaseStats::Reader.new
|
@@ -49,8 +53,45 @@ command :os do |c|
|
|
49
53
|
|
50
54
|
platform = map_platform(options)
|
51
55
|
|
52
|
-
wrapper = FirebaseStats::Wrapper.new(stats
|
56
|
+
wrapper = FirebaseStats::Wrapper.new(stats)
|
53
57
|
|
54
|
-
|
58
|
+
grouped = options.grouped || false
|
59
|
+
major_order = options.version_sorted || false
|
60
|
+
|
61
|
+
data = wrapper.os(platform: platform, grouped: grouped, major_order: major_order)
|
62
|
+
|
63
|
+
tp data
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
command :gender do |c|
|
68
|
+
c.syntax = 'gender'
|
69
|
+
c.summary = 'Prints out gender stats (if available)'
|
70
|
+
c.description = 'Prints out a table with number of users of each gender'
|
71
|
+
|
72
|
+
c.action do |args, options|
|
73
|
+
stats = FirebaseStats::Reader.new
|
74
|
+
stats.parse_file(args[0])
|
75
|
+
|
76
|
+
platform = map_platform(options)
|
77
|
+
|
78
|
+
wrapper = FirebaseStats::Wrapper.new(stats)
|
79
|
+
tp wrapper.gender
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
command :gender_age do |c|
|
84
|
+
c.syntax = 'gender_age'
|
85
|
+
c.summary = 'Prints out age group stats (if available)'
|
86
|
+
c.description = 'Prints out a table with percentage of users of each gender grouped by age'
|
87
|
+
|
88
|
+
c.action do |args, options|
|
89
|
+
stats = FirebaseStats::Reader.new
|
90
|
+
stats.parse_file(args[0])
|
91
|
+
|
92
|
+
platform = map_platform(options)
|
93
|
+
|
94
|
+
wrapper = FirebaseStats::Wrapper.new(stats)
|
95
|
+
tp wrapper.gender_age
|
55
96
|
end
|
56
97
|
end
|
data/lib/device_utils.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
module FirebaseStats
|
2
|
+
# Parses the Firebase CSV file into sections
|
3
|
+
class DeviceUtils
|
4
|
+
# Is this device name an iOS device?
|
5
|
+
# @param [CSV::Row] device_name
|
6
|
+
def self.ios_device?(device_name)
|
7
|
+
device_name.downcase.include?('iphone') or device_name.downcase.include?('ipad') or device_name.downcase.include?('ipod')
|
8
|
+
end
|
9
|
+
|
10
|
+
# Filters a device list to only the requested platform
|
11
|
+
# @param [CSV::Table] device_data
|
12
|
+
# @param [Symbol] platform One of :all, :ios, :android
|
13
|
+
def self.filter_device(device_data, platform)
|
14
|
+
case platform
|
15
|
+
when :android
|
16
|
+
device_data.reject { |row| ios_device? row['Device model'] }
|
17
|
+
when :ios
|
18
|
+
device_data.select { |row| ios_device? row['Device model'] }
|
19
|
+
else
|
20
|
+
device_data
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
data/lib/firebase-stats.rb
CHANGED
data/lib/reader.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
3
|
+
module FirebaseStats
|
4
4
|
require 'csv'
|
5
5
|
|
6
6
|
# Parses the Firebase CSV file into sections
|
@@ -22,7 +22,7 @@ class FirebaseStats
|
|
22
22
|
def parse(input)
|
23
23
|
curr_lines = []
|
24
24
|
input.each_with_index do |line, idx|
|
25
|
-
curr_lines.
|
25
|
+
curr_lines.push(line) unless comment?(line) || line.strip.empty?
|
26
26
|
|
27
27
|
if (idx == input.length - 1) || line.strip.empty?
|
28
28
|
process_lines curr_lines unless curr_lines.empty?
|
data/lib/version.rb
ADDED
data/lib/wrapper.rb
CHANGED
@@ -1,76 +1,85 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
3
|
+
module FirebaseStats
|
4
4
|
require 'csv'
|
5
|
-
|
5
|
+
require 'android/devices'
|
6
|
+
require 'open-uri'
|
6
7
|
|
7
8
|
# Transforms the parsed Firebase file into something more user friendly
|
8
9
|
class Wrapper
|
9
10
|
# @param [FirebaseStats::Reader] stats
|
10
|
-
|
11
|
-
def initialize(stats, platform = :all)
|
11
|
+
def initialize(stats)
|
12
12
|
super()
|
13
13
|
@stats = stats
|
14
|
-
@platform = platform
|
15
14
|
end
|
16
15
|
|
17
|
-
|
18
|
-
|
16
|
+
# Get all OS versions, grouped by Major version
|
17
|
+
# @param [Symbol] platform One of :all, :ios, :android
|
18
|
+
# @param [Boolean] grouped Group by Major OS version
|
19
|
+
# @param [Boolean] major_order Order by Major OS version (instead of percentage)
|
20
|
+
def os(platform: :all, grouped: true, major_order: true)
|
21
|
+
os_data = all_os
|
22
|
+
filtered = filter_os(os_data, platform)
|
23
|
+
|
24
|
+
data = if grouped
|
25
|
+
make_group_stats(filtered, platform)
|
26
|
+
else
|
27
|
+
filtered
|
28
|
+
end
|
19
29
|
|
30
|
+
major_order ? major_version_sort(data) : data
|
31
|
+
end
|
32
|
+
|
33
|
+
# Gets all devices
|
34
|
+
# @param [Boolean] friendly Transform the Android model numbers into their human numaes
|
35
|
+
# @param [Integer] limit Number of devices to turn
|
36
|
+
# @param [Symbol] platform One of :all, :ios, :android
|
37
|
+
def devices(friendly: false, limit: 10, platform: :all)
|
38
|
+
filtered = DeviceUtils.filter_device(@stats.data[:devices], platform)
|
39
|
+
filtered = filtered.take(limit || 10)
|
20
40
|
cleaned = []
|
21
41
|
filtered.each do |row|
|
22
|
-
|
23
|
-
'
|
24
|
-
'count' => row['Users'].to_i,
|
25
|
-
'percentage' => as_percentage(os_total, row['Users'].to_f)
|
42
|
+
device = {
|
43
|
+
'model' => row['Device model']
|
26
44
|
}
|
27
|
-
|
28
|
-
|
29
|
-
|
45
|
+
if friendly && ((platform == :all) || (platform == :android))
|
46
|
+
mapped = Android::Devices.search_by_model(row['Device model'])
|
47
|
+
device['friendly'] = if mapped.nil?
|
48
|
+
row['Device model']
|
49
|
+
else
|
50
|
+
mapped.name
|
51
|
+
end
|
52
|
+
end
|
53
|
+
device['count'] = row['Users'].to_i
|
30
54
|
|
31
|
-
|
32
|
-
raw_os = @stats.data[:os_version]
|
33
|
-
|
34
|
-
grouped = case @platform
|
35
|
-
when :ios
|
36
|
-
ios_os_group(raw_os)
|
37
|
-
when :android
|
38
|
-
android_os_group(raw_os)
|
39
|
-
else
|
40
|
-
android_os_group(raw_os).merge ios_os_group(raw_os)
|
41
|
-
end
|
42
|
-
computed = []
|
43
|
-
grouped.each do |k, v|
|
44
|
-
version_name = k
|
45
|
-
total = v.map { |version| version['Users'].to_i }.reduce(0, :+)
|
46
|
-
computed << { 'version' => version_name, 'total' => total, 'percentage' => as_percentage(os_total, total.to_f) }
|
55
|
+
cleaned << device
|
47
56
|
end
|
48
|
-
|
57
|
+
cleaned
|
49
58
|
end
|
50
59
|
|
51
|
-
def
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
60
|
+
def gender
|
61
|
+
raw = @stats.data[:gender]
|
62
|
+
data = []
|
63
|
+
raw.each do |row|
|
64
|
+
data << {
|
65
|
+
'gender' => row['Gender'],
|
66
|
+
'count' => row['Users']
|
67
|
+
}
|
56
68
|
end
|
57
|
-
|
69
|
+
data
|
58
70
|
end
|
59
71
|
|
60
|
-
def
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
'
|
66
|
-
'
|
72
|
+
def gender_age
|
73
|
+
raw = @stats.data[:gender_age]
|
74
|
+
data = []
|
75
|
+
raw.each do |row|
|
76
|
+
data << {
|
77
|
+
'age' => row['Category'],
|
78
|
+
'male' => (row['Male'].to_f * 100).round(2),
|
79
|
+
'female' => (row['Female'].to_f * 100).round(2)
|
67
80
|
}
|
68
|
-
# if friendly && ((@platform == :all) || (@platform == :android))
|
69
|
-
# device['friendly'] = Android::Devices.search_by_model(row['Device Model']).name
|
70
|
-
# end
|
71
|
-
cleaned << device
|
72
81
|
end
|
73
|
-
|
82
|
+
data
|
74
83
|
end
|
75
84
|
|
76
85
|
private
|
@@ -80,32 +89,14 @@ class FirebaseStats
|
|
80
89
|
def filter_os(os_data, platform)
|
81
90
|
case platform
|
82
91
|
when :android
|
83
|
-
os_data.select { |row| row['
|
92
|
+
os_data.select { |row| row['version'].downcase.include?('android') }
|
84
93
|
when :ios
|
85
|
-
os_data.select { |row| row['
|
94
|
+
os_data.select { |row| row['version'].downcase.include?('ios') }
|
86
95
|
else
|
87
96
|
os_data
|
88
97
|
end
|
89
98
|
end
|
90
99
|
|
91
|
-
# @param [CSV::Table] device_data
|
92
|
-
# @param [Symbol] platform One of :all, :ios, :android
|
93
|
-
def filter_device(device_data, platform)
|
94
|
-
case platform
|
95
|
-
when :android
|
96
|
-
device_data.reject { |row| ios_device? row['Device model'] }
|
97
|
-
when :ios
|
98
|
-
device_data.select { |row| ios_device? row['Device model'] }
|
99
|
-
else
|
100
|
-
device_data
|
101
|
-
end
|
102
|
-
end
|
103
|
-
|
104
|
-
# @param [CSV::Row] device_name
|
105
|
-
def ios_device?(device_name)
|
106
|
-
device_name.downcase.include?('iphone') or device_name.downcase.include?('ipad')
|
107
|
-
end
|
108
|
-
|
109
100
|
def as_percentage(total, value)
|
110
101
|
percentage = (value / total) * 100
|
111
102
|
if percentage < 0.01
|
@@ -116,11 +107,59 @@ class FirebaseStats
|
|
116
107
|
end
|
117
108
|
|
118
109
|
def ios_os_group(os_details)
|
119
|
-
filter_os(os_details, :ios).group_by { |row| row['
|
110
|
+
filter_os(os_details, :ios).group_by { |row| row['version'].match('(iOS [0-9]{1,2})').captures[0] }
|
120
111
|
end
|
121
112
|
|
122
113
|
def android_os_group(os_details)
|
123
|
-
filter_os(os_details, :android).group_by { |row| row['
|
114
|
+
filter_os(os_details, :android).group_by { |row| row['version'].match('(Android [0-9]{1,2})').captures[0] }
|
115
|
+
end
|
116
|
+
|
117
|
+
# Get all OS versions
|
118
|
+
def all_os
|
119
|
+
data = @stats.data[:os_version]
|
120
|
+
|
121
|
+
data.map do |row|
|
122
|
+
{
|
123
|
+
'version' => row['OS with version'],
|
124
|
+
'count' => row['Users'].to_i
|
125
|
+
}
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
def make_group_stats(os_data, platform)
|
130
|
+
data = make_os_groups(os_data, platform)
|
131
|
+
|
132
|
+
total_devices = os_total(os_data)
|
133
|
+
data.map do |k, v|
|
134
|
+
version_name = k
|
135
|
+
group_total = v.map { |version| version['count'].to_i }.reduce(0, :+)
|
136
|
+
{ 'version' => version_name,
|
137
|
+
'total' => group_total,
|
138
|
+
'percentage' => as_percentage(total_devices.to_f, group_total) }
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
def make_os_groups(os_data, platform)
|
143
|
+
case platform
|
144
|
+
when :ios
|
145
|
+
ios_os_group(os_data)
|
146
|
+
when :android
|
147
|
+
android_os_group(os_data)
|
148
|
+
else
|
149
|
+
android_os_group(os_data).merge ios_os_group(os_data)
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
def os_total(os_data)
|
154
|
+
os_data.map { |row| row['count'] }.reduce(0, :+)
|
155
|
+
end
|
156
|
+
|
157
|
+
def major_version_sort(data)
|
158
|
+
data.sort_by do |row|
|
159
|
+
version = row['version']
|
160
|
+
number = version.match('([0-9.]+)').captures[0]
|
161
|
+
Gem::Version.new(number)
|
162
|
+
end.reverse
|
124
163
|
end
|
125
164
|
end
|
126
165
|
end
|
metadata
CHANGED
@@ -1,15 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: firebase-stats
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 1.0.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- chedabob
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-03-
|
11
|
+
date: 2021-03-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: android-devices
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.0'
|
13
27
|
- !ruby/object:Gem::Dependency
|
14
28
|
name: commander
|
15
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -38,7 +52,50 @@ dependencies:
|
|
38
52
|
- - "~>"
|
39
53
|
- !ruby/object:Gem::Version
|
40
54
|
version: '1.5'
|
41
|
-
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rake
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '13'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '13'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rspec
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '3.10'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '3.10'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: rubocop
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '1.10'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '1.10'
|
97
|
+
description: A CLI tool to get different stats out of the huge Firebase Analytics
|
98
|
+
CSV
|
42
99
|
email: matt.malone1@gmail.com
|
43
100
|
executables:
|
44
101
|
- firebase-stats
|
@@ -47,10 +104,12 @@ extra_rdoc_files: []
|
|
47
104
|
files:
|
48
105
|
- bin/firebase-stats
|
49
106
|
- lib/.DS_Store
|
107
|
+
- lib/device_utils.rb
|
50
108
|
- lib/firebase-stats.rb
|
51
109
|
- lib/reader.rb
|
110
|
+
- lib/version.rb
|
52
111
|
- lib/wrapper.rb
|
53
|
-
homepage: https://
|
112
|
+
homepage: https://github.com/chedabob/firebase-stats
|
54
113
|
licenses:
|
55
114
|
- MIT
|
56
115
|
metadata: {}
|
@@ -60,17 +119,17 @@ require_paths:
|
|
60
119
|
- lib
|
61
120
|
required_ruby_version: !ruby/object:Gem::Requirement
|
62
121
|
requirements:
|
63
|
-
- - "
|
122
|
+
- - ">="
|
64
123
|
- !ruby/object:Gem::Version
|
65
|
-
version: '
|
124
|
+
version: '2.4'
|
66
125
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
67
126
|
requirements:
|
68
127
|
- - ">="
|
69
128
|
- !ruby/object:Gem::Version
|
70
129
|
version: '0'
|
71
130
|
requirements: []
|
72
|
-
rubygems_version: 3.2.
|
131
|
+
rubygems_version: 3.2.14
|
73
132
|
signing_key:
|
74
133
|
specification_version: 4
|
75
|
-
summary: Firebase CSV Stats
|
134
|
+
summary: Firebase CSV Stats CLI
|
76
135
|
test_files: []
|