示例#1
0
def main(form=None):
    if not form:
        form = cgi.FieldStorage()
    tamarin.printHeader("Submission and Grading Results")
    print("<h2>Submission and Grading Results</h2>")
    try:
        print("<p>")

        # check that submitted form was correct with all needed details
        if "uploaded" not in form:
            raise TamarinError("BAD_SUBMITTED_FORM", "Missing uploaded field.")

        # validate filename format, printing username and assignment
        filename = form.getfirst("uploaded")
        match = re.match(tamarin.UPLOADED_RE, filename)
        if not match:
            raise TamarinError("BAD_SUBMITTED_FORM", "Wrong filename format.")

        print("<b>Username:</b> " + match.group(1) + "<br>")
        print("<b>Assignment:</b> " + match.group(2) + "<br>")

        # check that uploaded file really exists
        uploadedFilename = os.path.join(tamarin.UPLOADED_ROOT, filename)
        if not os.path.exists(uploadedFilename):
            raise TamarinError("NO_UPLOADED_FILE")

        # create submitted filename and move uploaded file to submitted folder
        currentStamp = tamarin.convertTimeToTimestamp()
        submittedFilename = filename.replace(".", "-" + currentStamp + ".", 1)
        submittedFilename = os.path.join(tamarin.SUBMITTED_ROOT, submittedFilename)
        shutil.move(uploadedFilename, submittedFilename)
        print("<b>File submitted at:</b> " + currentStamp + "<br>")
        # Yay!  Submission is successful, and user is DONE
        print("<i>--Submission completed successfully--</i>")
        print("</p>")

        # now start grading...
        # (In future, might have option to grade in real time.  For now,
        #  just start the grade pipe and print results.)
        startGradePipe()

    except TamarinError as err:
        tamarin.printError(err)
        print("<p>")
        print(
            "Due to the above error, your file was <i>not</i> successfully "
            "submitted. You may want to try again or else contact your "
            "Tamarin administrator "
        )
        if tamarin.ADMIN_EMAIL:
            print("(" + tamarin.ADMIN_EMAIL + ")")
        print(" with the details of the error you encountered.")
        print("</p>")
    except:
        tamarin.printError("UNHANDLED_ERROR")
    finally:
        tamarin.printFooter()
示例#2
0
 def isLate(self, submittedTimestamp=None):
     """
     Determines whether the submittedTimestamp (in 'YYYYMMDD-HHMM' format)
     occurs before this assignment's deadline.  If submittedTimestamp is 
     None, uses the current time.
     """
     import tamarin
     if not submittedTimestamp:
         # use current time
         submittedTimestamp = tamarin.convertTimeToTimestamp()
     # nice thing about Tamarin timestamps is they also compare properly 
     return submittedTimestamp > self.due
示例#3
0
def main():
    """
    Displays current time, grading method, gradepipe status, number of
    uploaded (but unsubmitted files), and the submitted queue.
    """
    tamarin.printHeader("Tamarin Status")
    try: 
        print('<h2>Tamarin Status</h2>')
    
        # current time 
        # (Printed in two different formats as a way for users 
        # to learn how to make sense of Tamarin timestamp format)
        print('<p><b>Current System Time:</b> ')
        now = datetime.datetime.now()
        print(tamarin.convertTimeToTimestamp(now))
        print('&nbsp; (<i>' + now.isoformat(' ') + '</i>)')
        print('</p>')
    
        # uploaded file count
        print('<p><b>Uploaded (but not submitted) file count:</b> ')
        uploaded = glob.glob(os.path.join(tamarin.UPLOADED_ROOT, '*'))
        print(len(uploaded))
        
        # grade pipe status      
        print('<p><b>Gradepipe:</b> ')
        if os.path.exists(tamarin.GRADEPIPE_ACTIVE):
            print('<small>RUNNING</small>')
        else:
            print('<small>OFF</small>')
        if os.path.exists(tamarin.GRADEPIPE_DISABLED):
            print(' <small>(DISABLED)</small>')    
        print('</p>')
        
        # grading queue contents
        print('<p><b>Submitted (but not yet graded) queue:</b> ')
        submitted = tamarin.getSubmittedFilenames()
        if len(submitted) == 0:
            print('[empty]')
        else:
            print('<br>')
            for s in submitted:
                print('<span class="gradequeue">' + os.path.basename(s) + 
                      '</span><br>')
        print('</p>')

    except:
        tamarin.printError('UNHANDLED_ERROR')
    finally: 
        tamarin.printFooter()
