def getHrsInDayTime(self, start, end):
     "Split up given time range by PTCS day and night time hours."
     dur = TimeAgent.dtDiffHrs(start, end)
     startDate = date(start.year, start.month, start.day)
     #rise, set = self.sun.getRiseSet(date1)
     # cast a wide net: compute the rise and set times for any days
     # that might be covered by the given time range
     days = (end - start).days + 2
     dayTimes = []
     for day in range(days):
         dt = startDate + timedelta(days = day)
         dayTimes.append(self.sun.getPTCSRiseSet(dt))
     # where does our given time range intersect with day time?    
     ints = AnalogSet.intersects([dayTimes, [(start, end)]])
     if len(ints) > 0:
         # some day time
         day = 0.0
         for intersection in ints:
             td = intersection[1] - intersection[0]
             day += TimeAgent.timedelta2frachours(td)
         # the rest must be night time    
         night = abs(dur - day) 
     else:
         # our range is all night time.
         day = 0.0
         night = dur 
     return (day, night)
Beispiel #2
0
    def readWindFile(self, file):
        """
        Parsing this file is straight forward: we'll need the timestamp
        and *scalar* quantities from each row.
        """

        # read cleo forecast (ground)
        print 'Process cleo forecast data (ground) ...', file
        f          = open(file, 'r')
        lines      = f.readlines()
        header     = lines[0]
        assert header.strip() == windFileHeader.strip()  

        for line in lines[1:]:
            row = line.split(' ')
            timestamp = TimeAgent.hour(TimeAgent.mjd2dt(float(row[0]))) #mjd
            self.data[timestamp] = {}

            # what forecast type will this be?
            self.data[timestamp]['forecast_type_id'] = \
                self.getForecastTypeIdFromTimestamp(timestamp)

            self.readWindFileValues(header, timestamp, row)

            # Note: we'll stop doing this eventually, but for now:
            # need to insert a corrected wind speed into the DB.
            speed_mph = self.data[timestamp]['speed_mph']
            self.data[timestamp]['speed_ms'] = \
                self.dbimport.correctWindSpeed(timestamp
                                             , self.mph2mps(speed_mph))

        f.close()
Beispiel #3
0
def create_session(sesshun, project, fdata):
    "Utility method for creating a Sesshun to test."

    fsestype = fdata.get("type", "open")
    fobstype = fdata.get("science", "testing")
    proj_code = fdata.get("pcode", "Test-Project")

    st = Session_Type.objects.get(type = fsestype)
    ot = Observing_Type.objects.get(type = fobstype)

    sesshun.project          = project
    sesshun.session_type     = st
    sesshun.observing_type   = ot
    sesshun.original_id      = 0
    sesshun.name             = fdata.get("name", None)
    sesshun.frequency        = fdata.get("freq", None)
    sesshun.max_duration     = TimeAgent.rndHr2Qtr(float(fdata.get("req_max", 12.0)))
    sesshun.min_duration     = TimeAgent.rndHr2Qtr(float(fdata.get("req_min",  3.0)))
    sesshun.time_between     = fdata.get("between", None)

    allot = Allotment(psc_time          = fdata.get("PSC_time", 0.0)
                    , total_time        = fdata.get("total_time", 0.0)
                    , max_semester_time = fdata.get("sem_time", 0.0)
                    , grade             = fdata.get("grade", 4.0)
                      )
    allot.save()
    sesshun.allotment        = allot

    status = Status(
               enabled    = get_field(fdata, "enabled", True, bool)
             , authorized = get_field(fdata, "authorized", True, bool)
             , complete   = get_field(fdata, "complete", True, bool) 
             , backup     = get_field(fdata, "backup", True, bool) 
                    )
    status.save()
    sesshun.status = status
    sesshun.save()

    create_lst_exclusion(sesshun, fdata)
    
    proposition = fdata.get("receiver")
    save_receivers(sesshun, proposition)
    
    systemName = fdata.get("coord_mode", "J2000")
    system = System.objects.get(name = systemName)

    v_axis = fdata.get("source_v", 0.0)
    h_axis = fdata.get("source_h", 0.0)
    
    target = Target(session    = sesshun
                  , system     = system
                  , source     = fdata.get("source", None)
                  , vertical   = v_axis
                  , horizontal = h_axis
                    )
    target.save()
    sesshun.save()

    return sesshun
Beispiel #4
0
def filterPeriodsByDate(start):
    "Returns the periods within a given month and year."
    _, day = calendar.monthrange(start.year, start.month)
    stop  = datetime(start.year, start.month, day, 23, 59, 59)
    ustart = TimeAgent.est2utc(start)
    ustop  = TimeAgent.est2utc(stop)
    return [p for p in getPeriods() \
            if (p.start >= ustart or p.end() > ustart) and p.start < ustop]
