Exemplo n.º 1
0
def _generate_view(drink, user, session, keg):
    """Generates a single "view" (row) based on `drink`."""
    logger.debug(
        '>>> Building stats for drink={}: user={} session={} keg={}'.format(
            drink.id, user.username if user else None,
            session.id if session else None, keg.id if keg else None))

    # Determine previous drinks in the same view.  This *may* be empty if this
    # is the first drink for the view (first pour on the system, drink, etc.)
    prior_drinks_in_view = models.Drink.objects.filter(id__lt=drink.id)
    if user:
        prior_drinks_in_view = prior_drinks_in_view.filter(user=user.id)
    if session:
        prior_drinks_in_view = prior_drinks_in_view.filter(session=session.id)
    if keg:
        prior_drinks_in_view = prior_drinks_in_view.filter(keg=keg.id)

    prior_drinks_in_view = prior_drinks_in_view.order_by('-id')

    prior_stats = util.AttrDict()
    build_list = [drink]
    if prior_drinks_in_view.count():
        # Starting with the most recent prior drink, get its stats row.
        # If stats don't exist, add drink to build list and continue
        # until a stats row is found or all drinks are exhausted.
        # N.B. we avoid a recursive algorithm due to potentially large recursion
        # depth in certain cases.
        for prior_drink in prior_drinks_in_view:
            try:
                prior_stats = util.AttrDict(
                    models.Stats.objects.get(drink=prior_drink,
                                             user=user,
                                             session=session,
                                             keg=keg).stats)
                break
            except models.Stats.DoesNotExist:
                prior_stats = None
                build_list.insert(0, prior_drink)

    # Build all drinks on the hit list.
    for build_drink in build_list:
        logger.debug('  - operating on drink {}'.format(build_drink.id))
        stats = BUILDER.build(drink=build_drink, previous_stats=prior_stats)
        models.Stats.objects.create(drink=build_drink,
                                    user=user,
                                    session=session,
                                    keg=keg,
                                    stats=stats,
                                    is_first=(not prior_stats))
        prior_stats = stats
    logger.debug('<<< Done.')
Exemplo n.º 2
0
def _build_single_view(drink, view, prior_stats=None):
    """Generates all stats for a drink in the specified view.

    Args:
        drink: The target drink.
        view: The view.
        prior_stats: Dictionary of previous stats for this view.  If None,
            indicates that the prior stats are unknown.  When prior stats
            are unknown, they will be queried or generated as needed.
    """
    logger.debug('>>> Building stats for {}'.format(view))

    build_list = [drink]
    if prior_stats is None:
        prior_stats = util.AttrDict()
        prior_drinks_in_view = view.get_prior_drinks(drink)
        if prior_drinks_in_view.count():
            # Starting with the most recent prior drink, get its stats row.
            # If stats don't exist, add drink to build list and continue
            # until a stats row is found or all drinks are exhausted.
            # N.B. we avoid a recursive algorithm due to potentially large recursion
            # depth in certain cases.
            for prior_drink in prior_drinks_in_view:
                try:
                    prior_stats = util.AttrDict(
                        models.Stats.objects.get(drink=prior_drink,
                                                 user=view.user,
                                                 session=view.session,
                                                 keg=view.keg).stats)
                    break
                except models.Stats.DoesNotExist:
                    build_list.insert(0, prior_drink)

    # Build all drinks on the hit list.
    for build_drink in build_list:
        logger.debug('  - operating on drink {}'.format(build_drink.id))
        stats = BUILDER.build(drink=build_drink, previous_stats=prior_stats)
        models.Stats.objects.create(drink=build_drink,
                                    user=view.user,
                                    time=build_drink.time,
                                    session=view.session,
                                    keg=view.keg,
                                    stats=stats,
                                    is_first=(not prior_stats))
        prior_stats = stats
    logger.debug('<<< Done.')
    return stats
Exemplo n.º 3
0
 def __init__(self, drink, drink_qs, previous=None):
     self.drink = drink
     self.drinks = drink_qs
     self.previous = util.AttrDict(copy.deepcopy(previous))
     self.STAT_MAP = {}
     for name, fn in inspect.getmembers(self, inspect.ismethod):
         if hasattr(fn, 'statname'):
             self.STAT_MAP[fn.statname] = fn
Exemplo n.º 4
0
    def build(self, drink, previous_stats):
        if previous_stats is None:
            previous_stats = util.AttrDict()

        logger.debug('build: drink={}'.format(drink.id))
        stats = util.AttrDict()

        for statname, fn in self.functions:
            previous_value = previous_stats.get(statname, None)
            if previous_value is not None:
                val = fn(drink, previous_stats, previous_value=previous_value)
            else:
                val = fn(drink, previous_stats)

            if val is None:
                raise ValueError('Stat generator for %s returned None' %
                                 statname)
            stats[statname] = val
        return stats
