CSC/ECE 517 Fall 2018/E1860 Improvements to staggered deadline

From Expertiza_Wiki
Jump to navigation Jump to search

Introduction

Staggered Deadline Assignment is an assignment which can have different topics listed under it and each of these topics have their independent submission and review deadline. Topic's deadline can be the same as parent assignment or independent to it . Such assignments are useful when the class material is more sequential and instructor wants students to complete assignment as and when a topic gets covered in the class. For example it wouldn't make sense to write a paper on a topic from Chapter 4, until the class had covered Chapter 4.

Problem Statement

Staggered-deadline topic available for selection past its deadline

This issue occurs when a Topic is created with multiple slots. If the topic is not selected for the first round of topics(assignment) or all the slots did not get filled up, It is still available for selection in the subsequent rounds. If a team selects the topic in a later round, they are not able to submit their work as the submission deadline is already over. If the topic had only one slot which remained unselected, instructor can change the deadline for that topic to match the new deadlines, but for topics with multiple slots, if the deadline is extended, the teams who worked on this topic in the previous round can submit/review the topic again. This should not happen.

The signup option used by instructors to signup a team for a topic is visible to the students in their signup page beside every topic. This should not be visible to the students, also the above mentioned issue should be applicable to instructor signup as well.

Manual submission and review deadline entry required for all topics

When creating a topic an instructor is required to enter review and submission deadlines for all the topics. To reduce the manual we want to allow the instructor to apply one deadline entry to a set of topics and also let the system calculate subsequent dates for subsequent project phases like review and re-submission, based on an initial deadline entry. Instructor should also have the ability to edit each of those deadlines independently incase he wants to change a particular deadline of a topic.

New submissions not identifiable among pool of already graded entries

There is no way to identify new submissions or reviews are new since grading was last done. The Submissions and Reviews should appear in different color before and after they are graded. The color scheme should be compatible with the one used for review report. ie Red indicates incomplete Reviews, Blue indicates reviews that have not been graded and Brown for reviews that have grade assigned to them

Proposed Design

Issue 1

Solution :Prevent Students from Signing up for topics past deadline

Students can be prevented from signing up for a topic whose submission deadline has passed. Currently this is happening.

Additional Changes : Do not show sign other's up check mark to student. This has been implemented in User.rb and is being used _topic_names.html.erb to determine wether or not to show the check mark next to the topic name.

user.rb

/* The below code hides the instructor signup option from students and also displays it to only the Instructor or TA of the course, Below are the rules checked; Student can't signup Super Admin can signup Admin of the instructor of the course can signup Instructor and TA of the course can signup */

# This method is used to identify if the user (not student) can signup a team/student for an assignment
  def can_signup_someone_for?(id)
    assignment = Assignment.find(id.to_i)
    instructor = User.find(assignment.instructor_id)
    self.role.name != 'Student' && ((%w[Super-Administrator].include? self.role.name) ||         
        self.can_impersonate?(instructor) ||
        (assignment.instructor_id == self.id) ||
       (instructor.can_impersonate?(self) && self.role.name != 'Student') ||
        (assignment.course_id && Course.find(assignment.course_id).instructor_id == self.id))
  end

Logic currently Implemented to prevent the students from signing up for topics whos deadlines have passed is explained by the following diagram.


MOCK UI

Issue 2

Auto Populate the Due Dates based on First Topic's Dates

This is being achieved by calculating the offsets between the dates based on the offset in the dates of the first Topic of the Assignment.

