import string, os from copy import * from math import sqrt from sets import * class OffMap: pass class Grid: def __init__(self): self.names = (("SV", "SW", "SX", "SY", "SZ", "TV", "TW"), ("SQ", "SR", "SS", "ST", "SU", "TQ", "TR"), ("SL", "SM", "SN", "SO", "SP", "TL", "TM"), ("SF", "SG", "SH", "SJ", "SK", "TF", "TG"), ("SA", "SB", "SC", "SD", "SE", "TA", "TB"), ("NV", "NW", "NX", "NY", "NZ", "OV", "OW"), ("NQ", "NR", "NS", "NT", "NU", "OQ", "OR"), ("NL", "NM", "NN", "NO", "NP", "OL", "OM"), ("NF", "NG", "NH", "NJ", "NK", "OF", "OG"), ("NA", "NB", "NC", "ND", "NE", "OA", "OB"), ("HV", "HW", "HX", "HY", "HZ", "JV", "JW"), ("HQ", "HR", "HS", "HT", "HU", "JQ", "JR"), ("HL", "HM", "HN", "HO", "HP", "JL", "JM")) self.squares = {} self.letters = {} self.width = 7 self.scale = 1000 # number of 'tenths' in a 100km square side for i, row in enumerate(self.names): for j, sq in enumerate(row): self.squares[sq] = (j * self.scale, i * self.scale) self.letters[i * self.width + j] = sq self.Load() def Load(self, filename = os.environ['HOME'] + '/.makemaprc'): self.places = {} try: file = open(filename) lines = file.readlines() file.close() for line in lines[1:]: place, string_rep = string.split(line, ":") self.places[string.strip(place)] = string.strip(string_rep) except IOError: pass def NumRep(self, place): if place in self.places: string_rep = self.places[place] else: string_rep = place try: num_rep = self.squares[string.upper(string_rep[0:2])] num_rep = [num_rep[0], num_rep[1]] easting = string.lstrip(string_rep[2:5], '0') northing = string.lstrip(string_rep[5:8], '0') if easting == "": easting = "0" if northing == "": northing = "0" num_rep[0] += int(easting) num_rep[1] += int(northing) except: raise OffMap() return num_rep def StringRep(self, num_rep): i = num_rep[0] / self.scale j = num_rep[1] / self.scale easting = num_rep[0] - i * self.scale northing = num_rep[1] - j * self.scale try: string_rep = self.letters[j * self.width + i] + \ string.zfill(easting, 3) + string.zfill(northing, 3) except KeyError: raise OffMap() return string_rep grid = Grid() class Mapref: def __init__(self, rep): # No overloaded constructors, so use 'RTTI' to construct on variable # types. This is the right way to do it. if type(rep) == type('str'): self.num_rep = grid.NumRep(rep) else: self.num_rep = rep def __add__(self, mapref): m = deepcopy(self) m.num_rep[0] += mapref.num_rep[0] m.num_rep[1] += mapref.num_rep[1] return m def __sub__(self, mapref): num_rep = [self.num_rep[i] - mapref.num_rep[i] for i in range(2)] if mapref.__class__ == Mapref: return MaprefDelta(num_rep) elif mapref.__class__ == MaprefDelta: return Mapref(num_rep) else: assert(False) def __repr__(self): return grid.StringRep(self.num_rep) class MaprefDelta: def __init__(self, num_rep): self.num_rep = num_rep def __mul__(self, s): "Integer multiply" m = deepcopy(self) m.num_rep[0] *= s m.num_rep[1] *= s return m def __div__(self, s): "Floating point divide" m = deepcopy(self) e = float(m.num_rep[0]) n = float(m.num_rep[1]) e /= s n /= s m.num_rep[0] = int(e) m.num_rep[1] = int(n) return m def __repr__(self): return "MaprefDelta " + repr(self.num_rep) def Length(self): "Length in kilometres" return sqrt(float(self.num_rep[0] ** 2 + self.num_rep[1] ** 2)) / 10.0 def main(): try: house = Mapref("SP512098") coop = Mapref("Coop") delta = coop - house print delta.Length() except OffMap: print "off map" if __name__ == '__main__': main()