Beispiel #5
0
    def testGetWindowTimes(self):

        # test
        wa = WindowAlerts.WindowAlerts()
        now = datetime(2009, 1, 1)
        times = wa.getWindowTimes(now)

        # expected result
        sch = [(datetime(2009, 4, 6), self.window.end_datetime()) ]
        bss = [(datetime(2009, 4, 6), datetime(2009, 4, 7, 13, 0))]
        schHrs = TimeAgent.timedelta2minutes(sch[0][1] - sch[0][0])/60.0
        bssHrs = TimeAgent.timedelta2minutes(bss[0][1] - bss[0][0])/60.0
        exp = [(self.window
              , (schHrs
               , bssHrs
               , sch
               , [bss]))]

        self.assertEquals(exp[0][0], times[0][0])
        self.assertEquals(exp[0][1], times[0][1])

        # add some blacked out time - 3 days
        bsStart = datetime(2009, 4, 8)
        bsEnd   = datetime(2009, 4, 11)
        blackout = create_blackout(project = self.project,
                                   start   = bsStart,
                                   end     = bsEnd,
                                   repeat  = 'Once')
        bss.insert(0, (bsStart, bsEnd))
        bssHrs += 3*24

        times = wa.getWindowTimes(now)

        exp = [(self.window
              , (schHrs
               , bssHrs
               , sch
               , [bss]))]

        self.assertEquals(exp[0][0], times[0][0])
        self.assertEquals(exp[0][1], times[0][1])

        # move the current time forward
        now = datetime(2009, 4, 9, 12, 15, 0)
        times = wa.getWindowTimes(now)

        sch = [(now, self.window.end_datetime()) ]
        bss = [(now, bsEnd)]
        schHrs = TimeAgent.timedelta2minutes(sch[0][1] - sch[0][0])/60.0
        bssHrs = TimeAgent.timedelta2minutes(bss[0][1] - bss[0][0])/60.0
        exp = [(self.window
              , (schHrs
               , bssHrs
               , sch
               , [bss]))]

        self.assertEquals(exp[0][0], times[0][0])
        self.assertEquals(exp[0][1], times[0][1])
Beispiel #6
0
    def test_getSunRise(self):

        sun = Sun()

        # close to the winter solstice
        dt = date(2011, 12, 25)
        rise = TimeAgent.quarter(sun.getSunRise(dt))
        # 12:30 UT
        self.assertEqual(datetime(2011, 12, 25, 12, 30), rise) 
        # close to the summer solstice
        dt = date(2012, 6, 25)
        rise = TimeAgent.quarter(sun.getSunRise(dt))
        # 10 UT
        self.assertEqual(datetime(2012, 6, 25, 10, 0), rise) 
Beispiel #7
0
def filterPeriodsByDate(start):
    "Returns the periods within a given month and year."
    _, day = calendar.monthrange(start.year, start.month)
    stop   = datetime(start.year, start.month, day, 23, 59, 59)
    ustart = TimeAgent.est2utc(start)
    ustop  = TimeAgent.est2utc(stop)

    periods = []
    for p in ALL_PERIODS:
        if (p.start >= ustart or p.end() > ustart) and p.start < ustop:
            start, stop = normalizePeriodStartStop(p, start)
            periods.append([p, start, stop])

    return periods
Beispiel #8
0
    def test_getSunSet(self):

        sun = Sun()

        # close to the winter solstice
        dt = date(2011, 12, 25)
        set = TimeAgent.quarter(sun.getSunSet(dt))
        # 22:00 UT
        self.assertEqual(datetime(2011, 12, 25, 22, 0), set) 
        # close to the summer solstice
        dt = date(2012, 6, 25)
        set = TimeAgent.quarter(sun.getSunSet(dt))
        # 00:45 UT ON THE NEXT DAY
        self.assertEqual(datetime(2012, 6, 26, 0, 45), set) 
Beispiel #9
0
def normalizePeriodStartStop(period, dt):
    """
    Returns the start/stop time for a period ensuring it stays within the 
    given month.
    """
    start = TimeAgent.utc2est(period.start)
    if start.month != dt.month:
        start = datetime(dt.year, dt.month, 1, 0, 0, 0)

    stop = TimeAgent.utc2est(period.end())
    if stop.month != dt.month:
        _, day = calendar.monthrange(dt.year, dt.month)
        stop = datetime(dt.year, dt.month, day, 23, 59, 59)

    return start, stop
Beispiel #10
0
    def SetDate(self, date):
        if date:
            weekdays = {"0" : "Sun",
                        "1" : "Mon",
                        "2" : "Tue",
                        "3" : "Wed",
                        "4" : "Thu",
                        "5" : "Fri",
                        "6" : "Sat"}

            months = {"1"  : "Jan",
                      "2"  : "Feb",
                      "3"  : "Mar",
                      "4"  : "Apr",
                      "5"  : "May",
                      "6"  : "Jun",
                      "7"  : "Jul",
                      "8"  : "Aug",
                      "9"  : "Sep",
                      "10" : "Oct",
                      "11" : "Nov",
                      "12" : "Dec"}

            self.date = "%s, %s %s %s -0%d00" % (weekdays[date.strftime("%w")],
                                                 date.strftime("%d"),
                                                 months[str(int(date.strftime("%m")))],
                                                 date.strftime("%Y %H:%M:%S"),
                                                 TimeAgent.utcoffset())
        else:
            self.date = None
