Beispiel #1
0
def exercise(exercise_question, exercise_data, channel):
    args_data = get_content_node_args(exercise_data)
    contentnode_kwargs = get_content_node_kwargs(exercise_data)
    del contentnode_kwargs['extra_fields']
    mastery_model_dict = contentnode_kwargs['exercise_data']
    exercise = ExerciseNode(*args_data, **contentnode_kwargs)
    exercise.add_question(exercise_question)
    channel.add_child(exercise)
    exercise_data['questions'] = [exercise_question]
    exercise_data['extra_fields'] = mastery_model_dict
    del exercise_data['exercise_data']
    return exercise
Beispiel #2
0
def get_file(name, directory, filename, title=None):
    filepath = os.path.join(directory, filename)
    if title is None:
        title = name
    source_id = "{}/{}".format(name, filename)
    node = None
    if filename.endswith(".pdf"):
        node = DocumentNode(
            title=title,
            description="Documentación de {}".format(name),
            source_id=source_id,
            license=AIEP_License,
            language="es",
            files=[DocumentFile(
                path=filepath,
                language="es",
            )],
        )
    elif filename.endswith("h5p"):
        mp4_file = get_video_from_h5p(filepath)
        if mp4_file is None:
            classNode = H5PAppNode
            classFile = H5PFile
        else:
            classNode = VideoNode
            classFile = VideoFile
            filepath = mp4_file

        node = classNode(
            title=get_title_from_video(title, filename),
            description="Vídeo explicativo de la {}".format(name),
            source_id=source_id,
            license=AIEP_License,
            language="es",
            files=[classFile(
                path=filepath,
                language="es",
            )],
        )

    elif filename.endswith("xls"):
        node = ExerciseNode(
            source_id=source_id,
            title="Ejercicios de {}".format(name),
            author="Equipo de AIEP",
            description="Preguntas de la unidad 1",
            language="es",
            license=AIEP_License,
            thumbnail=None,
            exercise_data={
                "mastery_model": exercises.M_OF_N,  # \
                "m": 2,  # learners must get 2/3 questions correct to complete
                "n": 3,  # /
                "randomize": True,  # show questions in random order
            },
            questions=leer_preguntas(filepath),
        )

    return node
Beispiel #3
0
def create_node(node, assessment_dict, subtitle_path, vtt_videos, base_path,
                lite_version, lang_code):

    kind = node.get('kind')
    # Exercise node creation
    if kind == 'Exercise':
        child_node = ExerciseNode(
            source_id=node['id'],
            title=node['title'],
            exercise_data={
                'mastery_model': node.get('suggested_completion_criteria')
            },
            description='' if node.get("description") is None else node.get(
                "description", '')[:400],
            license=licenses.ALL_RIGHTS_RESERVED,
            thumbnail=node.get('image_url_256'),
        )

        # build exercise urls for previews
        full_path = base_path + node.get('path').strip('khan')
        slug = full_path.split('/')[-2]
        full_path = full_path.replace(slug, 'e') + slug

        # attach Perseus questions to Exercises
        for item in node['all_assessment_items']:
            # we replace all references to assessment images with the local file path to the image
            for match in re.finditer(FILE_URL_REGEX,
                                     assessment_dict[item['id']]["item_data"]):
                file_path = str(match.group(0)).replace('\\', '')
                file_path = file_path.replace(REPLACE_STRING,
                                              IMAGE_DL_LOCATION)
                assessment_dict[item['id']]["item_data"] = re.sub(
                    FILE_URL_REGEX, file_path,
                    assessment_dict[item['id']]["item_data"], 1)
            question = PerseusQuestion(
                id=item['id'],
                raw_data=assessment_dict[item['id']]['item_data'],
                source_url=full_path if not lite_version else None,
            )
            child_node.add_question(question)

    # Topic node creation
    elif kind == 'Topic':
        child_node = TopicNode(
            source_id=node["id"],
            title=node["title"],
            description='' if node.get("description") is None else node.get(
                "description", '')[:400])

    # Video node creation
    elif kind == 'Video':
        # standard download url for KA videos
        download_url = "https://cdn.kastatic.org/KA-youtube-converted/{0}.mp4/{1}.mp4".format(
            node['youtube_id'], node['youtube_id'])
        files = [VideoFile(download_url)]
        if node['youtube_id'] in vtt_videos:
            files.append(
                SubtitleFile(subtitle_path +
                             '/{}.vtt'.format(node['youtube_id']),
                             language=getlang(lang_code)))
        child_node = VideoNode(
            source_id=node["id"],
            title=node["title"],
            description='' if node.get("description") is None else node.get(
                "description", '')[:400],
            files=files,
            thumbnail=node.get('image_url'),
            license=licenses.CC_BY_NC_SA)

    else:  # unknown content file format
        return None

    return child_node
