131 lines
4.9 KiB
Python
131 lines
4.9 KiB
Python
#!/usr/bin/env python3
|
||
# -*- coding: utf-8 -*-
|
||
|
||
import datetime
|
||
import geopy.distance
|
||
import json
|
||
import math
|
||
import os
|
||
import glob
|
||
import re
|
||
import sys
|
||
|
||
class C2GAnalyse:
|
||
def __init__(self):
|
||
self.state = {}
|
||
self.in_use = []
|
||
self.total_minutes = 0.0
|
||
self.total_money = 0.0
|
||
self.total_distance = 0.0
|
||
self.run()
|
||
|
||
def find_car_type(self, vin):
|
||
# 1..3 = manufacturer code
|
||
# 4..6 = general type
|
||
# 7 = body form
|
||
# 8..9 = engine type
|
||
# 10 = steering (1=left, 2=right)
|
||
# 11 = manufacturing facilty
|
||
seg = vin[0:9]
|
||
typelist = {
|
||
"WDD117342": ["CLA 180", 0.34],
|
||
"WDC156912": ["GLA 180 CDI", 0.34],
|
||
"WDC156942": ["GLA 180", 0.34],
|
||
"WDC156943": ["GLA 200", 0.34],
|
||
"WDD176012": ["A 180 CDI", 0.31],
|
||
"WDD176042": ["A 180", 0.31],
|
||
"WDD176043": ["A 200", 0.31],
|
||
"WDD246242": ["B 180", 0.34],
|
||
"WME451334": ["smart fortwo 451", 0.26],
|
||
"WME451390": ["smart fortwo 451 ed", 0.29],
|
||
"WME451391": ["smart fortwo 451 ed", 0.29],
|
||
"WME453342": ["smart fortwo 453", 0.26],
|
||
}
|
||
|
||
if not seg in typelist:
|
||
print("Missing vehicle type for {} (VIN {})!".format(seg, vin))
|
||
|
||
return typelist[seg]
|
||
|
||
def run(self):
|
||
for f in sorted(glob.glob(os.path.join("../data/", "*.json"))):
|
||
self.scanfile(f)
|
||
print("{} cars seen in total.".format(len(self.state)))
|
||
print("Total kilometres driven: {}".format(self.total_distance))
|
||
print("Total minutes driven: {}".format(self.total_minutes))
|
||
print("Total money made: {}".format(self.total_money))
|
||
|
||
def scanfile(self, filename):
|
||
stamp = re.search(r'(\d{4}-\d\d-\d\d_\d{6})', filename)
|
||
stamp_str = stamp.group(1)
|
||
stamp_dt = datetime.datetime.strptime(stamp_str, "%Y-%m-%d_%H%M%S")
|
||
print("File: {} ({}, Totals: {:.3f}km, {:.1f}mins, {:.2f}€)".format(filename, stamp_str, self.total_distance, self.total_minutes, self.total_money), end="")
|
||
jf = open(filename, "r")
|
||
doc = json.load(jf)
|
||
jf.close()
|
||
root = doc["placemarks"]
|
||
print(" ({} cars available)".format(len(root)))
|
||
self.parse_cars(stamp_dt, root)
|
||
|
||
def parse_cars(self, stamp, placemarks):
|
||
not_in_use = []
|
||
for pm in placemarks:
|
||
self.update_car(stamp, pm)
|
||
not_in_use.append(pm["name"])
|
||
for car_id in self.state:
|
||
if not car_id in not_in_use:
|
||
if not car_id in self.in_use:
|
||
print("{} OCCUPIED!".format(car_id))
|
||
self.state[car_id]["occupied"] = stamp
|
||
self.in_use.append(car_id)
|
||
else:
|
||
if car_id in self.in_use:
|
||
#print("{} RETURNED!".format(car_id))
|
||
if "occupied" in self.state[car_id]:
|
||
del self.state[car_id]["occupied"]
|
||
self.in_use.remove(car_id)
|
||
|
||
def update_car(self, stamp, new_data):
|
||
car_id = new_data["name"]
|
||
if car_id in self.state:
|
||
old_data = self.state[car_id]
|
||
car_type = self.find_car_type(new_data["vin"])
|
||
if new_data["address"] != old_data["address"]:
|
||
## CAR MOVED
|
||
old_spot = (old_data["coordinates"][1], old_data["coordinates"][0])
|
||
new_spot = (new_data["coordinates"][1], new_data["coordinates"][0])
|
||
distance = geopy.distance.distance(old_spot, new_spot).kilometers
|
||
if not "occupied" in old_data:
|
||
old_data["occupied"] = "unknown"
|
||
minutes = -1
|
||
else:
|
||
minutes = (stamp - old_data["occupied"]).total_seconds() / 60
|
||
self.total_minutes += minutes
|
||
self.total_money += math.ceil(minutes) * car_type[1]
|
||
self.total_distance += distance
|
||
|
||
print("{} {} moved for {:.3f}km/{:.1f}mins: {} ({}%, {}, {}) {} -> {} {} ({}%, {}, {})".format(
|
||
car_type[0],
|
||
car_id,
|
||
distance,
|
||
minutes,
|
||
old_data["address"],
|
||
old_data["fuel"],
|
||
old_data["interior"],
|
||
old_data["exterior"],
|
||
old_data["occupied"],
|
||
stamp,
|
||
new_data["address"],
|
||
new_data["fuel"],
|
||
new_data["interior"],
|
||
new_data["exterior"]
|
||
))
|
||
elif new_data["fuel"] != old_data["fuel"]:
|
||
print("{} FUEL CHANGE: {} -> {}".format(car_id, old_data["fuel"], new_data["fuel"]))
|
||
if new_data["vin"] != old_data["vin"]:
|
||
print("{} ################# VIN CHANGE!!!".format(car_id))
|
||
self.state[car_id] = new_data
|
||
|
||
if __name__=="__main__":
|
||
C2GAnalyse()
|