Once a new Assignment is created, the default dates (the parent assignment's due dates) are not being assigned to the topic. Instead, we show blank space in the UI. Once the user/instructor enters the first submission date, our JS function grabs the offset from the first topic and applies it to the empty fields of this topic. This was done entirely in the frontend using JS to prevent storing any redundant data and increase the ease of usage.


All the fields in the _due_date.html.erb under sign_up_sheet has been changed to a datetimepicker which makes it easy for the instructor to select a date.

$('.datetimepicker').datetimepicker({
    dateFormat: 'yy/mm/dd',
    timeFormat: 'HH:mm:ss'
});

We have written a function which is fired onfocusout HTML event of the field. This function takes the table, extracts the offsets from the first topic and applies the offset to the topic currently being edited (Note: This does not happen for the first topic as we dont have any data yet)

function populateDueDates(topic_id, review_rounds) {
    elementsArray = [];
    $('[id^="due_date_<%= @assignment.sign_up_topics[0].id %>"]').each( function(i, e) {
        /* you can use e.id instead of $(e).attr('id') */
        elementsArray.push($(e).attr('value'));
    });

    // Calculate the offset Days from the difference in days of the first Topic.
    var offsetArray = [];
    var offset = 0
    for (var i = 1; i < elementsArray.length; i++) {
        // Check if the dates for first topic is filled up!
        if (elementsArray[i] != "" && elementsArray[i-1] != "") {
            offset += dateDiffInDays(new Date(elementsArray[i-1]), new Date(elementsArray[i]))
            offsetArray.push(offset);
        } else {
            offsetArray.push(0);
        }
    }

    // Get the ids of input field we need to populate
    var ids = [];
    for (i = 1; i <= review_rounds; i++) {
        ids.push('due_date_' + topic_id + '_submission_' + i + '_due_date');
        ids.push('due_date_' + topic_id + '_review_' + i + '_due_date');
    }

    // Date for the first Submission of the topic.
    var initialDate = jQuery("#" + ids[0]).val();
    for (i = 1; i < ids.length; i++) {
        // Do not update the value if offset is 0
        if (offsetArray[i-1] != 0) {
            // Add Days to the starting date
            var d = addDays(new Date(initialDate), offsetArray[i-1]);
            // "00" + d.getHours() -> slice(-2) returns date and time in the format 08 instead of 8 when the date or time is in single digit
            var formattedDate = d.getFullYear() + "-"  + 
                                ("00" + (d.getMonth() + 1)).slice(-2) + "-" + 
                                ("00" + d.getDate()).slice(-2) + " " + 
                                ("00" + d.getHours()).slice(-2) + ":" + 
                                ("00" + d.getMinutes()).slice(-2) + ":" + 
                                ("00" + d.getSeconds()).slice(-2)
            // Only Change the value of the field if it is empty, Do not change in case there is a date present there already
            if (jQuery("#" + ids[i]).val() == "") {
                jQuery("#" + ids[i]).val(formattedDate);
            }
        }
    }
}

// Add the offset day to the current date
function addDays(curDate, days) {
    curDate.setDate(curDate.getDate() + days);
    return curDate;
}

// Function used to calculate the difference between different deadline dates of the topic.
function dateDiffInDays(a, b) {
    const _MS_IN_DAY = 24 * 60 * 60 * 1000;
    // Discard the time and time-zone information.
    const utc1 = Date.UTC(a.getFullYear(), a.getMonth(), a.getDate());
    const utc2 = Date.UTC(b.getFullYear(), b.getMonth(), b.getDate());
    return Math.floor((utc2 - utc1) / _MS_IN_DAY);
}

Issue 3

Add Colors to the Graded Reviews

Below color coding will be used to indicate the current stage of the reviews :

Blue - Grade Unassigned to the Review

Brown - Review Complete/ Grade Assigned

This was working as intended and No changes have been made as discussed with the professor.

UI MOCK

Test Plan

Issue 1: # Don’t allow students to sign up for topics that has past due dates.

Pre-steps
1. Login as an instructor.
2. Edit any assignment under the General tab, mark it as staggered deadline assignment.
3. Provide deadlines for few topics in the past.
4. Impersonate a student.
5. In the Assignments section, Click on Sign-up sheet.
6. verify topics available for sign-up.
Data and Database Integrity Testing
None
Functional Testing
Expectations:
1. The modified topics should not be available for signup.
2. The unmodified topics with deadlines in future should be available for signup.
User Interface Testing
Expectation:
1. A green tick mark should be available under ‘Actions’ tab for topics with deadlines in the future.
2. Actions’ tab should be empty for topics with deadlines in the past.
Performance Testing
None

Issue 2: # Provide default deadline options for assignments with staggered deadlines.

Pre-steps
1. Login as an instructor.
2. Go to assignments and either create a new one or edit a pre-existing one.
3. Change assignment type to staggered deadline.
4. Type in a submission deadline for Round 1-Submission.
5. Verify that other due dates are auto populated.


Case 1: Instructor wants to assign default deadlines to a staggered assignment:
Steps
1. Click save.
Data and Database Integrity Testing
Expectations:
1. Verify all deadlines are updated in due_at field in due_dates tables for corresponding deadline types after saving the populated values.
Functional Testing
Expectations:
1. Deadlines auto-populated for other Round N should be in correspondence with default offset days between rounds.
2. The auto populated deadline should reflect in student assignment section.
User Interface Testing
Expectation:
1. The auto-population triggered on to corresponding fields by JavaScript should be correct.
2. The format of date auto populated should be as per current system.
Performance Testing
Expectation:
1. The response time to auto populate the dates to other rounds should be within 5 second latency.


Case 2: Instructor wants to enter a custom deadline only for a particular round:
Steps
1. Choose offset value from initial vale from dropdown option available against each deadline type.
Data and Database Integrity Testing
Expectations:
1. Verify all deadlines are updated in due_at field in due_dates tables for corresponding deadline types after saving the populated values.
Functional Testing
Expectations:
1. The auto populated deadline values are changed as per selected offset days from drop-down.
2. Same should reflect in student assignment section.
User Interface Testing
Expectation:
1. The triggered change on to corresponding fields by JavaScript should be correct..
2. The format of date auto populated should be as per current system.
Performance Testing
Expectation:
1. The response time to change the dates to other rounds should be within 5 second latency.
Case 3: Entering an incorrect date when manually entering a deadline for a particular round for a staggered deadline. When the user decides to enter a deadline manually rather than choosing the relative deadlines from the dropdown, care must be taken to ensure that the date is in the correct form:
Pre-steps
1. Impersonate a student.
2. Go to assignments and click on others work.
3. Request multiple reviews.
4. Submit one review.
5. Do not start another review and have another review incomplete.
6. Impersonate Instructor.
7. Go assignments page and view review report for this assignment for the impersonate student in step1.
8. verify the results.
User Interface Testing
Expectation:
1. Incomplete reviews are marked Red.
2. Ungraded reviews are marked Blue.
3. Graded reviews are marked Brown.


Automated Test Plan

Issue 1 : Topics should be available for signing up a team only by the Instructor or TA of the course, admin and super- admin

The following lines are added to spec/models/user_spec.rb file.


describe '#can_signup_someone_for?' do
  let(:admin) { build(:admin, id: 3) }
  let(:super_admin) {build (:superadmin)}
  let(:instructor) { build(:instructor, id: 6) }
  let(:student1) { build(:student, id: 6, name: :lily) }
  let(:assignment) { build(:assignment, id: 1, instructor_id: 6) }
  let(:participant) { build(:participant, id: 1, user_id: 6, assignment: assignment) }

  before(:each) do
    @params = {id: 1}
    allow(AssignmentParticipant).to receive(:find).with('1').and_return(participant)
    allow(AssignmentParticipant).to receive(:find).with(1).and_return(participant)
    allow(Assignment).to receive(:find).with('1').and_return(assignment)
    allow(Assignment).to receive(:find).with(1).and_return(assignment)
    stub_current_user(instructor, instructor.role.name, instructor.role)
    allow(Participant).to receive(:find_by).with('1').and_return(participant)
    allow(Participant).to receive(:find_by).with(parent_id: 1, user_id: 8).and_return(participant)
    allow(User).to receive(:find).with(6).and_return(instructor)

  end

  it 'can signup target user if current user is super admin' do
    allow(user).to receive_message_chain(:role, :name).and_return("Super-Administrator")
    expect(user.can_signup_someone_for?(@params[:id])).to be true
  end

  it 'can signup target user if current user is the instructor of the course' do
    allow(user).to receive_message_chain(:role, :name).and_return("Instructor")
    allow(user).to receive(:can_impersonate?).with(instructor).and_return(false)
    allow(user).to receive_message_chain(:id).and_return(6)
    allow(assignment).to receive_message_chain(:instructor_id).and_return(6)
    expect(user.can_signup_someone_for?(@params[:id])).to be true
  end

  it 'can signup target user if current user is the TA of the course' do
    allow(user).to receive_message_chain(:role, :name).and_return("Teaching Assistant")
    allow(user).to receive_message_chain(:role, :super_admin?).and_return(false)
    allow(user).to receive_message_chain(:role, :ta?).and_return(true)
    allow(instructor).to receive(:teaching_assistant_for?).with(user).and_return(true)
    allow(instructor).to receive(:recursively_parent_of).with(user).and_return(false)
    allow(instructor).to receive(:parent).and_return(nil)
    allow(instructor).to receive(:can_impersonate?).with(user).and_return(true)
    expect(user.can_signup_someone_for?(@params[:id])).to be true
  end


  it 'can signup target user if current user is the admin of the course' do
    allow(user).to receive_message_chain(:role, :name).and_return("Administrator")
    allow(user).to receive(:can_impersonate?).with(instructor).and_return(true)
    expect(user.can_signup_someone_for?(@params[:id])).to be true
  end

  it 'cannot signup target user if current user does not satisfy any of the requirements' do
     allow(user).to receive_message_chain(:role, :name).and_return("Teaching Assistant")
     allow(user).to receive(:can_impersonate?).with(instructor).and_return(false)
     expect(user.can_signup_someone_for?(@params[:id])).to be false
  end
end

Issue 2 : Check if the due_dates fields are being populated automatically once the due_date for the first submission is entered for a topic

# the test will test the Java script which is embedded into the sign up sheet. The java script will
  # computer the offset in dates for the deadlines using the first topic and as soon as we input the date
  # in the first field of a new topic , the other deadlines corresponding to the topic will be populated
  # automatically using the offsets that were calculated from the first topic.
  it "test4:When creating a new topic when already a topic exists for assignment , it should take the offset from the first topic for setting the due dates.",
     js: true do
    login_as("instructor6")
    assignment = Assignment.find_by(name: 'Assignment1665')
    visit "/assignments/#{assignment.id}/edit"
    click_link 'Topics'
    expect(page).to have_content 'Show start/due date'
    click_link 'Show start/due date'
    expect(page).to have_content 'Hide start/due date'
    current_time = DateTime.current
    fill_in 'due_date_3_submission_1_due_date', with: current_time
    expect(find_field("due_date_3_submission_1_due_date").value).to_not eq(nil)
    find(:xpath, ".//input[@id='due_date_3_review_1_due_date']").click
    expect(find_field("due_date_3_review_1_due_date").value).to_not eq(nil)
  end