Пример #1
0
    def post(self):
        """
        HTTP POST method to add the student.
        """
        # First, check that the logged in user is an instructor
        instructor = utils.check_privilege(model.Role.instructor)
        if not instructor:
            # Send them home and short circuit all other logic
            return self.redirect('/')
        # end

        # So first we need to get at the course and section
        course, section = utils.get_course_and_section_objs(self.request, instructor)
        # And grab the action from the page
        action = self.request.get('action')
        # Check that the action was actually supplied
        if not action:
            # Error if not
            utils.error('Invalid arguments: course_name or section_name or actoin is null', handler=self)
        else:
            # Now switch on the action
            if action == 'add':
                # Grab a list of the emails from the page
                emails = json.loads(self.request.get('emails'))
                # And create new students from that list
                self.add_students(section, emails)
            elif action == 'remove':
                # Grab the email from the page to remove
                email = self.request.get('email').lower()
                # And remove it
                self.remove_student(section, email)
            else:
                # Send an error if any other action is supplied
                utils.error('Unexpected action: ' + action, handler=self)
Пример #2
0
    def post(self):
        """
        HTTP POST method to create groups.
        """
        # First, check that the logged in user is an instructor
        instructor = utils.check_privilege(model.Role.instructor)
        if not instructor:
            # Send them home and short circuit all other logic
            return self.redirect('/')
        # end

        # So first we need to get at the course and section
        course, section = utils.get_course_and_section_objs(self.request, instructor)
        # Grab the action from the page
        action = self.request.get('action')
        # Check that the action was actually supplied
        if not action:
            # Error if not
            utils.error('Invalid argument: action is null', handler=self)
        else:
            # Switch on the action
            utils.log('action = ' + action)
            if action == 'add':
                # If add, grab the number of groups from the page
                group_count = int(self.request.get('groups'))
                # And modify the database
                self.modify_group_count(section, group_count)
            elif action == 'update':
                # For update, grab the group settings from the page
                groups = json.loads(self.request.get('groups'))
                # And modify the database
                self.update_groups(section, groups)
            else:
                # Send an error if a different action is supplied
                utils.error('Unknown action' + action if action else 'None', handler=self)
Пример #3
0
    def start_rounds(self, instructor):
        # So first we need to get at the course and section
        course, section = utils.get_course_and_section_objs(
            self.request, instructor)
        # And grab all of the rounds for this section
        rounds = model.Round.query(ancestor=section.key).fetch()
        # The view requires at least a initial question to add rounds, but check
        if not rounds:
            # Send an error if no rounds exist for this section
            utils.error('Error! No initial question exists; cannot start yet.',
                        handler=self)
            # And redirect
            return self.redirect('/')
        # end

        # Now simply turn on the first round
        section.current_round = 1
        section.put()

        # Add the dummy read only round if it's a rounds based discussion
        if section.has_rounds:
            self.add_rounds(num_of_rounds=1,
                            duration=0,
                            instructor=instructor,
                            type=model.Round.get_round_type('readonly'),
                            buffer_bw_rounds=0,
                            quiet=True)

        # And send a success message
        utils.log('Successfully started the first round.',
                  type='Success!',
                  handler=self)
Пример #4
0
 def toggle_anonymity(self, instructor):
     # So first we need to get at the course and section
     course, section = utils.get_course_and_section_objs(
         self.request, instructor)
     if section:
         section.is_anonymous = not section.is_anonymous
         section.put()
         utils.log('Anonymity toggled to: ' + str(section.is_anonymous))
     else:
         utils.error('Section not found')
Пример #5
0
 def toggle_round_structure(self, instructor):
     # So first we need to get at the course and section
     course, section = utils.get_course_and_section_objs(
         self.request, instructor)
     if section:
         section.has_rounds = not section.has_rounds
         section.put()
         utils.log('Rounds Structure toggled to: ' +
                   str(section.has_rounds))
     else:
         utils.error('Section not found')
Пример #6
0
    def add_rounds(self,
                   num_of_rounds,
                   duration,
                   instructor,
                   buffer_bw_rounds,
                   type=2,
                   quiet=False):
        # So first we need to get at the course and section
        course, section = utils.get_course_and_section_objs(
            self.request, instructor)
        # And grab all of the rounds for this section
        rounds = model.Round.query(ancestor=section.key).fetch()
        # The view requires at least a initial question to add rounds, but check
        if not rounds:
            # Send an error if no rounds exist for this section
            utils.error(
                'Error! No initial question exists; cannot add new rounds yet.',
                handler=self)
            # And redirect
            return self.redirect('/')
        # end

        # We'll need this later on when doing the buffer stuff
        # if rounds_buffer < 0
        #     # Make sure the buffer value is positive
        #     utils.error('Error! Buffer value must be greater than 0.', handler=self)
        #     # And redirect
        #     return self.redirect('/')
        # #end

        # Copy the summary round if it exists
        summary = copy_summary(section, rounds, num_of_rounds)
        # If it exists, pop it off the list
        if summary:
            rounds.pop()
        # end

        # Now create all the new rounds
        new_rounds = create_new_rounds(section, rounds, num_of_rounds,
                                       duration, buffer_bw_rounds, type)

        # And update the summary round
        update_summary(summary, new_rounds)
        # Now update the number of rounds attribute of the section
        update_section_rounds(new_rounds[-1].number, section)

        # Now send a success message
        if not quiet:
            utils.log(
                'Successfully added {0} new rounds.'.format(num_of_rounds),
                type='Success!',
                handler=self)
        utils.log('Added Rounds = ' + str(new_rounds))