Beispiel #4
0
    def create_exercise_nodes(self, channel):
        """
        This function adds a few exercise nodes to the channel content tree.
        TODO: handle exercises with embedded image links + base64 encoded data.
        """

        # EXERCISES
        exercices_folder = TopicNode(
            source_id='uniqid011',
            title='Exercise Nodes',
            description='Put folder description here',
            author=None,
            language=getlang('en').id,
            thumbnail=None,
        )
        channel.add_child(exercices_folder)

        exercise1 = ExerciseNode(
            source_id='uniqid012',
            title='Basic questions',
            author='LE content team',
            description=
            'Showcase of the simple exercises supported by Ricecooker and Studio',
            language=getlang('en').id,
            license=get_license(licenses.CC_BY,
                                copyright_holder='Copyright holder name'),
            thumbnail=None,
            exercise_data={
                'mastery_model': exercises.M_OF_N,  # or exercises.DO_ALL
                'randomize': True,
                'm': 2,
                'n': 3,
            },
            questions=[
                MultipleSelectQuestion(
                    id='ex2aQ1',
                    question=
                    "Which numbers are even?\n\nTest local image include: ![](content/ricecooker-channel-files/html5_vuejs.jpg)",
                    correct_answers=[
                        "2",
                        "4",
                    ],
                    all_answers=["1", "2", "3", "4", "5"],
                    hints=[
                        "There are two answers.",
                        "Both answers are multiples of two."
                    ]),
                SingleSelectQuestion(
                    id='ex2aQ2',
                    question="What is 2 times 3?",
                    correct_answer="6",
                    all_answers=["2", "3", "5", "6"],
                ),
                InputQuestion(
                    id='ex2aQ3',
                    question="Name a factor of 10.",
                    answers=["1", "2", "5", "10"],
                )
            ])
        exercices_folder.add_child(exercise1)

        # LOAD JSON DATA (as string) FOR PERSEUS QUESTIONS
        SAMPLE_PERSEUS_4_JSON = open(
            './content/ricecooker-channel-files/perseus_graph_question.json',
            'r').read()
        exercise2 = ExerciseNode(
            source_id='baszzzs1',
            title='Perseus questions',
            author='LE content team',
            description='An example exercise with Persus questions',
            language=getlang('en').id,
            license=get_license(licenses.CC_BY,
                                copyright_holder='Copyright holder name'),
            thumbnail=None,
            exercise_data={
                'mastery_model': exercises.M_OF_N,  # or exercises.DO_ALL
                'randomize': True,
                'm': 1,
                'n': 1,
            },
            questions=[
                PerseusQuestion(
                    id='ex2bQ4',
                    raw_data=SAMPLE_PERSEUS_4_JSON,
                    source_url=
                    'https://github.com/learningequality/sample-channels/blob/master/contentnodes/exercise/sample_perseus04.json'
                ),
            ])
        exercices_folder.add_child(exercise2)
    def add_lesson_practice(self, lesson, url, title, course_title,
                            module_title):
        LOGGER.info("Adding practice for the course {}...".format(
            lesson.title))
        # resp = downloader.make_request(url, cookies=self.cookies).content.decode("utf-8")
        file_path = "files/{}/{}/{}/{}-practice.txt".format(
            course_title, module_title, lesson.title, title)
        with open(file_path, "r") as resp:
            page = BeautifulSoup(resp, "html.parser")
            # Get the question description
            question_paras = page.find(
                "div", class_="activity-intro__question").find_all("p")
            question_description = ""
            for description in question_paras:
                question_description = question_description + description.text + "\n"

            # Get the practice data to parse
            pattern = re.compile("window.lessonData = (.*;)")
            lesson_data = json.loads(
                pattern.search(page.text).group(1).replace(";", ""))
            practice_data = lesson_data["activities"][0]["activity"]
            practice_type = lesson_data["activities"][0]["type"]
            questions_add_to_exercise = []
            practice_id = "{}-practice".format(lesson.source_id)

            # A multiple select question
            if practice_type in [
                    "select-right", "switches-text", "strike-through",
                    "tag-cloud"
            ]:
                questions_add_to_exercise.append(
                    self.add_a_multiple_select_question(
                        practice_data, question_description, practice_id))

            # A single select question
            elif practice_type in [
                    "swipe-selector", "twitter-draganddrop", "image-slider"
            ]:
                questions_add_to_exercise.append(
                    self.add_a_single_select_question(practice_data,
                                                      question_description,
                                                      practice_id))

            # Multiple single select questions
            elif practice_type in ["text-drawer", "boolean-selector"]:
                questions_add_to_exercise = self.add_multiple_single_select_questions(
                    practice_data["options"], question_description,
                    practice_id)

            else:
                LOGGER.error("Type {} hasn't been analyzed: {}".format(
                    practice_type, url))
                return

            # Create exercise node
            exercise_id = "{} Practice".format(lesson.title)
            exercise = ExerciseNode(
                source_id=exercise_id,
                title=title,
                license=CC_BY_NC_SALicense(
                    copyright_holder="Google Garage Digital"),
                language=CHANNEL_LANGUAGE,
                thumbnail=None,
                exercise_data={
                    "master_model": exercises.DO_ALL,
                    "randomize": False,
                },
                questions=questions_add_to_exercise,
            )
            lesson.add_child(exercise)
