示例#1
0
def _get_future_maintenance_dates3():
    today = TimeAgent.truncateDt(datetime.now())
    mp = Period.objects\
        .filter(session__observing_type__type = "maintenance")\
        .latest("start")

    last_date = mp.start
    week = today - timedelta(today.weekday()) # get the date of the Monday of this week.
    dates = {}

    # now loop, one week at a time, until that last date, gathering
    # all the maintenance periods.  Each group will be represented as
    # a day of the week: 'A' = 0 (Monday), 'B' = 1 (Tuesday), etc.
    # These dates are then entered into the list of possible future
    # dates.
    
    while week < last_date:
        groups = Maintenance_Activity_Group.get_maintenance_activity_groups(week)

        for i in groups:
            d = str(i.get_start().date())
            
            if not dates.has_key(d):
                dates[d] = []
                
            dates[d].append(str(i.rank))
            
        week += timedelta(7)

    return dates
        def get_due_date(template):
            if template.repeat_interval == 30:
                due_dates = get_monthly_due_dates(template)

                for i in range(0, 7):
                    dday = self.week + timedelta(days = i)
                    
                    if dday in due_dates:
                        return dday
                    
            if template.repeat_interval == 7:
                week = TimeAgent.truncateDt(self.week)
                start_date = TimeAgent.truncateDt(template.get_start())
                diff = timedelta(days = (week - start_date).days % \
                                     template.repeat_interval)
                return week + timedelta(7) - diff
            return None
示例#3
0
        def good_fit(template, mag):
            # Checks to see if this template wouldn't work better
            # elsewhere.  If so, returns False.  If not, returns True.

            # first, take care of simple cases: repeat = 1, or no
            # published mags this week, the template is due, and this
            # is the highest U:

            if template.repeat_interval == 1:
                return False if better_fit(t, other_groups_today) else True

            if len(published_groups_this_week) == 0 \
                    and is_highest_U(mag):
                return True

            if is_P(self):
                # Here we generate a dictionary to weigh the possible dates that a 
                # repeat event can be substantiated in. The lower the number the better. 
                # A slight preference is given to the date that comes before the due date
                # over one that comes after, but that's really just for tie-breaking purposes.
                #dm = {-4: 40, -3: 30, -2: 20, -1: 10, 0: 0, 1: 15, 2: 25, 3: 35, 4: 45}
                dayLen = 30
                dm = [(i,10*abs(i)) for i in range(-dayLen,1)]
                dm.extend([(i,(10*i)+5) for i in range(1,dayLen)])
                dm = dict(dm)

                today = TimeAgent.truncateDt(self.period.start)
                p = [mag.period for mag in published_groups_this_week]
                due_date = get_due_date(template)
                diff = (today - due_date).days

                if diff:
                    # doesn't fall on this date.  Is this the closest
                    # period though?
                    for j in p:
                        if j != self.period:  # check only other periods
                            mod = (TimeAgent.truncateDt(j.start) - due_date).days

                            # Test to see if it's a better fit in
                            # another period.  and if so, don't
                            # use here.
                            if dm[mod] < dm[diff]:
                                return False
                return True
            return False
示例#4
0
def _get_fixed_maint_events(mags, day, timezone):
    """
    _get_fixed_maint_events(mags, day, timezone)

    Takes a set of maintenance activity groups and returns the one for
    'day' if there is a fixed one for 'day'.
    """

    evs = []
    day = TimeAgent.truncateDt(day)
    tomorrow = day + timedelta(1)

    for mag in mags:
        if mag.period:  # fixed if period is set
            if (
                TimeAgent.truncateDt(mag.get_start(timezone)) == day
                or TimeAgent.truncateDt(mag.get_end(timezone)) == day
            ):
                ev = CalEventFixedMaintenance(
                    mag, mag.get_start(timezone) < day, mag.get_end(timezone) >= tomorrow, True, timezone
                )
                evs.append(ev)
    return evs
        def good_fit(template, mag):
            # Checks to see if this template wouldn't work better
            # elsewhere.  If so, returns False.  If not, returns True.

            # first, take care of simple cases: repeat = 1, or no
            # published mags this week, the template is due, and this
            # is the highest U:

            if template.repeat_interval == 1:
                return False if better_fit(t, other_groups_today) else True

            if len(published_groups_this_week) == 0 \
                    and is_highest_U(mag):
                return True

            if is_P(self):
                dm = {-4: 40, -3: 30, -2: 20, -1: 10, 0: 0, 1: 15, 2: 25, 3: 35, 4: 45}
                today = TimeAgent.truncateDt(self.period.start)
                p = [mag.period for mag in published_groups_this_week]
                due_date = get_due_date(template)
                diff = (today - due_date).days

                if diff:
                    # doesn't fall on this date.  Is this the closest
                    # period though?
                    for j in p:
                        if j != self.period:  # check only other periods
                            mod = (TimeAgent.truncateDt(j.start) - due_date).days

                            # Test to see if it's a better fit in
                            # another period.  and if so, don't
                            # use here.
                            if dm[mod] < dm[diff]:
                                return False
                return True
            return False
