def __call__(self): lecture = self.db.query(models.Lecture).get(self.lecture_id) tutorials = lecture.tutorials if self.request.method == 'POST': student_email = self.request.POST['student_email'] new_tutorial = int(self.request.POST['new_tutorial']) try: student = self.db.query(models.User).filter( models.User.email == student_email).one() except exc.NoResultFound: self.request.session.flash(u'Emailadresse nicht gefunden!', queue='errors') return {'lecture': lecture, 'tutorials': tutorials} tutorial = [t for t in tutorials if t.id == new_tutorial] if len(tutorial) != 1: raise HTTPForbidden( 'Tutorial gehoert nicht zu dieser Vorlesung!') tutorial = tutorial[0] if student in lecture.students.all(): self.request.session.flash( u'Der Student ist in diese Vorlesung bereits eingetragen!', queue='errors') else: lrs = self.request.db.query(models.LectureRemovedStudent).get( (lecture.id, student.id)) if lrs: self.request.db.delete(lrs) #ls = request.db.query(models.LectureStudent).get((lecture.id, request.user.id)) #if ls: # oldtutorial = ls.tutorial #else: ls = models.LectureStudent() ls.lecture = lecture ls.student = student oldtutorial = None ls.tutorial = tutorial if not ls in self.request.db: self.request.db.add(ls) self.request.db.commit() self.request.session.flash( u'Der Student %s wurde in das Tutorial %s (%s) eingetragen' % (student, tutorial.time.__html__(), tutorial.tutor_name), queue='messages') return {'lecture': lecture, 'tutorials': tutorials}
def subscribe(context=None, request=None, tutorial=None, user=None, db=None): tutorial = request.context.tutorials[0] if tutorial is None else tutorial user = request.user if user is None else user db = request.db if db is None else db lecture = tutorial.lecture if tutorial.max_students > tutorial.students.count(): lrs = db.query(models.LectureRemovedStudent).get((lecture.id, user.id)) if lrs: db.delete(lrs) ls = db.query(models.LectureStudent).get((lecture.id, user.id)) if ls: oldtutorial = ls.tutorial else: ls = models.LectureStudent() ls.lecture = lecture ls.student = user oldtutorial = None ls.tutorial = tutorial if not ls in db: db.add(ls) db.commit() if request is not None: if oldtutorial: sendChangesMailUnsubscribe(request, oldtutorial, user, toTutorial=tutorial) sendChangesMailSubscribe(request, tutorial, user, fromTutorial=oldtutorial) request.session.flash('Erfolgreich in Übungsgruppe eingetragen', queue='messages') else: if request is not None: request.session.flash('Maximale Teilnehmerzahl bereits erreicht', queue='errors') if request is not None: return HTTPFound( location=request.route_url('lecture_view', lecture_id=lecture.id))
def assign_student(request): student = request.context.student new_tutorial = request.context.tutorial lecture = new_tutorial.lecture lrs = request.db.query(models.LectureRemovedStudent).get( (lecture.id, student.id)) if lrs: request.db.delete(lrs) ls = request.db.query(models.LectureStudent).get((lecture.id, student.id)) if ls: pass # oldtutorial = ls.tutorial else: ls = models.LectureStudent() ls.lecture = lecture ls.student = student # oldtutorial = None ls.tutorial = new_tutorial if not ls in request.db: request.db.add(ls) request.db.commit() #if oldtutorial: # sendChangesMailUnsubscribe(request, oldtutorial, request.user, toTutorial=tutorial) #sendChangesMailSubscribe(request, tutorial, request.user, fromTutorial=oldtutorial) return {'student': student, 'new_tutorial': new_tutorial}
def assign_student(request): student = request.context.student new_tutorial = request.context.tutorial lecture = new_tutorial.lecture lrs = request.db.query(models.LectureRemovedStudent).get( (lecture.id, student.id)) if lrs: request.db.delete(lrs) lecture_student = request.db.query(models.LectureStudent).get( (lecture.id, student.id)) # TODO: is this really needed?! if not lecture_student: lecture_student = models.LectureStudent() lecture_student.lecture = lecture lecture_student.student = student lecture_student.tutorial = new_tutorial if lecture_student not in request.db: request.db.add(lecture_student) request.db.commit() request.session.flash('{} wurde der Übungsgruppe am {} zugeteilt!'.format( student.name, new_tutorial.time.formatted()), queue='messages') return HTTPFound(location=request.referrer)
def doAllocation(self): if not self.lecture.mode == 'prefs': raise Exception('Lecture not in preference mode') nodes = [] arcs = [] # every object in our optimization problem is a 'node' # the first node we add is the master node. The master node # is the destination for all network flow nodes.append( Node( type='master', id=-1, time=None ## XXX: make catalyst happy! )) # the next node is the 'ghost' node. it is a 'fake-time' which # is needed that our optimization problem _always_ has a solution. # there is always an arc from 'ghost' to 'master'. nodes.append(Node(type='time', id=-1, extra='ghost', time=None)) arcs.append( Arc(1, 0, priority=utils.ghostcapacity, type='times=>master')) # we do now add nodes for all different 'times' where # tutorials are happening. Every time gets an arc to the # master node. times = self.lecture.prepareTimePreferences() for time in times: time_tutorials = [] tuts = self.session.query(models.Tutorial).filter( models.Tutorial.lecture_id == self.lecture.id).filter( models.Tutorial.time == time['time']).all() for tut in tuts: time_tutorials.append({ 'id': tut.id, 'tutorial': tut, 'max_students': tut.max_students, 'act_students': 0 }) if time_tutorials: nodes.append( Node(type='time', time=time['time'], tutorials=time_tutorials)) arcs.append( Arc(len(nodes) - 1, 0, priority=time['max_students'], type='times=>master', extra='')) ## We do now add nodes for the students. Every preference of the ## student is an 'arc' from the student-node to the time-node. ## We do add the arcs here as well. time_preferences = self.lecture.time_preferences students = set([tp.student for tp in time_preferences]) student_nodes = {} for student in students: nodes.append(StudentNode(student=student, id=student.id, time=None)) student_nodes[student.id] = len(nodes) - 1 arcs.append( Arc(len(nodes) - 1, 1, priority=utils.ghostpenalty, type='priority_arc', extra='student=>ghost')) student_preferences = [ tp for tp in student.time_preferences if tp.lecture_id == self.lecture.id ] for tp in student_preferences: for i, node in enumerate(nodes): if node.type == 'time' and node.time and node.time == tp.time: arcs.append( Arc(len(nodes) - 1, i, priority=tp.penalty, type='priority_arc', extra='__need_to_be_filled__')) break elif node.type == 'student': break if len(students) == 0: return {'error_value': 0, 'students_processed': 0} # we do now write a file in the popular dimacs format. inputfile = "c This is Muesli. \n" inputfile += "p min %i %i\n" % (len(nodes), len(arcs)) for i, node in enumerate(nodes): inputfile += 'n %i ' % (i + 1) if node.type == 'master': inputfile += '-%i\n' % (len(students)) elif node.type == 'time': inputfile += '0\n' else: inputfile += '1\n' for i, arc in enumerate(arcs): inputfile += 'a %i %i 0 ' % (arc.src + 1, arc.dest + 1) if arc.type == 'times=>master': inputfile += '%i 1\n' % arc.priority else: inputfile += '1 %i\n' % arc.priority tmpfile = tempfile.NamedTemporaryFile(prefix='muesli', mode='w') tmpfile.write(inputfile) tmpfile.flush() out, err = subprocess.Popen( [utils.lpsolve, '-rxli', 'xli_DIMACS', tmpfile.name], stdout=subprocess.PIPE, universal_newlines=True).communicate() tmpfile.close() if 'Successfully' not in out: raise Exception('Optimizer Error: File Format wrong') out = out.split('Actual values')[1].split('\n', 1)[1] lines = out.split('\n') if not len(lines) > len(arcs): raise Exception('Optimizer Error: File Format wrong') lines = reversed(lines) self.lecture.lecture_students.delete() global_happiness = 0.0 students_unhappy = [] students_without_group = [] narcs = list(arcs) arc = narcs.pop() for line in lines: if line == '': continue line = line.split()[1] if arc.extra == '__need_to_be_filled__' and line == '1': sorted_tutorials = list(nodes[arc.dest].tutorials) sorted_tutorials.sort(key=lambda t: t['act_students']) ls = models.LectureStudent() ls.student = nodes[arc.src].student ls.lecture = self.lecture ls.tutorial = sorted_tutorials[0]['tutorial'] self.session.add(ls) sorted_tutorials[0]['act_students'] += 1 if arc.priority >= utils.students_unhappiness: students_unhappy.append(nodes[arc.src].student) global_happiness += 1 / float(arc.priority) elif arc.extra == 'student=>ghost' and line == '1': students_without_group.append(nodes[arc.src].student) elif arc.type == 'times=>master': break arc = narcs.pop() self.session.commit() return { 'error_value': 0, 'students_processed': len(students), 'students_without_group': students_without_group, 'students_unhappy': students_unhappy, 'global_happiness': 100.0 * global_happiness / (len(students) - len(students_without_group)) if len(students) != len(students_without_group) else 0 }