gcstats 1.0.0 → 1.0.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.
- data/{README.markdown → README.md} +7 -5
- data/bin/gcstats +18 -6
- data/config.ru +3 -0
- data/lib/gcstats/gcstats.rhtml +51 -5
- data/lib/gcstats/helpers.rb +36 -0
- data/lib/gcstats/mapping.rb +5 -3
- data/lib/gcstats/server.rb +8 -5
- data/lib/gcstats/template.rb +4 -0
- data/lib/gcstats/version.rb +3 -0
- metadata +27 -10
@@ -18,15 +18,17 @@ To install, change directory to where you have extracted the gcstats source file
|
|
18
18
|
|
19
19
|
Visit the [Pocket Queries][pq] page and click the _Add to Queue_ button (under _My Finds_). After a while, you will receive an email informing you that your Pocket Query file is available for download. Visit the [Pocket Queries][pq] page again and download the file under the _Pocket Queries Ready for Download_ tab.
|
20
20
|
|
21
|
-
Assuming your Pocket Query file is
|
21
|
+
Assuming your Pocket Query file is _1234567.zip_, issue:
|
22
22
|
|
23
|
-
|
23
|
+
gcstats 1234567.zip
|
24
24
|
|
25
|
-
|
25
|
+
This will write to _username.html_, where "username" is the one you have on [Geocaching.com][gc].
|
26
26
|
|
27
|
-
|
27
|
+
It is also possible to specify the output filename:
|
28
28
|
|
29
|
-
|
29
|
+
gcstats 1234567.zip mystats.html
|
30
|
+
|
31
|
+
This will write to _mystats.html_.
|
30
32
|
|
31
33
|
**Note:** You need to be a [Premium Member][pm] at [Geocaching.com][gc] to use [Pocket Queries][pq].
|
32
34
|
|
data/bin/gcstats
CHANGED
@@ -12,6 +12,8 @@ if in_fn.nil?
|
|
12
12
|
exit 1
|
13
13
|
end
|
14
14
|
|
15
|
+
start_ts = Time.new # for render_time helper
|
16
|
+
|
15
17
|
if File.extname(in_fn) == '.zip'
|
16
18
|
data = nil
|
17
19
|
|
@@ -27,12 +29,22 @@ else
|
|
27
29
|
out_fn ||= File.basename(in_fn, File.extname(in_fn)) + '.html'
|
28
30
|
end
|
29
31
|
|
30
|
-
|
32
|
+
libdir = File.join(File.dirname(__FILE__), '..', 'lib', 'gcstats')
|
31
33
|
|
32
|
-
rhtml = File.read(File.join(
|
34
|
+
rhtml = File.read(File.join(libdir, 'gcstats.rhtml'))
|
33
35
|
caches = GCStats::Caches.from_xml(data)
|
34
|
-
|
35
|
-
html
|
36
|
-
html.sub!('/* %
|
36
|
+
data = {:caches => caches, :start_ts => start_ts}
|
37
|
+
html = GCStats::Template.new(rhtml, data).result
|
38
|
+
html.sub!('/* %css% */', "\n" + File.read(File.join(libdir, 'gcstats.css')))
|
39
|
+
html.sub!('/* %js% */', "\n" + File.read(File.join(libdir, 'gcstats.js')))
|
40
|
+
|
41
|
+
if ARGV[1].nil? && caches[0] && caches[0].logs[0]
|
42
|
+
out_fn = caches[0].logs[0].finder
|
43
|
+
out_fn.downcase!
|
44
|
+
out_fn.gsub!(/\W/, '-')
|
45
|
+
out_fn.gsub!(/-+/, '-')
|
46
|
+
out_fn += '.html'
|
47
|
+
end
|
48
|
+
|
37
49
|
open(out_fn, 'w') {|f| f.write(html) }
|
38
|
-
puts "wrote #{out_fn}"
|
50
|
+
puts "wrote #{out_fn}" if test(?s, out_fn)
|
data/config.ru
CHANGED
data/lib/gcstats/gcstats.rhtml
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
3
3
|
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
|
4
4
|
<head>
|
5
|
-
<title
|
5
|
+
<title>Geocaching Stats for <%=h geocacher_name %></title>
|
6
6
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
7
7
|
<link type="text/css" rel="stylesheet" href="gcstats.css" media="screen" />
|
8
8
|
<style type="text/css">/* %css% */</style>
|
@@ -17,7 +17,7 @@
|
|
17
17
|
<caption>Cache Finds</caption>
|
18
18
|
<tr>
|
19
19
|
<th class="l">Geocacher</th>
|
20
|
-
<td class="hl b"><%= geocacher_name %></td>
|
20
|
+
<td class="hl b"><%=h geocacher_name %></td>
|
21
21
|
</tr>
|
22
22
|
<tr>
|
23
23
|
<th class="l">Total</th>
|
@@ -88,7 +88,7 @@
|
|
88
88
|
</tr>
|
89
89
|
<% finds_by_size.each {|size, finds| %>
|
90
90
|
<tr>
|
91
|
-
<td><%= size %></td>
|
91
|
+
<td><%=h size %></td>
|
92
92
|
<td class="r"><%= finds %></td>
|
93
93
|
<td class="r"><%= '%.1f' % (finds / total_finds.to_f * 100) %>%</td>
|
94
94
|
</tr>
|
@@ -106,7 +106,25 @@
|
|
106
106
|
</tr>
|
107
107
|
<% finds_by_type.each {|type, finds| %>
|
108
108
|
<tr>
|
109
|
-
<td><%= type %></td>
|
109
|
+
<td><%=h type %></td>
|
110
|
+
<td class="r"><%= finds %></td>
|
111
|
+
<td class="r"><%= '%.1f' % (finds / total_finds.to_f * 100) %>%</td>
|
112
|
+
</tr>
|
113
|
+
<% } %>
|
114
|
+
</table>
|
115
|
+
<%# }}} %>
|
116
|
+
|
117
|
+
<%# {{{ finds by cache owner %>
|
118
|
+
<table>
|
119
|
+
<caption>Finds by Cache Owner</caption>
|
120
|
+
<tr>
|
121
|
+
<th>Owner</th>
|
122
|
+
<th>Finds</th>
|
123
|
+
<th>Percentage</th>
|
124
|
+
</tr>
|
125
|
+
<% finds_by_owner.each {|owner, finds| %>
|
126
|
+
<tr>
|
127
|
+
<td><%=h owner %></td>
|
110
128
|
<td class="r"><%= finds %></td>
|
111
129
|
<td class="r"><%= '%.1f' % (finds / total_finds.to_f * 100) %>%</td>
|
112
130
|
</tr>
|
@@ -182,7 +200,7 @@
|
|
182
200
|
</tr>
|
183
201
|
<% finds_by_country.sort {|x, y| y[1] <=> x[1] }.each {|country, finds| %>
|
184
202
|
<tr>
|
185
|
-
<td><%= country %></td>
|
203
|
+
<td><%=h country %></td>
|
186
204
|
<td class="r"><%= finds %></td>
|
187
205
|
<td class="r"><%= '%.1f' % (finds / total_finds.to_f * 100) %>%</td>
|
188
206
|
</tr>
|
@@ -190,6 +208,32 @@
|
|
190
208
|
</table>
|
191
209
|
<%# }}} %>
|
192
210
|
|
211
|
+
<%# {{{ finds by state %>
|
212
|
+
<% finds_by_state.each {|country, states| %>
|
213
|
+
<table>
|
214
|
+
<caption>Finds by State in <%=h country %></caption>
|
215
|
+
<tr>
|
216
|
+
<th rowspan="2">State</th>
|
217
|
+
<th rowspan="2">Finds</th>
|
218
|
+
<th colspan="2">Percentage</th>
|
219
|
+
</tr>
|
220
|
+
<tr>
|
221
|
+
<th>Country</th>
|
222
|
+
<th>Total</th>
|
223
|
+
</tr>
|
224
|
+
<% country_finds = states.map {|s| s[1] }.sum %>
|
225
|
+
<% states.sort {|x, y| y[1] <=> x[1] }.each {|state, finds| %>
|
226
|
+
<tr>
|
227
|
+
<td><%=h state %></td>
|
228
|
+
<td class="r"><%= finds %></td>
|
229
|
+
<td class="r"><%= '%.1f' % (finds / country_finds.to_f * 100) %>%</td>
|
230
|
+
<td class="r"><%= '%.1f' % (finds / total_finds.to_f * 100) %>%</td>
|
231
|
+
</tr>
|
232
|
+
<% } %>
|
233
|
+
</table>
|
234
|
+
<% } %>
|
235
|
+
<%# }}} %>
|
236
|
+
|
193
237
|
<%# {{{ finds by date %>
|
194
238
|
<table id="finds_by_date">
|
195
239
|
<caption>Finds by Date</caption>
|
@@ -209,5 +253,7 @@
|
|
209
253
|
</table>
|
210
254
|
<%# }}} %>
|
211
255
|
|
256
|
+
<p>Generated with <a href="http://github.com/agorf/gcstats">gcstats</a> on <%= Time.new %> in <%= '%.3f' % render_time %> seconds.</p>
|
257
|
+
|
212
258
|
</body>
|
213
259
|
</html>
|
data/lib/gcstats/helpers.rb
CHANGED
@@ -176,6 +176,38 @@ module GCStats
|
|
176
176
|
end
|
177
177
|
end
|
178
178
|
|
179
|
+
def finds_by_state
|
180
|
+
@finds_by_state ||= begin
|
181
|
+
finds = {}
|
182
|
+
|
183
|
+
@caches.each {|cache|
|
184
|
+
next if cache.state.empty?
|
185
|
+
|
186
|
+
finds[cache.country] ||= {}
|
187
|
+
finds[cache.country][cache.state] ||= 0
|
188
|
+
finds[cache.country][cache.state] += cache.find_dates.size
|
189
|
+
}
|
190
|
+
|
191
|
+
finds
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
195
|
+
def finds_by_owner
|
196
|
+
@finds_by_owner ||= begin
|
197
|
+
finds = {}
|
198
|
+
|
199
|
+
@caches.each {|cache|
|
200
|
+
begin
|
201
|
+
finds[cache.owner] += cache.find_dates.size
|
202
|
+
rescue
|
203
|
+
finds[cache.owner] = cache.find_dates.size
|
204
|
+
end
|
205
|
+
}
|
206
|
+
|
207
|
+
finds.sort {|x, y| y[1] <=> x[1] }[0..9]
|
208
|
+
end
|
209
|
+
end
|
210
|
+
|
179
211
|
def geocacher_name
|
180
212
|
@caches[0].logs[0].finder
|
181
213
|
end
|
@@ -183,5 +215,9 @@ module GCStats
|
|
183
215
|
def finds_dates
|
184
216
|
@finds_dates ||= finds_by_date.keys.sort.reverse
|
185
217
|
end
|
218
|
+
|
219
|
+
def render_time
|
220
|
+
Time.new - @start_ts
|
221
|
+
end
|
186
222
|
end
|
187
223
|
end
|
data/lib/gcstats/mapping.rb
CHANGED
@@ -60,10 +60,12 @@ module GCStats
|
|
60
60
|
end
|
61
61
|
|
62
62
|
def owner
|
63
|
-
@owner ||= @cache_node.elements["#{NS}:
|
63
|
+
@owner ||= @cache_node.elements["#{NS}:owner"].text
|
64
64
|
end
|
65
65
|
|
66
|
-
|
66
|
+
def placed_by
|
67
|
+
@placed_by ||= @cache_node.elements["#{NS}:placed_by"].text
|
68
|
+
end
|
67
69
|
|
68
70
|
def type
|
69
71
|
@type ||= @cache_node.elements["#{NS}:type"].text
|
@@ -88,7 +90,7 @@ module GCStats
|
|
88
90
|
end
|
89
91
|
|
90
92
|
def state
|
91
|
-
@state ||= @cache_node.elements["#{NS}:state"].text
|
93
|
+
@state ||= @cache_node.elements["#{NS}:state"].text.strip
|
92
94
|
end
|
93
95
|
|
94
96
|
def logs
|
data/lib/gcstats/server.rb
CHANGED
@@ -28,6 +28,8 @@ end
|
|
28
28
|
|
29
29
|
post '/generate_stats' do
|
30
30
|
begin
|
31
|
+
start_ts = Time.new # for render_time helper
|
32
|
+
|
31
33
|
pq = params['pq']
|
32
34
|
|
33
35
|
if pq[:type] == 'application/zip'
|
@@ -43,13 +45,14 @@ post '/generate_stats' do
|
|
43
45
|
data = pq[:tempfile].read
|
44
46
|
end
|
45
47
|
|
46
|
-
|
48
|
+
libdir = File.dirname(__FILE__)
|
47
49
|
|
48
|
-
rhtml = open(File.join(
|
50
|
+
rhtml = open(File.join(libdir, 'gcstats.rhtml')).read
|
49
51
|
caches = GCStats::Caches.from_xml(data)
|
50
|
-
|
51
|
-
html
|
52
|
-
html.sub!('/* %
|
52
|
+
data = {:caches => caches, :start_ts => start_ts}
|
53
|
+
html = GCStats::Template.new(rhtml, data).result
|
54
|
+
html.sub!('/* %css% */', "\n" + File.read(File.join(libdir, 'gcstats.css')))
|
55
|
+
html.sub!('/* %js% */', "\n" + File.read(File.join(libdir, 'gcstats.js')))
|
53
56
|
|
54
57
|
return html
|
55
58
|
rescue
|
data/lib/gcstats/template.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: gcstats
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
|
4
|
+
hash: 21
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 1
|
8
|
+
- 0
|
9
|
+
- 1
|
10
|
+
version: 1.0.1
|
5
11
|
platform: ruby
|
6
12
|
authors:
|
7
13
|
- Aggelos Orfanakos
|
@@ -9,19 +15,23 @@ autorequire:
|
|
9
15
|
bindir: bin
|
10
16
|
cert_chain: []
|
11
17
|
|
12
|
-
date: 2010-
|
18
|
+
date: 2010-09-20 00:00:00 +03:00
|
13
19
|
default_executable:
|
14
20
|
dependencies:
|
15
21
|
- !ruby/object:Gem::Dependency
|
16
22
|
name: rubyzip
|
17
|
-
|
18
|
-
|
19
|
-
|
23
|
+
prerelease: false
|
24
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
20
26
|
requirements:
|
21
27
|
- - ">="
|
22
28
|
- !ruby/object:Gem::Version
|
29
|
+
hash: 3
|
30
|
+
segments:
|
31
|
+
- 0
|
23
32
|
version: "0"
|
24
|
-
|
33
|
+
type: :runtime
|
34
|
+
version_requirements: *id001
|
25
35
|
description: Simple and clean statistics of your Geocaching activity
|
26
36
|
email: agorf@agorf.gr
|
27
37
|
executables:
|
@@ -31,9 +41,10 @@ extensions: []
|
|
31
41
|
extra_rdoc_files: []
|
32
42
|
|
33
43
|
files:
|
34
|
-
- README.
|
44
|
+
- README.md
|
35
45
|
- config.ru
|
36
46
|
- bin/gcstats
|
47
|
+
- lib/gcstats/version.rb
|
37
48
|
- lib/gcstats/gcstats.css
|
38
49
|
- lib/gcstats/helpers.rb
|
39
50
|
- lib/gcstats/mapping.rb
|
@@ -51,21 +62,27 @@ rdoc_options: []
|
|
51
62
|
require_paths:
|
52
63
|
- lib
|
53
64
|
required_ruby_version: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
54
66
|
requirements:
|
55
67
|
- - ">="
|
56
68
|
- !ruby/object:Gem::Version
|
69
|
+
hash: 3
|
70
|
+
segments:
|
71
|
+
- 0
|
57
72
|
version: "0"
|
58
|
-
version:
|
59
73
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
74
|
+
none: false
|
60
75
|
requirements:
|
61
76
|
- - ">="
|
62
77
|
- !ruby/object:Gem::Version
|
78
|
+
hash: 3
|
79
|
+
segments:
|
80
|
+
- 0
|
63
81
|
version: "0"
|
64
|
-
version:
|
65
82
|
requirements: []
|
66
83
|
|
67
84
|
rubyforge_project:
|
68
|
-
rubygems_version: 1.3.
|
85
|
+
rubygems_version: 1.3.7
|
69
86
|
signing_key:
|
70
87
|
specification_version: 3
|
71
88
|
summary: Simple and clean statistics of your Geocaching activity
|