def schedule_object(request):
    
    log = logging.getLogger('abcast.schedulerviews.schedule_object')

    if not request.user.has_perm('abcast.schedule_emission'):
        log.warning('unauthorized attempt to schedule emission by: %s' % request.user)
        return { 'message': _('Sorry - you are not allowed to schedule an emission.') }
    
    ct = request.POST.get('ct', None) 
    obj_id = request.POST.get('obj_id', None)
    top = request.POST.get('top', None)
    left = request.POST.get('left', None)
    range_start = request.POST.get('range_start', None)
    range_end = request.POST.get('range_end', None)
    channel_id = request.POST.get('channel_id', SCHEDULER_DEFAULT_CHANNEL_ID)
    channel = Channel.objects.get(pk=channel_id)
    color = request.POST.get('color', 0)
    
    num_days = request.POST.get('num_days', SCHEDULER_NUM_DAYS)
    
    log.debug('content type: %s' % ct)
    
    if ct == 'playlist':
        obj = Playlist.objects.get(pk=int(obj_id))
        log.debug('object to schedule: %s' % obj.name)


        if not (obj.broadcast_status == 1 and obj.type == 'broadcast'):
            log.warning('attempt to shedule invalid playlist. pk: %s' % obj.pk)
            return { 'message': _('Sorry - this playlist does not meet all criterias to be scheduled.') }

    
    
    pph = SCHEDULER_PPH
    # ppd = SCHEDULER_PPD
    ppd = (SCHEDULER_GRID_WIDTH - SCHEDULER_GRID_OFFSET) / int(num_days)
    
    
    top = float(top) / pph * 60
    offset_min = int(15 * round(float(top)/15))
    
    left = float(left) / ppd
    offset_d = int(round(float(left)))
    
        
    log.debug('minutes (offset): %s' % offset_min)
    log.debug('days (offset): %s' % offset_d)
    
    # calculate actual date/time for position
    schedule_start = datetime.datetime.strptime('%s 00:00' % range_start, '%Y-%m-%d %H:%M')
    # add offsets
    time_start = schedule_start + datetime.timedelta(minutes=offset_min)
    time_start = time_start + datetime.timedelta(days=offset_d)
    
    time_start = time_start + datetime.timedelta(hours=SCHEDULER_OFFSET)
    
    # time_end = time_start + datetime.timedelta(milliseconds=obj.get_duration())
    # for duration calculation we use the 'target duration' (to avoid blocked slots)
    time_end = time_start + datetime.timedelta(seconds=(obj.target_duration))

    log.debug('time_start: %s' % time_start)
    log.debug('time_end: %s' % time_end)
    
    # check if in past
    now = datetime.datetime.now()
    lock_end = now + datetime.timedelta(seconds=SCHEDULER_LOCK_AHEAD)
    if lock_end > time_start:
        return { 'message': _('You cannot schedule emissions in the past.') }
    
    # check if slot is free
    # hm just allow some seconds of tolerance (in case of mini-overlaps)
    es = Emission.objects.filter(
        time_end__gt=time_start + datetime.timedelta(seconds=OVERLAP_TOLERANCE),
        time_start__lt=time_end,
        channel=channel)
    if es.count() > 0:
        message = _('The desired time slot does not seem to be available.')
        try:
            message += u'<br>Emission schedule "%s" - from %s to %s' % (e.name, time_start.time(), time_end.time())
            for conflicting_emission in es:
                message += u'<br> - overlaps "%s" - from %s to %s' % (conflicting_emission.name, conflicting_emission.time_start.time(), conflicting_emission.time_end.time())

        except:
            pass
        return { 'message': message }
    
    
    # if no errors so far -> create emission and attach object
    e = Emission(content_object=obj, time_start=time_start, user=request.user, channel=channel, color=color)
    e.save()

    action.send(request.user, verb='scheduled', target=e.content_object)
    
    
    
    data = {
            'status': True,
            'obj_id': obj_id
            }
    
    return data