示例#4
0
 def isTooLate(self, submittedTimestamp=None):
     """
     Determines whether the submittedTimestamp (in 'YYYYMMDD-HHMM' format)
     occurs after this assignment's deadline AND after all late policies.  
     If submittedTimestamp is None, uses the current time.
     """
     import tamarin
     if not submittedTimestamp:
         # use current time
         submittedTimestamp = tamarin.convertTimeToTimestamp()
     if self.policies:
         # just look at last one (already sorted)
         return submittedTimestamp > self.policies[-1].end
     else:
         return self.isLate()
示例#5
0
    def getPolicy(self, submittedTimestamp=None):
        """
        Returns the appropriate policy associated with this assignment based
        on the given timestamp.  If no timestamp is given, uses the current
        time.  May return None if this assignment has no late policies, or if
        the given timestamp is before the deadline but there is no early 
        submission policy.
        """
        import tamarin
        if not submittedTimestamp:
            # use current time
            submittedTimestamp = tamarin.convertTimeToTimestamp()        
        timestamp = submittedTimestamp 

        if not self.policies:
            return None
        elif self.isLate(timestamp):
            if self.policies[-1].isEarlyPolicy():
                # only have early policies, though, so none apply
                return None
            else:
                # find last late policy that applies (even if past last one)
                for policy in self.policies:
                    if not policy.isEarlyPolicy() and timestamp <= policy.end:
                        break
                return policy                
        else:
            if not self.policies[0].isEarlyPolicy():
                # submission is early, but only have late policies
                return None
            else:
                #find closest-to-deadline early policy that applies (or first)
                for policy in reversed(self.policies):
                    if policy.isEarlyPolicy() and timestamp >= policy.end:
                        break
                return policy
