def generate(self): # First, filter out any areas that have no values. values = dict(filter(lambda x: len(x[1]) > 0, self.values_map.items())) # Filter out areas that are invalid for this analysis values = dict( filter(lambda x: x[0] not in self.exclude_list, values.items())) # Convert the timedeltas into ints for key, value in values.items(): values[key] = list(map(lambda x: x.seconds, value)) # Used to determine where to place things overall_min = None overall_max = None # Should be of the form key: (max, min, 1st quart, 2nd quart, 3rd quart) box_plot_tuples = {} for key, area_value in values.items(): min_val = min(area_value) max_val = max(area_value) first = percentile(area_value, 25) second = percentile(area_value, 50) third = percentile(area_value, 75) box_plot_tuples[key] = (min_val, max_val, first, second, third) if overall_max is None or overall_min is None: overall_min = min_val overall_max = max_val if min_val < overall_min: overall_min = min_val if max_val > overall_max: overall_max = max_val # Transform the values to character positions from the minimum # Max width is reduced by 7 for 'KEY :: ' max_width_bar = self.max_width - len("KEY :: ") for key, values in box_plot_tuples.items(): if overall_min == overall_max: box_plot_tuples[key] = self._create_box_plot(0, 0, 0, 0, 0) else: positions = list( map( lambda x: int( round(max_width_bar * ((x - overall_min) / (overall_max - overall_min)))), values, )) box_plot_tuples[key] = self._create_box_plot(*positions) # Merge the labels and the box plots into a single string returnable_list = list( map(lambda x: "{0} :: {1}\n".format(x[0], x[1]), box_plot_tuples.items())) # Add the min/max labels min_formatted = utils.format_time_delta(timedelta(0, overall_min)) max_formatted = utils.format_time_delta(timedelta(0, overall_max)) returnable_list.append("MIN :: {0} // MAX :: {1}".format( min_formatted, max_formatted)) return returnable_list
def get_productivity_summary(self): def determine_dominant_hour(start_time, end_time): half_delta = (end_time - start_time) / 2 if (start_time + half_delta).hour == start_time.hour: return start_time.hour else: return end_time.hour entries = self.hord.get_rows() entries_count = len(entries) if len(entries) == 0: return EmptySummary() total_time = timedelta(0) hour_delta_map = {k: timedelta(0) for k in list(range(0, 24))} day_delta_map = {k: timedelta(0) for k in list(range(0, 7))} first_day = None last_day = None for result in entries: if first_day is None or result.start < first_day: first_day = result.start if last_day is None or result.end > last_day: last_day = result.end result_time = result.end - result.start total_time += result_time hour = determine_dominant_hour(result.start, result.end) hour_delta_map[hour] += result.end - result.start day_delta_map[result.start.weekday()] += result.end - result.start formatted_time = utils.format_time_delta(total_time) days = (last_day - first_day).days + 1 simple_summary = SimpleSummary(days, entries_count, formatted_time) return ProductivitySummary(simple_summary, hour_delta_map, day_delta_map, self.config)
def get_projects_summary(self): def projects_filter(entry): return entry.area in list(self.config.get_project_areas().keys()) entries = self.hord.get_rows(filter_func=projects_filter) entries_count = len(entries) if len(entries) == 0: return EmptySummary() total_time = timedelta(0) project_time_map = {} project_area_time_map = {} first_day = None last_day = None for result in entries: if first_day is None or result.start < first_day: first_day = result.start if last_day is None or result.end > last_day: last_day = result.end result_time = result.end - result.start total_time += result_time if result.obj not in project_time_map: project_time_map[result.obj] = result_time else: project_time_map[result.obj] += result_time if result.obj not in project_area_time_map: empty_map = dict( map( lambda x: (x, timedelta(0)), self.config.get_project_areas().keys(), )) project_area_time_map[result.obj] = empty_map project_area_time_map[result.obj][result.area] += result_time else: if result.area not in project_area_time_map[result.obj]: project_area_time_map[result.obj][ result.area] = result_time else: project_area_time_map[result.obj][ result.area] += result_time formatted_time = utils.format_time_delta(total_time) days = (last_day - first_day).days + 1 simple_summary = SimpleSummary(days, entries_count, formatted_time) return ProjectsSummary(simple_summary, project_time_map, project_area_time_map, self.config)
def get_summary(self, target=None, detailed=False): if target is None: entries = self.hord.get_rows() else: entries = self.hord.get_rows( filter_func=lambda x: x.area == target) entries_count = len(entries) if len(entries) == 0: return EmptySummary() total_time = timedelta(0) area_time_map = dict( map(lambda x: (x, []), self.config.get_areas().keys())) last_entries = entries[:10] first_day = None last_day = None for result in entries: if first_day is None or result.start < first_day: first_day = result.start if last_day is None or result.end > last_day: last_day = result.end result_time = result.end - result.start total_time += result_time if detailed: area_time_map[result.area].append(result_time) formatted_time = utils.format_time_delta(total_time) days = (last_day - first_day).days + 1 simple_summary = SimpleSummary(days, entries_count, formatted_time) if detailed and target is not None: return DetailedAreaSummary(simple_summary, target, area_time_map, last_entries, self.config) elif detailed: return DetailedSummary(simple_summary, area_time_map, last_entries, self.config) else: return simple_summary