Beispiel #11
0
    def test_lstInRange(self):

        # ra to lst: rads to hours
        lst = TimeAgent.rad2hr(self.sesshun.target.horizontal)

        # create the window range
        utcStart = datetime(2009, 6, 1)
        utcEnd   = datetime(2009, 6, 2)
        wr = WindowRange(window = self.w
                       , start_date = utcStart
                       , duration = (utcEnd - utcStart).days)
        wr.save()

        # any target should be in range, w/ out a buffer
        inRange = wr.lstInRange(lst)
        self.assertEquals(True, inRange)

        # but with a big enough buffer, no target can be in range
        buffer = 12.0
        inRange = wr.lstInRange(lst, buffer = buffer)
        self.assertEquals(False, inRange)
        
        # make the buffer reasonable enough, and it passes again
        buffer = 4.5
        inRange = wr.lstInRange(lst, buffer = buffer)
        self.assertEquals(True, inRange)
Beispiel #12
0
def filterPeriodsByDate(start):
    "Returns the periods (plus lost time) within a given month and year."
    _, day = calendar.monthrange(start.year, start.month)
    stop   = datetime(start.year, start.month, day, 23, 59, 59)
    ustart = TimeAgent.est2utc(start)
    ustop  = TimeAgent.est2utc(stop)

    periods = []
    for p in getPeriods():
        if (p.start >= ustart or p.end() > ustart) and p.start < ustop:
            start, stop = normalizePeriodStartStop(p, start)
            # normalize lost time too!
            lostTime = (diffHrs(start, stop)/p.duration) * p.accounting.lost_time()
            periods.append([p, start, stop, lostTime]) 

    return periods
Beispiel #13
0
    def test_summary(self):
        # setup a period for a month before
        lastMonth = self.start - timedelta(days = 31)
        lastMonthEst = TimeAgent.utc2est(lastMonth)
        pa = Period_Accounting(scheduled = self.dur)
        pa.save()
        p = Period( session = self.s
                  , start = lastMonth 
                  , duration = self.dur
                  , state = Period_State.get_state("S")
                  , accounting = pa
                  )
        p.save()          
        
        # get - sets up the form
        response = self.get('/schedule/summary')
        self.failUnlessEqual(response.status_code, 200)
        startStr = datetime.strftime(lastMonthEst, "%H:%M")
        self.assertTrue(startStr in response.content)
        self.assertTrue("mikes awesome project" in response.content)

        # post - they've requested something
        # first, the schedule summary report
        # default to last month
        response = self.post('/schedule/summary', {'summary' : 'schedule'})
        self.failUnlessEqual(response.status_code, 200)        
        self.assertTrue(startStr in response.content)
        self.assertTrue("mikes awesome project" in response.content)

        # now do an earlier month, and our period should not show up
        response = self.post('/schedule/summary'
                          , {'summary' : 'schedule'
                           , 'month'   : 'December'
                           , 'year'    : '2000'}
                            )
        self.failUnlessEqual(response.status_code, 200)        
        self.assertTrue(startStr not in response.content)
        self.assertTrue("mikes awesome project" not in response.content)

        # okay, now test the project summary report
        pcode = self.s.project.pcode
        response = self.post('/schedule/summary'
                          , {'summary' : 'project'
                           , 'project' : pcode}
                            )
        self.failUnlessEqual(response.status_code, 200)        
        self.assertTrue("GBT Project Summary for" in response.content)
        self.assertTrue(pcode in response.content)
        self.assertTrue(str(self.dur) in response.content)

        # make sure we can handle all projects 
        response = self.post('/schedule/summary'
                          , {'summary' : 'project'
                           , 'project' : None}
                            )
        self.failUnlessEqual(response.status_code, 200)        
        self.assertTrue("GBT Project Summary for" in response.content)
        self.assertTrue(pcode in response.content)
        self.assertTrue(str(self.dur) in response.content)
Beispiel #14
0
    def test_getPTCSRiseSet(self):

        sun = Sun()

        dt = date(2011, 12, 25)
        rise, set = sun.getPTCSRiseSet(dt)
        self.assertEqual(datetime(2011, 12, 25, 12,30)
                       , TimeAgent.quarter(rise)) 
        self.assertEqual(datetime(2011, 12, 26,  1, 0)
                       , TimeAgent.quarter(set)) 
        # close to the summer solstice
        dt = date(2012, 6, 25)
        rise, set = sun.getPTCSRiseSet(dt)
        self.assertEqual(datetime(2012, 6, 25, 10, 0)
                       , TimeAgent.quarter(rise)) 
        self.assertEqual(datetime(2012, 6, 26, 3, 45)
                       , TimeAgent.quarter(set)) 
