Ad

Modifications of original code.

Functions were modified to generate the required outcome.

Jupyter used to test ideas. Project saved for viewing if required.

All bar the fourth passed the test

Notes test 4 which failed. Unable to get speed rounded to one decimal place. Comments online suggest this a common problem to do with floating point numbers. However, problem did not occur on my Mac.

Additional comments added to script.

Code
Diff
  • """Test equipment positions."""
    from __future__ import annotations
    from collections import Counter, defaultdict
    import datetime as dt
    import math
    import numpy as np
    import pandas as pd
    from typing import Any
    
    from datetime import datetime    # datetime required for calculation of time differences.
    
    def data_dict() -> defaultdict[str, Any]:
        """Return all equipment positions."""
        d = defaultdict(list)
        d['T123'].append({'position': {'x': 42, 'y': 24, 'z': 0.42}, 'timestamp': dt.datetime(2022, 1, 1, hour=12, minute=0, second=0)})
        d['T456'].append({'position': {'x': 21.0, 'y': 34, 'z': 0.289}, 'timestamp': dt.datetime(2022, 1, 1, hour=12, minute=0, second=0)})
        d['T789'].append({'position': {'x': 17, 'y': 39, 'z': 0.789}, 'timestamp': dt.datetime(2022, 1, 1, hour=12, minute=0, second=0)})
        d['T456'].append({'position': {'x': 91.0, 'y': 114, 'z': 0.489}, 'timestamp': dt.datetime(2022, 1, 1, hour=12, minute=0, second=3)})
        d['T123'].append({'position': {'x': 43, 'y': 25, 'z': 0.43}, 'timestamp': dt.datetime(2022, 1, 1, hour=12, minute=0, second=1)})
        d['T789'].append({'position': {'x': 19., 'y': 79, 'z': 0.991}, 'timestamp': dt.datetime(2022, 1, 1, hour=12, minute=0, second=6)})
        d['T123'].append({'position': {'x': 46, 'y': 29, 'z': 0.44}, 'timestamp': dt.datetime(2022, 1, 1, hour=12, minute=0, second=2)})
        d['T456'].append({'position': {'x': 24.0, 'y': 37, 'z': 0.297}, 'timestamp': dt.datetime(2022, 1, 1, hour=12, minute=0, second=4)})
        d['T123'].append({'position': {'x': 49.0, 'y': 32, 'z': 0.451}, 'timestamp': dt.datetime(2022, 1, 1, hour=12, minute=0, second=3)})
        d['T789'].append({'position': {'x': 23., 'y': 81, 'z': 1.103}, 'timestamp': dt.datetime(2022, 1, 1, hour=12, minute=0, second=7)})
        return d
    
    
    def latest_snapshot() -> defaultdict[str, Any]:
        """Return a snapshot of latest equipment."""
        
        # put latest information into a defaultdict[list] list to match list type other def() such as data_dict
        
        #return {
        #    'T123': {'position': {'x': 49.0, 'y': 32, 'z': 0.451}, 'timestamp': dt.datetime(2022, 1, 1, hour=12, minute=0, second=3)},
        #    'T456': {'position': {'x': 24.0, 'y': 37, 'z': 0.297}, 'timestamp': dt.datetime(2022, 1, 1, hour=12, minute=0, second=4)},
        #    'T789': {'position': {'x': 23.0, 'y': 81, 'z': 1.103}, 'timestamp': dt.datetime(2022, 1, 1, hour=12, minute=0, second=7)},
        #}
        
        d = defaultdict(list)
        d['T123'].append({'position': {'x': 49.0, 'y': 32, 'z': 0.451}, 'timestamp': dt.datetime(2022, 1, 1, hour=12, minute=0, second=3)})
        d['T456'].append({'position': {'x': 24.0, 'y': 37, 'z': 0.297}, 'timestamp': dt.datetime(2022, 1, 1, hour=12, minute=0, second=4)})
        d['T789'].append({'position': {'x': 23.0, 'y': 81, 'z': 1.103}, 'timestamp': dt.datetime(2022, 1, 1, hour=12, minute=0, second=7)})
        
        return d
    
    
    def counts() -> dict[str, int]:
        """Return counts per equipment."""
        return {
            'T123': 4,
            'T456': 3,
            'T789': 3
        }
    
    
    def speeds() -> defaultdict[str, Any]:
        """Return speeds of equipment."""
        d = defaultdict(list)
        d['T123'].append({'speed': 4.242654947082074, 'timestamp': dt.datetime(2022, 1, 1, hour=12, minute=0, second=3)})
        d['T123'].append({'speed': 5.00000999999, 'timestamp': dt.datetime(2022, 1, 1, hour=12, minute=0, second=2)})
        d['T123'].append({'speed': 1.4142489172702237, 'timestamp': dt.datetime(2022, 1, 1, hour=12, minute=0, second=1)})
        d['T123'].append({'speed': None, 'timestamp': dt.datetime(2022, 1, 1, hour=12, minute=0, second=0)})
        d['T456'].append({'speed': 102.0687849638664, 'timestamp': dt.datetime(2022, 1, 1, hour=12, minute=0, second=4)})
        d['T456'].append({'speed': 35.43388209045123, 'timestamp': dt.datetime(2022, 1, 1, hour=12, minute=0, second=3)})
        d['T456'].append({'speed': None, 'timestamp': dt.datetime(2022, 1, 1, hour=12, minute=0, second=0)})
        d['T789'].append({'speed': 4.473538196997986, 'timestamp': dt.datetime(2022, 1, 1, hour=12, minute=0, second=7)})
        d['T789'].append({'speed': 6.6750796998987205, 'timestamp': dt.datetime(2022, 1, 1, hour=12, minute=0, second=6)})
        d['T789'].append({'speed': None, 'timestamp': dt.datetime(2022, 1, 1, hour=12, minute=0, second=0)})
        return d
    
    def find_furthest_west(d: defaultdict) -> str:
        """
        Find the name of the truck that is furthest west. That is,
        the truck with the smallest easting position component.
        """
    
        # get most west truck
    
        min_lat = 180
        truck = ''  # truck number
    
        for key in d.keys():
            a1 = d[key]
            posit = (a1.__getitem__(0))['position']  # get position
            lat_temp = posit['x']
            
            if lat_temp < min_lat:   # save truck number with lowest x (hence west) value.
                min_lat = lat_temp
                truck = key 
                
        return truck
    
    def get_latest_snapshot(d: defaultdict) -> dict[str, Any]:
        """
        Return a snapshot of the latest positional updates for the
        equipment.
        """
        
        # get latest entry for each truck. 
    
        e = defaultdict(list)
    
        for key in d.keys():     # Key is truck number
            
            truck = d[key]
    
            #print(len(truck))
        
            count  = 0
            #print(range(len(truck)))
        
            for entry_n1 in range(len(truck)):   # loop through all entries for a truck to get latest entry
        
                time_temp_n1 = (truck.__getitem__(entry_n1))['timestamp']    # get time information from list
            
                if count == 0:
                    time_temp_n2 = time_temp_n1
                    entry_n2 = entry_n1
                    count = 1
                else:
                    if time_temp_n1 > time_temp_n2:
                        time_temp_n2 = time_temp_n1
                        entry_n2 = entry_n1
                
            # put latest entry in e list.
            e[key].append({'position':(truck.__getitem__(entry_n2))['position'],'timestamp':time_temp_n2})
    
        return e
    
    def get_counts(d: defaultdict) -> dict[str, int]:
        """Return a dict of trucks and the times they have provided updates."""
                
        e = {}
    
        for key in d.keys():          # key is the truck number.
            truck = d[key]
            no_entries = len(truck)   # get number of entries per truck.
            e[key] = no_entries
        
        return(e)
            
    def calculate_speeds(d: defaultdict) -> defaultdict[str, Any]:
        """Return a dict of equipment and the speeds they are travelling at."""
        
        # Select a truck, order entries by time, calculate difference in time and space, calculate the speed.
        # No units is given so no conversion in speed is done. Speed in distance / second.
    
        e = defaultdict(list)
    
        for key in d.keys():
    
            truck = d[key]
        
            truck_ordered = truck.sort(key=lambda x:x['timestamp'])    # order truck time
        
            # get position and time difference. Calculuate speed.
        
            no_entries = len(truck)
    
            count = 0
            len_n1 = len(truck)
            for entry_n1 in range(len_n1):
    
                time_temp_n1 = (truck.__getitem__(entry_n1))['timestamp']      # get time
                position_temp_n1 = (truck.__getitem__(entry_n1))['position']   # get position
            
                if count == 0:
                    e[key].append({'speed':None,'timestamp':time_temp_n1})     # first time entry, set speed to None.
                    count = 1
                else:
                    time_temp_n2 = (truck.__getitem__(entry_n1 + 1))['timestamp']    
                    position_temp_n2 = (truck.__getitem__(entry_n1 + 1))['position']
                
                    # get spatial difference
                    x_diff = abs(position_temp_n2['x'] - position_temp_n1['x'])
                    y_diff = abs(position_temp_n2['y'] - position_temp_n1['y'])
                
                    distance = math.sqrt((x_diff * x_diff) + (y_diff * y_diff))
                
                    # get temporal difference
                        
                    time_diff = abs((time_temp_n1 - time_temp_n2).total_seconds())
                    
                    # calculate speed
                
                    speed = round((distance / time_diff),1)  # round to 1 decimal place
                        
                    e[key].append({'speed':speed,'timestamp':time_temp_n1})
                            
                    count = count + 1
                
                # Break loop
                if count == len_n1 - 1:
                    break
            
        return e
    
    
    
    
    • """Test equipment positions."""
    • from __future__ import annotations
    • from collections import Counter, defaultdict
    • import datetime as dt
    • import math
    • import numpy as np
    • import pandas as pd
    • from typing import Any
    • from datetime import datetime # datetime required for calculation of time differences.
    • def data_dict() -> defaultdict[str, Any]:
    • """Return all equipment positions."""
    • d = defaultdict(list)
    • d['T123'].append({'position': {'x': 42, 'y': 24, 'z': 0.42}, 'timestamp': dt.datetime(2022, 1, 1, hour=12, minute=0, second=0)})
    • d['T456'].append({'position': {'x': 21.0, 'y': 34, 'z': 0.289}, 'timestamp': dt.datetime(2022, 1, 1, hour=12, minute=0, second=0)})
    • d['T789'].append({'position': {'x': 17, 'y': 39, 'z': 0.789}, 'timestamp': dt.datetime(2022, 1, 1, hour=12, minute=0, second=0)})
    • d['T456'].append({'position': {'x': 91.0, 'y': 114, 'z': 0.489}, 'timestamp': dt.datetime(2022, 1, 1, hour=12, minute=0, second=3)})
    • d['T123'].append({'position': {'x': 43, 'y': 25, 'z': 0.43}, 'timestamp': dt.datetime(2022, 1, 1, hour=12, minute=0, second=1)})
    • d['T789'].append({'position': {'x': 19., 'y': 79, 'z': 0.991}, 'timestamp': dt.datetime(2022, 1, 1, hour=12, minute=0, second=6)})
    • d['T123'].append({'position': {'x': 46, 'y': 29, 'z': 0.44}, 'timestamp': dt.datetime(2022, 1, 1, hour=12, minute=0, second=2)})
    • d['T456'].append({'position': {'x': 24.0, 'y': 37, 'z': 0.297}, 'timestamp': dt.datetime(2022, 1, 1, hour=12, minute=0, second=4)})
    • d['T123'].append({'position': {'x': 49.0, 'y': 32, 'z': 0.451}, 'timestamp': dt.datetime(2022, 1, 1, hour=12, minute=0, second=3)})
    • d['T789'].append({'position': {'x': 23., 'y': 81, 'z': 1.103}, 'timestamp': dt.datetime(2022, 1, 1, hour=12, minute=0, second=7)})
    • return d
    • def latest_snapshot() -> dict[str, Any]:
    • def latest_snapshot() -> defaultdict[str, Any]:
    • """Return a snapshot of latest equipment."""
    • return {
    • 'T123': {'position': {'x': 49.0, 'y': 32, 'z': 0.451}, 'timestamp': dt.datetime(2022, 1, 1, hour=12, minute=0, second=3)},
    • 'T456': {'position': {'x': 24.0, 'y': 37, 'z': 0.297}, 'timestamp': dt.datetime(2022, 1, 1, hour=12, minute=0, second=4)},
    • 'T789': {'position': {'x': 23.0, 'y': 81, 'z': 1.103}, 'timestamp': dt.datetime(2022, 1, 1, hour=12, minute=0, second=7)},
    • }
    • # put latest information into a defaultdict[list] list to match list type other def() such as data_dict
    • #return {
    • # 'T123': {'position': {'x': 49.0, 'y': 32, 'z': 0.451}, 'timestamp': dt.datetime(2022, 1, 1, hour=12, minute=0, second=3)},
    • # 'T456': {'position': {'x': 24.0, 'y': 37, 'z': 0.297}, 'timestamp': dt.datetime(2022, 1, 1, hour=12, minute=0, second=4)},
    • # 'T789': {'position': {'x': 23.0, 'y': 81, 'z': 1.103}, 'timestamp': dt.datetime(2022, 1, 1, hour=12, minute=0, second=7)},
    • #}
    • d = defaultdict(list)
    • d['T123'].append({'position': {'x': 49.0, 'y': 32, 'z': 0.451}, 'timestamp': dt.datetime(2022, 1, 1, hour=12, minute=0, second=3)})
    • d['T456'].append({'position': {'x': 24.0, 'y': 37, 'z': 0.297}, 'timestamp': dt.datetime(2022, 1, 1, hour=12, minute=0, second=4)})
    • d['T789'].append({'position': {'x': 23.0, 'y': 81, 'z': 1.103}, 'timestamp': dt.datetime(2022, 1, 1, hour=12, minute=0, second=7)})
    • return d
    • def counts() -> dict[str, int]:
    • """Return counts per equipment."""
    • return {
    • 'T123': 4,
    • 'T456': 3,
    • 'T789': 3
    • }
    • def speeds() -> defaultdict[str, Any]:
    • """Return speeds of equipment."""
    • d = defaultdict(list)
    • d['T123'].append({'speed': 4.242654947082074, 'timestamp': dt.datetime(2022, 1, 1, hour=12, minute=0, second=3)})
    • d['T123'].append({'speed': 5.00000999999, 'timestamp': dt.datetime(2022, 1, 1, hour=12, minute=0, second=2)})
    • d['T123'].append({'speed': 1.4142489172702237, 'timestamp': dt.datetime(2022, 1, 1, hour=12, minute=0, second=1)})
    • d['T123'].append({'speed': None, 'timestamp': dt.datetime(2022, 1, 1, hour=12, minute=0, second=0)})
    • d['T456'].append({'speed': 102.0687849638664, 'timestamp': dt.datetime(2022, 1, 1, hour=12, minute=0, second=4)})
    • d['T456'].append({'speed': 35.43388209045123, 'timestamp': dt.datetime(2022, 1, 1, hour=12, minute=0, second=3)})
    • d['T456'].append({'speed': None, 'timestamp': dt.datetime(2022, 1, 1, hour=12, minute=0, second=0)})
    • d['T789'].append({'speed': 4.473538196997986, 'timestamp': dt.datetime(2022, 1, 1, hour=12, minute=0, second=7)})
    • d['T789'].append({'speed': 6.6750796998987205, 'timestamp': dt.datetime(2022, 1, 1, hour=12, minute=0, second=6)})
    • d['T789'].append({'speed': None, 'timestamp': dt.datetime(2022, 1, 1, hour=12, minute=0, second=0)})
    • return d
    • def find_furthest_west(d: defaultdict) -> str:
    • """
    • Find the name of the truck that is furthest west. That is,
    • the truck with the smallest easting position component.
    • """
    • return ''
    • # get most west truck
    • min_lat = 180
    • truck = '' # truck number
    • for key in d.keys():
    • a1 = d[key]
    • posit = (a1.__getitem__(0))['position'] # get position
    • lat_temp = posit['x']
    • if lat_temp < min_lat: # save truck number with lowest x (hence west) value.
    • min_lat = lat_temp
    • truck = key
    • return truck
    • def get_latest_snapshot(d: defaultdict) -> dict[str, Any]:
    • """
    • Return a snapshot of the latest positional updates for the
    • equipment.
    • """
    • return {}
    • # get latest entry for each truck.
    • e = defaultdict(list)
    • for key in d.keys(): # Key is truck number
    • truck = d[key]
    • #print(len(truck))
    • count = 0
    • #print(range(len(truck)))
    • for entry_n1 in range(len(truck)): # loop through all entries for a truck to get latest entry
    • time_temp_n1 = (truck.__getitem__(entry_n1))['timestamp'] # get time information from list
    • if count == 0:
    • time_temp_n2 = time_temp_n1
    • entry_n2 = entry_n1
    • count = 1
    • else:
    • if time_temp_n1 > time_temp_n2:
    • time_temp_n2 = time_temp_n1
    • entry_n2 = entry_n1
    • # put latest entry in e list.
    • e[key].append({'position':(truck.__getitem__(entry_n2))['position'],'timestamp':time_temp_n2})
    • return e
    • def get_counts(d: defaultdict) -> dict[str, int]:
    • """Return a dict of trucks and the times they have provided updates."""
    • return {}
    • e = {}
    • for key in d.keys(): # key is the truck number.
    • truck = d[key]
    • no_entries = len(truck) # get number of entries per truck.
    • e[key] = no_entries
    • return(e)
    • def calculate_speeds(d: defaultdict) -> defaultdict[str, Any]:
    • """Return a dict of equipment and the speeds they are travelling at."""
    • return defaultdict(list)
    • # Select a truck, order entries by time, calculate difference in time and space, calculate the speed.
    • # No units is given so no conversion in speed is done. Speed in distance / second.
    • e = defaultdict(list)
    • for key in d.keys():
    • truck = d[key]
    • truck_ordered = truck.sort(key=lambda x:x['timestamp']) # order truck time
    • # get position and time difference. Calculuate speed.
    • no_entries = len(truck)
    • count = 0
    • len_n1 = len(truck)
    • for entry_n1 in range(len_n1):
    • time_temp_n1 = (truck.__getitem__(entry_n1))['timestamp'] # get time
    • position_temp_n1 = (truck.__getitem__(entry_n1))['position'] # get position
    • if count == 0:
    • e[key].append({'speed':None,'timestamp':time_temp_n1}) # first time entry, set speed to None.
    • count = 1
    • else:
    • time_temp_n2 = (truck.__getitem__(entry_n1 + 1))['timestamp']
    • position_temp_n2 = (truck.__getitem__(entry_n1 + 1))['position']
    • # get spatial difference
    • x_diff = abs(position_temp_n2['x'] - position_temp_n1['x'])
    • y_diff = abs(position_temp_n2['y'] - position_temp_n1['y'])
    • distance = math.sqrt((x_diff * x_diff) + (y_diff * y_diff))
    • # get temporal difference
    • time_diff = abs((time_temp_n1 - time_temp_n2).total_seconds())
    • # calculate speed
    • speed = round((distance / time_diff),1) # round to 1 decimal place
    • e[key].append({'speed':speed,'timestamp':time_temp_n1})
    • count = count + 1
    • # Break loop
    • if count == len_n1 - 1:
    • break
    • return e