Skip to content

Commit

Permalink
✨(models) add downloaded verb to tincan vocabulary
Browse files Browse the repository at this point in the history
Simply add the http://id.tincanapi.com/verb/downloaded to the tincan
vocabulary so it can be used by other projects (here warren)
  • Loading branch information
lebrunthibault committed Jun 21, 2023
1 parent 0735466 commit 4f6688b
Show file tree
Hide file tree
Showing 7 changed files with 85 additions and 3 deletions.
4 changes: 3 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ and this project adheres to

- Implement edX open response assessment events pydantic models
- Implement edx peer instruction events pydantic models
- Implement xAPI VideoDownloaded pydantic model
(using xAPI TinCan `downloaded` verb)

### Changed

Expand All @@ -32,7 +34,7 @@ and this project adheres to
- Clean xAPI pydantic models naming convention
- Upgrade `fastapi` to `0.97.0`
- Upgrade `sentry_sdk` to `1.25.1`
- Set Clickhouse `client_options` to a dedicated Pydantic model
- Set Clickhouse `client_options` to a dedicated pydantic model
- Upgrade `httpx` to `0.24.1`
- Force a valid (JSON-formatted) IFI to be passed for the `/statements`
GET query `agent` filtering
Expand Down
1 change: 1 addition & 0 deletions src/ralph/models/xapi/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from .navigation.statements import PageTerminated, PageViewed
from .video.statements import (
VideoCompleted,
VideoDownloaded,
VideoEnableClosedCaptioning,
VideoInitialized,
VideoPaused,
Expand Down
14 changes: 14 additions & 0 deletions src/ralph/models/xapi/concepts/verbs/tincan_vocabulary.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,17 @@ class ViewedVerb(BaseXapiVerb):
"http://id.tincanapi.com/verb/viewed"
] = "http://id.tincanapi.com/verb/viewed"
display: Optional[Dict[Literal[LANG_EN_US_DISPLAY], Literal["viewed"]]]


class DownloadedVerb(BaseXapiVerb):
"""Pydantic model for downloaded `verb`.
Attributes:
id (str): Consists of the value `http://id.tincanapi.com/verb/downloaded`.
display (dict): Consists of the dictionary `{"en-US": "downloaded"}`.
"""

id: Literal[
"http://id.tincanapi.com/verb/downloaded"
] = "http://id.tincanapi.com/verb/downloaded"
display: Optional[Dict[Literal[LANG_EN_US_DISPLAY], Literal["downloaded"]]]
27 changes: 26 additions & 1 deletion src/ralph/models/xapi/video/contexts.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

from uuid import UUID

from pydantic import Field, NonNegativeFloat
from pydantic import Field, NonNegativeFloat, PositiveInt

from ..base.contexts import BaseXapiContext, BaseXapiContextContextActivities
from ..base.unnested_objects import BaseXapiActivity
Expand All @@ -20,6 +20,7 @@
CONTEXT_EXTENSION_COMPLETION_THRESHOLD,
CONTEXT_EXTENSION_FULL_SCREEN,
CONTEXT_EXTENSION_LENGTH,
CONTEXT_EXTENSION_QUALITY,
CONTEXT_EXTENSION_SCREEN_SIZE,
CONTEXT_EXTENSION_SESSION_ID,
CONTEXT_EXTENSION_SPEED,
Expand Down Expand Up @@ -132,6 +133,20 @@ class VideoBrowsingContextExtensions(VideoContextExtensions):
)


class VideoDownloadedContextExtensions(VideoContextExtensions):
"""Represents the context.extensions field for video `downloaded` xAPI statement.
Attributes:
length (float): Consists of the length of the video.
quality (int): Consists of the video resolution or quality of the video.
session (uuid): Consists of the ID of the active session.
"""

length: NonNegativeFloat = Field(alias=CONTEXT_EXTENSION_LENGTH)
quality: PositiveInt = Field(alias=CONTEXT_EXTENSION_QUALITY)
session_id: Optional[UUID] = Field(alias=CONTEXT_EXTENSION_SESSION_ID)


