diff --git a/bicycle_statistics/__main__.py b/bicycle_statistics/__main__.py index 9a0811b..d6b1bec 100644 --- a/bicycle_statistics/__main__.py +++ b/bicycle_statistics/__main__.py @@ -5,7 +5,6 @@ import threading import time from watchdog.observers import Observer - from gpx2html import Gpx2Html from input_observer import InputObserver @@ -14,6 +13,7 @@ LOG_FILE = "/var/log/bicycle-statistics.log" LOG_FORMAT = "%(asctime)s %(levelname)s %(message)s" logging.basicConfig(format=LOG_FORMAT, level=log_level, filename=LOG_FILE) +#logging.basicConfig(format=LOG_FORMAT, level=log_level) log = logging.getLogger('bicycle-statistics') def parse_args(): @@ -26,7 +26,6 @@ def parse_args(): "INFO".') return parser.parse_args() - class myLoop(threading.Thread): def __init__(self, infolder, outfolder): super(myLoop, self).__init__() @@ -36,10 +35,9 @@ class myLoop(threading.Thread): self.observer = Observer() self.in_obs = InputObserver(patterns=["*.gpx"]) - def run(self): - gpx2html = Gpx2Html(self.infolder, self.outfolder) - gpx2html.process() + gpx2html = Gpx2Html(self.infolder, self.outfolder, log) + gpx2html.update() self.observer.schedule(self.in_obs, self.infolder) self.observer.start() @@ -47,9 +45,8 @@ class myLoop(threading.Thread): new_file = self.in_obs.get_new_file() log.info("new file triggered: {}".format(new_file)) if new_file: - gpx2html.process() - log.info("new file processed: {}".format(new_file)) - + time.sleep(5) # ensure .gpx file instead of .part file appeared + gpx2html.update() def stop(self): self.run_condition = False @@ -57,7 +54,6 @@ class myLoop(threading.Thread): self.observer.stop() self.observer.join() - def set_log_level(level): global log_level if level == 'CRITICAL': @@ -74,7 +70,6 @@ def set_log_level(level): log_level = logging.NOTSET log.setLevel(level=log_level) - def main(): args = parse_args() @@ -92,6 +87,5 @@ def main(): my_loop.join() return 0 - if __name__ == '__main__': sys.exit(main()) diff --git a/gpx2html/__init__.py b/gpx2html/__init__.py index ffae2ad..0fa2d69 100755 --- a/gpx2html/__init__.py +++ b/gpx2html/__init__.py @@ -2,6 +2,7 @@ import argparse import datetime +import glob import sys import gpx_parser import matplotlib @@ -11,6 +12,10 @@ import numpy import os import pandas as pd import collections +from gpx_parser import Tracks + +MONTH_LABELS = ['jan', 'feb', 'mar', 'apr', 'may', 'jun', 'jul', 'aug', 'sep', 'oct', 'nov', 'dec'] + def plot_bar_chart(labels, ticklabels, values, title, xlabel, ylabel, filename, xtick_rotation=0): fig = plt.figure() @@ -41,43 +46,103 @@ def plot_bar_chart(labels, ticklabels, values, title, xlabel, ylabel, filename, plt.legend() plt.savefig(filename) - class Gpx2Html(object): - MONTH_LABELS = ['jan', 'feb', 'mar', 'apr', 'may', 'jun', 'jul', 'aug', 'sep', 'oct', 'nov', 'dec'] - - def __init__(self, infolder, outfolder): + def __init__(self, infolder, outfolder, logger): + self.logger = logger self.infolder = infolder self.outfolder = os.path.abspath(outfolder) - self.distance_diag_file = 'distance.png' - self.distance_diag_abs = os.path.join(self.outfolder, self.distance_diag_file) - self.avg_spd_diag_file = 'avg_spd.png' - self.avg_spd_diag_abs = os.path.join(self.outfolder, self.avg_spd_diag_file) - self.last_n_days_diag_file = None - self.html_file = os.path.join(self.outfolder, 'index.html') - self.years_distance = list() - self.years_avg_spd = list() - self.years = list() + self.tracks = Tracks(logger) + self.update() - def plot_distance_diagram(self): - plot_bar_chart(self.years, self.MONTH_LABELS, self.years_distance, - 'Distance', 'Month', 'km', self.distance_diag_abs) + def update(self): + infiles = glob.glob(os.path.join(self.infolder, '*.gpx')) + for filename in infiles: + self.tracks.add(filename) + self.logger.info("Begin update of png's/html...") + distances = list() + avg_speeds = list() + for year in self.tracks.years(): + distances.append(self.tracks.distances(year)) + avg_speeds.append(self.tracks.avg_speeds(year)) - def plot_avg_spd_diagram(self): - plot_bar_chart(self.years, self.MONTH_LABELS, self.years_avg_spd, - 'Average Speed', 'Month', 'km/h', self.avg_spd_diag_abs) + plot_bar_chart(self.tracks.years(), MONTH_LABELS, distances, + 'Distance', 'Month', 'km', + os.path.join(self.outfolder, 'distance.png')) + plot_bar_chart(self.tracks.years(), MONTH_LABELS, avg_speeds, + 'Average Speed', 'Month', 'km/h', + os.path.join(self.outfolder, 'avg_spd.png')) - def plot_last_n_days(self, day_count): - plot_bar_chart(["Distance", "Average speed"], self.date_distance.keys(), - [self.date_distance.values(), self.date_avg_spd.values()], - 'Last {} days'.format(day_count), 'Date', 'km, km/h', - os.path.join(self.outfolder, self.last_n_days_diag_file), 90) + end_date = datetime.datetime.today() + start_date = end_date - datetime.timedelta(days=14) + last_n_tracks = self.tracks.tracks(start_date, end_date) + last_n_distances = dict() + last_n_durations = dict() + dates = pd.date_range(start_date.date(), end_date.date()) + for date in dates: + for track in last_n_tracks: + if date.date() == track.start_time.date(): + get = 0 + try: + get = last_n_distances[date.date()] + except KeyError: + pass + if get == 0: + last_n_distances[date.date()] = track.distance / 1000 + else: + last_n_distances[date.date()] += track.distance / 1000 + try: + get = last_n_durations[date.date()] + except KeyError: + pass + if get == 0: + last_n_durations[date.date()] = track.duration.total_seconds() + else: + last_n_durations[date.date()] += track.duration.total_seconds() + else: + try: + get = last_n_distances[date.date()] + except KeyError: + last_n_distances[date.date()] = 0 + try: + get = last_n_durations[date.date()] + except KeyError: + last_n_durations[date.date()] = 0 + last_n_dist = list() + last_n_dur = list() + last_n_avg = list() + last_n_dates = list() + for date in dates: + try: + last_n_dist.append(last_n_distances[date.date()]) + except KeyError: + last_n_dist.append(0) + try: + last_n_dur.append(last_n_durations[date.date()]) + except KeyError: + last_n_dur.append(0) + date_str = "{0:04d}-{1:02d}-{2:02d}".format(date.year, date.month, date.day) + last_n_dates.append(date_str) + try: + if last_n_durations[date.date()] == 0: + last_n_avg.append(0) + else: + last_n_avg.append(last_n_distances[date.date()] / + (last_n_durations[date.date()] / 3600)) + except KeyError: + last_n_avg.append(0) + plot_bar_chart(["Distance", "Average speed"], last_n_dates, + [last_n_dist, last_n_avg], + 'Last 14 days', 'Date', 'km, km/h', + os.path.join(self.outfolder, 'last_14_days.png'), 90) + self.__write_html_file() + self.logger.info("End update of png's/html...") - def write_html_file(self): - with open(self.html_file, 'w') as handle: + def __write_html_file(self): + with open(os.path.join(self.outfolder, 'index.html'), 'w') as handle: handle.write('\n') handle.write('\n') handle.write('
\n') @@ -99,102 +164,24 @@ class Gpx2Html(object): handle.write('{} | \n'.format(year)) handle.write('|
---|---|
{} km | \n'.format(round(sum(self.years_distance[i]), 1))) + for year in self.tracks.years(): + handle.write('{} km | \n'.format(round(sum(self.tracks.distances(year)), 1))) handle.write('
\n') - handle.write('\n'.format(self.distance_diag_file)) - handle.write('\n'.format(self.avg_spd_diag_file)) - handle.write('\n'.format(self.last_n_days_diag_file)) + handle.write('\n'.format('distance.png')) + handle.write('\n'.format('avg_spd.png')) + handle.write('\n'.format('last_14_days.png')) handle.write('
\n') handle.write('\n') handle.write('