示例#6
0
def _get_future_maintenance_dates3():
    today = TimeAgent.truncateDt(datetime.now())
    mp = Period.objects\
        .filter(session__observing_type__type = "maintenance")\
        .latest("start")

    last_date = mp.start
    week = today - timedelta(today.weekday()) # get the date of the Monday of this week.
    dates = {}

    # now loop, one week at a time, until that last date, gathering
    # all the maintenance periods.  Each group will be represented as
    # a day of the week: 'A' = 0 (Monday), 'B' = 1 (Tuesday), etc.
    # These dates are then entered into the list of possible future
    # dates.

    while week < last_date:
        groups = Maintenance_Activity_Group.get_maintenance_activity_groups(week)

        for i in groups:
            d = str(i.get_start().date())

            if not dates.has_key(d):
                dates[d] = []

            # we want either the start time--in format "HH:MM"--if a
            # period is assigned, or the rank, if still floating.
            if (i.period):
                # t will be in format "HH:MM:SS"
                t = str(i.get_start(tzname = 'ET').time())
                # use only "HH:MM" part of time string
                dates[d].append(t[0:t.rfind(":")])
            else:
                dates[d].append(str(i.rank))

        week += timedelta(7)

    for i in dates:
        dates[i].sort()

    return dates
from users.models import Maintenance_Activity, Maintenance_Activity_Group
from scheduler.models import Period
from datetime import datetime, timedelta
from nell.utilities import TimeAgent

from scheduler.models import Period

periods = Period.objects.filter(session__observing_type__type = "maintenance")\
    .exclude(state__name = "Deleted").order_by("start")

for p in periods:
    if p:
        mag = Maintenance_Activity_Group()
        mag.save()
        mag.period = p
        mag.week = TimeAgent.truncateDt(p.start - timedelta(p.start.weekday()))
        mag.deleted = True if p.state.name == 'Deleted' else False
        mag.save()
        print "Period %i -> Group %i" % (p.id, mag.id)
        mas = [m for m in p.maintenance_activity_set.all()]
        for ma in mas:
            ma.group = mag
            ma.period = None
            ma.save()

mags = Maintenance_Activity_Group.objects.all()
week = set()

for mag in mags:
    week.add(mag.week)
示例#8
0
    def check_for_conflicting_resources(self, mas):
        """
        Checks other maintenance activities on the same day to see
        whether there are maintenance activities whose resource
        requirements conflict.  If it finds any, it appends the
        resource specification (presented in the same way the summary
        does) to a list.
        """

        start = TimeAgent.truncateDt(self.get_start())
        end = start + timedelta(days = 1)
        rval = []

        for i in range(0, len(mas)):
            if self.id == mas[i].id:
                continue

            else:
                my_start = self.get_start()
                my_end = my_start + timedelta(hours = self.duration)
                other_start = mas[i].get_start()
                other_end = other_start + timedelta(hours = mas[i].duration)

                #check 'self' for time intersection with mas[i]
                if not (my_start >= other_end or my_end <= other_start):
                    my_summary = self.get_resource_summary()[1:-1].split(', ')
                    other_summary = mas[i].get_resource_summary()[1:-1]\
                        .split(', ')

                    for i in my_summary:
                        if 'T=' in i:
                            for j in other_summary:
                                if 'T=' in j:  # both have 'T='
                                    tr = Maintenance_Telescope_Resources.objects\
                                         .filter(rc_code=i[2])[0]

                                    if j[2] not in tr.compatibility:
                                        rval.append(i)
                        elif 'S=' in i:
                            for j in other_summary:
                                if 'S=' in j:  # both have 'S='
                                    sr = Maintenance_Software_Resources.objects\
                                         .filter(rc_code=i[2])[0]

                                    if j[2] not in sr.compatibility:
                                        rval.append(i)
                        elif 'O=' in i:
                            #get resource 'x' in 'O=x'
                            other = Maintenance_Other_Resources.objects\
                                    .filter(rc_code=i[2])[0]

                            for j in other_summary:
                                # 'None' does not conflict with anything
                                if 'N' not in i:
                                    if 'O=' in j \
                                            and j[2] not in other.compatibility:
                                        rval.append(i)

                                    if 'R=' in j \
                                            and 'R' not in other.compatibility:
                                        rval.append(i)

                                    if 'B=' in j \
                                            and 'B' not in other.compatibility:
                                        rval.append(i)

                        else: #everything else: receivers, backends

                            # R, U, D (for Receiver, Up and Down) are
                            # equivalent.  Flag conflicts if any of
                            # these match, i.e. U=600 matches R=600.
                            # Also check against 'O=' not N

                            x = re.match('[RUD]=.', i)

                            for j in other_summary:
                                y = re.match('[RUD]=.', j)

                                if x and y:
                                    if i[2:] == j[2:]:
                                        rval.append(i)
                                elif i == j:
                                    if not 'T=' in i \
                                            and not 'S=' in i and not 'O=' in i:
                                        rval.append(i)

                                elif 'O=' in j and 'N' not in j:
                                    #get resource 'x' in 'O=x'
                                    other = Maintenance_Other_Resources.objects\
                                            .filter(rc_code=j[2])[0]

                                    if i[0] not in other.compatibility:
                                        rval.append(i)


        return rval
