Exemple #1
0
 def build_days(self,days,timestr):
     # merge days by term/week
     inweek = collections.defaultdict(set)
     for (term,week,day) in days:
         inweek[(term,week)].add(day_names[day])
     # flip the map around so index is by day set
     outweek = collections.defaultdict(set)
     for ((term,week),days) in inweek.iteritems():
         daystr = "".join(sorted(list(days),reverse=True))
         outweek[daystr].add((term,week))
     # For each day combination build term/week specs
     twout = collections.defaultdict(str)
     for (daystr,termweeks) in outweek.iteritems():
         for term in range(0,3):
             weeks = set()
             for (term2,week) in termweeks:
                 if term == term2:
                     weeks.add(week)
             if len(weeks):
                 week_str = util.number_range_text(weeks)
                 twout[int(term)*100+int(min(weeks))] += "%s%s %s" % (term_names[term],week_str,daystr)
     out = FullPattern()
     for k in sorted(twout.keys()):
         out.addOne("%s%s" % (twout[k],timestr))
     return out
Exemple #2
0
def update_details(path,cid,rs):
    logger = logging.getLogger('indium')
    changed = False
    for rv in rs:
        if rv.changedp():
            changed = True
            break
    if not changed:
        return
    logger.info("updating %s" % cid)
    old_det = load_or_new_details(path,cid)
    new_det = old_det.new_same_header()
    # Index values by eid and take copy as orig
    els = {}
    orig_els = {}
    for g in old_det.getGroups():
        for e in g.elements:
            id = e.eid(g.term) 
            els[id] = copy.deepcopy(e)
            orig_els[id] = e
    # Change values
    for rv in rs:
        # We need the orgi as only changes to rectangles should be propagated to the element to avoid the
        # risk of reversion if multiple rectangles map to an element and only early rectangles change.
        orig = orig_els[rv.key]
        new = els[rv.key]
        # what, where, who
        rv.update_to_element(new,orig)
        # did it move?
        if rv.saved_dt != rv.dt:
            # Remove the corresponding old daytimes for all patterns for this rectangle
            tws = []
            wout = FullPattern()
            for p in new.when.each():
                hit = p.removeDayTimeRangeDirect(rv.saved_dt)
                wout.addOne(p)
                if hit: # derive term/weeks from deleted patterns
                    tws.append(p)
            # Add in new daytime
            newp = patternatom.PatternAtom(False)
            newp.addDayTimeRangeDirect(rv.dt)
            for p in tws:
                newp.addTermWeeksFrom(p)
            wout.addOne(newp)
            new.when = wout
    # Populate based on changed values
    for (eid,e) in els.iteritems():
        new_det.addRow(element.Element(e.who,e.what,e.where,FullPattern(e.when),e.merge,e.type,new_det.name))
    if old_det.to_json(True) != new_det.to_json(True):
        print "  saving"
        det_fn = os.path.join(path,"details_%s.json" % cid)
        j = new_det.to_json() # outside open to allow exceptions
        c = open(det_fn,"wb")
        json.dump(j,c)
        c.close()
        return True
    else:
        logger.debug(" didn't seem to change")
        return False
Exemple #3
0
 def __init__(self, dt, course, type, key, order, merged, rcodehash=None):
     self.dt = dt
     self.type = type
     self._termweeks = [[], [], []]
     self._course = course
     self.meta = element.Element(type=type, course=course.cname)
     self.key = key
     self._patterns = FullPattern()
     self.order = order
     self._merged = merged
     self.text = None
     self.saved_dt = None
     self.rcodehash = rcodehash
Exemple #4
0
 def to_json(self):
     when = FullPattern(
         self.meta.when) if self.meta.specified('when') else ''
     rcode = "%s%d%2.2d%2.2d%2.2d%2.2d" % \
         ('Y' if self._merged else 'X',self.dt.day,self.dt.start[0],self.dt.start[1],self.dt.end[0],self.dt.end[1])
     out = {
         "day": self.dt.day,
         "starttime": self.dt.start,
         "endtime": self.dt.end,
         "cid": self._course.cid,
         "rid": rcode,
         "text": self.text if self.text is not None else self.meta.what,
         "cname": self._course.cname,
         "what": self.meta.what,
         "organiser": self.meta.who,
         "where": self.meta.where,
         "type": self.type,
         "termweeks": self._termweeks,
         "code": self.key,
         "when": str(when)
     }
     rcodehash = datahash.datahash(out)
     out['rid'] = "%s:%s:%s" % (rcodehash, out['rid'], util.rndid(
         rcode, "R"))
     return out