示例#6
0
    def __init__(self, policy, deadline):
        """
        Constructs a LatePolicy according to the given policy string.

        The deadline should be in Tamarin timestamp format.  
                
        Each policy should be a string in the form of: 'range:rule'
        
        A range has the following format: [+|-][[#d][#h][#m]|timestamp]
        
        That is, the range may optionally begin with either + or -.  
        If the sign is omitted, + is assumed.  
        
        The sign may then be followed by a span specified in days, 
        hours, and minutes.  This span is relative to the assignment deadline,
        either earlier (if sign is -) or later (if sign is +).  A particular
        unit may be omitted if unused; it will be assumed to be 0.  If more 
        than 23 hours or 59 minutes are specified, the corresponding overflow 
        into days and hours will be calculated.  At least one unit must be
        given though: d for day, h for hours, or m for minutes.  If more
        than one is used, they must be in that order.
        
        As an alternative to specifying a relative span, a specific timestamp
        may be given. The sign is ignored in these cases. (Since LatePolicies 
        usually apply across multiple assignments, specific timestamps are 
        rare.  However, they can be handy to specify a final cutoff date for 
        all assignments--such as the last day of the course.)  
        
        It is an error to have a 0 length span, either because the relative
        span is of size 0 or if the timestamp given is equal to the deadline.
        
        If neither span nor timestamp is given, the end of the span is 
        treated as year 0 for a - sign or year 9999 for a positive sign.
                
        The range is then separated from the associated rule by a colon (:).
        
        The rule is of the form: [+|-|=][#[%|$]][/[#d][#h][#m]]

        That is, the rule may begin with a sign: +, -, or =.  If omitted,
        = is assumed.  The sign specifies whether the grade should be 
        increased by (+), decreased (-) by, or set equal to (=) the following
        value. 
        
        The sign is followed by an integer value, which may be appended by 
        either % or $.  Without a modifier, the value is treated as a raw 
        point modifier.  If appended with a %, this is a percentage of the 
        assignment's total possible score.  If appended with a $, 
        it is a percentage of the submission's actual score.  (If the actual
        score to be modified is not numeric, will default to % instead.)
        
        Optionally, the modifier may be followed by a / and relative span.
        At least one value--whether day, hour, or minutes--must be given
        after a /.  When such a span is given, the modifier is applied for 
        each span that the assignment is late.  For example, /1d means apply
        the modifier for each day.  Such as span does nothing if applied to 
        an = modifier.  If this rule is associated with a -timespan ("bonus 
        policy"), it is applied for each full span. Otherwise, it is applied 
        for each partial span.
        
        The rule may be omitted.  In this case, the submission is marked late
        (or early), but no grade change is applied.
                
        Examples:
        +5d:-1/1d - For up to 5 days after the deadline, submissions suffer 
        a penalty of 1 point off for each (partial) day.
        
        +48h:-10% - For 2 days after the deadline, any submission loses 10% 
        of the assignment total.  (So, for a 5 point assignment, this would 
        be -1 point.)  Equivalent to '2d:-10%' (if relying on the assumed 
        + sign on the timespan).
        
        -3d:+5$/1d - An example of an "early bonus" policy, this grants a 
        cumulative bonus of 5 percent of the submission's score for each full 
        day early.
        
        20121221-1200:40$ - Using a timestamp to define the span, anything 
        submitted after the deadline but before noon on 21 Dec 2012 will 
        receive 40% of the score it would otherwise have received.  
        (:=40$ or :-60$ would also have been equivalent rules, since = is 
        assumed on rules without a sign.)
        
        1d: - Anything submitted for up to 1 day past the deadline is marked
        as late but its grade is unaffected.
        
        Given only the policies above, any submissions later than the deadline
        plus the given late period timespan would be refused by Tamarin.
        
        +:10% - Anything submitted after the deadline, no matter how late or 
        how bad, is given 10% of the total possible assignment value.  
        
        : - Anything submitted after the deadline is late but still accepted.
        
        """
        import tamarin
        self.raw = policy
        self.deadline = deadline
        assert re.match(r'\d{8}-\d{4}', self.deadline)
                
        span_re = r'(\+|-)?((\d{8}-\d{4})|((\d+d)?(\d+h)?(\d+m)?))'
        rule_re = r'(\+|-|=)?(\d*)([%$])?(/(\d+d)?(\d+h)?(\d+m)?)?'
        parsed = re.match(span_re + ':' + rule_re, policy)
        if not parsed:
            raise TamarinError('INVALID_LATE_POLICY', policy)

        (self.span_sign, unused_offset, self.span_timestamp, 
         relative, self.span_day, self.span_hour, self.span_minute,
         self.rule_sign, self.rule_value, self.rule_unit, 
         self.rule_repeater, 
         self.rule_day, self.rule_hour, self.rule_minute) = parsed.groups()
        
        #apply defaults and constrains
        if not self.span_sign:
            self.span_sign = '+'
        
        if self.span_timestamp:
            self.end = self.span_timestamp
        elif relative:
            day = hour = minute = 0
            sign = -1 if self.span_sign == '-' else 1           
            if self.span_day:
                day = int(self.span_day[:-1]) * sign
            if self.span_hour:
                hour = int(self.span_hour[:-1]) * sign
            if self.span_minute:
                minute = int(self.span_minute[:-1]) * sign
            endDate = tamarin.convertTimestampToTime(deadline)            
            shift = datetime.timedelta(days=day, hours=hour, minutes=minute)
            self.end = tamarin.convertTimeToTimestamp(endDate + shift)
        else:
            if self.span_sign == '-':
                self.end = '00000101-0000'
            else: 
                self.end = '99991231-2359'
        
        if self.end == self.deadline:
            raise TamarinError('INVALID_LATE_POLICY', 
                               "Parsable, but deadline == endpoint.")

        if self.rule_sign or self.rule_value or self.rule_unit or \
                self.rule_repeater:
            #some part of a rule given, so lets see if it's all valid
            if not self.rule_sign:
                self.rule_sign = '='
            if not self.rule_value:
                raise TamarinError('INVALID_LATE_POLICY', 
                                   "No grade change value given.")
            self.rule_value = int(self.rule_value)
            if self.rule_repeater and not self.rule_day and \
                    not self.rule_hour and not self.rule_minute:
                raise TamarinError('INVALID_LATE_POLICY', 
                                   "Empty /modifier given: " + self.raw)