le-utils 0.2.0__tar.gz → 0.2.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- le-utils-0.2.1/PKG-INFO +237 -0
- le-utils-0.2.1/le_utils/constants/completion_criteria.py +106 -0
- {le-utils-0.2.0 → le-utils-0.2.1}/le_utils/constants/labels/subjects.py +4 -1
- le-utils-0.2.1/le_utils/constants/mastery_criteria.py +76 -0
- le-utils-0.2.1/le_utils/constants/uuid.py +13 -0
- le-utils-0.2.1/le_utils/uuidv5.py +19 -0
- le-utils-0.2.1/le_utils.egg-info/PKG-INFO +237 -0
- {le-utils-0.2.0 → le-utils-0.2.1}/le_utils.egg-info/SOURCES.txt +2 -0
- {le-utils-0.2.0 → le-utils-0.2.1}/setup.py +1 -1
- le-utils-0.2.0/PKG-INFO +0 -234
- le-utils-0.2.0/le_utils/constants/completion_criteria.py +0 -32
- le-utils-0.2.0/le_utils/constants/mastery_criteria.py +0 -32
- le-utils-0.2.0/le_utils.egg-info/PKG-INFO +0 -234
- {le-utils-0.2.0 → le-utils-0.2.1}/LICENSE.txt +0 -0
- {le-utils-0.2.0 → le-utils-0.2.1}/MANIFEST.in +0 -0
- {le-utils-0.2.0 → le-utils-0.2.1}/README.md +0 -0
- {le-utils-0.2.0 → le-utils-0.2.1}/le_utils/__init__.py +0 -0
- {le-utils-0.2.0 → le-utils-0.2.1}/le_utils/constants/__init__.py +0 -0
- {le-utils-0.2.0 → le-utils-0.2.1}/le_utils/constants/content_kinds.py +0 -0
- {le-utils-0.2.0 → le-utils-0.2.1}/le_utils/constants/exercises.py +0 -0
- {le-utils-0.2.0 → le-utils-0.2.1}/le_utils/constants/file_formats.py +0 -0
- {le-utils-0.2.0 → le-utils-0.2.1}/le_utils/constants/file_types.py +0 -0
- {le-utils-0.2.0 → le-utils-0.2.1}/le_utils/constants/format_presets.py +0 -0
- {le-utils-0.2.0 → le-utils-0.2.1}/le_utils/constants/labels/__init__.py +0 -0
- {le-utils-0.2.0 → le-utils-0.2.1}/le_utils/constants/labels/accessibility_categories.py +0 -0
- {le-utils-0.2.0 → le-utils-0.2.1}/le_utils/constants/labels/learning_activities.py +0 -0
- {le-utils-0.2.0 → le-utils-0.2.1}/le_utils/constants/labels/levels.py +0 -0
- {le-utils-0.2.0 → le-utils-0.2.1}/le_utils/constants/labels/needs.py +0 -0
- {le-utils-0.2.0 → le-utils-0.2.1}/le_utils/constants/labels/resource_type.py +0 -0
- {le-utils-0.2.0 → le-utils-0.2.1}/le_utils/constants/languages.py +0 -0
- {le-utils-0.2.0 → le-utils-0.2.1}/le_utils/constants/licenses.py +0 -0
- {le-utils-0.2.0 → le-utils-0.2.1}/le_utils/constants/modalities.py +0 -0
- {le-utils-0.2.0 → le-utils-0.2.1}/le_utils/constants/roles.py +0 -0
- {le-utils-0.2.0 → le-utils-0.2.1}/le_utils/humanhash.py +0 -0
- {le-utils-0.2.0 → le-utils-0.2.1}/le_utils/proquint.py +0 -0
- {le-utils-0.2.0 → le-utils-0.2.1}/le_utils/resources/formatlookup.json +0 -0
- {le-utils-0.2.0 → le-utils-0.2.1}/le_utils/resources/kindlookup.json +0 -0
- {le-utils-0.2.0 → le-utils-0.2.1}/le_utils/resources/languagelookup.json +0 -0
- {le-utils-0.2.0 → le-utils-0.2.1}/le_utils/resources/licenselookup.json +0 -0
- {le-utils-0.2.0 → le-utils-0.2.1}/le_utils/resources/presetlookup.json +0 -0
- {le-utils-0.2.0 → le-utils-0.2.1}/le_utils.egg-info/dependency_links.txt +0 -0
- {le-utils-0.2.0 → le-utils-0.2.1}/le_utils.egg-info/requires.txt +0 -0
- {le-utils-0.2.0 → le-utils-0.2.1}/le_utils.egg-info/top_level.txt +0 -0
- {le-utils-0.2.0 → le-utils-0.2.1}/setup.cfg +0 -0
le-utils-0.2.1/PKG-INFO
ADDED
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: le-utils
|
|
3
|
+
Version: 0.2.1
|
|
4
|
+
Summary: LE-Utils contains shared constants used in Kolibri, Ricecooker, and Kolibri Studio.
|
|
5
|
+
Home-page: https://github.com/learningequality/le-utils
|
|
6
|
+
Author: Learning Equality
|
|
7
|
+
Author-email: info@learningequality.org
|
|
8
|
+
License: MIT
|
|
9
|
+
Download-URL: https://github.com/learningequality/le-utils/releases
|
|
10
|
+
Keywords: le-utils le_utils LE utils kolibri studio ricecooker content curation
|
|
11
|
+
Platform: UNKNOWN
|
|
12
|
+
Classifier: Development Status :: 2 - Pre-Alpha
|
|
13
|
+
Classifier: Programming Language :: Python
|
|
14
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
15
|
+
Classifier: Topic :: Utilities
|
|
16
|
+
Requires-Python: >=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*, <3.12
|
|
17
|
+
Description-Content-Type: text/markdown
|
|
18
|
+
Provides-Extra: lang_utils
|
|
19
|
+
License-File: LICENSE.txt
|
|
20
|
+
|
|
21
|
+
LE Utils
|
|
22
|
+
========
|
|
23
|
+
The `le-utils` package contains shared constants used by Ricecooker, Kolibri, and
|
|
24
|
+
Kolibri Studio. This package is not meant to be installed or used directly, but
|
|
25
|
+
plays an important role in all Learning Equality products.
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
Constants
|
|
29
|
+
=========
|
|
30
|
+
The Python files in the [le_utils/constants/](./le_utils/constants) are used to
|
|
31
|
+
define constants (usually in `ALL_CAPS` form) to be used from Python code.
|
|
32
|
+
The same constants and naming conventions are also provided in JSON format in the
|
|
33
|
+
folder [le_utils/resources/](le_utils/resources) for use in frontend code.
|
|
34
|
+
This means, adding a new constant may require editing multiple files: the Python
|
|
35
|
+
constant-defining file, the JSON-file, and any associated tests.
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
Languages
|
|
39
|
+
---------
|
|
40
|
+
The file [le_utils/constants/languages.py](./le_utils/constants/languages.py) and
|
|
41
|
+
the lookup table in [le_utils/resources/languagelookup.json](./le_utils/resources/languagelookup.json)
|
|
42
|
+
define the internal representation for languages codes used by Ricecooker, Kolibri,
|
|
43
|
+
and Kolibri Studio to identify educational content in different languages.
|
|
44
|
+
|
|
45
|
+
The internal representation uses a mixture of two-letter codes (e.g. `en`),
|
|
46
|
+
two-letter-and-country code (e.g. `pt-BR` for Brazilian Portuguese),
|
|
47
|
+
and three-letter codes (e.g., `zul` for Zulu).
|
|
48
|
+
|
|
49
|
+
In order to make sure you have the correct language code when interfacing with
|
|
50
|
+
the Kolibri ecosystem (e.g. when uploading new content to Kolibri Studio), you
|
|
51
|
+
must lookup the language object using the helper method `getlang`:
|
|
52
|
+
|
|
53
|
+
```
|
|
54
|
+
>>> from le_utils.constants.languages import getlang
|
|
55
|
+
>>> language_obj = getlang('en') # lookup language using language code
|
|
56
|
+
>>> language_obj
|
|
57
|
+
Language(native_name='English', primary_code='en', subcode=None, name='English', ka_name=None)
|
|
58
|
+
```
|
|
59
|
+
The function `getlang` will return `None` if the lookup fails. In such cases, you
|
|
60
|
+
can try lookup by name or lookup by alpha2 code (ISO_639-1) methods defined below.
|
|
61
|
+
|
|
62
|
+
Once you've successfully looked up the language object, you can obtain the internal
|
|
63
|
+
representation language code from the language object's `code` attribute:
|
|
64
|
+
```
|
|
65
|
+
>>> language_obj.code
|
|
66
|
+
'en'
|
|
67
|
+
```
|
|
68
|
+
The Ricecooker API expects these internal representation language codes will be
|
|
69
|
+
supplied for all `language` attributes (channel language, node language, and files language).
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
### More lookup helper methods
|
|
74
|
+
The helper method `getlang_by_name` allows you to lookup a language by name:
|
|
75
|
+
```
|
|
76
|
+
>>> from le_utils.constants.languages import getlang_by_name
|
|
77
|
+
>>> language_obj = getlang_by_name('English') # lookup language by name
|
|
78
|
+
>>> language_obj
|
|
79
|
+
Language(native_name='English', primary_code='en', subcode=None, name='English', ka_name=None)
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
The module `le_utils.constants.languages` defines two other language lookup methods:
|
|
83
|
+
- Use `getlang_by_native_name` for lookup up names by native language name,
|
|
84
|
+
e.g., you look for 'Français' to find French.
|
|
85
|
+
- Use `getlang_by_alpha2` to perform lookups using the standard two-letter codes
|
|
86
|
+
defined in [ISO_639-1](https://en.wikipedia.org/wiki/ISO_639-1) that are
|
|
87
|
+
supported by the `pycountries` library.
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
#### Useful links
|
|
91
|
+
|
|
92
|
+
The following websites are useful for researching language codes:
|
|
93
|
+
|
|
94
|
+
- https://www.ethnologue.com/
|
|
95
|
+
- https://en.wikipedia.org/wiki/List_of_ISO_639-2_codes
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
Licenses
|
|
100
|
+
--------
|
|
101
|
+
All content nodes within Kolibri and Kolibri Studio must have a license. The file
|
|
102
|
+
[le_utils/constants/licenses.py](./le_utils/constants/licenses.py) contains the
|
|
103
|
+
constants used to identify the license types. These constants are meant to be
|
|
104
|
+
used in conjunction with the helper method `ricecooker.classes.licenses.get_license`
|
|
105
|
+
to create `Licence` objects.
|
|
106
|
+
|
|
107
|
+
To initialize a license object, you must specify the license type and the
|
|
108
|
+
`copyright_holder` (str) which identifies a person or an organization. For example:
|
|
109
|
+
```
|
|
110
|
+
from ricecooker.classes.licenses import get_license
|
|
111
|
+
from le_utils.constants import licenses
|
|
112
|
+
license = get_license(licenses.CC_BY, copyright_holder="Khan Academy")
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
Note: The `copyright_holder` field is required for all License types except for
|
|
116
|
+
the public domain license for which `copyright_holder` can be None.
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
Content kinds (ContentNode subclasses)
|
|
122
|
+
--------------------------------------
|
|
123
|
+
Content items throughout the Kolibri ecosystem come in several kinds. The `kind`
|
|
124
|
+
attribute of each object can be one of ("topic", "video", "audio", "exercise"
|
|
125
|
+
"document", or "html5".
|
|
126
|
+
See [constants/content_kinds.py](https://github.com/learningequality/le-utils/blob/master/le_utils/constants/content_kinds.py#L11-L17) for latest list.
|
|
127
|
+
|
|
128
|
+
The currently supported content kinds are:
|
|
129
|
+
- Topic node (folder)
|
|
130
|
+
- Video content nodes backed by a video files and subtitles
|
|
131
|
+
- Audio content nodes backed by an audio files
|
|
132
|
+
- Document content nodes backed by a document files (PDF or ePub)
|
|
133
|
+
- HTML5 app content nodes backed by a HTML5 zip files
|
|
134
|
+
- Slideshow content nodes
|
|
135
|
+
- Exercise content nodes
|
|
136
|
+
|
|
137
|
+
The `kind` attribute identifies a subclass of the base content node class within
|
|
138
|
+
the data model, which differs on Ricecooker, Studio, and Kolibri:
|
|
139
|
+
- [ricecooker.classes.nodes.ContentNode](https://github.com/learningequality/ricecooker/blob/master/ricecooker/classes/nodes.py#L428-L506):
|
|
140
|
+
in-memory content node used to store metadata needed to upload new content to Kolibri Studio
|
|
141
|
+
- [contentcuration.contentcuration.models.ContentNode](https://github.com/learningequality/studio/blob/develop/contentcuration/contentcuration/models.py#L775):
|
|
142
|
+
node within one of the trees associated with a Kolibri Studio channel.
|
|
143
|
+
- [kolibri.core.content.models.ContentNode](https://github.com/learningequality/kolibri/blob/develop/kolibri/core/content/models.py#L175):
|
|
144
|
+
node within tree for a particular version of a channel on Kolibri.
|
|
145
|
+
|
|
146
|
+
For a detailed description of the common and different model attributes available
|
|
147
|
+
on content nodes in each part of the platform see [this doc](https://docs.google.com/spreadsheets/d/181hSEwJ7yVmMh7LEwaHENqQetYSsbSDwybHTO_0zZM0/edit#gid=1640972430).
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
File formats (extensions)
|
|
152
|
+
-------------------------
|
|
153
|
+
These are low-level constant that represents what type of file and are essentially
|
|
154
|
+
synonymous with file extensions. The file format `MP4` is simply a convenient
|
|
155
|
+
proxy for the file extension `mp4`.
|
|
156
|
+
See [file_formats.py](https://github.com/learningequality/le-utils/blob/master/le_utils/constants/file_formats.py)
|
|
157
|
+
and [resourcces/formatlookup.json](https://github.com/nucleogenesis/le-utils/blob/master/le_utils/resources/formatlookup.json).
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
Format presets (ContentNode-File relation)
|
|
162
|
+
------------------------------------------
|
|
163
|
+
Every `ContentNode` is associated with one or more `File` objects and nature of
|
|
164
|
+
this association is represented though the `format_preset` attribute of the file.
|
|
165
|
+
The `format_preset` is the role the file is playing in the content node,
|
|
166
|
+
e.g., thumbnail, high resolution video, or low resolution video.
|
|
167
|
+
Note that format presets are represented redundantly as python string in
|
|
168
|
+
[constants/format_presets.py](https://github.com/learningequality/le-utils/blob/master/le_utils/constants/format_presets.py)
|
|
169
|
+
and as json [resources/presetlookup.json](https://github.com/learningequality/le-utils/blob/master/le_utils/resources/presetlookup.json).
|
|
170
|
+
|
|
171
|
+
You can think of the different format presets on a content node as different "slots"
|
|
172
|
+
to be filled in by files, with certain slots being required while other optional.
|
|
173
|
+
For examples, for a VideoNode (kind=`video`) to be a valid content node, it must
|
|
174
|
+
have at least one video file associated with it filling either the `high_res_video`
|
|
175
|
+
slot or the `low_res_video` slot. Certain slots can have multiple files in them,
|
|
176
|
+
like the `video_subtitle` preset, since a VideoNode can have multiple subtitles
|
|
177
|
+
associated with it for different languages.
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
The figure below illustrates the structure between content nodes, files, and format presets.
|
|
181
|
+
|
|
182
|
+

|
|
183
|
+
|
|
184
|
+
In the Sample shown, the Video Node is of content kind `video` and has three
|
|
185
|
+
files associated with it:
|
|
186
|
+
- The first file has file format `mp4` and format preset `high_res_video`
|
|
187
|
+
- The second file is also in `mp4` format but the relation to the content node
|
|
188
|
+
is that `low_res_video`
|
|
189
|
+
- A third file with format `vtt` is associated with the content node with a
|
|
190
|
+
format preset of `video_subtitle`.
|
|
191
|
+
|
|
192
|
+
Format presets play a crucial role throughout the Kolibri content ecosystem and
|
|
193
|
+
govern such things as content validation rules applied by Ricecooker, Kolibri Studio
|
|
194
|
+
edit rules, and the rendering logic on Kolibri.
|
|
195
|
+
|
|
196
|
+
|
|
197
|
+
File types (ricecooker.files.File subclasses)
|
|
198
|
+
---------------------------------------------
|
|
199
|
+
Used on Ricecooker as identifiers to represents what type of file when serializing
|
|
200
|
+
things to JSON as part of the content import process. Note that file types constants
|
|
201
|
+
are internal to ricecooker operations and are not used in Kolibri Studio or Kolibri.
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
|
|
205
|
+
Exercises
|
|
206
|
+
---------
|
|
207
|
+
The file [le_utils/constants/exercises.py](./le_utils/constants/exercises.py)
|
|
208
|
+
contains identifiers for different question types and mastery models.
|
|
209
|
+
|
|
210
|
+
|
|
211
|
+
|
|
212
|
+
Proquint Channel Tokens
|
|
213
|
+
-----------------------
|
|
214
|
+
The file [le_utils/proquint.py](./le_utils/proquint.py) contains helper methods
|
|
215
|
+
for generating proquint identifiers for content channels. These are short strings
|
|
216
|
+
that are easy to enter on devices without a full keyboard, e.g. `sutul-hakuh`.
|
|
217
|
+
|
|
218
|
+
|
|
219
|
+
Roles
|
|
220
|
+
-----
|
|
221
|
+
The `role` constants are used for Role-based access control (RBAC) within the
|
|
222
|
+
Kolibri platform. Currently, only two levels of visibility are supported:
|
|
223
|
+
- `learner` (default): content nodes are visible to all Kolibri users
|
|
224
|
+
- `coach`: content nodes are only visible to Kolibri coaches and administrators
|
|
225
|
+
|
|
226
|
+
|
|
227
|
+
Metadata labels
|
|
228
|
+
---------------
|
|
229
|
+
|
|
230
|
+
These are encoded in spec/labels-v*.json. Once a spec has been finalized it will be
|
|
231
|
+
added to finalized_specs.yml to ensure that CI will fail any future modifications
|
|
232
|
+
to this specification. This ensures that the resulting built code has consistent
|
|
233
|
+
ordering so that generated bits for bitmasks are stable across releases.
|
|
234
|
+
We also require that all names in the specs be globally unique to minimize confusion
|
|
235
|
+
and reduce the chance of collisions in translations of these terms for users.
|
|
236
|
+
|
|
237
|
+
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
# Generated by scripts/generate_from_specs.py
|
|
3
|
+
from __future__ import unicode_literals
|
|
4
|
+
|
|
5
|
+
# CompletionCriteria
|
|
6
|
+
|
|
7
|
+
APPROX_TIME = "approx_time"
|
|
8
|
+
DETERMINED_BY_RESOURCE = "determined_by_resource"
|
|
9
|
+
MASTERY = "mastery"
|
|
10
|
+
PAGES = "pages"
|
|
11
|
+
REFERENCE = "reference"
|
|
12
|
+
TIME = "time"
|
|
13
|
+
|
|
14
|
+
choices = (
|
|
15
|
+
(APPROX_TIME, "Approx Time"),
|
|
16
|
+
(DETERMINED_BY_RESOURCE, "Determined By Resource"),
|
|
17
|
+
(MASTERY, "Mastery"),
|
|
18
|
+
(PAGES, "Pages"),
|
|
19
|
+
(REFERENCE, "Reference"),
|
|
20
|
+
(TIME, "Time"),
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
COMPLETIONCRITERIALIST = [
|
|
24
|
+
APPROX_TIME,
|
|
25
|
+
DETERMINED_BY_RESOURCE,
|
|
26
|
+
MASTERY,
|
|
27
|
+
PAGES,
|
|
28
|
+
REFERENCE,
|
|
29
|
+
TIME,
|
|
30
|
+
]
|
|
31
|
+
|
|
32
|
+
SCHEMA = {
|
|
33
|
+
"$id": "/schemas/completion_criteria",
|
|
34
|
+
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
35
|
+
"type": "object",
|
|
36
|
+
"description": "Schema for completion criteria of content nodes",
|
|
37
|
+
"additionalProperties": False,
|
|
38
|
+
"definitions": {
|
|
39
|
+
"model": {
|
|
40
|
+
"type": "string",
|
|
41
|
+
"$exportConstants": "completion_criteria",
|
|
42
|
+
"enum": [
|
|
43
|
+
"time",
|
|
44
|
+
"approx_time",
|
|
45
|
+
"pages",
|
|
46
|
+
"mastery",
|
|
47
|
+
"reference",
|
|
48
|
+
"determined_by_resource",
|
|
49
|
+
],
|
|
50
|
+
},
|
|
51
|
+
"mastery_criteria": {"$ref": "/schemas/mastery_criteria"},
|
|
52
|
+
},
|
|
53
|
+
"properties": {
|
|
54
|
+
"model": {"$ref": "#/definitions/model"},
|
|
55
|
+
"learner_managed": {"type": "boolean"},
|
|
56
|
+
"threshold": True,
|
|
57
|
+
},
|
|
58
|
+
"required": ["model"],
|
|
59
|
+
"anyOf": [
|
|
60
|
+
{
|
|
61
|
+
"properties": {
|
|
62
|
+
"model": {
|
|
63
|
+
"anyOf": [
|
|
64
|
+
{"const": "time"},
|
|
65
|
+
{"const": "approx_time"},
|
|
66
|
+
{"const": "pages"},
|
|
67
|
+
]
|
|
68
|
+
},
|
|
69
|
+
"threshold": {"type": "number", "exclusiveMinimum": 0},
|
|
70
|
+
},
|
|
71
|
+
"required": ["threshold"],
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
"properties": {
|
|
75
|
+
"model": {"const": "pages"},
|
|
76
|
+
"threshold": {
|
|
77
|
+
"type": "string",
|
|
78
|
+
"pattern": "^(100|[1-9][0-9]?)%$",
|
|
79
|
+
"description": "A percentage",
|
|
80
|
+
"minLength": 2,
|
|
81
|
+
"maxLength": 4,
|
|
82
|
+
},
|
|
83
|
+
},
|
|
84
|
+
"required": ["threshold"],
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
"properties": {
|
|
88
|
+
"model": {"const": "mastery"},
|
|
89
|
+
"threshold": {"$ref": "#/definitions/mastery_criteria"},
|
|
90
|
+
},
|
|
91
|
+
"required": ["threshold"],
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
"properties": {
|
|
95
|
+
"model": {
|
|
96
|
+
"anyOf": [
|
|
97
|
+
{"const": "reference"},
|
|
98
|
+
{"const": "determined_by_resource"},
|
|
99
|
+
]
|
|
100
|
+
},
|
|
101
|
+
"threshold": {"type": "null"},
|
|
102
|
+
},
|
|
103
|
+
"required": [],
|
|
104
|
+
},
|
|
105
|
+
],
|
|
106
|
+
}
|
|
@@ -86,7 +86,10 @@ choices = (
|
|
|
86
86
|
(FINANCIAL_LITERACY, "Financial Literacy"),
|
|
87
87
|
(FOR_TEACHERS, "For Teachers"),
|
|
88
88
|
(FOUNDATIONS, "Foundations"),
|
|
89
|
-
(
|
|
89
|
+
(
|
|
90
|
+
FOUNDATIONS_LOGIC_AND_CRITICAL_THINKING,
|
|
91
|
+
"Foundations Logic And Critical Thinking",
|
|
92
|
+
),
|
|
90
93
|
(GEOMETRY, "Geometry"),
|
|
91
94
|
(GUIDES, "Guides"),
|
|
92
95
|
(HISTORY, "History"),
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
# Generated by scripts/generate_from_specs.py
|
|
3
|
+
from __future__ import unicode_literals
|
|
4
|
+
|
|
5
|
+
# MasteryCriteria
|
|
6
|
+
|
|
7
|
+
DO_ALL = "do_all"
|
|
8
|
+
M_OF_N = "m_of_n"
|
|
9
|
+
NUM_CORRECT_IN_A_ROW_10 = "num_correct_in_a_row_10"
|
|
10
|
+
NUM_CORRECT_IN_A_ROW_2 = "num_correct_in_a_row_2"
|
|
11
|
+
NUM_CORRECT_IN_A_ROW_3 = "num_correct_in_a_row_3"
|
|
12
|
+
NUM_CORRECT_IN_A_ROW_5 = "num_correct_in_a_row_5"
|
|
13
|
+
|
|
14
|
+
choices = (
|
|
15
|
+
(DO_ALL, "Do All"),
|
|
16
|
+
(M_OF_N, "M Of N"),
|
|
17
|
+
(NUM_CORRECT_IN_A_ROW_10, "Num Correct In A Row 10"),
|
|
18
|
+
(NUM_CORRECT_IN_A_ROW_2, "Num Correct In A Row 2"),
|
|
19
|
+
(NUM_CORRECT_IN_A_ROW_3, "Num Correct In A Row 3"),
|
|
20
|
+
(NUM_CORRECT_IN_A_ROW_5, "Num Correct In A Row 5"),
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
MASTERYCRITERIALIST = [
|
|
24
|
+
DO_ALL,
|
|
25
|
+
M_OF_N,
|
|
26
|
+
NUM_CORRECT_IN_A_ROW_10,
|
|
27
|
+
NUM_CORRECT_IN_A_ROW_2,
|
|
28
|
+
NUM_CORRECT_IN_A_ROW_3,
|
|
29
|
+
NUM_CORRECT_IN_A_ROW_5,
|
|
30
|
+
]
|
|
31
|
+
|
|
32
|
+
SCHEMA = {
|
|
33
|
+
"$id": "/schemas/mastery_criteria",
|
|
34
|
+
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
35
|
+
"type": "object",
|
|
36
|
+
"description": "Schema for mastery criteria of exercise content types",
|
|
37
|
+
"additionalProperties": False,
|
|
38
|
+
"required": ["mastery_model"],
|
|
39
|
+
"definitions": {
|
|
40
|
+
"mastery_model": {
|
|
41
|
+
"type": "string",
|
|
42
|
+
"$exportConstants": "mastery_criteria",
|
|
43
|
+
"enum": [
|
|
44
|
+
"do_all",
|
|
45
|
+
"m_of_n",
|
|
46
|
+
"num_correct_in_a_row_2",
|
|
47
|
+
"num_correct_in_a_row_3",
|
|
48
|
+
"num_correct_in_a_row_5",
|
|
49
|
+
"num_correct_in_a_row_10",
|
|
50
|
+
],
|
|
51
|
+
}
|
|
52
|
+
},
|
|
53
|
+
"properties": {
|
|
54
|
+
"m": True,
|
|
55
|
+
"n": True,
|
|
56
|
+
"mastery_model": {"$ref": "#/definitions/mastery_model"},
|
|
57
|
+
},
|
|
58
|
+
"anyOf": [
|
|
59
|
+
{"properties": {"mastery_model": {"const": "m_of_n"}}, "required": ["m", "n"]},
|
|
60
|
+
{
|
|
61
|
+
"properties": {
|
|
62
|
+
"mastery_model": {
|
|
63
|
+
"enum": [
|
|
64
|
+
"do_all",
|
|
65
|
+
"num_correct_in_a_row_2",
|
|
66
|
+
"num_correct_in_a_row_3",
|
|
67
|
+
"num_correct_in_a_row_5",
|
|
68
|
+
"num_correct_in_a_row_10",
|
|
69
|
+
]
|
|
70
|
+
},
|
|
71
|
+
"m": {"type": "null"},
|
|
72
|
+
"n": {"type": "null"},
|
|
73
|
+
}
|
|
74
|
+
},
|
|
75
|
+
],
|
|
76
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
# Generated by scripts/generate_from_specs.py
|
|
3
|
+
from __future__ import unicode_literals
|
|
4
|
+
|
|
5
|
+
# Uuid
|
|
6
|
+
|
|
7
|
+
KOLIBRI_ECOSYSTEM_UUID_NAMESPACE = "237627f4-3601-11ee-a67c-595de72bede7"
|
|
8
|
+
|
|
9
|
+
choices = ((KOLIBRI_ECOSYSTEM_UUID_NAMESPACE, "Kolibri Ecosystem Uuid Namespace"),)
|
|
10
|
+
|
|
11
|
+
UUIDLIST = [
|
|
12
|
+
KOLIBRI_ECOSYSTEM_UUID_NAMESPACE,
|
|
13
|
+
]
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import uuid
|
|
2
|
+
|
|
3
|
+
from le_utils.constants.uuid import KOLIBRI_ECOSYSTEM_UUID_NAMESPACE
|
|
4
|
+
|
|
5
|
+
try:
|
|
6
|
+
from urlparse import urlparse
|
|
7
|
+
except ImportError:
|
|
8
|
+
from urllib.parse import urlparse
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def generate_ecosystem_namespaced_uuid(hostname_or_url):
|
|
12
|
+
"""
|
|
13
|
+
Generate a UUID for a given URL, namespaced by the Kolibri ecosystem UUID namespace.
|
|
14
|
+
:param hostname_or_url: A URL to generate a UUID-- only the netloc/host is used
|
|
15
|
+
:return: A namespaced UUID
|
|
16
|
+
"""
|
|
17
|
+
_url = urlparse(hostname_or_url)
|
|
18
|
+
|
|
19
|
+
return uuid.uuid5(uuid.UUID(KOLIBRI_ECOSYSTEM_UUID_NAMESPACE), _url.netloc)
|