Beispiel #6
0
    def create_exercise_nodes(self, channel):
        """
        This function adds a few exercise nodes to the channel content tree.
        TODO: handle exercises with embedded image links + base64 encoded data.
        """

        # EXERCISES
        exercices_folder = TopicNode(
            source_id='mdmdmai3i13',
            title='Exercise Nodes',
            description='Put folder description here',
            author=None,
            language=getlang('en').id,
            thumbnail=None,
        )
        channel.add_child(exercices_folder)

        exercise2a = ExerciseNode(
            source_id='asisis9',
            title='Basic questions',
            author='LE content team',
            description=
            'Showcase of the simple exercises supported by Ricecooker and Studio',
            language=getlang('en').id,
            license=get_license(licenses.CC_BY,
                                copyright_holder='Copyright holder name'),
            thumbnail=None,
            exercise_data={
                'mastery_model': exercises.M_OF_N,  # or exercises.DO_ALL
                'randomize': True,
                'm': 2,
                'n': 3,
            },
            questions=[
                MultipleSelectQuestion(
                    id='ex2aQ1',
                    question="Which numbers are even?",
                    correct_answers=[
                        "2",
                        "4",
                    ],
                    all_answers=["1", "2", "3", "4", "5"],
                    # hints?
                ),
                SingleSelectQuestion(
                    id='ex2aQ2',
                    question="What is 2 times 3?",
                    correct_answer="6",
                    all_answers=["2", "3", "5", "6"],
                    # hints?
                ),
                InputQuestion(
                    id='ex2aQ3',
                    question="Name a factor of 10.",
                    answers=["1", "2", "5", "10"],
                    # hints?
                )
            ])
        exercices_folder.add_child(exercise2a)

        # LOAD JSON DATA (as string) FOR PERSEUS QUESTIONS
        SAMPLE_PERSEUS_4_JSON = open(
            './content/ricecooker-channel-files/sample_perseus04.json',
            'r').read()
        exercise2b = ExerciseNode(
            source_id='baszzzs1',
            title='Perseus questions',
            author='LE content team',
            description='An example exercise with Persus questions',
            language=getlang('en').id,
            license=get_license(licenses.CC_BY,
                                copyright_holder='Copyright holder name'),
            thumbnail=None,
            exercise_data={
                'mastery_model': exercises.M_OF_N,  # or exercises.DO_ALL
                'randomize': True,
                'm': 2,
                'n': 3,
            },
            questions=[
                PerseusQuestion(
                    id='ex2bQ4',
                    raw_data=SAMPLE_PERSEUS_4_JSON,
                    source_url=
                    'https://github.com/learningequality/sample-channels/blob/master/contentnodes/exercise/sample_perseus04.json'
                ),
            ])
        exercices_folder.add_child(exercise2b)

        SAMPLE_PERSEUS_4_dhanam4_JSON = open(
            './content/ricecooker-channel-files/sample_perseus04dhanam4.json',
            'r').read()
        exercise2b_dhanam4 = ExerciseNode(
            source_id='test_dhanam4',
            title='Perseus question by dhanam4',
            author='dhanam4',
            description='dhanam4\'s example exercise with Persus questions',
            language=getlang('en').id,
            license=get_license(licenses.CC_BY, copyright_holder='dhanam4'),
            thumbnail=None,
            exercise_data={
                'mastery_model': exercises.M_OF_N,  # or exercises.DO_ALL
                'randomize': True,
                'm': 2,
                'n': 3,
            },
            questions=[
                PerseusQuestion(
                    id='test_ex2bQ4dhanam4',
                    raw_data=SAMPLE_PERSEUS_4_dhanam4_JSON,
                    source_url=
                    'doesnt matter what goes here.. used for information purposes only'
                ),
            ])
        exercices_folder.add_child(exercise2b_dhanam4)