def process_new_rectangle(path, caldata, r):
    print "New rectangle!"
    # identify cid
    cid = None
    for c in caldata.courses.itervalues():
        if c['name'] == r['cname']:
            cid = c['id']
    if cid is None:
        raise Exception("Unknown course")
    c = course.Course(cid, r['cname'])
    # load relevant details file
    det = load_or_new_details(path, cid)
    # build element
    el = element.Element(r['organiser'], r['what'], r['where'],
                         FullPattern(r['when']), False, r['type'], c)
    # add to groups
    for term in range(0, 3):
        e = copy.deepcopy(el)
        if e.restrictToTerm(term):
            g = det.getGroup(r['type'], term)
            g.group.append(e)
    # save details
    det_fn = os.path.join(path, "details_%s.json" % cid)
    j = det.to_json()  # outside open to allow exceptions
    c = open(det_fn, "wb")
    json.dump(j, c)
    c.close()
    return cid
Exemple #6
0
 def __init__(self,dt,course,type,key,order,merged,rcodehash = None):
     self.dt = dt
     self.type = type
     self._termweeks = [[],[],[]]
     self._course = course
     self.meta = element.Element(type = type,course = course.cname)
     self.key = key
     self._patterns = FullPattern()
     self.order = order
     self._merged = merged
     self.text = None
     self.saved_dt = None
     self.rcodehash = rcodehash
Exemple #7
0
 def from_json(data, order):
     dt = daytime.DayTimeRange(data['day'], data['starttime'],
                               data['endtime'])
     c = course.Course(data['cid'], data['cname'])
     (rcodehash, rid, _) = data['rid'].split(':')
     merge = rid[0] == 'Y' if 'rid' in data else False  # Is this correct?
     out = Rectangle(dt, c, data['type'], data['code'], order, merge,
                     rcodehash)
     out._termweeks = data['termweeks']
     el = element.Element(what=data['what'],
                          where=data['where'],
                          who=data['organiser'],
                          when=FullPattern(data['when']),
                          type=data['type'],
                          course=data['cname'],
                          merge=merge)
     out.meta.additional(el)
     out._patterns = FullPattern(data['when'])
     # Extract saved daytime
     out.saved_dt = daytime.DayTimeRange(int(rid[1]), int(rid[2:4]),
                                         int(rid[4:6]), int(rid[6:8]),
                                         int(rid[8:10]))
     return out
Exemple #8
0
 def merge(self, mergeState):
     # Fakes
     for cid in mergeState.courseIds:
         print >> sys.stderr, "MISSING %s" % cid
         ds = details.Details(cid, mergeState.names[cid],
                              "Example organiser", "Example location", {
                                  "notes": "",
                                  "course-description": ""
                              })
         for term in ['Michaelmas', 'Lent', 'Easter']:
             for type in ['Lecture', 'Practical']:
                 ds.addRow(
                     element.Element(
                         "Example person", mergeState.names[cid],
                         "Example location",
                         FullPattern(term[:2] + ' ' + self.fake_time()),
                         False, type, mergeState.names[cid]))
         filepaths.saveDetailFile(ds.to_json(), cid)
