Last active
July 10, 2018 23:09
-
-
Save nitely/ee2b17ade5b27a411e690bcef73a2332 to your computer and use it in GitHub Desktop.
Intercom challenge in Python 3.6
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# -*- coding: utf-8 -*- | |
""" | |
(venv35) bash-4.4$ python customers.py | |
4 Ian Kehoe | |
5 Nora Dempsey | |
6 Theresa Enright | |
8 Eoin Ahearn | |
11 Richard Finnegan | |
12 Christina McArdle | |
13 Olive Ahearn | |
15 Michael Ahearn | |
17 Patricia Cahill | |
23 Eoin Gallagher | |
24 Rose Enright | |
26 Stephen McArdle | |
29 Oliver Ahearn | |
30 Nick Enright | |
31 Alan Behan | |
39 Lisa Ahearn | |
""" | |
import json | |
import math | |
EARTH_RADIUS_KM = 6371 | |
OFFICE_COORS = ( | |
math.radians(53.339428), | |
math.radians(-6.257664)) | |
def _distance(origin, destination): | |
"""Calculate distance between latitude-longitude pairs""" | |
assert origin != destination | |
lat1, lon1 = origin | |
lat2, lon2 = destination | |
return math.acos( | |
math.sin(lat1) * math.sin(lat2) + | |
math.cos(lat1) * math.cos(lat2) * | |
math.cos(abs(lon1) - abs(lon2))) * EARTH_RADIUS_KM | |
class Customer: | |
"""Customer information""" | |
def __init__(self, latitude, longitude, name, user_id): | |
assert isinstance(user_id, int) | |
assert -180 <= float(longitude) <= 180 | |
assert -90 <= float(latitude) <= 90 | |
self.lat = float(latitude) | |
self.lon = float(longitude) | |
self.name = name | |
self.id = user_id | |
def __str__(self): | |
return "{} {}".format(self.id, self.name) | |
@property | |
def location(self): | |
"""Return location coordinates in radians""" | |
return math.radians(self.lat), math.radians(self.lon) | |
def distance_from_office(self): | |
"""Return distance from the office""" | |
return _distance(OFFICE_COORS, self.location) | |
def load_customers(path): | |
"""Load customers from json into a list of ``User``s""" | |
with open(path, 'r', encoding='utf-8') as fh: | |
return [ | |
Customer(**json.loads(line)) | |
for line in fh.readlines()] | |
def nearby(customers, dist=100): | |
""" | |
Return iterator of customers at\ | |
less or equal distance than ``dist``\ | |
from the office | |
""" | |
return iter( | |
c for c in customers | |
if c.distance_from_office() <= dist) | |
def by_id(customers): | |
"""Return customers sorted by their ID in ASC order""" | |
return sorted(customers, key=lambda c: c.id) | |
if __name__ == '__main__': | |
for c in by_id(nearby(load_customers('./customers.json'))): | |
print(str(c)) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# -*- coding: utf-8 -*- | |
import unittest | |
import logging | |
import customers | |
logging.disable(logging.CRITICAL) | |
class CustomerTest(unittest.TestCase): | |
"""Test Customer class""" | |
def test_location(self): | |
self.assertEqual( | |
customers.Customer("52.986375", "-6.043701", "Foo Bar", 1).location, | |
(0.9247867024464105, -0.10548248145607382)) | |
def test_bad_location(self): | |
self.assertRaises( | |
AssertionError, | |
customers.Customer, | |
"91", "-6.043701", "Foo Bar", 1) | |
self.assertRaises( | |
AssertionError, | |
customers.Customer, | |
"-91", "-6.043701", "Foo Bar", 1) | |
self.assertRaises( | |
AssertionError, | |
customers.Customer, | |
"52.986375", "181", "Foo Bar", 1) | |
self.assertRaises( | |
AssertionError, | |
customers.Customer, | |
"52.986375", "-181", "Foo Bar", 1) | |
def test_distance_from_office(self): | |
self.assertRaises( | |
AssertionError, | |
customers.Customer( | |
"53.339428", | |
"-6.257664", # office coors | |
"Esteban Castro", | |
1).distance_from_office) | |
self.assertEqual( | |
customers.Customer("52.986375", "-6.043701", "Foo Bar", 1).distance_from_office(), | |
41.76872550078046) | |
class FuncsTest(unittest.TestCase): | |
"""Test funcs""" | |
def test_load_customers(self): | |
"""should load a fixture of customers""" | |
self.assertTrue( | |
len(customers.load_customers('./customers.json')) >= 32) | |
self.assertEqual( | |
str(customers.load_customers('./customers.json')[0]), | |
str(customers.Customer("52.986375", "-6.043701", "Christina McArdle", 12))) | |
def test_nearby(self): | |
"""should filter everyone at less than 100km from the office""" | |
user_a = customers.Customer("53.2451022", "-6.238335", "Foo", 1) | |
user_b = customers.Customer("53.2451022", "-6.238335", "Bar", 2) | |
user_bad = customers.Customer("51.8856167", "-10.4240951", "Baz", 3) | |
self.assertEqual( | |
list(customers.nearby([user_a, user_b, user_bad])), | |
[user_a, user_b]) | |
def test_by_id(self): | |
"""should sort by ID in ASC order""" | |
user_a = customers.Customer("53.2451022", "-6.238335", "Foo", 1) | |
user_b = customers.Customer("53.2451022", "-6.238335", "Bar", 2) | |
self.assertEqual(list(customers.by_id([user_a, user_b])), [user_a, user_b]) | |
self.assertEqual(list(customers.by_id([user_b, user_a])), [user_a, user_b]) | |
if __name__ == '__main__': | |
import sys | |
argv = ['.', 'discover'] | |
if len(sys.argv) > 1: | |
argv = sys.argv | |
unittest.main(module=None, argv=argv) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment