import json import csv import os def activity_log_path(activity: str) -> str: """ Returns the path of the activity log file in .csv format :param activity: :return: """ filename = os.path.join("activity_logs", f"{activity}.csv") return filename def activity_units_path(activity: str) -> str: """ Returns the path of the activity activities file in .json format :param activity: :return: """ filename = os.path.join("activities", f"{activity}.json") return filename def is_convertable(activity: str) -> bool: """ Returns True if the activity has multiple units that needed to be converted. i.e. distance may be sent in feet, but would require to be converted in meters. :param activity: :return: """ filename = activity_units_path(activity) raw_data = json.load(open(filename)) return raw_data.get("transformable") def create_activity_log_file(activity: str) -> None: """ Creates the activity log file in .csv format :param activity: :return: """ if not os.path.exists(activity_units_path(activity)): raise ValueError(f"{activity} is not a valid activity") if not os.path.exists("activity_logs"): os.makedirs("activity_logs") filename = activity_log_path(activity) with open(filename, 'a') as f: writer = csv.writer(f) writer.writerow(["timestamp", "username", "value"]) def convert_units(activity: str, value: int | float, unit: str) -> float: """ Returns the value of activity in a factor of 1, i.e. converting feet to meters :param activity: :param value: :param unit: :return: """ filename = activity_units_path(activity) if not os.path.exists(filename): raise ValueError(f"{activity} is not a valid activity") # Consider None unit value as factor of 1 if unit is None: return value raw_data = json.load(open(filename)) units_data = raw_data.get("units") for unit_name, data in units_data.items(): if unit in data["aliases"]: return value * data["factor"] raise ValueError(f"{unit} is not a valid unit") def log_activity( timestamp: int, username: str, activity: str, value: int | float, unit: str | None ) -> None: """ Logs the activity in .csv file :param timestamp: :param username: :param activity: :param value: :param unit: :return: """ if value <= 0 or not isinstance(value, int | float): raise ValueError(f"{value} is not a valid value") filename = activity_log_path(activity) if not os.path.exists(filename): create_activity_log_file(activity) if is_convertable(activity): converted_value = round(convert_units(activity, value, unit), 2) else: converted_value = round(value, 2) with open(filename, 'a') as f: writer = csv.writer(f) writer.writerow([timestamp, username, converted_value]) if __name__ == "__main__": log_activity( timestamp=0, username="test", activity="climb", value=1, unit="m" )