Beispiel #15
0
 def getWindowTimeBlackedOut(self):
     "How many hours in this window have been blacked out?"
     bs = []
     for wr in self.ranges():
         bstart = wr.start_datetime()
         bend   = wr.end_datetime()
         bs.extend(self.session.project.get_blackout_times(bstart, bend))
     return sum([TimeAgent.timedelta2minutes(b[1] - b[0])/60.0 \
         for b in bs])
Beispiel #16
0
 def getWindowTimeNotSchedulable(self, blackouts = True):
     "How many hours in this window are not schedulable?"
     ns = []
     for wr in self.ranges():
         ns.extend(self.session.get_time_not_schedulable( \
             wr.start_datetime()
           , wr.end_datetime()
           , blackouts = blackouts))
     return sum([TimeAgent.timedelta2minutes(n[1] - n[0])/60.0 \
         for n in ns])
Beispiel #17
0
    def getSessionTable(self, periods):
        table  = "Start (ET)   |      UT      |  LST  |  (hr) | T | S |    PI     | Rx        | Session\n"
        table += "--------------------------------------------------------------------------------------\n"
        for p in periods:
            if p.session.project.pcode == "Maintenance":
                pi = ""
            else:
                pi = p.session.project.principal_investigator().last_name[:9] if p.session.project.principal_investigator() else "Unknown"

            table += "%s | %s | %s | %5s | %s | %s | %-9s | %-9s | %s\n" % (
                TimeAgent.utc2est(p.start).strftime('%b %d %H:%M') # start (ET)
              , p.start.strftime('%b %d %H:%M') # start (UT)
              , TimeAgent.dt2tlst(p.start).strftime('%H:%M') # LST
              , "%2.2f" % p.duration # dur (Hrs)
              , p.session.session_type.type[0].upper() # sess type
              , p.state.abbreviation # state
              , pi
              , p.session.receiver_list_simple()[:9]
              , p.session.name
            )
        return table
Beispiel #18
0
 def getHrsInGC(self, start, end):
     "Split up given time range by Galactic Center overlap."
     dur = TimeAgent.dtDiffHrs(start, end)
     # convert local time range to LST range
     lstStart = sla.Absolute2RelativeLST(start)
     lstEnd = sla.Absolute2RelativeLST(end)
     # be simplistic about the overalp
     if lstEnd < lstStart:
         lstEnd += 24.0
     
     gcHrs, nonGcHrs = self.findOverlap((lstStart, lstEnd), self.gcHrs, dur)
     return (gcHrs, nonGcHrs)
Beispiel #19
0
def getDowntime(periods, month):
    "This does not use getTime because lost time must be handled carefully"
                                     
    ps =  filterPeriods(periods, 'p.session.project.is_science()')
    ps.sort(key = lambda x: x.start)
    total = 0.0
    for p in ps:
        start, stop = normalizePeriodStartStop(p, month)
        hrs = TimeAgent.timedelta2frachours(stop - start)
        # We must normalize the lost time as well
        lostTime = (hrs/p.duration) * p.accounting.lost_time()
        total += lostTime
    return total 
Beispiel #20
0
    def lstOutOfRange(self):
        """
        Are any of the window ranges just one day, with the
        LST such that the session can't be scheduled?
        """
        lst = TimeAgent.rad2hr(self.session.target.horizontal)

        # how close can the lst be to the edges of the range?
        buffer = (self.session.min_duration + self.session.max_duration) / 2.0

        return [wr for wr in self.windowrange_set.all() \
            if wr.duration == 1 and \
                not wr.lstInRange(lst, buffer = buffer)]
Beispiel #21
0
    def test_getRiseSet(self):

        sun = Sun()

        dt = date(2011, 12, 25)
        rise, set = sun.getRiseSet(dt)
        # 12:30 UT
        self.assertEqual(datetime(2011, 12, 25, 12,30)
                       , TimeAgent.quarter(rise)) 
        self.assertEqual(datetime(2011, 12, 25, 22, 0)
                       , TimeAgent.quarter(set)) 
        # close to the summer solstice
        dt = date(2012, 6, 25)
        rise, set = sun.getRiseSet(dt)
        # 00:45 UT ON THE NEXT DAY
        self.assertEqual(datetime(2012, 6, 25, 10, 0)
                       , TimeAgent.quarter(rise)) 
        self.assertEqual(datetime(2012, 6, 26, 0, 45)
                       , TimeAgent.quarter(set)) 

        # close to the summer solstice
        dts = (date(2012, 8, 1)
             , date(2012, 8, 2)
             , date(2012, 8, 3)
             , date(2013, 1, 29)
             , date(2013, 1, 30)
             )
        expected = ((datetime(2012, 8, 1, 10, 21, 31), datetime(2012, 8, 2, 0, 30, 12))
                  , (datetime(2012, 8, 2, 10, 22, 24), datetime(2012, 8, 3, 0, 29, 12))
                  , (datetime(2012, 8, 3, 10, 23, 16), datetime(2012, 8, 4, 0, 28, 10))
                  , (datetime(2013, 1, 29, 12, 26, 38), datetime(2013, 1, 29, 22, 38, 52))
                  , (datetime(2013, 1, 30, 12, 25, 49), datetime(2013, 1, 30, 22, 40, 0))
                    )
        for dt, (exp_rise, exp_set) in zip(dts, expected):
            rise, set = sun.getRiseSet(dt)
            self.assertEqual(exp_rise, rise) 
            self.assertEqual(exp_set, set) 