Exemple #9
0
class Rectangle(object):
    default_metadata = ['notes','course-description','special-instructions']
    
    def __init__(self,dt,course,type,key,order,merged,rcodehash = None):
        self.dt = dt
        self.type = type
        self._termweeks = [[],[],[]]
        self._course = course
        self.meta = element.Element(type = type,course = course.cname)
        self.key = key
        self._patterns = FullPattern()
        self.order = order
        self._merged = merged
        self.text = None
        self.saved_dt = None
        self.rcodehash = rcodehash
    
    def addEvent(self,termweeks,elements,pattern):
        for (term,week) in termweeks.each():
            self._termweeks[term].append(week)
        self.meta.additional(elements)
        self._patterns.addOne(pattern)

    def __repr__(self):
        return "<dt=%s type=%s course=%s termweeks=%s>" % (self.dt.data(),self.type,self._course.cid,self._termweeks)

    def to_json(self):
        when = FullPattern(self.meta.when) if self.meta.specified('when') else ''
        rcode = "%s%d%2.2d%2.2d%2.2d%2.2d" % \
            ('Y' if self._merged else 'X',self.dt.day,self.dt.start[0],self.dt.start[1],self.dt.end[0],self.dt.end[1])
        out = {
            "day": self.dt.day,
            "starttime": self.dt.start,
            "endtime": self.dt.end,
            "cid": self._course.cid,
            "rid": rcode,
            "text": self.text if self.text is not None else self.meta.what,
            "cname": self._course.cname,
            "what": self.meta.what,
            "organiser": self.meta.who,
            "where": self.meta.where,
            "type": self.type,
            "termweeks": self._termweeks,
            "code": self.key,
            "when": str(when)
        }
        rcodehash = datahash.datahash(out)
        out['rid'] = "%s:%s:%s" % (rcodehash,out['rid'],util.rndid(rcode,"R"))
        return out

    def changedp(self):
        if self.rcodehash is None:
            return False
        cmp = copy.deepcopy(self.to_json())
        cmp['rid'] = cmp['rid'].split(":")[1]
        calced = datahash.datahash(cmp)
        return self.rcodehash != calced

    def update_to_element(self,el,orig):
        el.update_with(self.meta,orig)

    def add_rectangles_from_all(self,rs):
        for t in range(0,3):
            v = set(self._termweeks[t])
            for r in rs:
                v |= set(r._termweeks[t])
            self._termweeks[t] = sorted(list(v))

    @staticmethod        
    def from_json(data,order):
        dt = daytime.DayTimeRange(data['day'],data['starttime'],data['endtime'])
        c = course.Course(data['cid'],data['cname'])
        (rcodehash,rid,_) = data['rid'].split(':')
        merge = rid[0] == 'Y' if 'rid' in data else False # Is this correct?
        out = Rectangle(dt,c,data['type'],data['code'],order,merge,rcodehash)
        out._termweeks = data['termweeks']
        el = element.Element(what = data['what'], where = data['where'], who = data['organiser'], when = FullPattern(data['when']), 
                            type = data['type'],course = data['cname'],merge = merge)
        out.meta.additional(el)        
        out._patterns = FullPattern(data['when'])
        # Extract saved daytime
        out.saved_dt = daytime.DayTimeRange(int(rid[1]),int(rid[2:4]),int(rid[4:6]),int(rid[6:8]),int(rid[8:10]))
        return out

    def generate_new_details(self):
        metadata = {}
        for key in Rectangle.default_metadata:
            metadata[key] = ""
        return details.Details(self.course.cid,self.meta.what,self.meta.who,self.meta.where,metadata)

    def generate_direct_pattern(self,term):
        p = patternatom.PatternAtom(False)
        for w in self._termweeks[term]:
            p.addTermWeek(term,w)
        p.addDayTimeRangeDirect(self.dt)
        return p
