Skip to content

Instantly share code, notes, and snippets.

@nitely
Last active July 10, 2018 23:09
Show Gist options
  • Save nitely/ee2b17ade5b27a411e690bcef73a2332 to your computer and use it in GitHub Desktop.
Save nitely/ee2b17ade5b27a411e690bcef73a2332 to your computer and use it in GitHub Desktop.
Intercom challenge in Python 3.6
# -*- 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))
# -*- 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