Beispiel #22
0
    def readAtmoFile(self, file):
        """
        Parsing this file is more complicated, because each row contains
        *vector* quantities.
        """

        # read cleo forecast (atmosphere)
        print 'Process cleo forecast data (atmosphere) ... ', file
        f     = open(file, 'r')
        lines = f.readlines()
        header = lines[0]
        assert header.strip() == freqFileHeader.strip()
        first = lines[0].split(' ')
        lines = lines[1:]
        for line in lines:
            row = line.split(' ')
            timestamp  = TimeAgent.hour(TimeAgent.mjd2dt(float(row[0]))) #mjdt1
            if not self.data.has_key(timestamp):
                self.reportLine("ERROR: No wind data for %s\n" % timestamp)
                continue
            # frequencies
            self.data[timestamp]['freqs'] = []
            # OpacityTime<freq>List_avrg
            self.data[timestamp]['tauCleo']  = []
            # TsysTime<freq>List_avrg
            self.data[timestamp]['tSysCleo'] = []
            # TatmTime<freq>List_avrg
            self.data[timestamp]['tAtmCleo'] = []
            num = self.numAtmoFreqs
            for i in range(num):
                #print first[ifreq+1], first[ifreq+51], first[ifreq+101]
                self.data[timestamp]['freqs'].append(self.atmoFreqs[i])
                self.data[timestamp]['tauCleo'].append(float(row[i+1]))
                self.data[timestamp]['tSysCleo'].append(float(row[i+num+1]))
                self.data[timestamp]['tAtmCleo'].append(float(row[i+(num*2)+1]))
        f.close()
Beispiel #23
0
 def getStates(self, periodVersions):
    "What is the state history: a list of (dates, current state of period)?"
    states = []
    currentState = None
    for v in periodVersions:
        state = v.field_dict.get("state", None)
        if state is not None:
            currentState = state
        # the revision library saves things in ET - but we deal in UT    
        if not self.test:
            dt = TimeAgent.est2utc(v.revision.date_created)    
        else:
            # why make setting up the tests anymore complicated?
            dt = v.revision.date_created
        state = (dt, currentState)   
        if state not in states:
            states.append(state)
    return states        
Beispiel #24
0
    def getSessionTable(self, periods):
        table  = "Start (ET)   |      UT      |  LST  |  (hr) |    PI     | Rx        | Session\n"
        table += "------------------------------------------------------------------------------------\n"
        for p in periods:
            if p.session.project.pcode == "Maintenance":
                pi = ""
            else:
                pi = p.session.project.principal_investigator().last_name[:9] if p.session.project.principal_investigator() else "Unknown"

            table += "%s | %s | %s | %5s | %-9s | %-9s | %s\n" % (
                self.utc2estDT(p.start)
              , p.start.strftime('%b %d %H:%M')
              , TimeAgent.dt2tlst(p.start).strftime('%H:%M')
              , "%2.2f" % p.duration
              , pi
              , p.session.receiver_list_simple()[:9]
              , p.session.name
            )
        return table
Beispiel #25
0
    def test_lstOutOfRange(self):

        # ra to lst: rads to hours
        lst = TimeAgent.rad2hr(self.sesshun.target.horizontal)

        # this first window should not have a problem, since
        # duration > 1 day
        self.assertEquals(False, self.w.hasLstOutOfRange())
        self.assertEquals(False, self.w.hasNoLstInRange())

        # now create a one day window range
        utcStart = datetime(2009, 6, 1)
        utcEnd   = datetime(2009, 6, 2)
        wr = WindowRange(window = self.w
                       , start_date = utcStart
                       , duration = (utcEnd - utcStart).days)
        wr.save()

        # any target should be in range, w/ out a big buffer
        self.assertEquals(False, self.w.hasLstOutOfRange())
        self.assertEquals(False, self.w.hasNoLstInRange())

        # now, increase the buffer:
        self.sesshun.min_duration = 12.0
        self.sesshunmax_duration  = 12.0
        self.sesshun.save()
        self.assertEquals(True, self.w.hasLstOutOfRange())
        self.assertEquals([wr], self.w.lstOutOfRange())
        self.assertEquals(False, self.w.hasNoLstInRange())

        # now, shrink the original window range so that it 
        # is too small as well
        self.wr1.duration = 1
        self.wr1.save()
        self.assertEquals(True, self.w.hasLstOutOfRange())
        self.assertEquals(True, self.w.hasNoLstInRange())