Example #2
0
def schedule_object(request):

    if not request.user.has_perm('abcast.schedule_emission'):
        log.warning('unauthorized attempt to schedule emission by: %s' % request.user)
        data = { 'message': _('Sorry - you are not allowed to schedule an emission.') }
        return HttpResponse(json.dumps(data), content_type='application/json')


    data = json.loads(request.body)

    ct = data.get('ct', None)
    obj_id = data.get('obj_id', None)
    top = data.get('top', None)
    left = data.get('left', None)
    range_start = data.get('range_start', None)
    range_end = data.get('range_end', None)
    channel_id = data.get('channel_id', SCHEDULER_DEFAULT_CHANNEL_ID)
    channel = Channel.objects.get(pk=channel_id)
    color = data.get('color', 0)

    num_days = data.get('num_days', SCHEDULER_NUM_DAYS)

    log.debug('content type: %s' % ct)

    if ct == 'playlist':
        obj = Playlist.objects.get(pk=int(obj_id))
        log.debug('object to schedule: %s' % obj.name)


        if not (obj.broadcast_status == 1 and obj.type == 'broadcast'):
            log.warning('attempt to shedule invalid playlist. pk: %s' % obj.pk)
            return { 'message': _('Sorry - this playlist does not meet all criterias to be scheduled.') }


    pph = SCHEDULER_PPH
    ppd = (SCHEDULER_GRID_WIDTH - SCHEDULER_GRID_OFFSET) / int(num_days)

    top = float(top) / pph * 60
    offset_min = int(15 * round(float(top)/15))

    left = float(left) / ppd
    offset_d = int(round(float(left)))

    log.debug('minutes (offset): %s' % offset_min)
    log.debug('days (offset): %s' % offset_d)

    # calculate actual date/time for position
    schedule_start = datetime.datetime.strptime('%s 00:00' % range_start, '%Y-%m-%d %H:%M')
    # add offsets
    time_start = schedule_start + datetime.timedelta(minutes=offset_min)
    time_start = time_start + datetime.timedelta(days=offset_d)

    time_start = time_start + datetime.timedelta(hours=SCHEDULER_OFFSET)

    # time_end = time_start + datetime.timedelta(milliseconds=obj.get_duration())
    # for duration calculation we use the 'target duration' (to avoid blocked slots)
    time_end = time_start + datetime.timedelta(seconds=obj.target_duration)

    log.debug('time_start: %s' % time_start)
    log.debug('time_end: %s' % time_end)

    # check if in past
    now = datetime.datetime.now()
    lock_end = now + datetime.timedelta(seconds=SCHEDULER_LOCK_AHEAD)
    if lock_end > time_start:
        return { 'message': _('You cannot schedule emissions in the past.') }

    # check if slot is free
    # hm just allow some seconds of tolerance (in case of mini-overlaps)
    es = Emission.objects.filter(
        time_end__gt=time_start + datetime.timedelta(seconds=OVERLAP_TOLERANCE),
        time_start__lt=time_end,
        channel=channel)
    if es.count() > 0:
        message = _('The desired time slot does not seem to be available.')
        try:
            message += u'<br>Emission schedule from %s to %s' % (time_start.time(), time_end.time())
            for conflicting_emission in es:
                message += u'<br> - overlaps "%s" - from %s to %s' % (conflicting_emission.name, conflicting_emission.time_start.time(), conflicting_emission.time_end.time())

        except:
            pass
        return { 'message': message }


    # if no errors so far -> create emission and attach object
    e = Emission(content_object=obj, time_start=time_start, user=request.user, channel=channel, color=color)
    e.save()

    action.send(request.user, verb='scheduled', target=e.content_object)


    data = {
            'status': True,
            'obj_id': obj_id
            }

    return HttpResponse(json.dumps(data), content_type='application/json')