示例#9
0
def _process_activity(request, ma, form):
    """
    Does some processing in common between the add and the edit views.
    """
    # process the returned stuff here...
    ma.subject = form.cleaned_data['subject']

    # The date and time entered into the form will be ET.  It
    # must be converted to UTC.  The end-time need not be
    # converted since a duration is computed and stored in the
    # database instead of the end time.
    diffs = {}
    date = form.cleaned_data['date']
    start = datetime(date.year, date.month, date.day,
                     hour = int(form.cleaned_data['time_hr']),
                     minute = int(form.cleaned_data['time_min']))
    diffs = _record_diffs('start', ma.get_start('ET') if ma._start else start, start, diffs)
    ma.set_start(start, 'ET')
    oldval = ma.duration

    if form.cleaned_data["end_choice"] == "end_time":
        end_date = form.cleaned_data['date']
        end = datetime(year = end_date.year, month = end_date.month,
                       day = end_date.day,
                       hour = int(form.cleaned_data['end_time_hr']),
                       minute = int(form.cleaned_data['end_time_min']))
        delta = end - start
        ma.duration = delta.seconds / 3600.0 # in decimal hours
    else:
        ma.duration = float(form.cleaned_data['end_time_hr']) \
            + float(form.cleaned_data["end_time_min"]) / 60.0

    diffs = _record_diffs('duration', oldval, ma.duration, diffs)
    oldval = ma.contacts
    ma.contacts = form.cleaned_data["responsible"]
    diffs = _record_diffs('contacts', oldval, ma.contacts, diffs)
    oldval = ma.location
    ma.location = form.cleaned_data["location"]
    diffs = _record_diffs('location', oldval, ma.location, diffs)

    oldval = ma.telescope_resource
    trid = form.cleaned_data["telescope"]
    ma.telescope_resource = Maintenance_Telescope_Resources.objects \
        .filter(id = trid)[0]
    diffs = _record_diffs('telescope', oldval, ma.telescope_resource, diffs)

    oldval = ma.software_resource
    srid = form.cleaned_data["software"]
    ma.software_resource = Maintenance_Software_Resources.objects \
        .filter(id = srid)[0]
    diffs = _record_diffs('software', oldval, ma.software_resource, diffs)

    oldval = [p for p in ma.other_resources.all()]
    ma.other_resources.clear()

    for orid in form.cleaned_data["other_resources"]:
        other_r = Maintenance_Other_Resources.objects.filter(id = orid)[0]
        ma.other_resources.add(other_r)

    diffs = _record_m2m_diffs('other', oldval, ma.other_resources.all(), diffs)

    oldval = [p for p in ma.receivers.all()]
    ma.receivers.clear()

    for rid in form.cleaned_data["receivers"]:
        rcvr = Receiver.objects.filter(id = rid)[0]
        ma.receivers.add(rcvr)

    diffs = _record_m2m_diffs('receivers', oldval, ma.receivers.all(), diffs)

    if form.cleaned_data["change_receiver"] == True:
        down_rcvr_id = form.cleaned_data["old_receiver"]
        up_rcvr_id = form.cleaned_data["new_receiver"]

        # What is needed is a receiver swap entry that contains our
        # receivers in the correct order (i.e. a for b, not b for a).
        # To avoid creating duplicate entries (for instance, repeated
        # swaps of a for b and b for a), search for an existing one
        # first.  If there is none, then create a new swap pair.
        mrsg = Maintenance_Receivers_Swap.objects.filter(
            down_receiver = down_rcvr_id).filter(up_receiver = up_rcvr_id)

        if len(mrsg) == 0:
            down_rcvr = Receiver.objects \
                .filter(id = form.cleaned_data["old_receiver"])[0]
            up_rcvr = Receiver.objects \
                .filter(id = form.cleaned_data["new_receiver"])[0]
            mrs = Maintenance_Receivers_Swap(down_receiver = down_rcvr,
                                             up_receiver = up_rcvr)
            mrs.save()
        else:
            mrs = mrsg[0]

        ma.receiver_changes.clear()
        ma.receiver_changes.add(mrs)
    else:
        ma.receiver_changes.clear()

    oldval = [p for p in ma.backends.all()]
    ma.backends.clear()

    for bid in form.cleaned_data["backends"]:
        be = Backend.objects.filter(id = bid)[0]
        ma.backends.add(be)

    diffs = _record_m2m_diffs('backends', oldval, ma.backends.all(), diffs)
    oldval = ma.description
    ma.description = form.cleaned_data["description"]
    diffs = _record_diffs('description', oldval, ma.description, diffs)
    ma.repeat_interval = int(form.cleaned_data["recurrency_interval"])

    if ma.repeat_interval > 0:
        ma.repeat_end = form.cleaned_data["recurrency_until"]


    # Normally a maintenance activity comes with a group assigned.
    # But it is possible to add a maintenance activity without a
    # group.  In this case, assign right period for maintenance
    # activity, if the activity occurs during a scheduled maintenance
    # group.  If no group, this will remain 'None'
    if not ma.group:
        start = TimeAgent.truncateDt(ma._start)
        end = start + timedelta(days = 1)
        periods = Period.get_periods_by_observing_type(start, end, "maintenance")

        for p in periods:
            if p.isScheduled() and ma._start >= p.start and ma._start < p.end():
                g = Maintenance_Activity_Group.objects.filter(period = p)

                if g.count():
                    ma.group = g[0]

    # Now add user and timestamp for modification.  Earliest mod is
    # considered creation.
    u = get_requestor(request)
    modifying_user = _get_user_name(u)
    ma.add_modification(modifying_user)
    ma.save()

    # If this is a template, modify all subsequent activities based on
    # it.

    if ma.is_repeat_template():
        template = ma
    elif ma.is_future_template():
        template = ma.repeat_template
    else:
        template = None

    if template:
        mas = [m for m in Maintenance_Activity.objects\
               .filter(repeat_template = template)\
               .filter(_start__gte = ma._start)]

        # times neet to be carried over as ET so that the underlying
        # UT will compensate for DST.
        for i in mas:
            ma_time = ma.get_start('ET')
            i_time = i.get_start('ET')
            start = datetime(i_time.year, i_time.month, i_time.day,
                             ma_time.hour, ma_time.minute)

            i.copy_data(ma)
            i.set_start(start, 'ET')
            i.save()

    return diffs