Beispiel #26
0
    def adjustForLstDrift(self, dts):
        """
        Assuming the first datetime is the target LST, adjust all 
        datetimes to be on the same LST (when they are on different dates.
        Finally, make sure adjusted dates fall on quarter boundaries.
        """

        if len(dts) == 0:
            return []

        # what's the target LST?
        start = dts[0]
        lst = sla.Absolute2RelativeLST(start)

        # make sure each datetime stays on this lst
        adjusted = [start]
        for dt in dts[1:]:
            newDt = sla.RelativeLST2AbsoluteTime(lst, dt)
            if newDt > dt:
                dt2 = dt - timedelta(days = 1)
                newDt = sla.RelativeLST2AbsoluteTime(lst, dt2)
            adjusted.append(TimeAgent.quarter(newDt))
            
        return adjusted 
Beispiel #27
0
def gbt_schedule(request, *args, **kws):
    """
    Serves up a GBT schedule page tailored for Operations.

    Note: This view is in either ET or UTC, database is in UTC.
    """
    def cleanSD(startDate):
        try:
            return datetime.strptime(startDate, '%m/%d/%Y') if startDate else datetime.now() 
        except: # Bad input?
            return datetime.now()

    timezones = ['ET', 'UTC']

    # Note: we probably should have better error handling here,
    # but since the forms are Date Pickers and drop downs, it seems
    # difficult for the user to send us malformed params.

    # Default date, days, and timezone.  Loaded from the values
    # saved below, or from defaults if no values were saved.
    if request.method == 'POST':
        startDate, days, timezone = (None, 5, 'ET')
    else:
        startDate, days, timezone, _ = _get_calendar_defaults(request)
    data      = request.POST if request.method == 'POST' else request.GET
    timezone  = data.get('tz', timezone)
    days      = int(data.get('days', days))
    startDate = cleanSD(data.get('start', startDate))

    start   = TimeAgent.truncateDt(startDate)
    end     = start + timedelta(days = days)

    # save these values for use in 'GET' above.
    _save_calendar_defaults(request, start, days, timezone)
    requestor = get_requestor(request)
    supervisor_mode = True if (requestor in get_rescal_supervisors()) else False

    schedule = get_gbt_schedule_events(start, end, timezone)

    try:
        tzutc = Schedule_Notification.objects.latest('date').date.replace(tzinfo=UTC)
        pubdate = tzutc.astimezone(EST)
    except:
        pubdate = None

    printerFriendly = data.get('printerFriendly', None)
    template = 'users/schedules/schedule_friendly.html' if printerFriendly == '1' \
                   else 'users/schedule.html'
    return render_to_response(
        template,
        {'calendar'        : schedule,
         'day_list'        : range(1, 32),
         'tz_list'         : timezones,
         'timezone'        : timezone,
         'today'           : datetime.now(EST),
         'start'           : start,
         'startFmt'        : start.strftime('%m/%d/%Y'), 
         'days'            : days,
         'rschedule'       : Receiver_Schedule.extract_schedule(start, days),
         'requestor'       : requestor,
         'supervisor_mode' : supervisor_mode,
         'pubdate'         : pubdate,
         })
Beispiel #28
0
def summary(request, *args, **kws):
    """
    Serves up a page that allows Operations to run reconcilation reports. There
    are two basic reports - schedule and project. Even though it is specifically
    for Operations, any logged in user may view it.
    """
    now        = datetime.now()
    psummary = []

    if request.method == 'POST':
        summary = request.POST.get('summary', 'schedule')

        project = project_search(request.POST.get('project', ''))
        if isinstance(project, list) and len(project) == 1:
            project = project[0].pcode
        else:
            project = ''

        month = request.POST.get('month', None)
        year  = request.POST.get('year', None)
        year  = int(year) if year else None
        if month and year:
            start = datetime(int(year)
                           , [m for m in calendar.month_name].index(month)
                           , 1)
        else: # Default to this month
            start = datetime(now.year, now.month, 1)
            month = calendar.month_name[start.month]
            year  = start.year
    else: # Default to this month
        summary    = 'schedule'
        project    = ''
        start      = datetime(now.year, now.month, 1)
        month      = calendar.month_name[start.month]
        year       = start.year

    end = datetime(start.year
                 , start.month
                 , calendar.monthrange(start.year, start.month)[1]) + \
          timedelta(days = 1)

    # View is in ET, database is in UTC. Only use scheduled periods.
    periods = Period.in_time_range(TimeAgent.est2utc(start)
                                 , TimeAgent.est2utc(end))
    if project:
        periods = [p for p in periods if p.isScheduled() and p.session.project.pcode == project]

    # Handle either schedule or project summaries.
    if summary == "schedule":
        schedule = get_gbt_schedule_events(start, end, "ET", True)
        url      = 'users/schedule_summary.html'
        projects = []
        receivers = {}
        days     = {}
        hours    = {}
        summary  = {}
    else:
        url      = 'users/project_summary.html'
        projects = list(set([p.session.project for p in periods]))
        projects.sort(lambda x, y: cmp(x.pcode, y.pcode))

        receivers = {}
        for p in periods:
            rxs = receivers.get(p.session.project.pcode, [])
            rxs.extend([r.abbreviation for r in p.receivers.all()])
            receivers[p.session.project.pcode] = rxs

        schedule = {}
        days     = dict([(p.pcode, []) for p in projects])
        hours    = dict([(p.pcode, 0) for p in projects])
        summary  = dict([(c, 0) for c in Sesshun.getCategories()])
        for p in periods:
            pstart = TimeAgent.utc2est(p.start)
            pend   = TimeAgent.utc2est(p.end())

            # Find the days this period ran within the month.
            day = pstart.day if pstart >= start else pend.day
            days[p.session.project.pcode].append(str(day))
            if day != pend.day: # For multi-day periods
                days[p.session.project.pcode].append(str(pend.day))

            # Find the duration of this period within the month.
            duration = min(pend, end) - max(pstart, start)
            hrs = duration.seconds / 3600. + duration.days * 24.
            hours[p.session.project.pcode] += hrs

            # Tally hours for various categories important to Operations.
            summary[p.session.getCategory()] += hrs

            # If just for one project, create a more detailed summary.
            if project:
                psummary.append((pstart, hrs, p.receiver_list))

    return render_to_response(
               url
             , {'calendar' : schedule
              , 'projects' : [(p
                             , sorted(list(set(receivers[p.pcode])))
                             , sorted(list(set(days[p.pcode]))
                                    , lambda x, y: cmp(int(x), int(y)))
                             , hours[p.pcode]) for p in projects]
              , 'start'    : start
              , 'months'   : calendar.month_name
              , 'month'    : month
              , 'years'    : [y for y in xrange(2009, now.year + 2, 1)]
              , 'year'     : year
              , 'summary'  : [(t, summary[t]) for t in sorted(summary)]
              , 'project'  : project
              , 'psummary' : psummary
              , 'is_logged_in': request.user.is_authenticated()})
