Aktiv Learning

Logo

View the Project on GitHub Aktiv-Learning/Aktiv-Help

Home > Guides > Adaptive Follow Up (QA)

Use the following guides to QA Adaptive Follow Up.

Adaptive Follow Up QA Guide

  1. Adaptive Follow Up (or simmply Adaptive) is a new a feature that essentially auto-generates new assignments based off of a “source” assignment.

  2. Basically a student completes a normal assignment (the “source” assignment), and then the Aktiv system auto-generates a new assignment bassed off of this source assignment. It does this by having a look at what problems the source assignment contained and seeing how well the student performed on these problems, and then determines intelligently what problems to add to a new auto-generated “adaptive” assignment.

  3. The system that determines what problems the adaptive assignment should contain is called the “Adaptive Engine”. This is an independent process running in API Gateway + Lambda. The code is here - Aktiv-Adaptive.

  4. Essentially the backend Aktiv-Server system contacts the Aktiv-Adaptive (known as the “Adaptive Engine”) by providing it a source assignment and student as input, and then this responds with an output of a list of problems to use in a new “Adaptive” assignment.

  5. There is only ever ONE adaptive assignment for a source assignment. This adaptive assignment will contain all the problems chosen for all the students. Technically each student gets a different set of problems. So each problem in this adaptive assignment is only assigned to one student.

    For e.g. imagine we have StudentA and StudentB, then inside the Adaptive assignment we could have:

    • Problem0 (assigned to StudentA)
    • Problem1 (assigned to StudentA)
    • Problem2 (assigned to StudentB)
    • Problem3 (assigned to StudentB)

    Technically speaking this is how they are ordered in the assignment. Of course, StudentA only ever sees Problem0 and Problem1. And StudentB only ever sees Problem2 and Problem3.

    The frontend uses problemStudentView.number to display the “effecitve” display position to the user.

  6. Also it is possible that some students are assigned a different number of problems. So StudentA gets 5 problems and StudentB gets 6 problems etc.

  7. The backend has an “Adaptive Scheduler” which is basically a service that is scheduled to run roughly every 1-2 minutes, which will basically check our DB for any “source” assignments that need an adaptive assignment (that hasn’t been created yet). Think of this like the backend cron job that runs in the background to create needed new adaptive assignments every couple of minutes.

  8. The Adaptive Scheduler will look for source assignments that match the following criteria:

    1. Must be in a course that is available (i.e. course.archived != true AND course.deleted != true).
    2. Must be in a course that has adaptive follow up enabled (i.e. course.adaptiveEnabled = true).
    3. Must be in a course that a term for that is considered “current” or “previous” (i.e. course.term = thisSeasonalTerm || thisAcademicYear || previousSeasonTerm || previousAcademicYear).
    4. Must be in a course that has not expired (i.e. the course.expiration = future).
    5. The source assignment must be available (i.e. assignment.archived != true AND assignment.deleted != true).
    6. The source assignment must have adaptive follow up enabled (i.e. assignment.adaptiveEnabled = true).
    7. The source assignment must be published (i.e. assignment.states != DRAFT).
    8. The source assignment must have expired (the “default” due date) (i.e. assignment.dueDate = past).

    (Note that the source assignment does not have to have the sourceAssignment.adaptive settings set to anything), as the backend will use some defaults. It just needs the assignment.adaptiveEnabled = true.

  9. “Current” course term is defined as any seasonal term or academic yearly term that is within date range. A term is either a seasonal term such as WINTER_2023, or is an academic yearly term such as ACADAMIC_YEAR_2022_2023. Each term has a start date and end date based on customer success team definitions.

    1. WINTER and SPRING go from 1st of Jan to 30th of April.
    2. SUMMER and FALL go from 1st of May to 31st of December.
    3. ACADEMIC_YEAR_X go from 1st of May to 30th of April (the following year).

    Examples:

    • So for e.g. WINTER_2021 goes from 1st of Jan 2021, to 30th of April 2021.
    • So for e.g. SPRING_2021 goes from 1st of Jan 2021, to 30th of April 2021.
    • So for e.g. SUMMER_2021 goes from 1st of May 2021, to 31st of December 2021.
    • So for e.g. FALL_2021 goes from 1st of May 2021, to 31st of December 2021.
    • So for e.g. ACADEMIC_YEAR_2021_2022 goes from 1st of May 2021, to 30th of April 2022.
    • So for e.g. ACADEMIC_YEAR_2022_2023 goes from 1st of May 2022, to 30th of April 2023.

    “Current” Examples:

    • So for e.g. if today is 2021-05-01 then SUMMER_2021, FALL_2021 and ACADEMIC_YEAR_2021_2022 is current.
    • So for e.g. if today is 2021-04-30, then WINTER_2021, SPRING_2021 and ACADEMIC_YEAR_2020_2021 is current.
  10. “Previous” course term is defined as any term that is before a “Current” term.

    1. For e.g. 2023-04-30 returns:
      • SUMMER_2022
      • FALL_2022
      • WINTER_2023
      • SPRING_2023
      • ACADEMIC_YEAR_2021_2022
      • ACADEMIC_YEAR_2022_2023
    2. For e.g. 2023-05-01 returns:
      • WINTER_2023
      • SPRING_2023
      • SUMMER_2023
      • FALL_2023
      • ACADEMIC_YEAR_2022_2023
      • ACADEMIC_YEAR_2023_2024
  11. The Adaptive Scheduler after choosing the source assignments, will then look for students to generate problems for in the adaptive assignment:

    1. Only real+available students (student.spoofed != true).
    2. Only non-exempted students (assignment.exemptedStudentIds).
    3. Only students who have passed the assignment due date (the custom one for them). Students can have a custom due date, extensions etc. So even though the default due date has passed, they have their own due date, so we wait for them to pass this date also.
  12. An adaptive assignment is always of type ADAPTIVE. So you can search for adaptive assignments in the DB by { type: 'ADAPTIVE'}.

  13. An adaptive assignment will have a reference to the “source” assignment by the field adaptiveAssignment.sourceId. So the adaptiveAssignment.sourceId = sourceAssignment._id.

  14. The source assignment will also have a reference to the adaptive assignment by field sourceAssignment.targetAdaptiveIds.

  15. The adaptive assignment will take general assignment “settings” from the sourceAssignment.adaptive field. In this, the grading, start date, due date etc can be set. These will all be copied over to the adaptive assignment when it is created by the Adaptive Scheduler. If these sourceAssignment.adaptive settings are changed AFTER the adaptive assignment is created, then these settings are still applied. The only exception is if the adaptive assignment is published, then the date assigned will not be changed.

  16. Any time the source assignment is updated/saved (and has adaptiveEnabled=true), the corresponding adaptive assignment (if exists) will have its state also match. i.e. if you unpublish the source assignment, then this will unpublish the adaptive assignment. Or if you publish the source assignment this will publish the adaptive assignment.

  17. If the source assignment “turns off” adaptive follow up (and saves), then this will unpublish the adaptive assignment (if this had already been created and published). This field is handled by sourceAssignment.adaptiveEnabled.

  18. If students enroll on the course later, then these students will also get picked up and added to the existing adaptive assignment (as per the Adaptive Scheduler).

  19. The adaptive assignment in general is “created” shortly after the source assignment expires. However the “start” and “due” dates will be set independently and are based on the adaptive settings.

  20. Whenever the adaptive scheduler results in new adaptive assignments to be created then it must decide the start and due dates (adaptiveAssignment.startDate and adaptiveAssignment.dueDate).

    1. In the source assignment we have adaptive “settings”. This field is on sourceAssignment.adaptive.
    2. When the adaptive assignment gets created these settings will be copied over (and/or used as a basis to determine the fields to set on the adaptive assignment).
    3. Also, when the source assignment is updated (and its adaptive settings are changed) and there was an adaptive assignment already created, then the adaptive assignment will have the updated settings applied (as described above).
    4. Particularly, in the adaptive settings you can define the start date and the due date. And you can define these as some sort of relative date to the original source assignment due date.
    5. Generally the backend does not particularly enforce any strict validation on these fields at the point of saving the source assignment’s adaptive settings. So in theory you could set an adaptive setting’s start date to be earlier than the due date of the original source assignment.
    6. However, when the backend decides to set the start and due date of the adaptive assignment, it enforces a strict strategy so that dates line up as desired.
  21. Adaptive Assignment Start Date Strategy (adaptiveAssignment.startDate):

    1. Take the date from the adaptive settings start date (if exists).
      1. The absolute date (ignroed if is earlier than the sourceAssignment.dueDate).
      2. Or relative date, based off of the sourceAssignment.dueDate (ignored if sourceAssignment.dueDate is null).
    2. fallback to the sourceAssignment.dueDate (if this exists)
    3. fallback to the adaptiveAssignment.createdDate
  22. Adaptive Assignment Due Date Strategy (adaptiveAssignment.dueDate):

    (first we calculate the start date as above)

    1. Take the date from the adaptive settings due date (if exists).
      1. The absolute date (ignored if is earlier than the calculated adaptiveAssignment.startDate).
      2. Or relative date, based off of the calculated adaptiveAssignment.startDate
    2. Otherwise null (unlimited due date)
  23. Adaptive Assignment “Late” Due Date Strategy (adaptiveAssignment.lateDueDate):

    (first we calculate the due date as above)

    1. If the calculated adaptiveAssignment.dueDate is null (i.e. unlimited), then the adaptiveAssignment.lateDueDate will also always be null (which means late due date does not apply).
    2. Take the date from the adaptive settings “late” due date (if exists).
      1. The absolute date (ignored if is earlier than the calculated adaptiveAssignment.dueDate).
      2. Or relative date, based off of the calculated adaptiveAssignment.startDate (ignored if earlier than the calculated adaptiveAssignment.dueDate).
    3. Otherwise null (late due date does not apply)
  24. Note that just because the adaptive assignment has been created, it might not appear in the student feed because it has a later start date.

  25. API: Check which source assignments are pending to be picked up by the scheduler.

    • This will be constantly changing as the scheduler picks them up and generates new adaptive assignments.
    • So in other words this should slowly empty, on each call. And then be refilled as more adaptive-generable assignments come in.
    • curl https://dev.api.platform.aktiv.com/api/adaptive-assignment/source-assignments-pending
    • This requires an admin token to call (so please replace the X below).
     curl 'https://dev.api.platform.aktiv.com/api/adaptive-assignment/source-assignments-pending' \
         -H 'token: X'
    
  26. API: Get the source assignments that have recently failed by the scheduler (and are will be retried later).

  27. API: Check if a specific source assignment is “adaptive-generable”.

    • i.e. the scheduler should pick it up for adaptive assignment generation.
    • this will be true even if it has already picked it up.
    • curl https://dev.api.platform.aktiv.com/api/adaptive-assignment/{assignmentId}/is-generable
    • This requires an admin token to call (so please replace the X below).
    • This also requires the specific source assignment.id (so please replace the assignmentId below).
     curl 'https://dev.api.platform.aktiv.com/api/adaptive-assignment/{assignmentId}/is-generable' \
         -H 'token: X'
    
  28. API: Check if a specific source assignment is “adaptive-generable” for a particular student.

    • i.e. the scheduler should pick it up for adaptive assignment generation.
    • this will be true even if it has already picked it up.
    • curl https://dev.api.platform.aktiv.com/api/adaptive-assignment/{assignmentId}/is-generable/{studentId}
    • This requires an admin token to call (so please replace the X below).
    • This also requires the specific source assignment.id (so please replace the assignmentId below).
    • This also requires the specific source student.id (so please replace the studentId below).
     curl 'https://dev.api.platform.aktiv.com/api/adaptive-assignment/{assignmentId}/is-generable/{studentId}' \
         -H 'token: X'
    
  29. API: Check what adaptive assignment currently exist for the provided source assignment.

    • Use this to see what adaptive assignments have already been generated and are sitting in the DB.
    • This is useful as just because the adaptive assignment was generated, it doesn’t mean that it will appear in the feed due to possibly having a later start date.
    • curl https://dev.api.platform.aktiv.com/api/adaptive-assignment/{assignmentId}/adaptive-assignments
    • This requires an admin token to call (so please replace the X below).
    • This also requires the specific source assignment.id (so please replace the assignmentId below).
     curl 'https://dev.api.platform.aktiv.com/api/adaptive-assignment/{assignmentId}/adaptive-assignments' \
         -H 'token: X'