Exemplo n.º 5
0
    def get_latest_for_view(cls, user=None, keg=None, session=None):
        """Returns the most recent stats data for the (user, keg, session) tuple.

        Returns an empty dict if no stats available for this view.
        """
        try:
            ret = cls.objects.filter(user=user, keg=keg, session=session).order_by('-id')[0].stats
        except IndexError:
            ret = {}
        return util.AttrDict(ret)
Exemplo n.º 6
0
 def build(self, tag=None):
     stats = util.AttrDict()
     if not self.drink:
         return stats
     if self.previous:
         stats = copy.deepcopy(self.previous)
     for statname, fn in self.STAT_MAP.iteritems():
         previous = self.previous.get(statname, None)
         val = fn(previous)
         if val is None:
             raise ValueError('Stat generator for %s returned None' %
                              statname)
         stats[statname] = val
     return stats
Exemplo n.º 7
0
def _generate_view(drink, previous_drink, user, session, keg):
    """Generates a single "view" (row) based on `drink`."""
    logger.debug('>>> Building stats for drink={}: user={} session={} keg={}'.format(
        drink.id,
        user.username if user else None,
        session.id if session else None,
        keg.id if keg else None))

    # Determine previous drink with same view.  This *may* be empty if this is
    # the first drink for the view (first pour on the system, drink, etc.)
    qs = models.Drink.objects.filter(id__lt=drink.id)
    if user:
        qs = qs.filter(user=user.id)
    if session:
        qs = qs.filter(session=session.id)
    if keg:
        qs = qs.filter(keg=keg.id)

    try:
        previous_drink = qs.order_by('-id')[0]
    except IndexError:
        previous_drink = None

    # There's a previous drink in this view, so fetch its stats record to use
    # as the basis for this record. This *will* fail if the db is incoherent
    # (ie if there are gaps in stats table).
    previous_stats = util.AttrDict()
    if previous_drink:
        previous_row = models.Stats.objects.get(drink=previous_drink, user=user,
            session=session, keg=keg)
        previous_stats = util.AttrDict(previous_row.stats)

    stats = BUILDER.build(drink=drink, previous_stats=previous_stats)
    ret = models.Stats.objects.create(drink=drink, user=user, session=session,
        keg=keg, stats=stats, is_first=(previous_drink is None))
    logger.debug('<<< Done.')
    return ret
Exemplo n.º 8
0
def ProtoMessageToDict(message):
    ret = util.AttrDict()
    #if not message.IsInitialized():
    #  raise ValueError, 'Message not initialized'
    for descriptor, value in message.ListFields():
        if descriptor.label == descriptor.LABEL_REPEATED:
            if descriptor.type == descriptor.TYPE_MESSAGE:
                ret[descriptor.name] = [ProtoMessageToDict(v) for v in value]
            else:
                ret[descriptor.name] = [v for v in value]
        else:
            if descriptor.type == descriptor.TYPE_MESSAGE:
                ret[descriptor.name] = ProtoMessageToDict(value)
            else:
                ret[descriptor.name] = value
    return ret
Exemplo n.º 9
0
 def GetStats(self):
     ret = {}
     record = self.GetStatsRecord()
     if record:
         ret = record.stats
     return util.AttrDict(ret)
Exemplo n.º 10
0
    def testStuff(self):
        site = models.KegbotSite.get()
        stats = site.GetStats()
        self.assertEquals(stats, {})

        now = make_datetime(2012, 1, 2, 12, 00)
        self.maxDiff = None

        d = self.backend.RecordDrink('kegboard.flow0',
                                     ticks=1,
                                     volume_ml=100,
                                     username='******',
                                     pour_time=now)
        expected = util.AttrDict({
            u'volume_by_year': {
                u'2012': 100.0
            },
            u'total_pours': 1,
            u'has_guest_pour': False,
            u'greatest_volume_ml': 100.0,
            u'registered_drinkers': [u'user1'],
            u'volume_by_day_of_week': {
                u'1': 100.0
            },
            u'greatest_volume_id': d.id,
            u'volume_by_drinker': {
                u'user1': 100.0
            },
            u'last_drink_id': d.id,
            u'sessions_count': 1,
            u'average_volume_ml': 100.0,
            u'total_volume_ml': 100.0
        })
        stats = site.GetStats()
        self.assertDictEqual(expected, stats)

        now = make_datetime(2012, 1, 3, 12, 00)
        d = self.backend.RecordDrink('kegboard.flow0',
                                     ticks=200,
                                     volume_ml=200,
                                     username='******',
                                     pour_time=now)
        stats = site.GetStats()
        expected.total_pours = 2
        expected.greatest_volume_ml = 200.0
        expected.greatest_volume_id = d.id
        expected.registered_drinkers.append(u'user2')
        expected.volume_by_drinker[u'user2'] = 200.0
        expected.last_drink_id = d.id
        expected.average_volume_ml = 150.0
        expected.total_volume_ml = 300.0
        expected.volume_by_day_of_week[u'2'] = 200.0
        expected.volume_by_year[u'2012'] = 300.0
        expected.sessions_count = 2
        print 'EXPECTED'
        import pprint
        pprint.pprint(expected)
        print '----'
        print 'ACTUAL'
        pprint.pprint(stats)
        self.assertDictEqual(expected, stats)