Beispiel #29
0
    def test_get_time_not_schedulable(self):
        "Test a number of overlapping bad things"

        # First bad thing: a receiver schedule that leaves out our rx
        # Schedule = 4/01/2009:   450,   600,  800
        #            4/06/2009:   600,   800, 1070
        #            4/11/2009:   800,  1070,  1_2
        #            4/16/2009:  1070,   1_2,  2_3
        #            4/21/2009:   1_2,   2_3,  4_6
        #            4/26/2009:   2_3,   4_6, 8_10
        #            5/01/2009:   4_6,  8_10, 12_18
        #            5/06/2009:  8_10, 12_18, 18_26
        #            5/11/2009: 12_18, 18_26, 26_40
        start   = datetime(2009, 4, 1, 0) # April 1
        end     = datetime(2009, 6, 1, 0) # June  1
        rcvr_id = 3
        for i in range(9):
            start_date = start + timedelta(5*i)
            for j in range(1, 4):
                rcvr_id = rcvr_id + 1
                rs = Receiver_Schedule()
                rs.start_date = start_date
                rs.receiver = Receiver.objects.get(id = rcvr_id)
                rs.save()
            rcvr_id = rcvr_id - 2

        # Now add some receivers to this session
        SessionHttpAdapter(self.sesshun).save_receivers('L | (X & S)')
        blackouts = self.sesshun.get_time_not_schedulable(start, end)

        # No available receivers at these times:
        exp = [(datetime(2009, 4, 1), datetime(2009, 4, 11))
             , (datetime(2009, 5, 1), end)
              ]
        expected = set(exp)
        self.assertEquals(exp, blackouts)

        # Now add a project w/ prescheduled times.
        otherproject = Project()
        pdata = {"semester"   : "09A"
               , "type"       : "science"
               , "total_time" : "10.0"
               , "PSC_time"   : "10.0"
               , "sem_time"   : "10.0"
               , "grade"      : "4.0"
               , "notes"      : "notes"
               , "schd_notes" : "scheduler's notes"
        }
        adapter = ProjectHttpAdapter(otherproject)
        adapter.update_from_post(pdata)

        othersesshun = create_sesshun()
        othersesshun.project = otherproject
        othersesshun.save()

        fdata = {'session'  : othersesshun.id
               , 'date'     : '2009-04-20'
               , 'time'     : '13:00'
               , 'duration' : 1.0
               , 'backup'   : False}
        otherperiod = Period()
        adapter = PeriodHttpAdapter(otherperiod)
        adapter.init_from_post(fdata, 'UTC')
        otherperiod.state = Period_State.objects.filter(abbreviation = 'S')[0]
        otherperiod.save()

        #exp.append((datetime(2009, 4, 20, 13, 0), datetime(2009, 4, 20, 14, 0)))
        exp = [(datetime(2009, 4, 1), datetime(2009, 4, 11))
             , (datetime(2009, 4, 20, 13), datetime(2009, 4, 20, 14))
             , (datetime(2009, 5, 1), end)
              ]

        blackouts = self.sesshun.get_time_not_schedulable(start, end)
        self.assertEquals(exp, blackouts)

        # how much time is that?
        hrsNotSchedulable = sum([TimeAgent.timedelta2minutes(b[1] - b[0])/60.0\
            for b in blackouts])
        self.assertEquals(985.0, hrsNotSchedulable)

        # how does this work when limiting the range?
        newEnd = datetime(2009, 4, 3)
        blackouts = self.sesshun.get_time_not_schedulable(start, newEnd)
        self.assertEquals([(start, newEnd)], blackouts)

        # extend this with a Project Blackout
        blackout = create_blackout(project = self.sesshun.project,
                                   start   = datetime(2009, 4, 18, 12),
                                   end     = datetime(2009, 4, 23, 12),
                                   repeat  = 'Once')

        exp = [(datetime(2009, 4, 1), datetime(2009, 4, 11))
             , (datetime(2009, 4, 18, 12), datetime(2009, 4, 23, 12))
             , (datetime(2009, 5, 1), end)
              ]
        blackouts = self.sesshun.get_time_not_schedulable(start, end)
        self.assertEquals(exp, blackouts)


        # test the time available blacked out calculations
        # Calculate the expected result:
        # it turns out that the project blackout overlaps with all
        # schedulable time, except for one hour on 4/20
        hrsBlackedOut = (TimeAgent.timedelta2minutes(blackout.getEndDate()
                                                     - blackout.getStartDate()) / 60.0) - 1.0
        totalTime = TimeAgent.timedelta2minutes(end - start) / 60.0
        hrsSchedulable = totalTime - hrsNotSchedulable

        s, b, ss, bb = self.sesshun.getBlackedOutSchedulableTime(start, end)
        self.assertEquals(hrsSchedulable, s)
        self.assertEquals(hrsBlackedOut, b)

        # test it some more, but in different ranges
        start = datetime(2009, 5, 1)
        s, b, ss, bb = self.sesshun.getBlackedOutSchedulableTime(start, end)
        self.assertEquals(0.0, b)

        start = datetime(2009, 4, 22)
        end   = datetime(2009, 4, 26)
        totalTime = TimeAgent.timedelta2minutes(end - start) / 60.0
        s, b, ss, bb = self.sesshun.getBlackedOutSchedulableTime(start, end)
        self.assertEquals(totalTime, s)
        self.assertEquals(36.0, b)

        # cleanup
        self.sesshun.receiver_group_set.all().delete()