Пример #7
0
 def end_current_round(self, instructor):
     utils.log("trying to end the current round")
     course, section = utils.get_course_and_section_objs(
         self.request, instructor)
     current_round = utils.get_current_round_object(section)
     next_round = utils.get_next_round_object(section)
     if not current_round:
         utils.log("current round is empty!")
         return
     utils.log("current round is number " + str(current_round.number))
     # if/else is to support both legacy (string) and new (datetime) data types
     current_round.deadline = datetime.datetime.now()
     current_round.put()
     if next_round:
         next_round.starttime = datetime.datetime.now()
         next_round.put()
         section.current_round = next_round.number
         section.put()
Пример #8
0
    def delete_round(self, instructor, round_id):
        # So first we need to get at the course and section
        course, section = utils.get_course_and_section_objs(
            self.request, instructor)
        # And grab all of the rounds for this section
        rounds = model.Round.query(ancestor=section.key).fetch()
        # The view requires at least a initial question to add rounds, but check
        if not rounds:
            # Send an error if no rounds exist for this section
            utils.error(
                'Error! No initial question exists; cannot add new rounds yet.',
                handler=self)
            # And redirect
            return self.redirect('/')
        # end

        # Now shift all the rounds and remove the round with the input id
        shift_rounds(rounds, round_id)

        # Now let's check if we need to copy a summary question over or not
        if rounds[-1].description == 'summary':
            # Delete the next to last round and remove from the list
            rounds[-2].put().delete()
            rounds.pop(-2)
            # And copy the summary round and update the times
            summary = copy_summary(section, rounds, -1)
            # Remove the old summary from the list
            rounds.pop()
            update_summary(summary, rounds)
        else:
            # Finally, remove the very last round from the list
            rounds[-1].put().delete()
        # end

        # Since we shifted rounds forward, remove the last round from the list
        rounds.pop()
        # And update the section
        update_section_rounds(rounds[-1].number, section)
        # And send a success message
        utils.log('Successfully deleted round {0}'.format(round_id),
                  type='Success!',
                  handler=self)
Пример #9
0
    def edit_round(self, instructor, round_id):
        # So first we need to get at the course and section
        course, section = utils.get_course_and_section_objs(
            self.request, instructor)
        # And grab all of the rounds for this section
        rounds = model.Round.query(ancestor=section.key).fetch()
        # The view requires at least a initial question to add rounds, but check
        if not rounds:
            # Send an error if no rounds exist for this section
            utils.error(
                'Error! No initial question exists; cannot add new rounds yet.',
                handler=self)
            # And redirect
            return self.redirect('/')
        # end

        # TODO allow editing the _deadline_ even after the round has started

        # Now grab the inputs from the page
        description = self.request.get('description')
        # and get the start and end times for the round
        start_time = utils.to_utc(self.request.get('start_time'))
        deadline = utils.to_utc(self.request.get('deadline'))

        # Loop over the rounds to find the one we're trying to edit
        for i in range(len(rounds)):
            if rounds[i].number == round_id:
                # First, let's set the description
                rounds[i].description = description

                # Now, let's grab the deadline of the previous round
                previous_end = rounds[i - 1].deadline
                # Check if the new start time is BEFORE the previous round's
                # end time
                if start_time < previous_end:
                    # Send an error if so
                    utils.error(
                        'Error! Cannot set new start time earlier than \
                            deadline of round {0}.'.format(i - 1),
                        handler=self)
                    # And exit
                    break
                # end
                # Otherwise, the new start time doesn't overlap; we can set it
                rounds[i].starttime = start_time
                # And now set the new deadline for this round
                rounds[i].deadline = deadline

                # Now, check to see if there's a rounds we need to propagate to
                if i != len(rounds) - 1:
                    # Grab the start time of the next round
                    next_start = rounds[i + 1].starttime
                    # If the new deadline isn't the same as the next start time
                    if deadline != next_start:
                        # We need to move the start and end times of the rest
                        # of the rounds, so loop over them
                        for j in range(i + 1, len(rounds)):
                            # First, get the duration of the round
                            duration = get_duration(rounds[j].starttime,
                                                    rounds[j].deadline)
                            # Now set the new start time to be the
                            # deadline of the previous round
                            rounds[j].starttime = rounds[j - 1].deadline
                            # And calculate and set the new end time
                            rounds[j].deadline = rounds[j].starttime + duration
                            # And save it back to the database
                            rounds[j].put()
                            # end
                            # end
                # end
                # And commit the changes to the database
                rounds[i].put()
                # Since we've done our updating, break the loop
                utils.log('Successfully updated round {0}.'.format(round_id),
                          type='S',
                          handler=self)
                break
