easymap 0.0.2
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/.gitignore +20 -0
- data/.rvmrc +34 -0
- data/Gemfile +14 -0
- data/LICENSE +22 -0
- data/README.md +16 -0
- data/Rakefile +8 -0
- data/lib/algorithms/weighted_mean_center.rb +39 -0
- data/lib/engine/engine.rb +4 -0
- data/lib/generators/ovimap/build/build_generator.rb +28 -0
- data/lib/generators/ovimap/display/display_generator.rb +24 -0
- data/lib/generators/ovimap/heatmap/heatmap_generator.rb +34 -0
- data/lib/generators/ovimap/helpers.rb +91 -0
- data/lib/generators/ovimap/install/install_generator.rb +32 -0
- data/lib/generators/ovimap/install/templates/map.js +22 -0
- data/lib/generators/ovimap/install/templates/underscore-min.js +32 -0
- data/lib/generators/ovimap/pin/pin_generator.rb +35 -0
- data/lib/map/map.rb +14 -0
- data/lib/ovimaps.rb +4 -0
- data/lib/version.rb +3 -0
- data/notes.txt +46 -0
- data/ovi.gemspec +19 -0
- data/spec/lib/map/map_spec.rb +22 -0
- data/spec/spec_helper.rb +18 -0
- metadata +103 -0
data/.gitignore
ADDED
data/.rvmrc
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
#!/usr/bin/env bash
|
2
|
+
|
3
|
+
# This is an RVM Project .rvmrc file, used to automatically load the ruby
|
4
|
+
# development environment upon cd'ing into the directory
|
5
|
+
|
6
|
+
# First we specify our desired <ruby>[@<gemset>], the @gemset name is optional,
|
7
|
+
# Only full ruby name is supported here, for short names use:
|
8
|
+
# echo "rvm use 1.9.3" > .rvmrc
|
9
|
+
environment_id="ruby-1.9.3-p194@ovi"
|
10
|
+
|
11
|
+
# Uncomment the following lines if you want to verify rvm version per project
|
12
|
+
# rvmrc_rvm_version="1.13.0 ()" # 1.10.1 seams as a safe start
|
13
|
+
# eval "$(echo ${rvm_version}.${rvmrc_rvm_version} | awk -F. '{print "[[ "$1*65536+$2*256+$3" -ge "$4*65536+$5*256+$6" ]]"}' )" || {
|
14
|
+
# echo "This .rvmrc file requires at least RVM ${rvmrc_rvm_version}, aborting loading."
|
15
|
+
# return 1
|
16
|
+
# }
|
17
|
+
|
18
|
+
# First we attempt to load the desired environment directly from the environment
|
19
|
+
# file. This is very fast and efficient compared to running through the entire
|
20
|
+
# CLI and selector. If you want feedback on which environment was used then
|
21
|
+
# insert the word 'use' after --create as this triggers verbose mode.
|
22
|
+
if [[ -d "${rvm_path:-$HOME/.rvm}/environments"
|
23
|
+
&& -s "${rvm_path:-$HOME/.rvm}/environments/$environment_id" ]]
|
24
|
+
then
|
25
|
+
\. "${rvm_path:-$HOME/.rvm}/environments/$environment_id"
|
26
|
+
[[ -s "${rvm_path:-$HOME/.rvm}/hooks/after_use" ]] &&
|
27
|
+
\. "${rvm_path:-$HOME/.rvm}/hooks/after_use" || true
|
28
|
+
else
|
29
|
+
# If the environment file has not yet been created, use the RVM CLI to select.
|
30
|
+
rvm --create "$environment_id" || {
|
31
|
+
echo "Failed to create RVM environment '${environment_id}'."
|
32
|
+
return 1
|
33
|
+
}
|
34
|
+
fi
|
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2012 Nick Soto
|
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.
|
data/README.md
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
<h2>A (very simple) gem for all your mapping needs</h2>
|
2
|
+
|
3
|
+
<p><strong>easymap</strong> allows you to quickly get setup with the Nokia Ovi Maps API. Convert Open Office spreadsheets with geographic coordinates into interactive heatmaps. Create maps with multiple circular and polygon overlays. </p>
|
4
|
+
<br />
|
5
|
+
<br />
|
6
|
+
<ol>
|
7
|
+
<li>To start, you must register your app. Go to the <a href="https://sso.developer.nokia.com">Nokia Developer site</a>, signup, and obtain the necessary token and app ID keys</li>
|
8
|
+
<li>After obtaining these, open your bash_profile and set the keys (e.g. export APP_ID=yourf332password2342here). Save the bash_profile file then reload all terminal windows. </li>
|
9
|
+
<li>Add 'easymap' to your gemfile and run 'bundle:install'. You will now have access to "rails g ovimap:install". Running this command will install the js files to your assets path. </li>
|
10
|
+
<br />
|
11
|
+
<br />
|
12
|
+
<br />
|
13
|
+
<img src="http://oi48.tinypic.com/2r6k6lh.jpg" width="650" height="450" alt="Spreadsheet Picture" />
|
14
|
+
<img src="http://oi46.tinypic.com/23iv4nl.jpg" width="650" height="450" alt="Heatmap 1" />
|
15
|
+
|
16
|
+
</ol>
|
data/Rakefile
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'bigdecimal'
|
2
|
+
|
3
|
+
class WeightedMeanCenter
|
4
|
+
|
5
|
+
points_array = []
|
6
|
+
|
7
|
+
5.times do #should iterate through DATA set that is n number of rows
|
8
|
+
|
9
|
+
lat = BigDecimal.new("-81.5215") #argument should be index[0] of iterated data set
|
10
|
+
foo = lat * 223019 #should multiply by second argument of iterator (i.e. the "value" field value of data set)
|
11
|
+
lat_return = foo.round(2)/1.0
|
12
|
+
|
13
|
+
#lat_return.inspect
|
14
|
+
# 9161709.73
|
15
|
+
|
16
|
+
long = BigDecimal.new("41.0804")
|
17
|
+
bar = long * 223019
|
18
|
+
long_return = bar.round(2)/1.0
|
19
|
+
|
20
|
+
#long_return.inspect
|
21
|
+
# 9161709.73
|
22
|
+
|
23
|
+
points_array << [lat_return, long_return]
|
24
|
+
|
25
|
+
end
|
26
|
+
|
27
|
+
# p empty
|
28
|
+
#[[-18180843.41, 9161709.73], [-18180843.41, 9161709.73]]
|
29
|
+
|
30
|
+
sum_of_all_xtimesp = points_array.inject(0) { |result, element| result + element[0] }
|
31
|
+
sum_of_all_ytimesp = points_array.inject(0) { |result, element| result + element[1] }
|
32
|
+
|
33
|
+
weighted_x = sum_of_all_xtimesp / 5 #or n rows
|
34
|
+
weighted_y = sum_of_all_ytimesp / 5 #or n rows
|
35
|
+
|
36
|
+
#p weighted_x
|
37
|
+
# -18180843.41
|
38
|
+
|
39
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'generators/ovimap/helpers'
|
2
|
+
require 'rails/generators'
|
3
|
+
require 'rails'
|
4
|
+
|
5
|
+
module Ovimap
|
6
|
+
module Generators
|
7
|
+
class BuildGenerator < Rails::Generators::Base
|
8
|
+
argument :controller_name, :type => :string, :required => true
|
9
|
+
argument :action_name, :type => :string, :required => true
|
10
|
+
include Ovimap::Generators::Helpers
|
11
|
+
|
12
|
+
def self.source_root
|
13
|
+
@source_root ||= File.expand_path("../templates", __FILE__)
|
14
|
+
end
|
15
|
+
|
16
|
+
def build
|
17
|
+
append_file "#{stylesheets}/#{controller_name}.css.scss",
|
18
|
+
"\n#mapContainer { top: 0; left: 0; position: absolute; height:100%; width:100% }"
|
19
|
+
|
20
|
+
prepend_file "app/views/#{controller_name}/#{action_name}.html.erb", "#{content_for}"
|
21
|
+
printf "\e[32m \n\t\t\tSUCCESS. A content_for tag is now located in #{controller_name}/#{action_name}.html.erb.\n
|
22
|
+
To manipulate the size of the map, style the #mapContainer directly in css.\n
|
23
|
+
#mapContainer.\n"
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'generators/ovimap/helpers'
|
2
|
+
require 'rails/generators'
|
3
|
+
require 'rails'
|
4
|
+
|
5
|
+
module Ovimap
|
6
|
+
module Generators
|
7
|
+
class DisplayGenerator < Rails::Generators::Base
|
8
|
+
argument :map_type, :type => :string, :required => true
|
9
|
+
include Ovimap::Generators::Helpers
|
10
|
+
|
11
|
+
def self.source_root
|
12
|
+
@source_root ||= File.expand_path("../templates", __FILE__)
|
13
|
+
end
|
14
|
+
|
15
|
+
def display
|
16
|
+
if File.readlines("#{js_path}/map.js").grep(/nokia.maps.map.Display.[A-Z+_]/).any?
|
17
|
+
gsub_file "#{js_path}/map.js", /map.set\("baseMapType", nokia.maps.map.Display.[A-Z+_]{2,}\);/, "#{map_swap}"
|
18
|
+
else
|
19
|
+
insert_into_file "#{js_path}/map.js", "#{map_select}", :after => /MAP TYPE\/\//
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'generators/ovimap/helpers'
|
2
|
+
require 'rails/generators'
|
3
|
+
require 'rails'
|
4
|
+
require 'rubygems'
|
5
|
+
require 'ods'
|
6
|
+
|
7
|
+
module Ovimap
|
8
|
+
module Generators
|
9
|
+
class HeatmapGenerator < Rails::Generators::Base
|
10
|
+
include Ovimap::Generators::Helpers
|
11
|
+
|
12
|
+
@var = File.expand_path('lib/data.ods')
|
13
|
+
ods = Ods.new(@var)
|
14
|
+
sheet = ods.sheets[0]
|
15
|
+
@ending_row = sheet.rows.count
|
16
|
+
|
17
|
+
DATA_SET = (2..@ending_row).to_a.map {|x|
|
18
|
+
"{value: #{sheet[x, :A].value}, latitude: #{sheet[x, :B].value}, longitude: #{sheet[x, :C].value}}" }
|
19
|
+
|
20
|
+
CLEANED_DATA = DATA_SET.to_s.gsub /"/,''
|
21
|
+
|
22
|
+
def self.source_root
|
23
|
+
@source_root ||= File.expand_path("../templates", __FILE__)
|
24
|
+
end
|
25
|
+
|
26
|
+
def heatmap
|
27
|
+
# unless File.readlines(#{js_path}/map.js).grep(/var data/).any?
|
28
|
+
insert_into_file "#{js_path}/map.js", "\nvar data = #{CLEANED_DATA};", :after => /HEAT MAP DATA\/\//
|
29
|
+
# end
|
30
|
+
insert_into_file "#{js_path}/map.js", "\n#{heatmap_options}", :after => /HEAT MAP OPTIONS\/\//
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
module Ovimap
|
2
|
+
module Generators
|
3
|
+
module Helpers
|
4
|
+
|
5
|
+
def asset_path
|
6
|
+
"app/assets"
|
7
|
+
end
|
8
|
+
|
9
|
+
def js_path
|
10
|
+
"#{asset_path}/javascripts"
|
11
|
+
end
|
12
|
+
|
13
|
+
def stylesheets
|
14
|
+
"#{asset_path}/stylesheets"
|
15
|
+
end
|
16
|
+
|
17
|
+
def layouts
|
18
|
+
"app/views/layouts"
|
19
|
+
end
|
20
|
+
|
21
|
+
def map_style
|
22
|
+
"\n#mapContainer {\nwidth: 100%; \nheight: 100%; \nleft: 0; \ntop: 0; \nposition: absolute;\n}\n"
|
23
|
+
end
|
24
|
+
|
25
|
+
def nokia_script
|
26
|
+
"\n<script type=\"text/javascript\" charset=\"UTF-8\" src=\"http://api.maps.nokia.com/2.2.0/jsl.js?with=all\"></script>\n"
|
27
|
+
end
|
28
|
+
|
29
|
+
def content_for
|
30
|
+
<<-eos.gsub /^\s+/, ""
|
31
|
+
<% content_for :map do %>
|
32
|
+
<%= javascript_include_tag 'map.js' %>
|
33
|
+
<% end %>
|
34
|
+
|
35
|
+
<div id="mapContainer"></div>
|
36
|
+
eos
|
37
|
+
end
|
38
|
+
|
39
|
+
def map_select
|
40
|
+
"\nmap.set(\"baseMapType\", nokia.maps.map.Display.#{map_type.upcase});\n"
|
41
|
+
end
|
42
|
+
|
43
|
+
def map_swap
|
44
|
+
"map.set(\"baseMapType\", nokia.maps.map.Display.#{map_type.upcase});"
|
45
|
+
end
|
46
|
+
|
47
|
+
def heatmap_options
|
48
|
+
<<-eof.gsub /^\s+/, ""
|
49
|
+
|
50
|
+
var colorizeAPI = {
|
51
|
+
stops: {
|
52
|
+
"0": "#CCFF00",
|
53
|
+
"0.5": "#FF9900",
|
54
|
+
"1": "#CC0000"
|
55
|
+
},
|
56
|
+
interpolate: true
|
57
|
+
};
|
58
|
+
|
59
|
+
var heatmapProvider = new nokia.maps.heatmap.Overlay({
|
60
|
+
label: 'My Map',
|
61
|
+
description: 'Generated with EasyMap',
|
62
|
+
max: 20,
|
63
|
+
opacity: 0.9,
|
64
|
+
type: "value",
|
65
|
+
coarseness: 10,
|
66
|
+
colors: colorizeAPI,
|
67
|
+
});
|
68
|
+
|
69
|
+
heatmapProvider.addData(data);
|
70
|
+
map.overlays.add(heatmapProvider);
|
71
|
+
eof
|
72
|
+
end
|
73
|
+
|
74
|
+
def pin_options
|
75
|
+
<<-eof.gsub /^\s+/, ""
|
76
|
+
|
77
|
+
pindata = _.zip(_.pluck(data, "latitude"), _.pluck(data, "longitude"));
|
78
|
+
|
79
|
+
_.each(pindata, function(num){
|
80
|
+
|
81
|
+
map.objects.add(new nokia.maps.map.Circle(
|
82
|
+
new nokia.maps.geo.Coordinate(num[0], num[1]), 40000,
|
83
|
+
{ pen: { strokeColor: "black", lineWidth: 0 }, brush: { color: "yellow" }}));
|
84
|
+
});
|
85
|
+
eof
|
86
|
+
end
|
87
|
+
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'generators/ovimap/helpers'
|
2
|
+
require 'rails/generators'
|
3
|
+
require 'rails'
|
4
|
+
|
5
|
+
module Ovimap
|
6
|
+
module Generators
|
7
|
+
class InstallGenerator < Rails::Generators::Base
|
8
|
+
include Ovimap::Generators::Helpers
|
9
|
+
|
10
|
+
def self.source_root
|
11
|
+
@source_root ||= File.expand_path("../templates", __FILE__)
|
12
|
+
end
|
13
|
+
|
14
|
+
def install
|
15
|
+
directory @source_root, "#{js_path}"
|
16
|
+
insert_into_file "#{layouts}/application.html.erb", "#{nokia_script}", :before => '</head>'
|
17
|
+
insert_into_file "#{layouts}/application.html.erb", '<%= yield :map %>', :before => '</body>'
|
18
|
+
unless ENV['APP_ID'] == nil || ENV['APP_TOKEN'] == nil
|
19
|
+
gsub_file "#{js_path}/map.js", /YOUR_APPID/, ENV['APP_ID']
|
20
|
+
gsub_file "#{js_path}/map.js", /YOUR_TOKEN/, ENV['APP_TOKEN']
|
21
|
+
printf "\e[32m \n\t\t\tSUCCESS. Now run 'rails g ovimap:build CONTROLLER ACTION'. The\n
|
22
|
+
CONTROLLER and ACTION should point to the location of the file which will have the\n
|
23
|
+
map.\n"
|
24
|
+
else
|
25
|
+
printf "\e[32m \n\t\t\tYou must first register as a Nokia Developer, then save your APP_ID\n
|
26
|
+
and APP_TOKEN as environmental variables in the bash_profile. For further information, please\n
|
27
|
+
see the documentation.\n"
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
nokia.Settings.set("appId", "YOUR_APPID");
|
2
|
+
nokia.Settings.set("authenticationToken", "YOUR_TOKEN");
|
3
|
+
var mapContainer = document.getElementById("mapContainer");
|
4
|
+
var map = new nokia.maps.map.Display(mapContainer, {
|
5
|
+
center: [52.51, 13.4],
|
6
|
+
zoomLevel: 4,
|
7
|
+
components: [
|
8
|
+
new nokia.maps.map.component.ZoomBar(),
|
9
|
+
new nokia.maps.map.component.Overview(),
|
10
|
+
new nokia.maps.map.component.Behavior(),
|
11
|
+
new nokia.maps.map.component.ContextMenu()
|
12
|
+
]
|
13
|
+
});
|
14
|
+
//MAP TYPE//
|
15
|
+
|
16
|
+
//HEAT MAP DATA//
|
17
|
+
|
18
|
+
//HEAT MAP OPTIONS//
|
19
|
+
|
20
|
+
//PIN MAP OPTIONS//
|
21
|
+
|
22
|
+
;
|
@@ -0,0 +1,32 @@
|
|
1
|
+
// Underscore.js 1.3.3
|
2
|
+
// (c) 2009-2012 Jeremy Ashkenas, DocumentCloud Inc.
|
3
|
+
// Underscore is freely distributable under the MIT license.
|
4
|
+
// Portions of Underscore are inspired or borrowed from Prototype,
|
5
|
+
// Oliver Steele's Functional, and John Resig's Micro-Templating.
|
6
|
+
// For all details and documentation:
|
7
|
+
// http://documentcloud.github.com/underscore
|
8
|
+
(function(){function r(a,c,d){if(a===c)return 0!==a||1/a==1/c;if(null==a||null==c)return a===c;a._chain&&(a=a._wrapped);c._chain&&(c=c._wrapped);if(a.isEqual&&b.isFunction(a.isEqual))return a.isEqual(c);if(c.isEqual&&b.isFunction(c.isEqual))return c.isEqual(a);var e=l.call(a);if(e!=l.call(c))return!1;switch(e){case "[object String]":return a==""+c;case "[object Number]":return a!=+a?c!=+c:0==a?1/a==1/c:a==+c;case "[object Date]":case "[object Boolean]":return+a==+c;case "[object RegExp]":return a.source==
|
9
|
+
c.source&&a.global==c.global&&a.multiline==c.multiline&&a.ignoreCase==c.ignoreCase}if("object"!=typeof a||"object"!=typeof c)return!1;for(var f=d.length;f--;)if(d[f]==a)return!0;d.push(a);var f=0,g=!0;if("[object Array]"==e){if(f=a.length,g=f==c.length)for(;f--&&(g=f in a==f in c&&r(a[f],c[f],d)););}else{if("constructor"in a!="constructor"in c||a.constructor!=c.constructor)return!1;for(var h in a)if(b.has(a,h)&&(f++,!(g=b.has(c,h)&&r(a[h],c[h],d))))break;if(g){for(h in c)if(b.has(c,h)&&!f--)break;
|
10
|
+
g=!f}}d.pop();return g}var s=this,I=s._,o={},k=Array.prototype,p=Object.prototype,i=k.slice,J=k.unshift,l=p.toString,K=p.hasOwnProperty,y=k.forEach,z=k.map,A=k.reduce,B=k.reduceRight,C=k.filter,D=k.every,E=k.some,q=k.indexOf,F=k.lastIndexOf,p=Array.isArray,L=Object.keys,t=Function.prototype.bind,b=function(a){return new m(a)};"undefined"!==typeof exports?("undefined"!==typeof module&&module.exports&&(exports=module.exports=b),exports._=b):s._=b;b.VERSION="1.3.3";var j=b.each=b.forEach=function(a,
|
11
|
+
c,d){if(a!=null)if(y&&a.forEach===y)a.forEach(c,d);else if(a.length===+a.length)for(var e=0,f=a.length;e<f;e++){if(e in a&&c.call(d,a[e],e,a)===o)break}else for(e in a)if(b.has(a,e)&&c.call(d,a[e],e,a)===o)break};b.map=b.collect=function(a,c,b){var e=[];if(a==null)return e;if(z&&a.map===z)return a.map(c,b);j(a,function(a,g,h){e[e.length]=c.call(b,a,g,h)});if(a.length===+a.length)e.length=a.length;return e};b.reduce=b.foldl=b.inject=function(a,c,d,e){var f=arguments.length>2;a==null&&(a=[]);if(A&&
|
12
|
+
a.reduce===A){e&&(c=b.bind(c,e));return f?a.reduce(c,d):a.reduce(c)}j(a,function(a,b,i){if(f)d=c.call(e,d,a,b,i);else{d=a;f=true}});if(!f)throw new TypeError("Reduce of empty array with no initial value");return d};b.reduceRight=b.foldr=function(a,c,d,e){var f=arguments.length>2;a==null&&(a=[]);if(B&&a.reduceRight===B){e&&(c=b.bind(c,e));return f?a.reduceRight(c,d):a.reduceRight(c)}var g=b.toArray(a).reverse();e&&!f&&(c=b.bind(c,e));return f?b.reduce(g,c,d,e):b.reduce(g,c)};b.find=b.detect=function(a,
|
13
|
+
c,b){var e;G(a,function(a,g,h){if(c.call(b,a,g,h)){e=a;return true}});return e};b.filter=b.select=function(a,c,b){var e=[];if(a==null)return e;if(C&&a.filter===C)return a.filter(c,b);j(a,function(a,g,h){c.call(b,a,g,h)&&(e[e.length]=a)});return e};b.reject=function(a,c,b){var e=[];if(a==null)return e;j(a,function(a,g,h){c.call(b,a,g,h)||(e[e.length]=a)});return e};b.every=b.all=function(a,c,b){var e=true;if(a==null)return e;if(D&&a.every===D)return a.every(c,b);j(a,function(a,g,h){if(!(e=e&&c.call(b,
|
14
|
+
a,g,h)))return o});return!!e};var G=b.some=b.any=function(a,c,d){c||(c=b.identity);var e=false;if(a==null)return e;if(E&&a.some===E)return a.some(c,d);j(a,function(a,b,h){if(e||(e=c.call(d,a,b,h)))return o});return!!e};b.include=b.contains=function(a,c){var b=false;if(a==null)return b;if(q&&a.indexOf===q)return a.indexOf(c)!=-1;return b=G(a,function(a){return a===c})};b.invoke=function(a,c){var d=i.call(arguments,2);return b.map(a,function(a){return(b.isFunction(c)?c||a:a[c]).apply(a,d)})};b.pluck=
|
15
|
+
function(a,c){return b.map(a,function(a){return a[c]})};b.max=function(a,c,d){if(!c&&b.isArray(a)&&a[0]===+a[0])return Math.max.apply(Math,a);if(!c&&b.isEmpty(a))return-Infinity;var e={computed:-Infinity};j(a,function(a,b,h){b=c?c.call(d,a,b,h):a;b>=e.computed&&(e={value:a,computed:b})});return e.value};b.min=function(a,c,d){if(!c&&b.isArray(a)&&a[0]===+a[0])return Math.min.apply(Math,a);if(!c&&b.isEmpty(a))return Infinity;var e={computed:Infinity};j(a,function(a,b,h){b=c?c.call(d,a,b,h):a;b<e.computed&&
|
16
|
+
(e={value:a,computed:b})});return e.value};b.shuffle=function(a){var b=[],d;j(a,function(a,f){d=Math.floor(Math.random()*(f+1));b[f]=b[d];b[d]=a});return b};b.sortBy=function(a,c,d){var e=b.isFunction(c)?c:function(a){return a[c]};return b.pluck(b.map(a,function(a,b,c){return{value:a,criteria:e.call(d,a,b,c)}}).sort(function(a,b){var c=a.criteria,d=b.criteria;return c===void 0?1:d===void 0?-1:c<d?-1:c>d?1:0}),"value")};b.groupBy=function(a,c){var d={},e=b.isFunction(c)?c:function(a){return a[c]};
|
17
|
+
j(a,function(a,b){var c=e(a,b);(d[c]||(d[c]=[])).push(a)});return d};b.sortedIndex=function(a,c,d){d||(d=b.identity);for(var e=0,f=a.length;e<f;){var g=e+f>>1;d(a[g])<d(c)?e=g+1:f=g}return e};b.toArray=function(a){return!a?[]:b.isArray(a)||b.isArguments(a)?i.call(a):a.toArray&&b.isFunction(a.toArray)?a.toArray():b.values(a)};b.size=function(a){return b.isArray(a)?a.length:b.keys(a).length};b.first=b.head=b.take=function(a,b,d){return b!=null&&!d?i.call(a,0,b):a[0]};b.initial=function(a,b,d){return i.call(a,
|
18
|
+
0,a.length-(b==null||d?1:b))};b.last=function(a,b,d){return b!=null&&!d?i.call(a,Math.max(a.length-b,0)):a[a.length-1]};b.rest=b.tail=function(a,b,d){return i.call(a,b==null||d?1:b)};b.compact=function(a){return b.filter(a,function(a){return!!a})};b.flatten=function(a,c){return b.reduce(a,function(a,e){if(b.isArray(e))return a.concat(c?e:b.flatten(e));a[a.length]=e;return a},[])};b.without=function(a){return b.difference(a,i.call(arguments,1))};b.uniq=b.unique=function(a,c,d){var d=d?b.map(a,d):a,
|
19
|
+
e=[];a.length<3&&(c=true);b.reduce(d,function(d,g,h){if(c?b.last(d)!==g||!d.length:!b.include(d,g)){d.push(g);e.push(a[h])}return d},[]);return e};b.union=function(){return b.uniq(b.flatten(arguments,true))};b.intersection=b.intersect=function(a){var c=i.call(arguments,1);return b.filter(b.uniq(a),function(a){return b.every(c,function(c){return b.indexOf(c,a)>=0})})};b.difference=function(a){var c=b.flatten(i.call(arguments,1),true);return b.filter(a,function(a){return!b.include(c,a)})};b.zip=function(){for(var a=
|
20
|
+
i.call(arguments),c=b.max(b.pluck(a,"length")),d=Array(c),e=0;e<c;e++)d[e]=b.pluck(a,""+e);return d};b.indexOf=function(a,c,d){if(a==null)return-1;var e;if(d){d=b.sortedIndex(a,c);return a[d]===c?d:-1}if(q&&a.indexOf===q)return a.indexOf(c);d=0;for(e=a.length;d<e;d++)if(d in a&&a[d]===c)return d;return-1};b.lastIndexOf=function(a,b){if(a==null)return-1;if(F&&a.lastIndexOf===F)return a.lastIndexOf(b);for(var d=a.length;d--;)if(d in a&&a[d]===b)return d;return-1};b.range=function(a,b,d){if(arguments.length<=
|
21
|
+
1){b=a||0;a=0}for(var d=arguments[2]||1,e=Math.max(Math.ceil((b-a)/d),0),f=0,g=Array(e);f<e;){g[f++]=a;a=a+d}return g};var H=function(){};b.bind=function(a,c){var d,e;if(a.bind===t&&t)return t.apply(a,i.call(arguments,1));if(!b.isFunction(a))throw new TypeError;e=i.call(arguments,2);return d=function(){if(!(this instanceof d))return a.apply(c,e.concat(i.call(arguments)));H.prototype=a.prototype;var b=new H,g=a.apply(b,e.concat(i.call(arguments)));return Object(g)===g?g:b}};b.bindAll=function(a){var c=
|
22
|
+
i.call(arguments,1);c.length==0&&(c=b.functions(a));j(c,function(c){a[c]=b.bind(a[c],a)});return a};b.memoize=function(a,c){var d={};c||(c=b.identity);return function(){var e=c.apply(this,arguments);return b.has(d,e)?d[e]:d[e]=a.apply(this,arguments)}};b.delay=function(a,b){var d=i.call(arguments,2);return setTimeout(function(){return a.apply(null,d)},b)};b.defer=function(a){return b.delay.apply(b,[a,1].concat(i.call(arguments,1)))};b.throttle=function(a,c){var d,e,f,g,h,i,j=b.debounce(function(){h=
|
23
|
+
g=false},c);return function(){d=this;e=arguments;f||(f=setTimeout(function(){f=null;h&&a.apply(d,e);j()},c));g?h=true:i=a.apply(d,e);j();g=true;return i}};b.debounce=function(a,b,d){var e;return function(){var f=this,g=arguments;d&&!e&&a.apply(f,g);clearTimeout(e);e=setTimeout(function(){e=null;d||a.apply(f,g)},b)}};b.once=function(a){var b=false,d;return function(){if(b)return d;b=true;return d=a.apply(this,arguments)}};b.wrap=function(a,b){return function(){var d=[a].concat(i.call(arguments,0));
|
24
|
+
return b.apply(this,d)}};b.compose=function(){var a=arguments;return function(){for(var b=arguments,d=a.length-1;d>=0;d--)b=[a[d].apply(this,b)];return b[0]}};b.after=function(a,b){return a<=0?b():function(){if(--a<1)return b.apply(this,arguments)}};b.keys=L||function(a){if(a!==Object(a))throw new TypeError("Invalid object");var c=[],d;for(d in a)b.has(a,d)&&(c[c.length]=d);return c};b.values=function(a){return b.map(a,b.identity)};b.functions=b.methods=function(a){var c=[],d;for(d in a)b.isFunction(a[d])&&
|
25
|
+
c.push(d);return c.sort()};b.extend=function(a){j(i.call(arguments,1),function(b){for(var d in b)a[d]=b[d]});return a};b.pick=function(a){var c={};j(b.flatten(i.call(arguments,1)),function(b){b in a&&(c[b]=a[b])});return c};b.defaults=function(a){j(i.call(arguments,1),function(b){for(var d in b)a[d]==null&&(a[d]=b[d])});return a};b.clone=function(a){return!b.isObject(a)?a:b.isArray(a)?a.slice():b.extend({},a)};b.tap=function(a,b){b(a);return a};b.isEqual=function(a,b){return r(a,b,[])};b.isEmpty=
|
26
|
+
function(a){if(a==null)return true;if(b.isArray(a)||b.isString(a))return a.length===0;for(var c in a)if(b.has(a,c))return false;return true};b.isElement=function(a){return!!(a&&a.nodeType==1)};b.isArray=p||function(a){return l.call(a)=="[object Array]"};b.isObject=function(a){return a===Object(a)};b.isArguments=function(a){return l.call(a)=="[object Arguments]"};b.isArguments(arguments)||(b.isArguments=function(a){return!(!a||!b.has(a,"callee"))});b.isFunction=function(a){return l.call(a)=="[object Function]"};
|
27
|
+
b.isString=function(a){return l.call(a)=="[object String]"};b.isNumber=function(a){return l.call(a)=="[object Number]"};b.isFinite=function(a){return b.isNumber(a)&&isFinite(a)};b.isNaN=function(a){return a!==a};b.isBoolean=function(a){return a===true||a===false||l.call(a)=="[object Boolean]"};b.isDate=function(a){return l.call(a)=="[object Date]"};b.isRegExp=function(a){return l.call(a)=="[object RegExp]"};b.isNull=function(a){return a===null};b.isUndefined=function(a){return a===void 0};b.has=function(a,
|
28
|
+
b){return K.call(a,b)};b.noConflict=function(){s._=I;return this};b.identity=function(a){return a};b.times=function(a,b,d){for(var e=0;e<a;e++)b.call(d,e)};b.escape=function(a){return(""+a).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'").replace(/\//g,"/")};b.result=function(a,c){if(a==null)return null;var d=a[c];return b.isFunction(d)?d.call(a):d};b.mixin=function(a){j(b.functions(a),function(c){M(c,b[c]=a[c])})};var N=0;b.uniqueId=
|
29
|
+
function(a){var b=N++;return a?a+b:b};b.templateSettings={evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,escape:/<%-([\s\S]+?)%>/g};var u=/.^/,n={"\\":"\\","'":"'",r:"\r",n:"\n",t:"\t",u2028:"\u2028",u2029:"\u2029"},v;for(v in n)n[n[v]]=v;var O=/\\|'|\r|\n|\t|\u2028|\u2029/g,P=/\\(\\|'|r|n|t|u2028|u2029)/g,w=function(a){return a.replace(P,function(a,b){return n[b]})};b.template=function(a,c,d){d=b.defaults(d||{},b.templateSettings);a="__p+='"+a.replace(O,function(a){return"\\"+n[a]}).replace(d.escape||
|
30
|
+
u,function(a,b){return"'+\n_.escape("+w(b)+")+\n'"}).replace(d.interpolate||u,function(a,b){return"'+\n("+w(b)+")+\n'"}).replace(d.evaluate||u,function(a,b){return"';\n"+w(b)+"\n;__p+='"})+"';\n";d.variable||(a="with(obj||{}){\n"+a+"}\n");var a="var __p='';var print=function(){__p+=Array.prototype.join.call(arguments, '')};\n"+a+"return __p;\n",e=new Function(d.variable||"obj","_",a);if(c)return e(c,b);c=function(a){return e.call(this,a,b)};c.source="function("+(d.variable||"obj")+"){\n"+a+"}";return c};
|
31
|
+
b.chain=function(a){return b(a).chain()};var m=function(a){this._wrapped=a};b.prototype=m.prototype;var x=function(a,c){return c?b(a).chain():a},M=function(a,c){m.prototype[a]=function(){var a=i.call(arguments);J.call(a,this._wrapped);return x(c.apply(b,a),this._chain)}};b.mixin(b);j("pop,push,reverse,shift,sort,splice,unshift".split(","),function(a){var b=k[a];m.prototype[a]=function(){var d=this._wrapped;b.apply(d,arguments);var e=d.length;(a=="shift"||a=="splice")&&e===0&&delete d[0];return x(d,
|
32
|
+
this._chain)}});j(["concat","join","slice"],function(a){var b=k[a];m.prototype[a]=function(){return x(b.apply(this._wrapped,arguments),this._chain)}});m.prototype.chain=function(){this._chain=true;return this};m.prototype.value=function(){return this._wrapped}}).call(this);
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'generators/ovimap/helpers'
|
2
|
+
require 'rails/generators'
|
3
|
+
require 'rails'
|
4
|
+
require 'rubygems'
|
5
|
+
require 'ods'
|
6
|
+
|
7
|
+
module Ovimap
|
8
|
+
module Generators
|
9
|
+
class PinGenerator < Rails::Generators::Base
|
10
|
+
include Ovimap::Generators::Helpers
|
11
|
+
|
12
|
+
@var = File.expand_path('lib/data.ods')
|
13
|
+
ods = Ods.new(@var)
|
14
|
+
sheet = ods.sheets[0]
|
15
|
+
@ending_row = sheet.rows.count
|
16
|
+
|
17
|
+
DATA_SET = (2..@ending_row).to_a.map {|x|
|
18
|
+
"{value: #{sheet[x, :A].value}, latitude: #{sheet[x, :B].value}, longitude: #{sheet[x, :C].value}}" }
|
19
|
+
|
20
|
+
CLEANED_DATA = DATA_SET.to_s.gsub /"/,''
|
21
|
+
|
22
|
+
def self.source_root
|
23
|
+
@source_root ||= File.expand_path("../templates", __FILE__)
|
24
|
+
end
|
25
|
+
|
26
|
+
def pin
|
27
|
+
# unless File.readlines(#{js_path}/map.js).grep(/var data/).any?
|
28
|
+
insert_into_file "#{js_path}/map.js", "\nvar data = #{CLEANED_DATA};", :after => /HEAT MAP DATA\/\//
|
29
|
+
# end
|
30
|
+
insert_into_file "#{js_path}/map.js", "\n#{pin_options}", :after => /PIN MAP OPTIONS\/\//
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
data/lib/map/map.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
require "httparty"
|
2
|
+
Dir[File.dirname(__FILE__) + '/map/*.rb'].each do |file|
|
3
|
+
require file
|
4
|
+
end
|
5
|
+
|
6
|
+
$APP_ID = ENV['APP_ID']
|
7
|
+
$APP_TOKEN = ENV['OVI_TOKEN']
|
8
|
+
|
9
|
+
module Map
|
10
|
+
class Mapview
|
11
|
+
include HTTParty
|
12
|
+
base_uri "http://m.nok.it/?app_id=#{$APP_ID}&token=#{$APP_TOKEN}&nord"
|
13
|
+
end
|
14
|
+
end
|
data/lib/ovimaps.rb
ADDED
data/lib/version.rb
ADDED
data/notes.txt
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
TO DO LIST
|
2
|
+
|
3
|
+
|
4
|
+
1. BUILD A KEYPRESS NAVIGATION FOR MAP COMPONENTS. SHOULD BE ABLE TO PUSH AND SHIFT OFF COMPONENTS IN THE
|
5
|
+
MAP.JS COMPONENTS ARRAY. MODAL BOX SHOULD OPEN ON COMMAND+SHIFT+5.
|
6
|
+
|
7
|
+
$(document).ready(function()
|
8
|
+
{
|
9
|
+
$(document).keypress(function(e)
|
10
|
+
{
|
11
|
+
switch(e.which)
|
12
|
+
{
|
13
|
+
// user presses the "___" KEY
|
14
|
+
case 97: showViaKeypress("#home");
|
15
|
+
break;
|
16
|
+
|
17
|
+
// user presses the "___" KEY
|
18
|
+
case 115: showViaKeypress("#about");
|
19
|
+
}
|
20
|
+
});
|
21
|
+
});
|
22
|
+
|
23
|
+
// shows a given element and hides all others
|
24
|
+
function showViaKeypress(element_id)
|
25
|
+
{
|
26
|
+
$(element_id).slideDown("slow");
|
27
|
+
}
|
28
|
+
|
29
|
+
// shows proper DIV depending on link 'href'
|
30
|
+
function showViaLink(array)
|
31
|
+
{
|
32
|
+
array.each(function(i)
|
33
|
+
{
|
34
|
+
$(this).click(function()
|
35
|
+
{
|
36
|
+
var target = $(this).attr("href");
|
37
|
+
$(".container").css("display","none");
|
38
|
+
$(target).slideDown("slow");
|
39
|
+
});
|
40
|
+
});
|
41
|
+
}
|
42
|
+
|
43
|
+
|
44
|
+
-----------------------------------------
|
45
|
+
|
46
|
+
gem needs underscore.js in javascripts folder. should add modernizr to conditionally load.
|
data/ovi.gemspec
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require File.expand_path('../lib/./version', __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |gem|
|
5
|
+
gem.authors = ["Nick Soto"]
|
6
|
+
gem.email = ["nickesoto@gmail.com"]
|
7
|
+
gem.description = %q{easymap gem}
|
8
|
+
gem.summary = %q{easymap gem}
|
9
|
+
gem.homepage = "https://github.com/nicksoto/easymap"
|
10
|
+
|
11
|
+
gem.files = `git ls-files`.split($\)
|
12
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
13
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
14
|
+
gem.name = "easymap"
|
15
|
+
gem.require_paths = ["lib"]
|
16
|
+
gem.version = OviGem::VERSION
|
17
|
+
gem.add_development_dependency "yalab-ruby-ods"
|
18
|
+
gem.add_runtime_dependency "yalab-ruby-ods"
|
19
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require_relative '../../spec_helper'
|
2
|
+
require 'minitest/spec'
|
3
|
+
|
4
|
+
describe Map::Mapview do
|
5
|
+
|
6
|
+
before do
|
7
|
+
@it = Map::Mapview
|
8
|
+
end
|
9
|
+
|
10
|
+
it "must not be nil" do
|
11
|
+
@it.wont_be_nil
|
12
|
+
end
|
13
|
+
|
14
|
+
it "must include httparty methods" do
|
15
|
+
@it.must_include HTTParty
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should include api base_uri with nok.it" do
|
19
|
+
@it.base_uri.must_include 'http://m.nok.it'
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
require_relative '../lib/map/map'
|
2
|
+
|
3
|
+
require 'minitest/spec'
|
4
|
+
require 'minitest/autorun'
|
5
|
+
require 'webmock/minitest'
|
6
|
+
require 'vcr'
|
7
|
+
require 'turn'
|
8
|
+
|
9
|
+
Turn.config do |c|
|
10
|
+
c.format = :outline
|
11
|
+
c.trace = true
|
12
|
+
c.natural = true
|
13
|
+
end
|
14
|
+
|
15
|
+
VCR.configure do |c|
|
16
|
+
c.cassette_library_dir = 'spec/fixtures/map_cassettes'
|
17
|
+
c.hook_into :webmock
|
18
|
+
end
|
metadata
ADDED
@@ -0,0 +1,103 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: easymap
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.2
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Nick Soto
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-06-29 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: yalab-ruby-ods
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :development
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: yalab-ruby-ods
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
38
|
+
type: :runtime
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
description: easymap gem
|
47
|
+
email:
|
48
|
+
- nickesoto@gmail.com
|
49
|
+
executables: []
|
50
|
+
extensions: []
|
51
|
+
extra_rdoc_files: []
|
52
|
+
files:
|
53
|
+
- .gitignore
|
54
|
+
- .rvmrc
|
55
|
+
- Gemfile
|
56
|
+
- Gemfile.lock
|
57
|
+
- LICENSE
|
58
|
+
- README.md
|
59
|
+
- Rakefile
|
60
|
+
- lib/algorithms/weighted_mean_center.rb
|
61
|
+
- lib/engine/engine.rb
|
62
|
+
- lib/generators/ovimap/build/build_generator.rb
|
63
|
+
- lib/generators/ovimap/display/display_generator.rb
|
64
|
+
- lib/generators/ovimap/heatmap/heatmap_generator.rb
|
65
|
+
- lib/generators/ovimap/helpers.rb
|
66
|
+
- lib/generators/ovimap/install/install_generator.rb
|
67
|
+
- lib/generators/ovimap/install/templates/map.js
|
68
|
+
- lib/generators/ovimap/install/templates/underscore-min.js
|
69
|
+
- lib/generators/ovimap/pin/pin_generator.rb
|
70
|
+
- lib/map/map.rb
|
71
|
+
- lib/ovimaps.rb
|
72
|
+
- lib/version.rb
|
73
|
+
- notes.txt
|
74
|
+
- ovi.gemspec
|
75
|
+
- spec/lib/map/map_spec.rb
|
76
|
+
- spec/spec_helper.rb
|
77
|
+
homepage: https://github.com/nicksoto/easymap
|
78
|
+
licenses: []
|
79
|
+
post_install_message:
|
80
|
+
rdoc_options: []
|
81
|
+
require_paths:
|
82
|
+
- lib
|
83
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
84
|
+
none: false
|
85
|
+
requirements:
|
86
|
+
- - ! '>='
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
version: '0'
|
89
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
90
|
+
none: false
|
91
|
+
requirements:
|
92
|
+
- - ! '>='
|
93
|
+
- !ruby/object:Gem::Version
|
94
|
+
version: '0'
|
95
|
+
requirements: []
|
96
|
+
rubyforge_project:
|
97
|
+
rubygems_version: 1.8.24
|
98
|
+
signing_key:
|
99
|
+
specification_version: 3
|
100
|
+
summary: easymap gem
|
101
|
+
test_files:
|
102
|
+
- spec/lib/map/map_spec.rb
|
103
|
+
- spec/spec_helper.rb
|