Exemple #10
0
class Rectangle(object):
    default_metadata = ['notes', 'course-description', 'special-instructions']

    def __init__(self, dt, course, type, key, order, merged, rcodehash=None):
        self.dt = dt
        self.type = type
        self._termweeks = [[], [], []]
        self._course = course
        self.meta = element.Element(type=type, course=course.cname)
        self.key = key
        self._patterns = FullPattern()
        self.order = order
        self._merged = merged
        self.text = None
        self.saved_dt = None
        self.rcodehash = rcodehash

    def addEvent(self, termweeks, elements, pattern):
        for (term, week) in termweeks.each():
            self._termweeks[term].append(week)
        self.meta.additional(elements)
        self._patterns.addOne(pattern)

    def __repr__(self):
        return "<dt=%s type=%s course=%s termweeks=%s>" % (
            self.dt.data(), self.type, self._course.cid, self._termweeks)

    def to_json(self):
        when = FullPattern(
            self.meta.when) if self.meta.specified('when') else ''
        rcode = "%s%d%2.2d%2.2d%2.2d%2.2d" % \
            ('Y' if self._merged else 'X',self.dt.day,self.dt.start[0],self.dt.start[1],self.dt.end[0],self.dt.end[1])
        out = {
            "day": self.dt.day,
            "starttime": self.dt.start,
            "endtime": self.dt.end,
            "cid": self._course.cid,
            "rid": rcode,
            "text": self.text if self.text is not None else self.meta.what,
            "cname": self._course.cname,
            "what": self.meta.what,
            "organiser": self.meta.who,
            "where": self.meta.where,
            "type": self.type,
            "termweeks": self._termweeks,
            "code": self.key,
            "when": str(when)
        }
        rcodehash = datahash.datahash(out)
        out['rid'] = "%s:%s:%s" % (rcodehash, out['rid'], util.rndid(
            rcode, "R"))
        return out

    def changedp(self):
        if self.rcodehash is None:
            return False
        cmp = copy.deepcopy(self.to_json())
        cmp['rid'] = cmp['rid'].split(":")[1]
        calced = datahash.datahash(cmp)
        return self.rcodehash != calced

    def update_to_element(self, el, orig):
        el.update_with(self.meta, orig)

    def add_rectangles_from_all(self, rs):
        for t in range(0, 3):
            v = set(self._termweeks[t])
            for r in rs:
                v |= set(r._termweeks[t])
            self._termweeks[t] = sorted(list(v))

    @staticmethod
    def from_json(data, order):
        dt = daytime.DayTimeRange(data['day'], data['starttime'],
                                  data['endtime'])
        c = course.Course(data['cid'], data['cname'])
        (rcodehash, rid, _) = data['rid'].split(':')
        merge = rid[0] == 'Y' if 'rid' in data else False  # Is this correct?
        out = Rectangle(dt, c, data['type'], data['code'], order, merge,
                        rcodehash)
        out._termweeks = data['termweeks']
        el = element.Element(what=data['what'],
                             where=data['where'],
                             who=data['organiser'],
                             when=FullPattern(data['when']),
                             type=data['type'],
                             course=data['cname'],
                             merge=merge)
        out.meta.additional(el)
        out._patterns = FullPattern(data['when'])
        # Extract saved daytime
        out.saved_dt = daytime.DayTimeRange(int(rid[1]), int(rid[2:4]),
                                            int(rid[4:6]), int(rid[6:8]),
                                            int(rid[8:10]))
        return out

    def generate_new_details(self):
        metadata = {}
        for key in Rectangle.default_metadata:
            metadata[key] = ""
        return details.Details(self.course.cid, self.meta.what, self.meta.who,
                               self.meta.where, metadata)

    def generate_direct_pattern(self, term):
        p = patternatom.PatternAtom(False)
        for w in self._termweeks[term]:
            p.addTermWeek(term, w)
        p.addDayTimeRangeDirect(self.dt)
        return p
def update_details(path, cid, rs):
    logger = logging.getLogger('indium')
    changed = False
    for rv in rs:
        if rv.changedp():
            changed = True
            break
    if not changed:
        return
    logger.info("updating %s" % cid)
    old_det = load_or_new_details(path, cid)
    new_det = old_det.new_same_header()
    # Index values by eid and take copy as orig
    els = {}
    orig_els = {}
    for g in old_det.getGroups():
        for e in g.elements:
            id = e.eid(g.term)
            els[id] = copy.deepcopy(e)
            orig_els[id] = e
    # Change values
    for rv in rs:
        # We need the orgi as only changes to rectangles should be propagated to the element to avoid the
        # risk of reversion if multiple rectangles map to an element and only early rectangles change.
        orig = orig_els[rv.key]
        new = els[rv.key]
        # what, where, who
        rv.update_to_element(new, orig)
        # did it move?
        if rv.saved_dt != rv.dt:
            # Remove the corresponding old daytimes for all patterns for this rectangle
            tws = []
            wout = FullPattern()
            for p in new.when.each():
                hit = p.removeDayTimeRangeDirect(rv.saved_dt)
                wout.addOne(p)
                if hit:  # derive term/weeks from deleted patterns
                    tws.append(p)
            # Add in new daytime
            newp = patternatom.PatternAtom(False)
            newp.addDayTimeRangeDirect(rv.dt)
            for p in tws:
                newp.addTermWeeksFrom(p)
            wout.addOne(newp)
            new.when = wout
    # Populate based on changed values
    for (eid, e) in els.iteritems():
        new_det.addRow(
            element.Element(e.who, e.what, e.where, FullPattern(e.when),
                            e.merge, e.type, new_det.name))
    if old_det.to_json(True) != new_det.to_json(True):
        print "  saving"
        det_fn = os.path.join(path, "details_%s.json" % cid)
        j = new_det.to_json()  # outside open to allow exceptions
        c = open(det_fn, "wb")
        json.dump(j, c)
        c.close()
        return True
    else:
        logger.debug(" didn't seem to change")
        return False