示例#10
0
 def comp_mag(mag):
     return TimeAgent.truncateDt(mag.get_start()) == date and mag.rank.upper() == rank.upper()
示例#11
0
def edit_activity(request, activity_id = None):

    if request.method == 'POST':
        form = RCAddActivityForm(request.POST)

        if form.is_valid():
            # process the returned stuff here...
            ma = Maintenance_Activity.objects \
                .filter(id = form.cleaned_data["entity_id"])[0]
            approved = ma.approved  # save approval status; _process_activity will clear this.
            diffs = _process_activity(request, ma, form)

            if approved: # Notify supervisor if approved activity is modified
                supervisors = get_rescal_supervisors()
                view_url = "http://%s/resourcecal_display_activity/%s/" % (request.get_host(), ma.id)
                rc_notifier.notify(supervisors,
                                   "modified",
                                   ma.get_start("ET").date(),
                                   view_url,
                                   changes = diffs)

            return HttpResponseRedirect('/schedule/')
    else:
        u = get_requestor(request)
        supervisors = get_rescal_supervisors()
        supervisor_mode = True if (u in supervisors) else False

        if request.GET['ActionEvent'] == 'Modify':
            ma = Maintenance_Activity.objects.filter(id = activity_id)[0]
            form = _modify_activity_form(ma)

        elif request.GET['ActionEvent'] == 'ModifyFuture':
            # In this case we want to go back to the template, and set
            # its 'future_template' to this one.
            ma = Maintenance_Activity.objects.filter(id = activity_id)[0]
            ma.set_as_new_template()
            form = _modify_activity_form(ma)

        elif request.GET['ActionEvent'] == 'ModifyAll':
            today = TimeAgent.truncateDt(datetime.now())
            ma = Maintenance_Activity.objects.filter(id = activity_id)[0]
            start_ma = Maintenance_Activity.objects\
                       .filter(repeat_template = ma.repeat_template)\
                       .filter(_start__gte = today)\
                       .order_by('_start')[0]
            start_ma.set_as_new_template()
            form = _modify_activity_form(start_ma)

        elif request.GET['ActionEvent'] == 'Delete':
            ma = Maintenance_Activity.objects.filter(id = activity_id)[0]
            ma.deleted = True
            ma.save()
            creator = _get_ma_creator(ma)

            if creator:
                recipients = supervisors + [creator]
            else:
                recipients = supervisors

            view_url = "http://%s/resourcecal_display_activity/%s/" % (request.get_host(), ma.id)
            rc_notifier.notify(recipients,
                               "deleted",
                               ma.get_start("ET").date(),
                               view_url)

            return HttpResponseRedirect('/schedule/')

        elif request.GET['ActionEvent'] == 'DeleteFuture':
            ma = Maintenance_Activity.objects.filter(id = activity_id)[0]
            ma.repeat_template.repeat_end = ma.get_start('ET').date()
            ma.repeat_template.save()
            mas = Maintenance_Activity.objects\
                  .filter(_start__gte = TimeAgent.truncateDt(ma.get_start()))\
                  .filter(repeat_template = ma.repeat_template)

            for i in mas:
                i.deleted = True
                i.save()

            return HttpResponseRedirect('/schedule/')

        elif request.GET['ActionEvent'] == 'DeleteAll':
            ma = Maintenance_Activity.objects.filter(id = activity_id)[0]
            ma.repeat_template.deleted = True
            ma.repeat_template.save()
            mas = Maintenance_Activity.objects \
                .filter(repeat_template = ma.repeat_template)

            for i in mas:
                i.deleted = True
                i.save()

            return HttpResponseRedirect('/schedule/')

        elif request.GET['ActionEvent'] == 'Approve':
            ma = Maintenance_Activity.objects.filter(id = activity_id)[0]
            u = get_requestor(request)
            user = _get_user_name(u)
            ma.add_approval(user)
            ma.save()

            # Record any receiver changes in the receiver schedule table.
            for i in ma.get_receiver_changes():
                start = ma.get_start()
                rsched = datetime(start.year, start.month, start.day, 16)
                Receiver_Schedule.change_schedule(rsched, [i.up_receiver],
                                                  [i.down_receiver])
            creator = _get_ma_creator(ma)

            if creator:
                view_url = "http://%s/resourcecal_display_activity/%s/" % \
                    (request.get_host(), ma.id)
                rc_notifier.notify(creator,
                                   "approved",
                                   ma.get_start("ET").date(),
                                   view_url)

            return HttpResponseRedirect('/schedule/')

        elif request.GET['ActionEvent'] == 'Move':
            rank = request.GET['Rank']
            ma = Maintenance_Activity.objects.get(id = activity_id)
            u = get_requestor(request)
            user = _get_user_name(u)
            d = request.GET['Destination'].split('-')
            date = datetime(int(d[0]), int(d[1]), int(d[2]))
            group = _get_maintenance_activity_group_by_date(date, rank)

            if group:
                ma.group = group          # assuming here 1 maintenance period
                ma.approved = False       # per day.  UI does not support more
                ma.add_modification(user) # than this.
                ma.save()

            return HttpResponseRedirect('/schedule/')

        elif request.GET['ActionEvent'] == 'Copy':
            rank = request.GET['Rank']
            ma = Maintenance_Activity.objects.get(id = activity_id)
            u = get_requestor(request)
            user = _get_user_name(u)
            d = request.GET['Destination'].split('-')
            date = datetime(int(d[0]), int(d[1]), int(d[2]))
            group = _get_maintenance_activity_group_by_date(date, rank)

            if group:
                new_ma = ma.clone(group)
                new_ma.add_modification(user)
                new_ma.save()

            return HttpResponseRedirect('/schedule/')

    return render_to_response('users/rc_add_activity_form.html',
                              {'form': form,
                               'supervisor_mode': supervisor_mode,
                               'add_activity' : False })