Beispiel #30
0
    def testGetWindowTimesNonContigious(self):

        # test
        now = datetime(2009, 1, 1)
        wa = WindowAlerts.WindowAlerts()
        times = wa.getWindowTimes(now)

        # expected result
        sch = [(datetime(2009, 4, 6), self.window.end_datetime()) ]
        bss = [(datetime(2009, 4, 6), datetime(2009, 4, 7, 13, 0))]
        schHrs = TimeAgent.timedelta2minutes(sch[0][1] - sch[0][0])/60.0
        bssHrs = TimeAgent.timedelta2minutes(bss[0][1] - bss[0][0])/60.0
        exp = [(self.window
              , (schHrs
               , bssHrs
               , sch
               , [bss]))]

        self.assertEquals(exp[0][0], times[0][0])
        self.assertEquals(exp[0][1], times[0][1])

        # now split up this window into two ranges w/ out changing result
        # 4/5 -> 4/12 changes to 4/2 - 4/4 and 4/6 - 4/12
        wr1 = self.window.windowrange_set.all()[0]
        wr1.start_date = datetime(2009, 4, 6)
        wr1.duration = 6 # days
        wr1.save()

        wr2 = WindowRange(window = self.window
                        , start_date = datetime(2009, 4, 2)
                        , duration = 2)
        wr2.save()

        wa = WindowAlerts.WindowAlerts()
        times = wa.getWindowTimes(now)

        # expected result
        sch = [(datetime(2009, 4, 6), self.window.end_datetime()) ]
        bss = [(datetime(2009, 4, 6), datetime(2009, 4, 7, 13, 0))]
        schHrs = TimeAgent.timedelta2minutes(sch[0][1] - sch[0][0])/60.0
        bssHrs = TimeAgent.timedelta2minutes(bss[0][1] - bss[0][0])/60.0
        exp = [(self.window
              , (schHrs
               , bssHrs
               , sch
               , [bss]))]

        self.assertEquals(exp[0][0], times[0][0])
        self.assertEquals(exp[0][1], times[0][1])

        # now change the window ranges to affect the result - change the 
        # second range so that there is less scheduable time
        wr1.start_date = datetime(2009, 4, 7)
        wr1.duration = 5
        wr1.save()

        wa = WindowAlerts.WindowAlerts()
        times = wa.getWindowTimes(now)

        # expected result
        sch = [(datetime(2009, 4, 7), self.window.end_datetime()) ]
        bss = [(datetime(2009, 4, 7), datetime(2009, 4, 7, 13, 0))]
        schHrs = TimeAgent.timedelta2minutes(sch[0][1] - sch[0][0])/60.0
        bssHrs = TimeAgent.timedelta2minutes(bss[0][1] - bss[0][0])/60.0
        exp = [(self.window
              , (schHrs
               , bssHrs
               , sch
               , [bss]))]