77# the License, or (at your option) any later version.
88
99import os
10- from string import Template
10+ from io import open
1111from math import *
12+ from string import Template
1213
13- MAP_MARKER = """
14+ MAP_MARKER = """
1415 var M$num = new google.maps.Marker({
1516 position: new google.maps.LatLng($latlon),
1617 map: map,
1920 M$num.setMap(map);
2021"""
2122
22- MAP_LINE = """
23+ MAP_LINE = """
2324 var L$num = [ new google.maps.LatLng($e_ll), new google.maps.LatLng($d_ll)];
2425 var P$num = new google.maps.Polyline({ path: L$num, strokeColor: "#FF8378", strokeOpacity: 1.0, strokeWeight: 2 });
2526 P$num.setMap(map);
2627"""
2728
29+
2830def haversine (lat1 , lon1 , lat2 , lon2 ):
2931 """calculate the great circle distance between two points on the earth"""
3032 lon1 , lat1 , lon2 , lat2 = map (radians , [lon1 , lat1 , lon2 , lat2 ])
3133 dlon = lon2 - lon1
3234 dlat = lat2 - lat1
33- a = sin (dlat / 2 ) ** 2 + cos (lat1 ) * cos (lat2 ) * sin (dlon / 2 ) ** 2
35+ a = sin (dlat / 2 ) ** 2 + cos (lat1 ) * cos (lat2 ) * sin (dlon / 2 ) ** 2
3436 c = 2 * asin (sqrt (a ))
3537 km = 6367 * c
3638 return km
3739
40+
3841class Entry :
39- def __init__ (self , code , name , lat , lon , tag = None , datacenter = None ):
42+ def __init__ (self , code , name , lat , lon , tag = None , datacenter = None , alldcs = None ):
4043 self .code = code
4144 self .name = name
4245 self .lat = lat
4346 self .lon = lon
4447
4548 self .tag = tag
4649 self .datacenter = datacenter
50+ self .alldcs = alldcs
4751
4852 @property
4953 def latlon (self ):
5054 """convenience property used in map generation"""
5155 return "%s, %s" % (self .lat , self .lon )
5256
57+
5358class Entries (dict ):
5459 def __init__ (self ):
5560 self .datacenters = {}
5661
5762 def _get_closest_datacenter (self , lat , lon ):
58- """returns closest regional datacenter using haversine formula"""
63+ """returns the closest regional datacenter using haversine formula"""
5964 distances = {}
6065 for name , datacenter in self .datacenters .items ():
6166 distance = haversine (lat , lon , datacenter .lat , datacenter .lon )
6267 distances [distance ] = name
6368
6469 return distances [min (distances .keys ())]
6570
71+ def _get_datacenters_ordered_by_closest (self , lat , lon ):
72+ """returns all the datacenters, ordered by closest to farthest"""
73+ distances = {}
74+ for name , datacenter in self .datacenters .items ():
75+ distance = haversine (lat , lon , datacenter .lat , datacenter .lon )
76+ distances [distance ] = name
77+
78+ return "," .join (dict (sorted (distances .items ())).values ())
79+
6680 def add_datacenter (self , code , name , lat , lon ):
6781 """add a regional datacenter"""
6882 self .datacenters [code ] = Entry (code , name , lat , lon )
@@ -71,12 +85,13 @@ def add_entry(self, code, name, lat, lon, tag=""):
7185 """add an entry"""
7286 codetag = "-" .join ([code , tag ])
7387 datacenter = self ._get_closest_datacenter (lat , lon )
74- self [codetag ] = Entry (code , name , lat , lon , tag , datacenter )
88+ alldcs = self ._get_datacenters_ordered_by_closest (lat , lon )
89+ self [codetag ] = Entry (code , name , lat , lon , tag , datacenter , alldcs )
7590
7691 def override_entry (self , code , name , tag , datacenter ):
7792 """override an entries datacenter or create a new one"""
7893 codetag = "-" .join ([code , tag ])
79- if self . has_key ( codetag ) :
94+ if codetag in self :
8095 self [codetag ].datacenter = datacenter
8196 else :
8297 self [codetag ] = Entry (code , name , None , None , tag , datacenter )
@@ -87,13 +102,13 @@ def write_index(self, tag, filepath):
87102
88103 for entry in self :
89104 if entry .tag == tag :
90- print >> fd , "%s;%s;%s" % (entry .code , entry .name , entry .datacenter )
105+ fd . write ( "%s;%s;%s;%s \n " % (entry .code , entry .name , entry .datacenter , entry . alldcs ) )
91106
92107 fd .close ()
93108
94109 def write_map (self , template , cables , output ):
95110 """generate map from template (cables, markers, lines)"""
96- t = Template (file (template ).read ())
111+ t = Template (open (template ).read ())
97112
98113 # markers
99114 n = 0
@@ -114,22 +129,23 @@ def write_map(self, template, cables, output):
114129 d = self .datacenters [e .datacenter ]
115130 lines .append (line .substitute (num = n , e_ll = e .latlon , d_ll = d .latlon ))
116131
117- html = t .substitute ( CABLES = file (cables ).read (),
118- MARKERS = "\n " .join (markers ),
119- LINES = "\n " .join (lines ) )
132+ html = t .substitute (CABLES = open (cables ).read (),
133+ MARKERS = "\n " .join (markers ),
134+ LINES = "\n " .join (lines ))
120135
121136 fd = open (output , 'w' )
122137 fd .write (html )
123138 fd .close ()
124139
125140 def __iter__ (self ):
126141 """iterate over the dictionary as it if were a sorted list"""
127- return (self [key ] for key in iter (sorted (dict .iterkeys (self ))))
142+ return (self [key ] for key in iter (sorted (dict .keys (self ))))
143+
128144
129145def main ():
130146 entries = Entries ()
131147
132- for line in file ("input/datacenters" ).readlines ():
148+ for line in open ("input/datacenters" ).readlines ():
133149 if line [0 ] == '#' :
134150 continue
135151 code , name , lat , lon = line .rstrip ().split (";" )
@@ -139,15 +155,15 @@ def main():
139155 if line [0 ] == '#' :
140156 continue
141157 tag = os .path .basename (filepath )
142- for line in file (filepath ).readlines ():
158+ for line in open (filepath ).readlines ():
143159 code , name , lat , lon = line .rstrip ().split (";" )
144160 entries .add_entry (code , name , float (lat ), float (lon ), tag )
145161
146- for line in file ("input/overrides" ).readlines ():
162+ for line in open ("input/overrides" ).readlines ():
147163 if line [0 ] == '#' :
148164 continue
149165 code , tag , name , datacenter = line .rstrip ().split (";" )
150- if entries .datacenters . has_key ( code ) :
166+ if datacenter in entries .datacenters :
151167 entries .override_entry (code , name , tag , datacenter )
152168
153169 entries .write_index ("usa" , "output/usa.index" )
@@ -157,4 +173,3 @@ def main():
157173
158174if __name__ == "__main__" :
159175 main ()
160-
0 commit comments