gcstats 1.0.0 → 1.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|