Skip to content

Commit

Permalink
✨(models) add edx open response assessment pydantic event models
Browse files Browse the repository at this point in the history
ORA2 events describe the activity for assessments pair reviewing.
Edx defined models and their selectors are described with Pydantic.
  • Loading branch information
quitterie-lcs committed Jun 19, 2023
1 parent a748536 commit 587578b
Show file tree
Hide file tree
Showing 9 changed files with 792 additions and 10 deletions.
25 changes: 15 additions & 10 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ and this project adheres to

## [Unreleased]

### Added

- Implement edX open response assessment events pydantic models

### Changed

- Allow to use a query for HTTP backends in the CLI
Expand Down Expand Up @@ -135,6 +139,7 @@ as per the xAPI specification

- Restore ES and Mongo backends ability to use client options


## [3.1.0] - 2022-11-17

### Added
Expand All @@ -155,7 +160,7 @@ as per the xAPI specification

### Added

- Implement edx video browser events pydantic models
- Implement edX video browser events pydantic models
- Create a `post` endpoint for statements implementing the LRS spec
- Implement support for the MongoDB database backend
- Implement support for custom queries when using database backends `get`
Expand Down Expand Up @@ -201,8 +206,8 @@ as per the xAPI specification

### Added

- Implement edx problem interaction events pydantic models
- Implement edx textbook interaction events pydantic models
- Implement edX problem interaction events pydantic models
- Implement edX textbook interaction events pydantic models
- `ws` websocket stream backend (compatible with the `fetch` command)
- bundle `jq`, `curl` and `wget` in the `fundocker/ralph` Docker image
- Tray: enable ralph app deployment command configuration
Expand Down Expand Up @@ -244,16 +249,16 @@ as per the xAPI specification
- xAPI video `seeked` pydantic models
- xAPI video `initialized` pydantic models
- xAPI video `paused` pydantic models
- `convert` command to transform edx events to xAPI format
- `convert` command to transform edX events to xAPI format
- EdX to xAPI converters for page `viewed` and`page_close` events
- Implement core event format converter
- xAPI video `played` pydantic models
- xAPI page `viewed` and page `terminated` pydantic models
- Implement edx navigational events pydantic models
- Implement edx enrollment events pydantic models
- Implement edX navigational events pydantic models
- Implement edX enrollment events pydantic models
- Install security updates in project Docker images
- Model selector to retrieve associated pydantic model of a given event
- `validate` command to lint edx events using pydantic models
- `validate` command to lint edX events using pydantic models
- Support all available bulk operation types for the elasticsearch backend
(create, index, update, delete) using the `--es-op-type` option

Expand All @@ -265,7 +270,7 @@ as per the xAPI specification
- Upgrade `click-option-group` to `0.5.3`
- Upgrade `pydantic` to `1.8.2`
- Upgrade `sentry_sdk` to `1.1.0`
- Rename edx models
- Rename edX models
- Migrate model tests from factories to hypothesis strategies
- Tray: switch from openshift to k8s (BC)
- Tray: remove useless deployment probes
Expand All @@ -278,8 +283,8 @@ as per the xAPI specification

### Added

- EdX server event pydantic model and factory
- EdX page_close browser event pydantic model and factory
- edX server event pydantic model and factory
- edX page_close browser event pydantic model and factory
- Tray: allow to specify a self-generated elasticsearch cluster CA certificate