Example #3
0
    def schedule_daypart(self, daypart):

        log.info('Scheduling daypart: {abs_time_start}-{abs_time_end} - Weekday: {weekday}"'.format(**daypart))

        daypart_duration = (daypart['abs_time_end'] - daypart['abs_time_start'])
        log.debug('Slot duration: {:} seconds'.format(daypart_duration.seconds))


        theme = 3

        if daypart['abs_time_start'].hour in [7, 19]:
            theme = 1

        if daypart['abs_time_start'].hour == 12:
            theme = 2

        if daypart['abs_time_start'].hour == 0:
            theme = 0

        # get applying dayparts & playlists for current slot
        daypart_qs = self.get_daypart_qs(
            weekday=daypart['weekday'],
            time_start=daypart['abs_time_start'],
            time_end=daypart['abs_time_end'],
        )


        next_start = daypart['abs_time_start']
        num_tries = 0
        while next_start and next_start < daypart['abs_time_end']:

            if num_tries > 20:
                raise IOError('io 10??')

            # needs to be re-fetched in every loop
            playlists_qs = self.get_playlist_qs(dayparts=daypart_qs)

            if not playlists_qs.exists():
                next_start = None

            else:

                max_min_durations = playlists_qs.values("target_duration").aggregate(
                        max=Max('target_duration'),
                        min=Min('target_duration')
                )

                next_start, next_end, min_duration, slot_duration = self.get_next_slot(
                        time_start=daypart['abs_time_start'],
                        time_end=daypart['abs_time_end'],
                        min_duration=max_min_durations.get('min', 0)
                )

            if next_start:
                qs = playlists_qs.filter(target_duration__lte=slot_duration)

                if qs.exists():

                    playlists = list(qs.order_by('?'))
                    shuffle(playlists)

                    playlist = playlists[0]
                    #playlist = qs.order_by('?')[0]



                    log.info('Scheduling at {:} - pk: {:} "{:}"'.format(next_start, playlist.pk, playlist.name))

                    emission = Emission(
                        content_object=playlist,
                        time_start=next_start,
                        channel=self.channel,
                        user=self.user,
                        color=theme
                    )

                    emission.save()

                    self.add_playlist_exclude(playlist.pk)

                    self.add_scheduled_emission(emission)



                    time.sleep(1)

            num_tries += 1
    def add_emissions(self, abs_start, abs_end):

        slot_duration = (abs_end - abs_start).seconds
        slot_time_left = slot_duration
        slot_time_offset = 0





        print 'adding emissions to slot: %s to %s' % (abs_start, abs_end)
        print 'weekday: %s' % abs_start.weekday()
        print 'slot_duration: %s' % slot_duration


        from abcast.models import Emission
        from alibrary.models import Playlist

        # look for playlists that match daypart criterias

        # pl_dayparts query
        from alibrary.models import Daypart as PlaylistDaypart

        pldps = PlaylistDaypart.objects.filter(
            day=abs_start.weekday(),
            time_start__lte=abs_start.time(),
            time_end__gte=abs_end.time()
        )

        # very ugly. but no beter quick idea on how to get these bits
        if abs_start.hour == 16:
            pldps = PlaylistDaypart.objects.filter(
                day=abs_start.weekday(),
                time_start__lte=datetime.time(17, 0),
                time_end__gte=datetime.time(20, 0),
            )

        # very ugly. but no beter quick idea on how to get these bits
        if abs_start.hour >= 20:
            pldps = PlaylistDaypart.objects.filter(
                day=abs_start.weekday(),
                time_start__gte=datetime.time(20, 0),
            )

        print 'matching dayparts:'
        for pldp in pldps:
            print pldp

        if slot_duration <= 3600:
            target_durations = [3600]
        else:
            target_durations = [3600, 7200]

        qs = Playlist.objects.filter(
            type='broadcast',
            broadcast_status=1,
            rotation=True,
            dayparts__in=pldps,
            target_duration__in=target_durations
        )

        if self.user_ids:
            qs = qs.filter(user__pk__in=self.user_ids)





        # filling in slots
        while slot_time_left > 0:

            if slot_time_left <= 3600:
                qs = qs.filter(target_duration__in=[3600])
            else:
                qs = qs.filter(target_duration__in=[3600, 7200])

            #print 'excludes: %s' % self.used_playlist_ids
            qs = qs.exclude(pk__in=self.used_playlist_ids)
            print 'adding emission, have %s options' % qs.count()


            playlist = qs.order_by('?')[0]


            print '// random pick:'
            print 'slot_time_left:   %s' % slot_time_left
            print 'slot_time_offset: %s' % slot_time_offset

            print playlist
            print playlist.target_duration
            print

            emission_start = (abs_start + datetime.timedelta(seconds=slot_time_offset))


            theme = SCHEDULER_DEFAULT_THEME

            if abs_start.hour == 6:
                theme = 1

            if abs_start.hour == 12:
                theme = 2

            if abs_start.hour == 19:
                theme = 4


            emission = Emission(
                content_object=playlist,
                time_start=emission_start,
                channel=self.channel,
                user=self.user,
                color=theme
            )

            emission.save()




            # mark as used
            self.used_playlist_ids.append(playlist.id)
            slot_time_left -= playlist.target_duration
            # a bit redundant, i see
            slot_time_offset += playlist.target_duration
