Exemple #1
0
    def qn(self):
        qn = []

        # cats.
        for fname, mrel in [
            ('cats__in', self.loccats),
            ('user__cats__in', self.usercats),
            ('place__cats__in', self.placecats),
        ]:
            if mrel.exists():
                mrel = utils.tree_all_downs(mrel.all())
                qn.append(_q(fname, mrel))

        # addresses.
        tmpl = 'address__%s__in'
        for suffix, mrel in [
            ('area', self.areas),
            ('area__city', self.cities),
            ('area__city__state', self.states),
            ('area__city__state__country', self.countries),
            ('area__zip', self.zips),
            ('area__zip__brick', self.bricks),
        ]:
            if mrel.exists():
                qn.append(_qn_or([ _q('%saddress__%s__in' % (prefix, suffix), mrel.all()) for prefix in [ '', 'place__' ] ]))

        # print 'VisitCond', self, qn

        return qn
Exemple #2
0
 def _node_data(_node):
     d = cached.get(_node)
     iscached = d is not None
     if not iscached:
         _upnodes = utils.tree_ups(_node)
         _itemcats = utils.tree_all_downs(utils.list_flatten(_upnodes, lambda enode: enode.itemcats.all()))
         d = dict(
             upnodes = _upnodes,
             itemcats = _itemcats,
             items = ItemCat.els_get(_itemcats),
         )
         cached[_node] = d
     # print '_node_data cached', iscached, _node, d
     return d
Exemple #3
0
 def get_queryset(self):
     qset = super(AbstractView, self).get_queryset()
     for name, deep in [ ('incats', True), ('cats', False) ]:
         cats = self.request.QUERY_PARAMS.get(name)
         if cats:
             model = qset.model # self.get_serializer().opts.model
             field = model._meta.get_field('cats')
             if field:
                 cats = utils.str_ints(cats)
                 if cats:
                     if deep:
                         target = field.related.parent_model
                         cats = utils.list_compact([ utils.db_get(target, cat) for cat in cats ])
                         cats = utils.tree_all_downs(cats)
                     qset = qset.filter(cats__in=cats)
                     # print 'get_queryset', self, type(qset), model, cats
     return qset
Exemple #4
0
 def _reps_usercats():
     ucats = utils.tree_all_downs(form.repusercats.all())
     ucats2 = baseuser.allcats()
     nreps = ucats & ucats2
     # print '_reps_usercats', baseuser, len(ucats), len(ucats2), len(nreps)
     return _reps(False, repdict_usercats, nreps)
Exemple #5
0
 def _reps_items():
     reps1 = form.repitems.all()
     repcats = utils.tree_all_downs(form.repitemcats.all())
     reps2 = ItemCat.els_get(repcats)
     nreps = (reps1 | reps2).distinct()
     return _reps(True, repdict_items, nreps)
Exemple #6
0
 def allcats(self):
     return utils.tree_all_downs(self.cats.all())
