tasks.py 2.26 KB
from __future__ import absolute_import

from celery.task import Task
import majordome
from scheduler.models import Scheduler
from pyrosapp.models import *

from decimal import Decimal
import math
import itertools

class scheduling(Task):

    def run(self, first_schedule=False, alert=False):

        '''First, we delete scheduled sequences (and plans in case of alert) '''
        if alert is True:
            majordome.TaskManager.delete_pending_alert()
        else:
            majordome.TaskManager.delete_pending_routine()

        Log.objects.create(agent='Scheduler', message='Start schedule')
        self.scheduler = Scheduler()
        if first_schedule is True:
            self.determine_schedule_limits()
        self.scheduler.make_schedule(first_schedule)

        schedule = Schedule.objects.order_by("-created")[0]
        shs_list = schedule.shs.filter(status=Sequence.PENDING)
        Log.objects.create(agent='Scheduler', message='Scheduling finished')

        ''' We create an execute_sequence task for every scheduled sequence '''
        for shs in shs_list:
            res = majordome.tasks.execute_sequence.delay(shs.pk)
            TaskId.objects.create(task_id=res.id, task="execute_sequence")

    def determine_schedule_limits(self):
        sequences = Sequence.objects.all()
        ''' Find the most recurrent night in all sequences '''
        days = {}
        for sequence in sequences:
            truncated = math.floor(float(sequence.jd1))
            if truncated in days.keys():
                days[truncated] += 1
            else:
                days[truncated] = 1
        maximum_truncated = max(days.keys(), key=(lambda key: days[key]))

        ''' Kick all the sequences not in this night '''
        sequences = [sequence for sequence in sequences if math.floor(
            float(sequence.jd1)) == maximum_truncated]

        ''' Set schedule limits as the smallest JD1 and the biggest JD2 '''
        plan_start = -1
        plan_end = -1
        for sequence in sequences:
            if plan_start == -1 or sequence.jd1 < plan_start:
                plan_start = sequence.jd1
            if plan_end == -1 or sequence.jd2 > plan_end:
                plan_end = sequence.jd2
        self.scheduler.set_night_limits(Decimal(plan_start), Decimal(plan_end))