Example #5
0
def schedule_object(request):
    
    log = logging.getLogger('abcast.schedulerviews.schedule_object')
    
    ct = request.POST.get('ct', None) 
    obj_id = request.POST.get('obj_id', None)
    top = request.POST.get('top', None)
    left = request.POST.get('left', None)
    range_start = request.POST.get('range_start', None)
    range_end = request.POST.get('range_end', None)
    
    num_days = request.POST.get('num_days', SCHEDULER_NUM_DAYS)
    
    log.debug('content type: %s' % ct)
    
    if ct == 'playlist':
        obj = Playlist.objects.get(pk=int(obj_id))
        log.debug('object to schedule: %s' % obj.name)
    
    
    pph = SCHEDULER_PPH
    # ppd = SCHEDULER_PPD
    ppd = (SCHEDULER_GRID_WIDTH - SCHEDULER_GRID_OFFSET) / int(num_days)
    
    
    top = float(top) / pph * 60
    offset_min = int(15 * round(float(top)/15))
    
    left = float(left) / ppd
    offset_d = int(round(float(left)))
    
        
    log.debug('minutes (offset): %s' % offset_min)
    log.debug('days (offset): %s' % offset_d)
    
    # calculate actual date/time for position
    schedule_start = datetime.datetime.strptime('%s 00:00' % range_start, '%Y-%m-%d %H:%M')
    # add offsets
    time_start = schedule_start + datetime.timedelta(minutes=offset_min)
    time_start = time_start + datetime.timedelta(days=offset_d)
    
    time_start = time_start + datetime.timedelta(hours=SCHEDULER_OFFSET)
    
    # time_end = time_start + datetime.timedelta(milliseconds=obj.get_duration())
    # for duration calculation we use the 'target duration' (to avoid blocked slots)
    time_end = time_start + datetime.timedelta(seconds=(obj.target_duration))

    log.debug('time_start: %s' % time_start)
    log.debug('time_end: %s' % time_end)
    
    # check if in past
    now = datetime.datetime.now()
    lock_end = now + datetime.timedelta(seconds=SCHEDULER_LOCK_AHEAD)
    if lock_end > time_start:
        return { 'message': _('You cannot schedule things in the past!') }
    
    # check if slot is free
    # hm just allow some seconds of tolerance (in case of mini-overlaps)
    es = Emission.objects.filter(time_end__gt=time_start + datetime.timedelta(seconds=2), time_start__lt=time_end)
    if es.count() > 0:
        for em in es:
            print 'Blocking emission: %s' % em.id
            print em.time_start
            print em.time_end
        return { 'message': _('Sorry, but the desired time does not seem to be available.') }
    
    
    # if no errors so far -> create emission and attach object
    e = Emission(content_object=obj, time_start=time_start, user=request.user)
    e.save()
    
    
    
    data = {
            'status': True,
            'obj_id': obj_id
            }
    
    return data
    def add_emission(self, slot_start):

        from abcast.models import Channel, Emission
        from alibrary.models import Playlist
        
        log = logging.getLogger('abcast.autopilot.add_emission')
        log.debug('auto-adding emission, slot start: %s' % slot_start)

        # check if overlapping emission exists
        ces = Emission.objects.filter(time_start__lt=slot_start, time_end__gt=slot_start, channel=self.channel)
        print 'coliding emissions'
        print ces
        if ces.count() > 0:
            next_start = ces[0].time_end
        else:
            next_start = slot_start
            
        print 'next_start: %s' % next_start
        next_start = round_dt(next_start, 300) # round to 5 minutes
        print 'next_start rounded: %s' % next_start
            
        # check how much time is available until next emission
        fes = Emission.objects.filter(time_start__gte=next_start, channel=self.channel).order_by('time_start')
        print fes
        free_slot = 14400
        if fes.count() > 0:
            log.debug('got %s emissions scheduled in future' % fes.count())
            diff = fes[0].time_start - next_start
            free_slot = int(diff.total_seconds())


        log.debug('length of free slot is: %s seconds' % free_slot)
        log.debug('length of free slot is: %s hours' % (int(free_slot) / 60 / 60))
            
        if free_slot == 0 or free_slot < 60:
            print 'FREE SLOT IS %s. ENDS AT:' % free_slot
            print fes[0].time_end
            return fes[0].time_end
            
        """
        look for possible playlists to schedule
        """
        ps = Playlist.objects.filter(target_duration__lte=free_slot, rotation=True, status=1, type="broadcast", duration__gte=29*60*1000).order_by('?')
        
        if ps.count() > 0:
            p = ps[0]
        else:
            p = None
        
        print 'The random selection i!!'
        print p
        
        # create the scheduler entry
        if p:
            e = Emission(content_object=p, time_start=next_start, channel=self.channel, user=self.user, color=SCHEDULER_DEFAULT_THEME)
            e.save()
            # e, c = Emission.objects.get_or_create(content_object=p, time_start=next_start, channel=self.channel, user=self.user, color=SCHEDULER_DEFAULT_THEME)
            
            print 'Created emission, will run until: %s' % e.time_end
            
            return e.time_end