示例#12
0
    def _get_elective_mags(utc_day):
        mags = []

        try:
            delta = timedelta(days = 7)
            # get maintenance electives for the date span
            me = Elective.objects\
                .filter(session__observing_type__type = 'maintenance')\
                .filter(periods__start__gte = utc_day)\
                .filter(periods__start__lt = utc_day + delta)\
                .distinct()

            # don't care about elective with all deleted periods.
            me = [e for e in me if e.periods.count() > e.deletedPeriods().count()]

            # need as many floating groups as there are elective
            # maintenance days.  First, count up the maintenance days,
            # then the groups.  If not equal, we must either truncate
            # the groups or add to them.  Finally any groups within
            # the tally must be marked not deleted (in case they were
            # deleted earlier), and any outside the tally must be
            # marked deleted.

            maintenance_periods = len(me)
            # When obtaining the maintenance activity groups for this
            # week, ensure that the query will match the mag's 'week'
            # field by stripping off the time of 'utc_day'.  Otherwise
            # it may not pick it up.  Also we include a generous time
            # range for 'week' just to make sure time issues don't
            # crop in and exclude any group.
            dbmags = Maintenance_Activity_Group.objects\
                .filter(week__gte = TimeAgent.truncateDt(utc_day))\
                .filter(week__lt = TimeAgent.truncateDt(utc_day) + delta)\
                .exclude(rank = 'x') \
                .order_by("rank")
            mags = [mag for mag in dbmags]

            # these are all ordered by rank now, relabel rank in case
            # it doesn't start with 'A' ('B', 'C', etc.), or there is
            # a gap ('A', 'B', 'D', etc.) (would occur if manually
            # deleted from database, etc., and leaving old rank might
            # confuse users.)
            for i in range(0, len(mags)):
                if mags[i].rank != chr(65 + i):
                    mags[i].rank = chr(65 + i)
                    mags[i].save()

            # either too many or not enough mags.  Deal with it
            # accordingly...
            if maintenance_periods != len(mags):
                # too many; mark the excess as deleted.
                if len(mags) > maintenance_periods:
                    for i in range(maintenance_periods, len(mags)):
                        mag = mags[i]
                        mag.deleted = True
                        mag.period = None
                        mag.save()
                # too few; create more to make up the numbers.
                if len(mags) < maintenance_periods:
                    for i in range(len(mags), maintenance_periods):
                        mag = Maintenance_Activity_Group()
                        mag.week = TimeAgent.truncateDt(utc_day)
                        mag.deleted = False
                        mag.rank = chr(65 + i)
                        mag.save()
                        mags.append(mag)

            # Mark all mags from 0 to number of maintenance periods as
            # undeleted.  This reuses any previously deleted mags.
            for i in range(0, maintenance_periods):
                mag = mags[i]
                if mag.deleted:
                    mag.deleted = False
                    mag.save()

            # now make sure scheduled electives get assigned the
            # correct group.
            sched_periods = []

            for i in me:
                sched_periods += i.periodsByState('S')

            # sort periods by start, groups by rank.  Makes them easy
            # to match up.  Any previous matchups will be undone.
            sched_periods.sort(key = lambda x: x.start)
            mags.sort(key = lambda x: x.rank)

            def in_query_set(item, qset):
                for i in qset:
                    if item == i:
                        return True
                    return False

            for i in range(0, len(mags)):
                mag = mags[i]

                if i < len(sched_periods):
                    p = sched_periods[i]

                    # update the period if the mag is not the right
                    # one, or if it has more than one mag, to ensure
                    # just one per period.
                    if not in_query_set(mag, p.maintenance_activity_group_set.all()) \
                            or p.maintenance_activity_group_set.count() > 1:
                        p.maintenance_activity_group_set.clear()
                        p.maintenance_activity_group_set.add(mag)
                else:
                    if mag.period:
                        mag.period = None
                        mag.save()
        except:
            if settings.DEBUG == True:
                printException(formatExceptionInfo())

        return mags