Пример #10
0
    def add_leadin_summary(self, instructor):
        # So first we need to get at the course and section
        course, section = utils.get_course_and_section_objs(
            self.request, instructor)

        # Before anything, we need to check that the deadline is in the future
        if datetime.datetime.now() > utils.to_utc(self.request.get('time')):
            # Send an error if so and exit
            utils.error('Error! Cannot create deadline in the past.',
                        handler=self)
            return
        # end

        # Build the round object
        round_obj = self.build_round_obj(section)

        # Now grab all of the rounds
        rounds = model.Round.query(ancestor=section.key).fetch()
        # And switch on the type to create our start time
        if round_obj.description == 'initial':
            round_obj.type = model.Round.get_round_type('initial')
            add_lead_in(round_obj, rounds)
        else:
            # If not a lead-in question, we know it's a summary
            # And check that we're not trying to add a summary as the first
            if not rounds:
                # Send an error if so and return
                utils.error(
                    'Error! Summary question cannot be first round added.',
                    handler=self)
                return
            # end

            # First check if we're editing the summary
            if rounds[-1].description == 'summary':
                # And if so, grab the deadline of the round before the summary
                last_time = rounds[-2].deadline
                # And remove the old summary from the database
                rounds[-1].put().delete()
            else:
                # Otherwise, grab the deadline of the previous round
                last_time = rounds[-1].deadline
            # end

            # Assign the proper type
            round_obj.type = model.Round.get_round_type('final')

            # Let's check that the deadline doesn't conflict with the last round
            if round_obj.deadline <= last_time:
                # Send an error if so and return
                utils.error(
                    'Error! Cannot set end time of final before end of last discussion.',
                    handler=self)
                return
            # end
            # Set start time of summary as the deadline of the last round
            round_obj.starttime = utils.str_to_datetime(last_time)

        # end

        # Now save the round to the database
        round_obj.put()
        # And grab all the rounds one last time
        rounds = model.Round.query(ancestor=section.key).fetch()
        # And update the section rounds attribute if necessary
        update_section_rounds(rounds[-1].number, section)
        # And send our success message
        # utils.log('Success, round added.', type='Success!', handler=self)
        utils.log('Success! Round added.', type='S', handler=self)
Пример #11
0
    def post(self):
        # First, check that the logged in user is an instructor
        instructor = utils.check_privilege(model.Role.instructor)
        if not instructor:
            # Send them home and short circuit all other logic
            return self.redirect('/')
        # end

        # Now let's grab the action from the page
        action = self.request.get('action')
        # And check that it was actually passed
        if not action:
            # Error if not
            utils.error('Error! Invalid arguments: action is null',
                        handler=self)
        else:
            # Now switch on the action
            if action == 'add':
                # Only the lead-in or summary are listed as an 'add' action
                self.add_leadin_summary(instructor)
            elif action == 'end-current-round':
                self.end_current_round(instructor)
            elif action == 'add_disc':
                # Now, let's grab the number of rounds and duration from page
                num_of_rounds = int(self.request.get('total_discussions'))
                duration_of_round = int(self.request.get('duration'))
                # And grab the buffer time between rounds
                buffer_bw_rounds = 0  # int(self.request.get('buffer_time'))

                # Get the type based on whether it's a rounds based discussion or sequential
                course, section = utils.get_course_and_section_objs(
                    self.request, instructor)
                # round_type = model.Round.get_round_type(
                #     'discussion') if section.has_rounds else model.Round.get_round_type('sequential')
                round_type = 2 if section.has_rounds else 3
                # Send the number and duration to the add rounds function
                self.add_rounds(num_of_rounds=num_of_rounds,
                                duration=duration_of_round,
                                instructor=instructor,
                                type=round_type,
                                buffer_bw_rounds=buffer_bw_rounds)
            elif action == 'delete':
                # Send the id of the round to be deleted
                round_id = int(self.request.get('round_id'))
                self.delete_round(instructor, round_id)
            elif action == 'change':
                # Send the id of the round to be edited
                round_id = int(self.request.get('round_id'))
                self.edit_round(instructor, round_id)
            elif action == 'start':
                # Simply kick off the first round
                self.start_rounds(instructor)
                # Send mail to students
                # Grab section object and instructor email to pass to email function
                email_course, email_section = utils.get_course_and_section_objs(
                    self.request, instructor)
                # Grab the message of the email
                message = self.request.get('message')
                # Grab the subject of the email
                subject = self.request.get('subject')
                to_emails = [s.email for s in email_section.students]
                utils.send_mails(to_emails, subject, message)
                email_course.recent_section = email_section.name
                email_course.put()
            elif action == 'toggle_anon':
                self.toggle_anonymity(instructor)
            elif action == 'toggle_round_structure':
                self.toggle_round_structure(instructor)
            else:
                # Send an error if any other action is supplied
                utils.error('Error! Unexpected action: ' + action,
                            handler=self)