class VideoEnableClosedCaptioningContextExtensions(VideoContextExtensions):
"""Represents the context.extensions field for video `interacted` xAPI statement.
Expand Down Expand Up @@ -232,6 +247,16 @@ class VideoTerminatedContext(BaseVideoContext):
extensions: VideoBrowsingContextExtensions


class VideoDownloadedContext(BaseVideoContext):
"""Pydantic model for video downloaded `context` property.
Attributes:
extensions (dict): See VideoDownloadedContextExtensions.
"""

extensions: VideoDownloadedContextExtensions


class VideoEnableClosedCaptioningContext(BaseVideoContext):
"""Pydantic model for video enable closed captioning `context` property.
Expand Down
21 changes: 21 additions & 0 deletions src/ralph/models/xapi/video/statements.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,11 @@
InteractedVerb,
TerminatedVerb,
)
from ..concepts.verbs.tincan_vocabulary import DownloadedVerb
from ..concepts.verbs.video import PausedVerb, PlayedVerb, SeekedVerb
from .contexts import (
VideoCompletedContext,
VideoDownloadedContext,
VideoEnableClosedCaptioningContext,
VideoInitializedContext,
VideoPausedContext,
Expand Down Expand Up @@ -170,6 +172,25 @@ class VideoTerminated(BaseVideoStatement):
context: VideoTerminatedContext


class VideoDownloaded(BaseVideoStatement):
"""Pydantic model for video downloaded statement.
Example: John downloaded (rather than accessed or opened) a video.
Attributes:
verb (dict): See DownloadedVerb.
context (dict): See VideoDownloadedContext.
"""

__selector__ = selector(
object__definition__type="https://w3id.org/xapi/video/activity-type/video",
verb__id="http://id.tincanapi.com/verb/downloaded",
)

verb: DownloadedVerb = DownloadedVerb()
context: VideoDownloadedContext


class VideoEnableClosedCaptioning(BaseVideoStatement):
"""Pydantic model for video enable closed captioning statement.
Expand Down
6 changes: 5 additions & 1 deletion tests/models/xapi/concepts/test_verbs.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,10 @@
InteractedVerb,
TerminatedVerb,
)
from ralph.models.xapi.concepts.verbs.tincan_vocabulary import ViewedVerb
from ralph.models.xapi.concepts.verbs.tincan_vocabulary import (
DownloadedVerb,
ViewedVerb,
)
from ralph.models.xapi.concepts.verbs.video import PausedVerb, PlayedVerb, SeekedVerb
from ralph.models.xapi.concepts.verbs.virtual_classroom import (
LoweredHandVerb,
Expand Down Expand Up @@ -47,6 +50,7 @@
(InteractedVerb, "http://adlnet.gov/expapi/verbs/interacted"),
(TerminatedVerb, "http://adlnet.gov/expapi/verbs/terminated"),
(ViewedVerb, "http://id.tincanapi.com/verb/viewed"),
(DownloadedVerb, "http://id.tincanapi.com/verb/downloaded"),
(PausedVerb, "https://w3id.org/xapi/video/verbs/paused"),
(PlayedVerb, "https://w3id.org/xapi/video/verbs/played"),
(SeekedVerb, "https://w3id.org/xapi/video/verbs/seeked"),
Expand Down
15 changes: 15 additions & 0 deletions tests/models/xapi/test_video.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
from ralph.models.validator import Validator
from ralph.models.xapi.video.statements import (
VideoCompleted,
VideoDownloaded,
VideoEnableClosedCaptioning,
VideoInitialized,
VideoPaused,
Expand All @@ -33,6 +34,7 @@
VideoPlayed,
VideoSeeked,
VideoTerminated,
VideoDownloaded,
],
)
@custom_given(st.data())
Expand Down Expand Up @@ -148,6 +150,19 @@ def test_models_xapi_video_terminated_with_valid_statement(statement):
)


@custom_given(VideoDownloaded)
def test_models_xapi_video_downloaded_with_valid_statement(statement):
"""Tests that a video terminated statement has the expected `verb`.`id` and
`object`.`definition`.`type` property values.
"""

assert statement.verb.id == "http://id.tincanapi.com/verb/downloaded"
assert (
statement.object.definition.type
== "https://w3id.org/xapi/video/activity-type/video"
)


@custom_given(VideoEnableClosedCaptioning)
def test_models_xapi_video_enable_closed_captioning_with_valid_statement(statement):
"""Tests that a video enable closed captioning statement has the expected
Expand Down

0 comments on commit 4f6688b

Please sign in to comment.