示例#13
0
    def get_maintenance_activity_set2(self):
        """
        Returns a set of maintenance activities occuring during this
        group's duration, in time order.
        """

        unscheduled_maintenance = "Unscheduled Maintenance"

        if not self.period or self.period.session.name == unscheduled_maintenance:
            mas = self.maintenance_activity_set.all()
        else:
            # To handle repeat maintenance activity objects:
            period = self.period

            # Get the templates:
            repeatQ = models.Q(deleted = False) \
                & (models.Q(repeat_interval = 1) \
                       | models.Q(repeat_interval = 7) \
                       | models.Q(repeat_interval = 30)) \
                       & (models.Q(_start__lte = period.end()) \
                              & models.Q(repeat_end__gte = period.end()))

            # Get the time period
            start_endQ = models.Q(start__gte = period.start) \
                & models.Q(start__lte = period.end())
            today = TimeAgent.truncateDt(period.start)
            # Get other groups today.  They will be used below to see
            # if any of them is a better fit.  We must exclude any
            # possible emergency maintenance periods:
            other_groups_today = Maintenance_Activity_Group.objects\
                .filter(period__start__gte = today)\
                .filter(period__start__lt = today + timedelta(1))\
                .exclude(id = self.id) \
                .exclude(period__session__name = unscheduled_maintenance)

            groupQ  = models.Q(group = self)
            dbmas   = Maintenance_Activity.objects.filter(groupQ)
            dbrmas  = Maintenance_Activity.objects.filter(repeatQ)
            mas     = [i for i in dbmas if not i.is_repeat_template()]
            rmas    = [i for i in dbrmas]

            # rmas is the list repeating activity templates that may
            # apply for this period.  We need clones of these to
            # include in mas.  If however there are already clones in
            # mas, we'll want to skip that template.  We will also
            # skip the template if there is a better candidate
            # maintenance activity group on this day (by better, a
            # better match in time, defined by the activity's start
            # time being within the maintenance activity group's time
            # span).

            x = []

            for i in rmas:
                for j in mas:
                    if j.repeat_template == i:
                        x.append(i)

                for g in other_groups_today:
                    if i.get_start().time() >= g.get_start().time() \
                            and i.get_start().time() < g.get_end().time():
                        x.append(i)


            # Weekly repeats have a problem: what if the repeat falls on a
            # day that is not a maintenance day?  Where should we put it?
            # One strategy is to examine the maintenance periods from 3
            # days in the past to 3 days into the future.  if none of
            # those is more suitable, we keep the weekly activity here. If
            # there is a tie, we favor the earlier date. This is done by
            # taking the modulo 7 of start - maintenance_activity.start
            # and mapping it to the values in 'dm'.  Lowest value wins.

            dm = {4: 30, 5: 20, 6: 10, 0: 0, 1: 15, 2: 25, 3: 35}
            delta = timedelta(days = 3)
            today = TimeAgent.truncateDt(period.start)
            p = Period.get_periods_by_observing_type(today - delta,
                                                     today + delta,
                                                     "maintenance")

            for i in rmas:
                if i.repeat_interval > 1:
                    start_date = TimeAgent.truncateDt(i.get_start())
                    diff = (today - start_date).days % i.repeat_interval

                    if diff:
                        # doesn't fall on this date.  Is this the closest
                        # period though?

                        if diff > 6:     # monthly not due
                            x.append(i)
                        else:            # weekly or monthly that is due this week
                            for j in p:
                                if j != period:  # check only other periods
                                    mod = (j.start.date() \
                                               - start_date.date()).days \
                                               % i.repeat_interval

                                    # Test to see if it's a better fit in
                                    # another period.  and if so, don't
                                    # use here.
                                    if mod < 7 and dm[mod] < dm[diff]:
                                        x.append(i)
                                        break

            # Now that we have a list of templates that are not suitable,
            # cull the template list:
            for i in x:
                if i in rmas:
                    rmas.remove(i)

            # The remaining templates may be used:
            for i in rmas:
                ma = i.clone(self)
                mas.append(ma)

        # remove all activities marked deleted.  This must be done
        # after all the above to prevent a replacement being generated
        # for a deleted activity, for repeat activities.
        mas = [i for i in mas if not i.deleted]
        mas.sort(cmp = lambda x, y: cmp(x.get_start(),
                                        y.get_start()))

        return mas
