Changeset 30:b8003f616519 in stamper


Ignore:
Timestamp:
Aug 9, 2014, 2:59:49 AM (8 years ago)
Author:
Borja Lopez <borja@…>
Branch:
default
Phase:
public
Message:

Refactored the graphs/charts code:

  • Fixed a bug introduced when we added the date-based filtering
  • Moved the graph/chart code into a separate method, calling only that method when the user wants to generate a graph.
  • Integrated the code a bit better with the new details method.
  • The svg files are generated using the current date and time, adding a -latest.svg symlink so finding the latest one is easier.

Some examples:

  • generate a chart of all the times recorded for all customers:

stamps -g

  • generates a chart of all the times recorded for all customers for the past week:

stamps -g 1w

  • generates a chart of all the times for a given customer since the first day of 2014:

stamps -g customer 2014-01-01*

(see the filters code to learn more about them)

Still some work needed here though, and I've disabled the nice stacking
bars, which should be back with some form of chart types selector
(so users can set on runtime which type of chart they want)

Files:
2 edited

Legend:

Unmodified
Added
Removed
  • bin/stamps

    r29 r30  
    3636    if args.timeline:
    3737        s.timeline()
     38    elif args.graph:
     39        s.graph_stamps(args.customer, args.filter)
    3840    else:
    39         s.show_stamps(args.customer, args.filter, args.verbose, args.sum,
    40                       args.graph)
     41        s.show_stamps(args.customer, args.filter, args.verbose, args.sum)
  • stamper/stamper.py

    r28 r30  
    44import pygal
    55from datetime import datetime, date, timedelta
    6 from os.path import expanduser, exists
     6from os.path import expanduser, exists, islink
     7from os import symlink, remove
    78from collections import OrderedDict
    89
     
    1011STAMPS_FILE = expanduser('~/.workstamps.json')
    1112DATE_FORMAT = '%Y-%m-%d'
     13TIME_FORMAT = '%H:%M:%S'
    1214DATETIME_FORMAT = '%Y-%m-%d %H:%M'
    1315HOURS_DAY = 8
     
    128130        return filter_from, filter_to
    129131
     132    @property
    130133    def customers(self):
    131134        customers = []
     
    212215                                stamp['action']]))
    213216
     217    def graph_stamps(self, customer=None, stamp_filter=None):
     218        """
     219        Generate charts with information from the stamps
     220        """
     221        filter_from, filter_to = self.validate_filter(stamp_filter)
     222        chart = pygal.Bar(title='Work hours per day',
     223                          range=(0, HOURS_DAY),
     224                          x_title='Days',
     225                          y_title='Work hours',
     226                          x_label_rotation=45)
     227
     228        details, totals, totals_customers = self.details(customer,
     229                                                         filter_from,
     230                                                         filter_to)
     231        days = []
     232        values = {}
     233        for c in self.customers:
     234            values[c] = []
     235
     236        found = []
     237
     238        for day in details:
     239            for c in values:
     240                seconds = totals_customers[day].get(c, 0)
     241                if seconds and c not in found:
     242                    found.append(c)
     243                human = timedelta(seconds=seconds).__str__()
     244                values[c].append({'value': seconds/60.00/60.00,
     245                                  'label': day + ': ' + human})
     246            days.append(day)
     247        chart.x_labels = map(str, days)
     248
     249        if customer:
     250            chart.add(customer, values[customer])
     251        else:
     252            for c in found:
     253                chart.add(c, values[c])
     254
     255        chart_name = 'chart-%s.svg' % datetime.today().strftime(
     256            '%Y-%m-%d_%H%M%S')
     257        chart_symlink = 'chart-latest.svg'
     258        chart.render_to_file('graphs/' + chart_name)
     259        if islink('graphs/'+ chart_symlink):
     260            remove('graphs/'+ chart_symlink)
     261        symlink(chart_name, 'graphs/'+ chart_symlink)
     262
    214263    def show_stamps(self, customer=None, stamp_filter=None, verbose=False,
    215         sum=False, graph=False):
    216 
     264        sum=False):
    217265        filter_from, filter_to = self.validate_filter(stamp_filter)
    218266
     
    263311                    totalDays, remainingHr, remainingMin, HOURS_DAY
    264312                ))
    265 
    266         if graph:
    267             DAYS = 15
    268             list_days = []
    269             list_tot = []
    270             stackedbar_chart = pygal.StackedBar()
    271             stackedbar_chart.title = 'Worked time per day (in hours)'
    272 
    273             if customer:
    274                 for day, tot in totals.iteritems():
    275                     list_days.append(day)
    276                     (h, m, s) = tot.split(':')
    277                     tot_sec = int(h) * 3600 + int(m) * 60 + int(s)
    278                     tot_h = float(tot_sec / float(60) / float(60))
    279                     list_tot.append(tot_h)
    280                 stackedbar_chart.add(customer, list_tot)
    281                 stackedbar_chart.x_labels = map(str, list_days)
    282                 stackedbar_chart.render_to_file('graphs/chart-%s.svg' % customer )
    283             else:
    284                 all_customers = self.customers()
    285                 total_per_customer = {}
    286                 details, totals, total_customer = self.details()
    287                 chars = 0
    288                 total_customer_reverse = total_customer.items()
    289                 total_customer_reverse.reverse()
    290                 for day, tot in total_customer_reverse:
    291                     if chars < DAYS:
    292                         list_days.append(day)
    293                         for cust in self.customers():
    294                             if cust not in tot:
    295                                 tot[cust] = 0
    296                         for cus, time in tot.iteritems():
    297                                 tot_h = float(time / float(60) / float(60))
    298                                 if cus not in total_per_customer:
    299                                     total_per_customer[cus] = []
    300                                 total_per_customer[cus].append(tot_h)
    301                     chars = chars + 1
    302                 for ccus, ctime in total_per_customer.iteritems():
    303                     stackedbar_chart.add(ccus, ctime)
    304                 stackedbar_chart.x_labels = map(str, list_days[-DAYS:])
    305                 stackedbar_chart.render_to_file('graphs/chart-all.svg')
Note: See TracChangeset for help on using the changeset viewer.