Example #7
0
def schedule_object(request):

    log = logging.getLogger('abcast.schedulerviews.schedule_object')

    ct = request.POST.get('ct', None)
    obj_id = request.POST.get('obj_id', None)
    top = request.POST.get('top', None)
    left = request.POST.get('left', None)
    range_start = request.POST.get('range_start', None)
    range_end = request.POST.get('range_end', None)

    num_days = request.POST.get('num_days', SCHEDULER_NUM_DAYS)

    log.debug('content type: %s' % ct)

    if ct == 'playlist':
        obj = Playlist.objects.get(pk=int(obj_id))
        log.debug('object to schedule: %s' % obj.name)

    pph = SCHEDULER_PPH
    # ppd = SCHEDULER_PPD
    ppd = (SCHEDULER_GRID_WIDTH - SCHEDULER_GRID_OFFSET) / int(num_days)

    top = float(top) / pph * 60
    offset_min = int(15 * round(float(top) / 15))

    left = float(left) / ppd
    offset_d = int(round(float(left)))

    log.debug('minutes (offset): %s' % offset_min)
    log.debug('days (offset): %s' % offset_d)

    # calculate actual date/time for position
    schedule_start = datetime.datetime.strptime('%s 00:00' % range_start,
                                                '%Y-%m-%d %H:%M')
    # add offsets
    time_start = schedule_start + datetime.timedelta(minutes=offset_min)
    time_start = time_start + datetime.timedelta(days=offset_d)

    time_start = time_start + datetime.timedelta(hours=SCHEDULER_OFFSET)

    time_end = time_start + datetime.timedelta(milliseconds=obj.get_duration())

    log.debug('time_start: %s' % time_start)
    log.debug('time_end: %s' % time_end)

    # check if in past
    now = datetime.datetime.now()
    lock_end = now + datetime.timedelta(seconds=SCHEDULER_LOCK_AHEAD)
    if lock_end > time_start:
        return {'message': _('You cannot schedule things in the past!')}

    # check if slot is free
    es = Emission.objects.filter(time_end__gt=time_start,
                                 time_start__lt=time_end)
    if es.count() > 0:
        for em in es:
            print 'Blocking emission: %s' % em.id
            print em.time_start
            print em.time_end
        return {
            'message':
            _('Sorry, but the desired time does not seem to be available.')
        }

    # if no errors so far -> create emission and attach object
    e = Emission(content_object=obj, time_start=time_start, user=request.user)
    e.save()

    data = {'status': True, 'obj_id': obj_id}

    return data