示例#14
0
    def get_maintenance_activity_set(self):
        """
        Returns a set of maintenance activities occuring during this
        group's duration, in time order.
        """

        floating_maintenance = u'Maintenance day'
        fixed_maintenance = u'Maintenance'

        # We need some functions...
        def is_P(mag):
            return True if mag.period and \
                mag.period.session.name == fixed_maintenance \
                else False

        def is_U(mag):
            return True if not mag.period else False

        def is_highest_U(mag):
            if not is_U(mag):
                return False

            week = mag.week
            mags = Maintenance_Activity_Group.objects.filter(week = week)\
                .filter(period = None).order_by("rank")
            return mag == mags[0]

        def already_instantiated(template, mag):
            # the answer is 'True' if it is in this mag...
            for j in mag.maintenance_activity_set.all():
                if j.repeat_template == template:
                    return True

            # or, if daily template, in another mag today...
            if template.repeat_interval == 1:
                for omag in other_groups_today:
                    for j in omag.maintenance_activity_set.all():
                        if j.repeat_template == template:
                            return True

            # or, if weekly or monthly, if it is in another mag this week.
            if template.repeat_interval == 7 or template.repeat_interval == 30:
                for omag in other_groups_this_week:
                    for j in omag.maintenance_activity_set.all():
                        if j.repeat_template == template:
                            return True
            # Not instantiated.
            return False

        def get_monthly_due_dates(template):
            start_date = template._start.date()
            end = template.repeat_end
            dates = []
            midnight = time(0, 0, 0)
            months = 0
            ddate = start_date

            while ddate < end:
                dates.append(datetime.combine(ddate, midnight))
                months = months + 1
                ddate = TimeAgent.add_months(start_date, months)
            return dates

        def get_due_date(template):
            if template.repeat_interval == 30:
                due_dates = get_monthly_due_dates(template)

                for i in range(0, 7):
                    dday = self.week + timedelta(days = i)
                    
                    if dday in due_dates:
                        return dday
                    
            if template.repeat_interval == 7:
                week = TimeAgent.truncateDt(self.week)
                start_date = TimeAgent.truncateDt(template.get_start())
                diff = timedelta(days = (week - start_date).days % \
                                     template.repeat_interval)
                return week + timedelta(7) - diff
            return None


        def template_due(template):
            # daily and weekly will always be due this week.
            if template.repeat_interval == 1 or template.repeat_interval == 7:
                return True

            return False if not get_due_date(template) else True


        def good_fit(template, mag):
            # Checks to see if this template wouldn't work better
            # elsewhere.  If so, returns False.  If not, returns True.

            # first, take care of simple cases: repeat = 1, or no
            # published mags this week, the template is due, and this
            # is the highest U:

            if template.repeat_interval == 1:
                return False if better_fit(t, other_groups_today) else True

            if len(published_groups_this_week) == 0 \
                    and is_highest_U(mag):
                return True

            if is_P(self):
                dm = {-4: 40, -3: 30, -2: 20, -1: 10, 0: 0, 1: 15, 2: 25, 3: 35, 4: 45}
                today = TimeAgent.truncateDt(self.period.start)
                p = [mag.period for mag in published_groups_this_week]
                due_date = get_due_date(template)
                diff = (today - due_date).days

                if diff:
                    # doesn't fall on this date.  Is this the closest
                    # period though?
                    for j in p:
                        if j != self.period:  # check only other periods
                            mod = (TimeAgent.truncateDt(j.start) - due_date).days

                            # Test to see if it's a better fit in
                            # another period.  and if so, don't
                            # use here.
                            if dm[mod] < dm[diff]:
                                return False
                return True
            return False


        def better_fit(template, other_mags):
            for g in other_mags:
                if template.get_start().time() >= g.get_start().time() \
                        and template.get_start().time() < g.get_end().time():
                    return True
            return False

        def instantiate(template, mag):
            ma = template.clone(mag)

        if is_P(self) or is_U(self):
            # set up all the data we need:
            if is_P(self):
                today = TimeAgent.truncateDt(self.period.start)
                end = self.period.end()
            else:
                today = self.week
                end = self.week + timedelta(days = 7)

            # Get repeat templates
            repeatQ = models.Q(deleted = False) \
                & (models.Q(repeat_interval = 1) \
                       | models.Q(repeat_interval = 7) \
                       | models.Q(repeat_interval = 30)) \
                       & (models.Q(_start__lte = end) \
                              & models.Q(repeat_end__gte = today))
            dbrmas = Maintenance_Activity.objects.filter(repeatQ)
            templates = [p for p in dbrmas]

            allowed_sessionsQ = models.Q(period__session__name = fixed_maintenance) \
                | models.Q(period__session__name = floating_maintenance)

            if is_P(self):
                today = TimeAgent.truncateDt(self.period.start)
                # Get other groups today.  They will be used below to see
                # if any of them is a better fit.  We must exclude any
                # possible emergency maintenance periods:

                other_groups_today = Maintenance_Activity_Group.objects\
                    .exclude(id = self.id) \
                    .filter(period__start__gte = today)\
                    .filter(period__start__lt = today + timedelta(1))\
                    .filter(allowed_sessionsQ)
            else:
                other_groups_today = []

            this_week = self.get_week()

            published_groups_this_week =  Maintenance_Activity_Group.objects\
                .exclude(id = self.id) \
                .filter(period__start__gte = this_week)\
                .filter(period__start__lt = today + timedelta(7))\
                .filter(allowed_sessionsQ)

            unpublished_groups_this_week =  Maintenance_Activity_Group.objects\
                .exclude(id = self.id) \
                .filter(week__gte = this_week)\
                .filter(week__lt = today + timedelta(7))\
                .filter(period = None)

            other_groups_this_week = [mag for mag in published_groups_this_week] \
                + [mag for mag in unpublished_groups_this_week]

            # Meat and potatoes: For each template, see if we must
            # instantiate it.  We do so if it is due and hasn't been
            # taken care of yet.

            for t in templates:
                if template_due(t):
                    if not already_instantiated(t, self):
                        if good_fit(t, self):
                            instantiate(t, self)

        groupQ  = models.Q(group = self)
        dbmas   = Maintenance_Activity.objects.filter(groupQ)
        # remove all activities marked deleted.  This must be done
        # after all the above to prevent a replacement being generated
        # for a deleted activity, for repeat activities.
        mas = [i for i in dbmas if not i.deleted and not i.is_repeat_template()]
        mas.sort(cmp = lambda x, y: cmp(x.get_start(),
                                        y.get_start()))
        return mas
示例#15
0
 def get_week(self):
     """
     Returns the start-of-week date of the week this activity will
     take place in.
     """
     return TimeAgent.truncateDt(self.week) if self.week else None