Exemple #7
0
    def _generate(self):
        sys = Sys.objects.first()
        print '_generate', self, sys

        qn = [] # collection of multiple conds.

        def _qn_and_or(_qn, _isand):
            return _qn_and(_qn) if _isand else _qn_or(_qn)

        for cond in self.conds.all():
            eqn = cond.qn()
            if eqn:
                qn.append(_qn_and_or(eqn, not self.isand))

        if not qn: # not any ([ getattr(self, e).exists() for e in 'usercats loccats areas cities states countries zips bricks'.split() ])
            # raise ValidationError('Must select at least one condition for Users / Locs.')
            self.generate = False
            self.save()
            return # revert generate and ABORT, so we do NOT waste this builder.

        if qn:
            locs = Loc.objects.filter(_qn_and_or(qn, self.isand))
            # print 'query', locs.query
            locs = list(locs)
        else:
            locs = []

        def _sortkey(eloc):
            addr = eloc.addr()
            by = self.orderby
            def _val():
                v = addr.area
                if by == 'area': return v
                if by in [ 'zip', 'brick' ]:
                    v = v.zip
                    return v if by == 'zip' else v.brick
                v = v.city
                if by == 'city': return v
                v = v.state
                if by == 'state': return v
                v = v.country
                if by == 'country': return v
                error
            val = _val().name
            # print '_sortkey', by, val, eloc
            return val

        locs = sorted(locs, key=_sortkey)
        print 'locs', len(locs), locs

        pcats = utils.tree_all_downs(self.periodcats.all())
        pn1 = list(PeriodCat.els_get(pcats))
        pn2 = list(self.periods.all())
        pn = sorted(set(pn1 + pn2), key=lambda e: e.end)
        print 'pn', pn

        def _day(week, date):
            return getattr(week, utils.weekdays[date.weekday()])

        def _onoff(dt, week, sources, suffix):
            day = _day(week, dt)
            # print '_onoff', dt, week, day
            ok = False
            if day:
                dtdate = dt.date()
                dttime = dt.time()
                intime = False
                for time in day.times.all():
                    if dttime >= time.start and dttime <= time.end:
                        intime = True
                        break
                if intime:
                    sources = utils.list_compact(sources) # remove None's.
                    def _get(prefix, cmp2, checkdate):
                        xn = utils.list_flatten(sources, lambda e: getattr(e, prefix + suffix).all())
                        # print '_onoff._get', cmp2, xn
                        def _filter(e):
                            return cmp2 >= e.start and cmp2 <= e.end and (not e.date or e.date == dtdate if checkdate else True)
                        return utils.list_last(sorted(
                            [ e for e in xn if _filter(e) ],
                            key = lambda e: e.start,
                        ))
                    def _ison(pt):
                        return not pt or pt.on
                    operiod = _get('onoffperiod', dtdate, False)
                    if _ison(operiod):
                        otime = _get('onofftime', dttime, True)
                        if _ison(otime):
                            ok = True
            # if not ok: print '_onoff - FAILED', dt
            return ok

        with transaction.atomic():
            mgr = ForceVisit.objects
            self.qty_slots = 0
            self.qty_slots_skips = 0
            self.qty_locs = len(locs)
            self.qty_locs_skips = 0
            self.qty_node_skips = 0
            nodeskips = 0
            visits = []

            for ep in pn:
                start, end = ep.dates()
                qv = mgr.filter(datetime__range=(start, end)) # query within the current period (start - end).
                delta = end - start
                dates = [ start + datetime.timedelta(days=i) for i in range(delta.days + 1) ]
                week = ep.week or sys.week_period
                print '_generate > ep', ep, week, start, end # dates
                for edate in dates:
                    day = _day(week, edate)
                    print '_generate > edate', edate, day
                    if day:
                        def _datetime(_time): # can't use timedelta with simple times.
                            return datetime.datetime.combine(edate, _time)
                        for etime in day.times.all():
                            dt = _datetime(etime.start)
                            dt2 = _datetime(etime.end)
                            while dt < dt2:
                                self.qty_slots += 1
                                # print '_generate > slot', dt
                                user = self.node.user
                                ison = _onoff(
                                    dt,
                                    (user.week_visit if user else None) or sys.week_user_visit,
                                    [ user ],
                                    '_visit',
                                )
                                if ison:
                                    if qv.filter(node=self.node, datetime=dt).exists(): # visit already generated for the node in this time slot.
                                        self.qty_node_skips += 1
                                        print '_generate > qty_node_skips', dt, self.node
                                    else:

                                        # try (potentially multiple) locs for this specific time slot.
                                        tryloc = True
                                        locs2 = [] # queue for tried locs, which should be retried in the next time slot.
                                        while locs and tryloc:
                                            loc = locs.pop(0) if locs else None
                                            # print '_tryloc', dt, loc
                                            if loc:
                                                if qv.filter(loc=loc): # loc already visited during this period.
                                                    self.qty_locs_skips += 1
                                                    print '_generate > qty_locs_skips', dt, loc
                                                else:
                                                    ison = _onoff(
                                                        dt,
                                                        loc.week or loc.user.week_visited or sys.week_user_visited,
                                                        [ loc, loc.user ],
                                                        '_visited',
                                                    )
                                                    if ison:
                                                        visit = mgr.create(
                                                            builder = self,
                                                            node = self.node,
                                                            loc = loc,
                                                            datetime = dt,
                                                            duration = self.duration,
                                                        )
                                                        print '==> _generate > visit', dt, visit
                                                        visits.append(visit)
                                                        tryloc = False
                                                    else:
                                                        # print '_generate > SKIP VISITED (locs2 queue)', dt, loc
                                                        locs2.append(loc)
                                        locs[0:0] = locs2 # re-insert in order at the beginning, for immediate try during the subsequent time slots.

                                else:
                                    # print '_generate > SKIP VISIT', dt, user
                                    pass
                                dt = utils.datetime_plus(dt, self.duration, self.gap)
            self.qty_visits = len(visits)
            print 'done > generated visits & remaining locs', self.qty_visits, len(locs)
            self.save()