### Fixed
Expand Down
12 changes: 12 additions & 0 deletions src/ralph/models/edx/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,18 @@
UIEdxCourseEnrollmentUpgradeClicked,
)
from .navigational.statements import UIPageClose, UISeqGoto, UISeqNext, UISeqPrev
from .open_response_assessment.statements import (
ORACreateSubmission,
ORAGetPeerSubmission,
ORAGetSubmissionForStaffGrading,
ORAPeerAssess,
ORASaveSubmission,
ORASelfAssess,
ORAStaffAssess,
ORAStudentTrainingAssessExample,
ORASubmitFeedbackOnAssessments,
ORAUploadFile,
)
from .problem_interaction.statements import (
EdxProblemHintDemandhintDisplayed,
EdxProblemHintFeedbackDisplayed,
Expand Down
1 change: 1 addition & 0 deletions src/ralph/models/edx/open_response_assessment/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# noqa: D104
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# noqa: D104
275 changes: 275 additions & 0 deletions src/ralph/models/edx/open_response_assessment/fields/events.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,275 @@
"""Open Response Assessment events model event fields definitions."""

from datetime import datetime
from typing import Dict, List, Optional, Union

try:
from typing import Literal
except ImportError:
from typing_extensions import Literal

from uuid import UUID

from pydantic import constr

from ralph.models.edx.base import AbstractBaseEventField, BaseModelWithConfig


class ORAGetPeerSubmissionEventField(AbstractBaseEventField):
"""Pydantic model for `openassessmentblock.get_peer_submission`.`event` field.
Attributes:
course_id (str): Consists of the course identifier including the assessment.
item_id (str): Consists of the locator string that identifies the problem in
the course.
requesting_student_id (str): Consists of the course-specific anonymized user ID
of the learner who retrieved the response for peer assessment.
submission_returned_uuid (str): Consists of the unique identifier of the
response that was retrieved for assessment. Set to `None` if no assessment
available.
"""

course_id: constr(max_length=255)
item_id: constr(
regex=(
r"^block-v1:.+\+.+\+.+type@openassessment" # noqa : F722
r"+block@[a-f0-9]{32}$" # noqa : F722
)
)
requesting_student_id: str
submission_returned_uuid: Union[str, None]


class ORAGetSubmissionForStaffGradingEventField(AbstractBaseEventField):
# noqa: D205, D415
"""Pydantic model for `openassessmentblock.get_submission_for_staff_grading`.
`event` field.
Attributes:
item_id (str): Consists of the locator string that identifies the problem in
the course.
submission_returned_uuid (str): Consists of the unique identifier of the
response that was retrieved for assessment. Set to `None` if no assessment
available.
requesting_staff_id (str): Consists of the course-specific anonymized user ID
of the course team member who is retrieved the response for grading.
type (str): Consists of the type of staff grading that is being performed.
Currently set to `full-grade`.
"""

item_id: constr(
regex=(
r"^block-v1:.+\+.+\+.+type@openassessment" # noqa : F722
r"+block@[a-f0-9]{32}$" # noqa : F722
)
)
submission_returned_uuid: Union[str, None]
requesting_staff_id: str
type: Literal["full-grade"]


class ORAAssessEventPartsCriterionField(BaseModelWithConfig):
"""Pydantic model for assessement `event`.`parts`.`criterion` field.
Attributes:
name (str): Consists of the criterion name.
points_possible (int): Consists of the maximum number of points
allocated to the criterion.
"""

name: str
points_possible: int


class ORAAssessEventPartsField(BaseModelWithConfig):
"""Pydantic model for assessment `event`.`parts` field.
Attributes:
option (str): Consists of the option that the learner selected for it.
criterion (dict): see ORAAssessEventPartsCriterionField.
feedback (str): Consists of feedback comments that the learner could have
supplied.
"""

option: str
criterion: ORAAssessEventPartsCriterionField
feedback: Optional[str]


class ORAAssessEventRubricField(BaseModelWithConfig):
"""Pydantic model for assessment `event`.`rubric` field.
This field is defined in:
- `openassessmentblock.peer_assess`
- `openassessmentblock.self_assess`
- `openassessmentblock.staff_assess`
Attributes:
content_hash: Consists of the identifier of the rubric that the learner used to
assess the response.
"""

content_hash: constr(regex=r"^[a-f0-9]{1,40}$") # noqa: F722


class ORAAssessEventField(AbstractBaseEventField):
"""Pydantic model for assessment `event` field.
This field is defined in:
- `openassessmentblock.peer_assess`
- `openassessmentblock.self_assess`
- `openassessmentblock.staff_assess`
Attributes:
feedback (str): Consists of the learner's comments about the submitted response.
parts (list): see ORAAssessEventPartsField.
rubric (dict): see ORAPeerAssessEventRubricField.
scored_at (datetime): Consists of the timestamp for when the assessment was
submitted.
scorer_id (str): Consists of the course-specific anonymized user ID of the
learner who submitted the assessment.
score_type (str): Consists of either `PE` value for a peer assessment, `SE` for
a self assessment or `ST` for a staff assessment.
submission_uuid (str): Consists of the unique identifier for the submitted
response.
"""

feedback: str
parts: List[ORAAssessEventPartsField]
rubric: ORAAssessEventRubricField
scored_at: datetime
scorer_id: constr(max_length=40)
score_type: Literal["PE", "SE", "ST"]
submission_uuid: UUID


class ORAStaffAssessEventField(ORAAssessEventField):
"""Pydantic model for `openassessmentblock.staff_assess`.`event` field.
Attributes:
type (str): Consists of the type of staff grading that is being performed. Can
be either equalt to `regrade` in the case of a grade override or
`full-grade` in the case of an included staff assessment step.
"""

type: Literal["regrade", "full-grade"]


class ORASubmitFeedbackOnAssessmentsEventField(AbstractBaseEventField):
# noqa: D205, D415
"""Pydantic model for `openassessmentblock.submit_feedback_on_assessments`.
`event` field.
Attributes:
feedback_text (str): Consists of the learner's comments about the assessment
process.
options (list): Consists of the label of each checkbox option that the learner
selected to evaluate the assessment process.
submission_uuid (str): Consists of the unique identifier for for the feedback.
"""

feedback_text: str
options: List[str]
submission_uuid: UUID


class ORACreateSubmissionEventAnswerField(BaseModelWithConfig):
# noqa: D205, D415
"""Pydantic model for `openassessmentblock.create_submission`.`event`.`answer`
field.
Attributes:
parts (dict): Consists of a key-value dictionary with all answers text.
file_keys (list): Consists of a list of file identifiers if files are given for
answer.
files_description (list): Consists of a list of file descriptions if files are
given for answer.
"""

parts: List[Dict[Literal["text"], str]]
file_keys: Optional[List[str]]
files_descriptions: Optional[List[str]]


class ORACreateSubmissionEventField(AbstractBaseEventField):
"""Pydantic model for `openassessmentblock.create_submission`.`event` field.
Attributes:
answer (dict): see ORACreateSubmissionEventAnswerField.
attempt_number (int): Consists of the number of submission attempts. Currently,
this value is set to 1.
created_at (datetime): Consists of the timestamp for when the learner submitted
the response.
submitted_at (datetime): Consists of the timestamp for when the learner
submitted the response. This value is the same as `submitted_at`.
submission_uuid (str): Consists of the unique identifier of the response.
"""

answer: ORACreateSubmissionEventAnswerField
attempt_number: int
created_at: datetime
submitted_at: datetime
submission_uuid: UUID


class ORASaveSubmissionEventSavedResponseField(BaseModelWithConfig):
"""Pydantic model for `openassessmentblock.save_submission`.`saved_response` field.
Attributes:
text (str): Consists of the response text.
file_upload_key (str): Consists of the AWS S3 key that identifies the location
of the uploaded file on the Amazon S3 storage service. Only present when
responses include an image, .pdf, or other file.
"""

text: str
file_upload_key: Optional[str]


class ORASaveSubmissionEventField(AbstractBaseEventField):
"""Pydantic model for `openassessmentblock.save_submission`.`event` field.
Attributes:
saved_response (str): Consists of a JSON string of the users saved responses.
Note:
Responses have a length limit of 100000 in the front-end but not in the
back-end. Events are truncated at `TRACK_MAX_EVENT` which is 50000 by
default. Also the `eventtracking.backends.logger.LoggerBackend`
silently drops events when they exceed `TRACK_MAX_EVENT`.
"""

# pylint: disable=unsubscriptable-object
saved_response: ORASaveSubmissionEventSavedResponseField


class ORAStudentTrainingAssessExampleEventField(AbstractBaseEventField):
# noqa: D205, D415
"""Pydantic model for `openassessment.student_training_assess_example`.`event`
field.
Attributes:
corrections (dict): Consists of a set of name/value pairs that identify
criteria for which the learner selected a different option than the course
team.
options_selected (dict): Consists of a set of name/value pairs that identify
the option that the learner selected for each criterion in the rubric.
submission_uuid (str): Consists of the unique identifier of the response.
"""

corrections: Dict[str, str]
options_selected: Dict[str, str]
submission_uuid: UUID


class ORAUploadFileEventField(BaseModelWithConfig):
"""Pydantic model for `openassessment.upload_file`.`event` field.
Attributes:
fileName (str): Consists of the name of the uploaded file.
fileSize (int): Consists of the bytes size of the uploaded file.
fileType (str): Consists of the MIME type of the uploaded file.
"""

fileName: constr(max_length=255)
fileSize: int
fileType: str
Loading

0 comments on commit 587578b

Please sign in to comment.