Exemplo n.º 11
0
    def testStuff(self):
        site = models.KegbotSite.get()
        stats = site.get_stats()
        self.assertEquals(stats, {})

        now = make_datetime(2012, 1, 2, 12, 00)
        self.maxDiff = None

        d = self.backend.record_drink('kegboard.flow0',
                                      ticks=1,
                                      volume_ml=100,
                                      username='******',
                                      pour_time=now)
        expected = util.AttrDict({
            u'volume_by_year': {
                u'2012': 100.0
            },
            u'total_pours': 1,
            u'has_guest_pour': False,
            u'greatest_volume_ml': 100.0,
            u'registered_drinkers': [u'user1'],
            u'volume_by_day_of_week': {
                u'1': 100.0
            },
            u'greatest_volume_id': d.id,
            u'volume_by_drinker': {
                u'user1': 100.0
            },
            u'volume_by_session': {
                u'1': 100.0
            },
            u'last_drink_id': d.id,
            u'keg_ids': [d.keg.id],
            u'sessions_count': 1,
            u'average_volume_ml': 100.0,
            u'total_volume_ml': 100.0,
            u'largest_session': {
                u'session_id': 1,
                u'volume_ml': 100
            },
        })
        stats = site.get_stats()
        self.assertDictEqual(expected, stats)

        now = make_datetime(2012, 1, 3, 12, 00)
        d = self.backend.record_drink('kegboard.flow0',
                                      ticks=200,
                                      volume_ml=200,
                                      username='******',
                                      pour_time=now)
        stats = site.get_stats()
        expected.total_pours = 2
        expected.greatest_volume_ml = 200.0
        expected.greatest_volume_id = d.id
        expected.registered_drinkers.append(u'user2')
        expected.volume_by_drinker[u'user2'] = 200.0
        expected.last_drink_id = d.id
        expected.average_volume_ml = 150.0
        expected.total_volume_ml = 300.0
        expected.volume_by_day_of_week[u'2'] = 200.0
        expected.volume_by_year[u'2012'] = 300.0
        expected.sessions_count = 2
        expected.volume_by_session = {u'1': 100.0, u'2': 200.0}
        expected.largest_session = {u'session_id': 2, u'volume_ml': 200.0}

        self.assertDictEqual(expected, stats)

        d = self.backend.record_drink('kegboard.flow0',
                                      ticks=300,
                                      volume_ml=300,
                                      username='******',
                                      pour_time=now)

        stats = site.get_stats()
        expected.total_pours = 3
        expected.greatest_volume_ml = 300.0
        expected.greatest_volume_id = d.id
        expected.volume_by_drinker[u'user2'] = 500.0
        expected.last_drink_id = d.id
        expected.average_volume_ml = 200.0
        expected.total_volume_ml = 600.0
        expected.volume_by_day_of_week[u'2'] = 500.0
        expected.volume_by_year[u'2012'] = 600.0
        expected.sessions_count = 2
        expected.volume_by_session = {u'1': 100.0, u'2': 500.0}
        expected.largest_session = {u'session_id': 2, u'volume_ml': 500.0}

        self.assertDictEqual(expected, stats)
        previous_stats = copy.copy(stats)

        d = self.backend.record_drink('kegboard.flow0',
                                      ticks=300,
                                      volume_ml=300,
                                      pour_time=now)

        stats = site.get_stats()
        self.assertTrue(stats.has_guest_pour)

        self.backend.cancel_drink(d)
        stats = site.get_stats()

        self.assertDictEqual(previous_stats, stats)
Exemplo n.º 12
0
 def GetAllTaps(self):
     return [util.AttrDict(d) for d in TEST_TAPS]