Beispiel #1
0
 def new_exercise(self, videoPath, exercisePath, translationPath, langId):
     self.exercise = Exercise()
     self.exercise.set_media_change_callback(self.media_change_call_back)
     self.exercise.new()
     self.exercise.set_language_id(langId)
     self._set_paths(videoPath, exercisePath,
                     translationPath)  # This initialize the exercise
     self._reload(True)
     self._activate_sequence()
     self.gui_controller.set_title("", True)
Beispiel #2
0
def sample_exercise(author):
    exercise = Exercise(author=author,
                    title="#{} - New exercise".format(len(Exercise.objects)),
                    description=config.default_description,
                    boilerplate_code=config.default_boilerplate_code,
                    reference_code=config.default_boilerplate_code,
                    tags=['algorithms'])

    test = Test(input="1\n", output="42", cpu_time="100", memory_used="100").save()
    exercise.tests.append(test)
    test = Test(input="2\n", output="43", cpu_time="100", memory_used="100").save()
    exercise.published = True
    exercise.tests.append(test)

    return exercise
Beispiel #3
0
 def new_exercise(self, videoPath, exercisePath, translationPath, langId):
     self.exercise = Exercise()
     self.exercise.set_media_change_callback(self.media_change_call_back)
     self.exercise.new()
     self.exercise.set_language_id(langId)
     self._set_paths(videoPath, exercisePath, translationPath) # This initialize the exercise
     self._reload(True);
     self._activate_sequence()
     self.gui_controller.set_title("", True)
Beispiel #4
0
def monitoring():
    if not g.user.editor:
        redirect('/')

    users = User.objects(editor=False)
    exercises = Exercise.objects()
    progress = {user: {p.exercise: p for p in ExerciseProgress.objects(user=user)} for user in users}

    breadcrumbs = [('Home', '/'), ('Monitoring', None)]
    return render_template('monitoring.html', users=users, exercises=exercises, progress=progress, breadcrumbs=breadcrumbs)
Beispiel #5
0
 def add_random_guitar(self):
     random_number = random.randint(1, 100)
     if random_number >= 1 and random_number < 60:
         random_guitar = self._GUITAR_M
     elif random_number >= 60 and random_number < 90:
         random_guitar = self._GUITAR_D
     else:
         random_guitar = self._GUITAR_A
     guitar_step = ExerciseStep(random_guitar)
     guitar_exercise = Exercise("Guitar", "Pick the following guitar",
                                [guitar_step])
     self._exercises.insert(0, guitar_exercise)
Beispiel #6
0
def search_words():
    words = request.json['words']
    tags = request.json['tags'].split()
    words = words.lower()
    find = [words] + words.split()
    if tags == [] :
        exercises = Exercise.objects
    else :
        exercises = Exercise.objects(tags__in=tags)
    try:
        user_id = g.user.id
    except:
        user_id = None
    found = set([e for e in exercises for w in find if w in e.title.lower() or w in e.description.lower()])
    found = [f.to_dict() for f in found if f.published or f.author.id == user_id]
    return jsonify(ok=True, result=found, user=user_id)
Beispiel #7
0
    def get_exercise(self, quantity: int, guitar: dict) -> Exercise:
        """ Returns random chord exercises """
        if guitar["kind"] != "instrument":
            return None

        random_steps = []
        note = Note()
        chord = Chord()

        for pos in range(0, quantity):  # pylint: disable=W0612
            pentatonic_key = note.get_random_note()
            target_chord = chord.get_random_chord()
            step = ExerciseStep(f"{pentatonic_key} Pentatonic", target_chord)
            random_steps.append(step)

        output = Exercise(self._TITLE,
                          self._SUBTITLE,
                          random_steps,
                          practice_category=self.category)

        return output
    def get_exercise(self, quantity: int, guitar: dict) -> Exercise:
        """ Returns exercise """
        if guitar["kind"] != "instrument":
            return None
        random_steps = []

        random_chords = Chord().get_random_chords(quantity)
        key_signature = KeySignature()

        for chord in random_chords:
            try:
                note = key_signature.get_random_relative_note(chord)
            except Exception:
                continue

            random_step = ExerciseStep(f"{note} -> {chord}")
            random_steps.append(random_step)

        output = Exercise(self._TITLE,
                          self._SUBTITLE,
                          random_steps,
                          practice_category=self.category)

        return output
Beispiel #9
0
class Core(object):
    WAIT_BEGIN = 0
    WAIT_END = 1

    def __init__(self):
        self.player = None
        self.last_save = False
        self.exercise = None
        self.config = config
        self.logger = logging.Logger("Core")
        self.logger.setLevel(defaultLoggingLevel)
        self.logger.addHandler(defaultLoggingHandler)

    #Call by the main, give an handler to the main gui
    def set_gui(self, gui):
        self.gui_controller = gui

    #Create a new exercice based on paths. load the new exercise and
    #begin to play
    def new_exercise(self, videoPath, exercisePath, translationPath, langId):
        self.exercise = Exercise()
        self.exercise.set_media_change_callback(self.media_change_call_back)
        self.exercise.new()
        self.exercise.set_language_id(langId)
        self._set_paths(videoPath, exercisePath,
                        translationPath)  # This initialize the exercise
        self._reload(True)
        self._activate_sequence()
        self.gui_controller.set_title("", True)

    #Configure the paths for the current exercice. Reload subtitles list.
    def _set_paths(self, videoPath, exercisePath, translationPath):
        self.exercise.set_video_path(videoPath)
        self.exercise.set_exercise_path(exercisePath)
        self.exercise.set_translation_path(translationPath)
        self.exercise.initialize()

    #Reload media player and begin to play (if the params is True)
    def _reload(self, load):
        if self.player != None:
            self.player.close()

        self.player = VideoPlayer()
        self.player.set_window_id(self.gui_controller.get_video_window_id())
        self.player.activate_video_callback(
            self.gui_controller.activate_video_area)
        self.player.open(self.exercise.get_video_path())
        self.player.set_callback(self._time_callback)
        self.paused = False
        self.gui_controller.activate_video_area(False)
        self.gui_controller.activate("loaded")
        self._update_word_list()
        self.timeUpdateThreadId = thread.start_new_thread(
            self.time_update_thread, ())

        if load and self.exercise.get_repeat_count_limit_by_sequence() == 0:
            #Auto start play only if repeat is not limited
            self.play()
        else:
            self.pause()

    #play the media
    def play(self):
        self.gui_controller.set_playing(True)
        self.player.play()
        self.paused = False

    #pause the media
    def pause(self):
        self.gui_controller.set_playing(False)
        self.player.pause()
        self.paused = True

    #Modify media speed
    def set_speed(self, speed):
        self.gui_controller.set_speed(speed)
        self.player.set_speed(speed)

    #Callback call by video player to notify change of media position.
    #Stop the media at the end of uncompleted sequences
    def _time_callback(self):
        if self.state == Core.WAIT_BEGIN:
            self.player.set_next_callback_time(
                self.exercise.get_current_sequence().get_time_end() +
                self.exercise.get_play_margin_after())
            self.state = Core.WAIT_END
        elif self.state == Core.WAIT_END:
            self.state = Core.WAIT_BEGIN
            if self.exercise.get_current_sequence().is_valid():
                gtk.gdk.threads_enter()
                self.next_sequence(False)
                gtk.gdk.threads_leave()
            else:
                self.pause()

    #Repeat the currence sequence
    def repeat_sequence(self):
        if not self.exercise.is_current_sequence_repeat_limit_reach():
            #Repeat limit not reach or no limit
            self.goto_sequence_begin()
            self.play()
            self.exercise.increment_current_sequence_repeat_count()

    #Change the active sequence
    def select_sequence(self, num, load=True):
        if self.exercise.get_current_sequence_id() == num:
            return
        self.exercise.goto_sequence(num)
        self._activate_sequence()
        if load and self.exercise.get_repeat_count_limit_by_sequence() == 0:
            #Auto start play only if repeat is not limited
            self.repeat_sequence()
        self.set_can_save(True)

    #Goto next sequence
    def next_sequence(self, load=True):
        if self.exercise.goto_next_sequence():
            self.set_can_save(True)
        self._activate_sequence()
        if load and self.exercise.get_repeat_count_limit_by_sequence() == 0:
            #Auto start play only if repeat is not limited
            self.repeat_sequence()

    #Goto previous sequence
    def previous_sequence(self, load=True):
        if self.exercise.goto_previous_sequence():
            self.set_can_save(True)
        self._activate_sequence()
        if load and self.exercise.get_repeat_count_limit_by_sequence() == 0:
            #Auto start play only if repeat is not limited
            self.repeat_sequence()

    #Goto next valid sequence
    def next_valid_sequence(self, load=True):
        if self.exercise.goto_next_valid_sequence():
            self.set_can_save(True)
        self._activate_sequence()
        if load and self.exercise.get_repeat_count_limit_by_sequence() == 0:
            #Auto start play only if repeat is not limited
            self.repeat_sequence()

    #Goto previous valid sequence
    def previous_valid_sequence(self, load=True):
        if self.exercise.goto_previous_valid_sequence():
            self.set_can_save(True)
        self._activate_sequence()
        if load and self.exercise.get_repeat_count_limit_by_sequence() == 0:
            #Auto start play only if repeat is not limited
            self.repeat_sequence()

    #Update interface with new sequence. Configure stop media callback
    def _activate_sequence(self):
        self.state = Core.WAIT_BEGIN
        self.set_speed(1)
        self.player.set_next_callback_time(
            self.exercise.get_current_sequence().get_time_begin() -
            self.exercise.get_play_margin_before())

        self.gui_controller.set_sequence_number(
            self.exercise.get_current_sequence_id(),
            self.exercise.get_sequence_count())
        self.gui_controller.set_sequence(self.exercise.get_current_sequence())
        self.__activate_translation()
        self.__activate_previous_sequence_text()
        self._update_stats()

    #_update displayed translation on new active sequence
    def __activate_translation(self):
        if not self.exercise.get_translation_list():
            self.gui_controller.set_translation("")
        else:
            translation = ""
            currentBegin = self.exercise.get_current_sequence().get_time_begin(
            )
            currentEnd = self.exercise.get_current_sequence().get_time_end()
            for sub in self.exercise.get_translation_list():
                begin = sub.get_time_begin()
                end = sub.get_time_end()
                if (begin >= currentBegin and begin <= currentEnd) or (
                        end >= currentBegin
                        and end <= currentEnd) or (begin <= currentBegin
                                                   and end >= currentEnd):
                    translation += sub.get_text() + " "

            self.gui_controller.set_translation(translation)

    #_update displayed previous sentence text
    def __activate_previous_sequence_text(self):
        previous_sequence_text = ""
        previous_sequence = self.exercise.get_previous_sequence()
        if previous_sequence:
            for i, symbol in enumerate(previous_sequence.get_symbols()):
                previous_sequence_text += symbol
                if i < len(previous_sequence.get_words()):
                    word = previous_sequence.get_words()[i]
                    if word.is_valid():
                        previous_sequence_text += word.get_valid(lower=False)
                    else:
                        word_text = word.get_text()
                        if len(word_text):
                            previous_sequence_text += word.get_text()
                        else:
                            previous_sequence_text += "_"

        self.gui_controller.set_previous_sequence_text(previous_sequence_text)

    #Update displayed stats on new active sequence
    def _update_stats(self):
        sequenceCount = self.exercise.get_sequence_count()
        sequenceFound = 0
        wordCount = 0
        wordFound = 0
        for sequence in self.exercise.get_sequence_list():
            wordCount = wordCount + sequence.get_word_count()
            if sequence.is_valid():
                sequenceFound += 1
                wordFound += sequence.get_word_count()
            else:
                wordFound += sequence.get_word_found()
        if wordFound == 0:
            repeatRate = float(0)
        else:
            repeatRate = float(
                self.exercise.get_repeat_count()) / float(wordFound)
        self.gui_controller.set_statitics(sequenceCount, sequenceFound,
                                          wordCount, wordFound, repeatRate)

    def _update(self):
        self.gui_controller.set_sequence(self.exercise.get_current_sequence())
        self.__validate_sequence()

    #Verify if the sequence is complete
    def __validate_sequence(self):
        if self.exercise.get_current_sequence().is_valid():
            if self.exercise.get_repeat_after_completed():
                if self.exercise.get_repeat_count_limit_by_sequence() == 0:
                    #Auto start play only if repeat is not limited
                    self.repeat_sequence()
            else:
                self.next_sequence(load=False)
                if self.exercise.get_repeat_count_limit_by_sequence() == 0:
                    #Auto start play only if repeat is not limited
                    if self.player.get_seek(
                    ) > (self.exercise.get_current_sequence().get_time_begin()
                         - self.exercise.get_play_margin_before()):
                        self.goto_sequence_begin()
                        self.play()
                    else:
                        self.play()

    #Goto beginning of the current sequence. Can start to play as soon
    #as the media player is ready
    def goto_sequence_begin(self, asSoonAsReady=False):
        self.state = Core.WAIT_END
        begin_time = self.exercise.get_current_sequence().get_time_begin(
        ) - self.exercise.get_play_margin_before()
        if begin_time < 0:
            begin_time = 0
        if asSoonAsReady:
            self.player.seek_as_soon_as_ready(begin_time)
        else:
            self.player.seek(begin_time)
        self.player.set_next_callback_time(
            self.exercise.get_current_sequence().get_time_end() +
            self.exercise.get_play_margin_after())

    #Write a char in current sequence at cursor position
    def write_char(self, char):
        if self.exercise.is_character_match(char):
            self.exercise.get_current_sequence().write_char(char)
            self.exercise.get_current_sequence().update_cursor_position()
            self._update()
            self.set_can_save(True)
        else:
            self._update()

    #Goto next word in current sequence
    def next_word(self):
        self.exercise.get_current_sequence().next_word()
        self._update()

    #Goto previous word in current sequence
    def previous_word(self):
        self.exercise.get_current_sequence().previous_word()
        self._update()

    #Choose current word in current sequence
    def select_sequence_word(self, wordIndex, wordIndexPos):
        try:
            self.exercise.get_current_sequence().select_sequence_word(
                wordIndex, wordIndexPos)
        except NoCharPossible:
            self.exercise.get_current_sequence().select_sequence_word(
                wordIndex, -1)
        self._update()

    #Goto first word in current sequence
    def first_word(self):
        self.exercise.get_current_sequence().first_word()
        self._update()

    #Goto last word in current sequence
    def last_word(self):
        self.exercise.get_current_sequence().last_word()
        self._update()

    #Delete a char before the cursor in current sequence
    def delete_previous_char(self):
        self.exercise.get_current_sequence().delete_previous_char()
        self._update()
        self.set_can_save(True)

    #Delete a char after the cursor in current sequence
    def delete_next_char(self):
        self.exercise.get_current_sequence().delete_next_char()
        self._update()
        self.set_can_save(True)

    #Goto previous char in current sequence
    def previous_char(self):
        self.exercise.get_current_sequence().previous_char()
        #The sequence don't change but the cursor position is no more up to date
        self._update()

    #Goto next char in current sequence
    def next_char(self):
        self.exercise.get_current_sequence().next_char()
        #The sequence don't change but the cursor position is no more up to date
        self._update()

    #Reveal correction for word at cursor in current sequence
    def complete_word(self):
        self.exercise.get_current_sequence().show_hint()
        self._update()
        self.set_can_save(True)

    #Reveal correction for word at cursor in current sequence
    def reveal_word(self):
        self.exercise.get_current_sequence().complete_word()
        self.exercise.get_current_sequence().next_word()
        self._update()
        self.set_can_save(True)

    #Reveal correction for word at cursor in current sequence
    def reveal_sequence(self):
        self.exercise.get_current_sequence().complete_all()
        self._update()
        self.set_can_save(True)

    #reset whole exercise
    def reset_exercise_content(self):
        self.exercise.reset()
        self.exercise.goto_sequence(0)  #FIXME
        self._update()
        self.set_can_save(True)
        self.logger.debug("need to stop the current sequence")  #FIXME

    #pause or play media
    def toggle_pause(self):
        if self.player.is_paused() and self.paused:
            self.play()
        elif not self.player.is_paused() and not self.paused:
            self.pause()

    #Change position in media and play it
    def seek_sequence(self, time):
        begin_time = self.exercise.get_current_sequence().get_time_begin(
        ) - self.exercise.get_play_margin_before()
        if begin_time < 0:
            begin_time = 0

        pos = begin_time + time
        self.player.seek(pos)
        self.player.set_next_callback_time(
            self.exercise.get_current_sequence().get_time_end() +
            self.exercise.get_play_margin_after())
        self.state = Core.WAIT_END
        if self.exercise.get_repeat_count_limit_by_sequence() == 0:
            #Auto start play only if repeat is not limited
            self.play()

    #Thread to update slider position in gui
    def time_update_thread(self):
        timeUpdateThreadId = self.timeUpdateThreadId
        while timeUpdateThreadId == self.timeUpdateThreadId:
            time.sleep(0.5)
            pos_int = self.player.get_current_time()
            if pos_int != None:
                end_time = self.exercise.get_current_sequence().get_time_end()
                begin_time = self.exercise.get_current_sequence(
                ).get_time_begin() - self.exercise.get_play_margin_before()
                if begin_time < 0:
                    begin_time = 0
                duration = end_time - begin_time
                pos = pos_int - begin_time
                self.gui_controller.set_sequence_time(pos, duration)

    #Save current exercice
    def save(self, saveAs=False):
        if not self.exercise:
            self.logger.error("Save called but no exercise load")
            return

        if saveAs or self.exercise.get_output_save_path() == None:
            outputSavePath = self.gui_controller.ask_save_path()
            if not outputSavePath:
                return
            self.exercise.set_output_save_path(outputSavePath + ".perroquet")

        save_exercise(self.exercise, self.exercise.get_output_save_path())

        self.config.set("lastopenfile", self.exercise.get_output_save_path())

        #lastopenfileS
        l = self.config.get("lastopenfiles")
        path = self.exercise.get_output_save_path()
        name = self.exercise.get_name() or path
        self.config.set("lastopenfiles",
                        [[path, name]] + [p for p in l if p[0] != path][:10])

        self.set_can_save(False)

    #load the exercice at path
    def load_exercise(self, path):
        self.gui_controller.activate("closed")
        if self.exercise:
            self.save()
        try:
            self.exercise = load_exercise(path)
            self.exercise.set_media_change_callback(
                self.media_change_call_back)
        except IOError:
            self.logger.exception("No file at " + path)
            return
        if not self.exercise:
            return

        validPaths, errorList = self.exercise.is_paths_valid()
        if not validPaths:
            for error in errorList:
                self.gui_controller.signal_exercise_bad_path(error)

            self.set_can_save(False)
            self.gui_controller.activate("load_failed")
            self.gui_controller.ask_properties()
            return

        self._reload(False)
        if self.exercise.get_output_save_path() == None:
            self.set_can_save(True)
        else:
            self.set_can_save(False)
        self._activate_sequence()
        self.goto_sequence_begin(True)
        if self.exercise.get_repeat_count_limit_by_sequence() == 0:
            #Auto start play only if repeat is not limited
            self.play()

    #Change paths of current exercice and reload subtitles and video
    def _update_paths(self, videoPath, exercisePath, translationPath):
        self.exercise.set_video_path(videoPath)
        self.exercise.set_exercise_path(exercisePath)
        self.exercise.set_translation_path(translationPath)

        validPaths, errorList = self.exercise.is_paths_valid()
        if not validPaths:
            for error in errorList:
                self.gui_controller.signal_exercise_bad_path(error)
            self.gui_controller.activate("load_failed")
            self.set_can_save(False)
            return

        self._set_paths(videoPath, exercisePath, translationPath)
        self._reload(True)
        self.set_can_save(True)
        self._activate_sequence()
        self.goto_sequence_begin(True)
        if self.exercise.get_repeat_count_limit_by_sequence() == 0:
            #Auto start play only if repeat is not limited
            self.play()

    def update_properties(self):
        self.exercise.initialize()
        self._reload(True)
        self.set_can_save(True)
        self._activate_sequence()
        self.goto_sequence_begin(True)
        if self.exercise.get_repeat_count_limit_by_sequence() == 0:
            #Auto start play only if repeat is not limited
            self.play()

    #get paths of current exercise
    def get_paths(self):
        return (self.exercise.get_video_path(),
                self.exercise.get_exercise_path(),
                self.exercise.get_translation_path())

    #Udpates vocabulary list in interface
    def _update_word_list(self):
        self.gui_controller.set_word_list(self.exercise.extract_word_list())

    #Notify the user use the repeat command (for stats)
    def user_repeat(self):
        self.exercise.increment_repeat_count()
        self.set_can_save(True)

    #Signal to the gui that the exercise has unsaved changes
    def set_can_save(self, save):
        self.gui_controller.set_can_save(save)

        if self.exercise == None:
            title = ""
        elif self.exercise.get_name() != None:
            title = self.exercise.get_name()
        elif self.exercise.get_output_save_path() != None:
            title = self.exercise.get_output_save_path()
        else:
            title = _("Untitled exercise")

        self.last_save = save
        self.gui_controller.set_title(title, save)

    def get_can_save(self):
        return self.last_save

    def get_exercise(self):
        return self.exercise

    def get_player(self):
        return self.player

    def media_change_call_back(self):
        self.logger.info("new media : " + self.exercise.get_video_path())
        """self.Pause()
        self.player.open(self.exercise.get_video_path())
        """
        self._reload(True)
        self._activate_sequence()
        self.goto_sequence_begin(True)
        if self.exercise.get_repeat_count_limit_by_sequence() == 0:
            #Auto start play only if repeat is not limited
            self.play()

    def export_as_template(self):
        self.gui_controller.ask_properties_advanced()
        path = self.gui_controller.ask_export_as_template_path()
        if path:
            self.exercise.set_template(True)
            save_exercise(self.exercise, path)
            self.exercise.set_template(False)

    def export_as_package(self):
        self.gui_controller.ask_properties_advanced()
        path = self.gui_controller.ask_export_as_package_path()
        if path:
            repoManager = ExerciseRepositoryManager()
            repoManager.export_as_package(self.exercise, path)
            self.logger.info("Export done")
        else:
            self.logger.warn("No valid path to export??")

    def import_package(self):
        import_path = self.gui_controller.ask_import_package()

        if import_path is not None:
            repo_manager = ExerciseRepositoryManager()
            error = repo_manager.import_package(import_path)
            if error is None:
                self.gui_controller.display_message(
                    _("Import finish succesfully. Use the exercises manager to use the newly installed exercise."
                      ))
            else:
                self.gui_controller.display_message(
                    _("Import failed." + " " + error))
 def add_guitar(self, guitar: dict):
     """ Adds a new instrument """
     guitar_step = ExerciseStep(guitar["type"])
     guitar_exercise = Exercise("Guitar", "Pick the following guitar",
                                [guitar_step])
     self._exercises.insert(0, guitar_exercise)
Beispiel #11
0
def test_db():
    """ Wipes the database and initializes it with some dummy data """
    db = mongoengine.connect(config.db_name)
    db.drop_database(config.db_name)

    # Dummy users
    User.new_user(email="dummy@{}".format(config.email_domain),
                  username="******", password="******", editor=False).save()

    # Other dummmy users
    for i in xrange(8):
        User.new_user(email="dummy{}@{}".format(i + 1, config.email_domain),
                      username="******".format(i+1), password="******", editor=False).save()

    # Editor user
    editor = User.new_user(email="editor@{}".format(config.email_domain),
              username="******", password="******", editor=True).save()

    # Other editor users
    for i in xrange(8):
        User.new_user(email="editor{}@{}".format(i + 1, config.email_domain),
                      username="******".format(i+1), password="******", editor=True).save()


    # Dummy exercises
    for i in xrange(8):
        test1 = Test(input='1\n', output='1').save()
        test2 = Test(input='2\n', output='2').save()
        test3 = Test(input='2\n', output='2').save()

        exercise = Exercise(author=editor, title="Dummy exercise {}".format(i),
                            description="## This is an exercise\n\n" +
                                        "* You get a single number as an input\n" +
                                        "* Simply return that number as an output\n",
                            boilerplate_code=config.default_boilerplate_code, reference_code=config.default_boilerplate_code, tags=['sort','trees'])

        exercise.tests = [test1, test2, test3]
        exercise.published = True
        exercise.save()

    # "Doable" exercise
    exercise = Exercise(author=editor, title="Return n²",
                    description="### Return the given number to the 2 !\n\n" +
                                "* You get a\n" +
                                "* Print a²\n" +
                                "![Alt text](/static/img/cat.jpeg)",
                    boilerplate_code=config.default_boilerplate_code,
                    reference_code=config.default_boilerplate_code,
                    tags=['algorithms'])
    test1 = Test(input='1\n', output='1').save()
    test2 = Test(input='2\n', output='4').save()
    test3 = Test(input='-2\n', output='4').save()
    exercise.tests = [test1, test2, test3]
    exercise.published = True
    exercise.save()

    # Palindrome exercise
    reference_code = """
#include <iostream>
#include <stack>
#include <sstream>
using namespace std;

struct node {
    node* next;
    int data;
    explicit node(int data):node(nullptr,data){}
    node(node* head,int data):next(head),data(data){}
};

node* insert(node* head,int data){
    return new node(head,data);
}

bool is_palindrome(node* head){
    auto temp = head;
    std::stack<node*> s;
    while(nullptr != temp){
        s.push(temp);
        temp = temp->next;
    }
    while(!s.empty()){
        if(head->data != s.top()->data){
            return false;
        }
        s.pop();
        head = head->next;
    }
    return true;
}

int main() {
    string line;
    while(getline(cin,line)){
        istringstream iss(line);
        int value;
        if(iss >> value){
            auto l = insert(nullptr,value);
            while(iss >> value){
                l = insert(l,value);
            }
            cout << is_palindrome(l) << endl;
        }
    }
    return 0;
}
    """

    boilerplate_code = """
#include <iostream>
#include <stack>
#include <sstream>
using namespace std;

struct node {
    node* next;
    int data;
    explicit node(int data):node(nullptr,data){}
    node(node* head,int data):next(head),data(data){}
};

node* insert(node* head,int data){
    return new node(head,data);
}

bool is_palindrome(node* head){
    // Your code here
}

int main() {
    string line;
    while(getline(cin,line)){
        istringstream iss(line);
        int value;
        if(iss >> value){
            auto l = insert(nullptr,value);
            while(iss >> value){
                l = insert(l,value);
            }
            cout << is_palindrome(l) << endl;
        }
    }
    return 0;
}
    """

    exercise = Exercise(author=editor, title="Palindrome",
                description="### Trouver les palindromes !\n\n" +
                            "* Chaque ligne de l'entrée standard comprend des entiers séparés par des espaces.\n" +
                            "* Il faut transformer chaque ligne en une **liste chaînée** et déterminer si c'est un palindrome.\n" +
                            "* A chaque ligne de l'entrée standard doit correspondre une ligne de la sortie standard avec un 1 dans le cas d'un palindrome et un 0 sinon.\n" +
                            "![Alt text](http://onapo.files.wordpress.com/2009/04/palyndrome1.gif)\n\n" +
                            "**Exemples**\n\n" +
                            "Entrée :\n\n" +
                            "    1 2 3 3 2 1\n" +
                            "Sortie attendue :\n\n" +
                            "    1\n\n" +
                            "Entrée :\n\n" +
                            "    1 2 3 4 2 1\n" +
                            "    1 2 3 2 1\n\n" +
                            "Sortie attendue :\n\n" +
                            "    0\n" +
                            "    1\n\n",
                boilerplate_code=boilerplate_code,
                reference_code=reference_code,
                tags=['algorithms', 'strings', 'data-structures'],
                score=42)

    test1 = Test(input='1 2 3 3 2 1', output='1\n').save()
    test2 = Test(input='1 2 3 4 2 1\n1 2 3 2 1', output='0\n1\n').save()
    test3 = Test(input=(('1 2 3 2 1' * 10000 + '\n') * 15)[:-1], output='1\n' * 15).save()
    exercise.tests = [test1, test2, test3]
    exercise.published = True
    exercise.save()

    # Palindrome exercise with std
    reference_code = """
#include <iostream>
#include <stack>
#include <sstream>
using namespace std;

struct node {
    node* next;
    int data;
    explicit node(int data):node(nullptr,data){}
    node(node* head,int data):next(head),data(data){}
};

node* insert(node* head,int data){
    return new node(head,data);
}

bool is_palindrome(node* head){
    auto temp = head;
    std::stack<node*> s;
    while(nullptr != temp){
        s.push(temp);
        temp = temp->next;
    }
    while(!s.empty()){
        if(head->data != s.top()->data){
            return false;
        }
        s.pop();
        head = head->next;
    }
    return true;
}

int main() {
    string line;
    while(getline(cin,line)){
        istringstream iss(line);
        int value;
        if(iss >> value){
            auto l = insert(nullptr,value);
            while(iss >> value){
                l = insert(l,value);
            }
            cout << is_palindrome(l) << endl;
        }
    }
    return 0;
}
    """

    boilerplate_code = """
#include <iostream>
#include <sstream>

using namespace std;

int main() {
	string line;
	while(getline(cin,line)){
		istringstream iss(line);
		int value;
		if(iss >> value){

            /* Your code here */

			while(iss >> value){
                /* Your code here */
			}

			cout << /* Your code here */ endl;
		}
	}
	return 0;
}
    """

    exercise = Exercise(author=editor, title="Palindrome - Le retour",
                description="### Trouver les palindromes !\n\n" +
                            "* Chaque ligne de l'entrée standard comprend des entiers séparés par des espaces.\n" +
                            "* Il s'agit de déterminer si chaque liste d'entiers est un palindrome ou non.\n" +
                            "* A chaque ligne de l'entrée standard doit correspondre une ligne de la sortie standard avec un 1 dans le cas d'un palindrome et un 0 sinon.\n" +
                            "![Alt text](http://onapo.files.wordpress.com/2009/04/palyndrome1.gif)\n\n" +
                            "**Exemples**\n\n" +
                            "Entrée :\n\n" +
                            "    1 2 3 3 2 1\n" +
                            "Sortie attendue :\n\n" +
                            "    1\n\n" +
                            "Entrée :\n\n" +
                            "    1 2 3 4 2 1\n" +
                            "    1 2 3 2 1\n\n" +
                            "Sortie attendue :\n\n" +
                            "    0\n" +
                            "    1\n\n",
                boilerplate_code=boilerplate_code,
                reference_code=reference_code,
                tags=['algorithms', 'strings', 'data-structures'],
                score=42)

    test1 = Test(input='1 2 3 3 2 1', output='1\n').save()
    test2 = Test(input='1 2 3 4 2 1\n1 2 3 2 1', output='0\n1\n').save()
    test3 = Test(input=(('1 2 3 2 1' * 100000 + '\n') * 15)[:-1], output='1\n' * 15).save()
    exercise.tests = [test1, test2, test3]
    exercise.published = True
    exercise.save()

    return exercise



    return exercise
Beispiel #12
0
def get_occurences():
    occurrences = []
    tags = list(set(t for e in Exercise.objects(published=True) for t in e.tags))
    for t in tags :
        occurrences.append(str(len(Exercise.objects(tags=t,published=True))))
    return jsonify(ok=True, tags=tags, occurrences=occurrences)
Beispiel #13
0
class Core(object):
    WAIT_BEGIN = 0
    WAIT_END = 1

    def __init__(self):
        self.player = None
        self.last_save = False
        self.exercise = None
        self.config = config
        self.logger = logging.Logger("Core")
        self.logger.setLevel(defaultLoggingLevel)
        self.logger.addHandler(defaultLoggingHandler)

    #Call by the main, give an handler to the main gui
    def set_gui(self, gui):
        self.gui_controller = gui

    #Create a new exercice based on paths. load the new exercise and
    #begin to play
    def new_exercise(self, videoPath, exercisePath, translationPath, langId):
        self.exercise = Exercise()
        self.exercise.set_media_change_callback(self.media_change_call_back)
        self.exercise.new()
        self.exercise.set_language_id(langId)
        self._set_paths(videoPath, exercisePath, translationPath) # This initialize the exercise
        self._reload(True);
        self._activate_sequence()
        self.gui_controller.set_title("", True)

    #Configure the paths for the current exercice. Reload subtitles list.
    def _set_paths(self, videoPath, exercisePath, translationPath):
        self.exercise.set_video_path(videoPath)
        self.exercise.set_exercise_path(exercisePath)
        self.exercise.set_translation_path(translationPath)
        self.exercise.initialize()

    #Reload media player and begin to play (if the params is True)
    def _reload(self, load):
        if self.player != None:
            self.player.close()

        self.player = VideoPlayer()
        self.player.set_window_id(self.gui_controller.get_video_window_id())
        self.player.activate_video_callback(self.gui_controller.activate_video_area)
        self.player.open(self.exercise.get_video_path())
        self.player.set_callback(self._time_callback)
        self.paused = False
        self.gui_controller.activate_video_area(False)
        self.gui_controller.activate("loaded")
        self._update_word_list()
        self.timeUpdateThreadId = thread.start_new_thread(self.time_update_thread, ())

        if load and self.exercise.get_repeat_count_limit_by_sequence() == 0:
            #Auto start play only if repeat is not limited
            self.play()
        else:
            self.pause()

    #play the media
    def play(self):
        self.gui_controller.set_playing(True)
        self.player.play()
        self.paused = False

    #pause the media
    def pause(self):
        self.gui_controller.set_playing(False)
        self.player.pause()
        self.paused = True

    #Modify media speed
    def set_speed(self, speed):
        self.gui_controller.set_speed(speed)
        self.player.set_speed(speed)

    #Callback call by video player to notify change of media position.
    #Stop the media at the end of uncompleted sequences
    def _time_callback(self):
        if self.state == Core.WAIT_BEGIN:
            self.player.set_next_callback_time(self.exercise.get_current_sequence().get_time_end() + self.exercise.get_play_margin_after())
            self.state = Core.WAIT_END
        elif self.state == Core.WAIT_END:
            self.state = Core.WAIT_BEGIN
            if self.exercise.get_current_sequence().is_valid():
                gtk.gdk.threads_enter()
                self.next_sequence(False)
                gtk.gdk.threads_leave()
            else:
                self.pause()

    #Repeat the currence sequence
    def repeat_sequence(self):
        if not self.exercise.is_current_sequence_repeat_limit_reach():
            #Repeat limit not reach or no limit
            self.goto_sequence_begin()
            self.play()
            self.exercise.increment_current_sequence_repeat_count()


    #Change the active sequence
    def select_sequence(self, num, load=True):
        if self.exercise.get_current_sequence_id() == num:
            return
        self.exercise.goto_sequence(num)
        self._activate_sequence()
        if load and self.exercise.get_repeat_count_limit_by_sequence() == 0:
            #Auto start play only if repeat is not limited
            self.repeat_sequence()
        self.set_can_save(True)

    #Goto next sequence
    def next_sequence(self, load=True):
        if self.exercise.goto_next_sequence():
            self.set_can_save(True)
        self._activate_sequence()
        if load and self.exercise.get_repeat_count_limit_by_sequence() == 0:
            #Auto start play only if repeat is not limited
            self.repeat_sequence()

    #Goto previous sequence
    def previous_sequence(self, load=True):
        if self.exercise.goto_previous_sequence():
            self.set_can_save(True)
        self._activate_sequence()
        if load and self.exercise.get_repeat_count_limit_by_sequence() == 0:
            #Auto start play only if repeat is not limited
            self.repeat_sequence()

    #Goto next valid sequence
    def next_valid_sequence(self, load=True):
        if self.exercise.goto_next_valid_sequence():
            self.set_can_save(True)
        self._activate_sequence()
        if load and self.exercise.get_repeat_count_limit_by_sequence() == 0:
            #Auto start play only if repeat is not limited
            self.repeat_sequence()

    #Goto previous valid sequence
    def previous_valid_sequence(self, load=True):
        if self.exercise.goto_previous_valid_sequence():
            self.set_can_save(True)
        self._activate_sequence()
        if load and self.exercise.get_repeat_count_limit_by_sequence() == 0:
            #Auto start play only if repeat is not limited
            self.repeat_sequence()

    #Update interface with new sequence. Configure stop media callback
    def _activate_sequence(self):
        self.state = Core.WAIT_BEGIN
        self.set_speed(1)
        self.player.set_next_callback_time(self.exercise.get_current_sequence().get_time_begin() - self.exercise.get_play_margin_before())

        self.gui_controller.set_sequence_number(self.exercise.get_current_sequence_id(), self.exercise.get_sequence_count())
        self.gui_controller.set_sequence(self.exercise.get_current_sequence())
        self.__activate_translation()
        self.__activate_previous_sequence_text()
        self._update_stats()

    #_update displayed translation on new active sequence
    def __activate_translation(self):
        if not self.exercise.get_translation_list():
            self.gui_controller.set_translation("")
        else:
            translation = ""
            currentBegin = self.exercise.get_current_sequence().get_time_begin()
            currentEnd = self.exercise.get_current_sequence().get_time_end()
            for sub in self.exercise.get_translation_list():
                begin = sub.get_time_begin()
                end = sub.get_time_end()
                if (begin >= currentBegin and begin <= currentEnd) or (end >= currentBegin and end <= currentEnd) or (begin <= currentBegin and end >= currentEnd):
                    translation += sub.get_text() + " "

            self.gui_controller.set_translation(translation)

    #_update displayed previous sentence text
    def __activate_previous_sequence_text(self):
        previous_sequence_text = "";
        previous_sequence = self.exercise.get_previous_sequence()
        if previous_sequence:
            for i, symbol in enumerate(previous_sequence.get_symbols()):
                previous_sequence_text += symbol
                if i < len(previous_sequence.get_words()):
                    word = previous_sequence.get_words()[i]
                    if word.is_valid():
                        previous_sequence_text += word.get_valid(lower=False)
                    else:
                        word_text = word.get_text()
                        if len(word_text):
                            previous_sequence_text += word.get_text()
                        else:
                            previous_sequence_text += "_"

        self.gui_controller.set_previous_sequence_text(previous_sequence_text)

    #Update displayed stats on new active sequence
    def _update_stats(self):
        sequenceCount = self.exercise.get_sequence_count()
        sequenceFound = 0
        wordCount = 0
        wordFound = 0
        for sequence in self.exercise.get_sequence_list():
            wordCount = wordCount + sequence.get_word_count()
            if sequence.is_valid():
                sequenceFound += 1
                wordFound += sequence.get_word_count()
            else:
                wordFound += sequence.get_word_found()
        if wordFound == 0:
            repeatRate = float(0)
        else:
            repeatRate = float(self.exercise.get_repeat_count()) / float(wordFound)
        self.gui_controller.set_statitics(sequenceCount, sequenceFound, wordCount, wordFound, repeatRate)

    def _update(self):
        self.gui_controller.set_sequence(self.exercise.get_current_sequence())
        self.__validate_sequence()

    #Verify if the sequence is complete
    def __validate_sequence(self):
        if self.exercise.get_current_sequence().is_valid():
            if self.exercise.get_repeat_after_completed():
                if self.exercise.get_repeat_count_limit_by_sequence() == 0:
                    #Auto start play only if repeat is not limited
                    self.repeat_sequence()
            else:
                self.next_sequence(load=False)
                if self.exercise.get_repeat_count_limit_by_sequence() == 0:
                    #Auto start play only if repeat is not limited
                    if self.player.get_seek() > (self.exercise.get_current_sequence().get_time_begin() - self.exercise.get_play_margin_before()):
                        self.goto_sequence_begin()
                        self.play()
                    else:
                        self.play()


    #Goto beginning of the current sequence. Can start to play as soon
    #as the media player is ready
    def goto_sequence_begin(self, asSoonAsReady=False):
        self.state = Core.WAIT_END
        begin_time = self.exercise.get_current_sequence().get_time_begin() - self.exercise.get_play_margin_before()
        if begin_time < 0:
            begin_time = 0
        if asSoonAsReady:
            self.player.seek_as_soon_as_ready(begin_time)
        else:
            self.player.seek(begin_time)
        self.player.set_next_callback_time(self.exercise.get_current_sequence().get_time_end() + self.exercise.get_play_margin_after())


    #Write a char in current sequence at cursor position
    def write_char(self, char):
        if self.exercise.is_character_match(char):
            self.exercise.get_current_sequence().write_char(char)
            self.exercise.get_current_sequence().update_cursor_position()
            self._update()
            self.set_can_save(True)
        else:
            self._update()

    #Goto next word in current sequence
    def next_word(self):
        self.exercise.get_current_sequence().next_word()
        self._update()

    #Goto previous word in current sequence
    def previous_word(self):
        self.exercise.get_current_sequence().previous_word()
        self._update()

    #Choose current word in current sequence
    def select_sequence_word(self, wordIndex, wordIndexPos):
        try:
            self.exercise.get_current_sequence().select_sequence_word(wordIndex, wordIndexPos)
        except NoCharPossible:
            self.exercise.get_current_sequence().select_sequence_word(wordIndex, -1)
        self._update()

    #Goto first word in current sequence
    def first_word(self):
        self.exercise.get_current_sequence().first_word()
        self._update()

    #Goto last word in current sequence
    def last_word(self):
        self.exercise.get_current_sequence().last_word()
        self._update()

    #Delete a char before the cursor in current sequence
    def delete_previous_char(self):
        self.exercise.get_current_sequence().delete_previous_char()
        self._update()
        self.set_can_save(True)

    #Delete a char after the cursor in current sequence
    def delete_next_char(self):
        self.exercise.get_current_sequence().delete_next_char()
        self._update()
        self.set_can_save(True)

    #Goto previous char in current sequence
    def previous_char(self):
        self.exercise.get_current_sequence().previous_char()
        #The sequence don't change but the cursor position is no more up to date
        self._update()

    #Goto next char in current sequence
    def next_char(self):
        self.exercise.get_current_sequence().next_char()
        #The sequence don't change but the cursor position is no more up to date
        self._update()

    #Reveal correction for word at cursor in current sequence
    def complete_word(self):
        self.exercise.get_current_sequence().show_hint()
        self._update()
        self.set_can_save(True)
    
    #Reveal correction for word at cursor in current sequence
    def reveal_word(self):
        self.exercise.get_current_sequence().complete_word()
        self.exercise.get_current_sequence().next_word()
        self._update()
        self.set_can_save(True)

    #Reveal correction for word at cursor in current sequence
    def reveal_sequence(self):
        self.exercise.get_current_sequence().complete_all()
        self._update()
        self.set_can_save(True)

    #reset whole exercise
    def reset_exercise_content(self):
        self.exercise.reset()
        self.exercise.goto_sequence(0) #FIXME
        self._update()
        self.set_can_save(True)
        self.logger.debug("need to stop the current sequence") #FIXME

    #pause or play media
    def toggle_pause(self):
        if self.player.is_paused() and self.paused:
            self.play()
        elif not self.player.is_paused() and not self.paused:
            self.pause()

    #Change position in media and play it
    def seek_sequence(self, time):
        begin_time = self.exercise.get_current_sequence().get_time_begin() - self.exercise.get_play_margin_before()
        if begin_time < 0:
            begin_time = 0

        pos = begin_time + time
        self.player.seek(pos)
        self.player.set_next_callback_time(self.exercise.get_current_sequence().get_time_end() + self.exercise.get_play_margin_after())
        self.state = Core.WAIT_END
        if self.exercise.get_repeat_count_limit_by_sequence() == 0:
            #Auto start play only if repeat is not limited
            self.play()

    #Thread to update slider position in gui
    def time_update_thread(self):
        timeUpdateThreadId = self.timeUpdateThreadId
        while timeUpdateThreadId == self.timeUpdateThreadId:
            time.sleep(0.5)
            pos_int = self.player.get_current_time()
            if pos_int != None:
                end_time = self.exercise.get_current_sequence().get_time_end()
                begin_time = self.exercise.get_current_sequence().get_time_begin() - self.exercise.get_play_margin_before()
                if begin_time < 0:
                    begin_time = 0
                duration = end_time - begin_time
                pos = pos_int - begin_time
                self.gui_controller.set_sequence_time(pos, duration)

    #Save current exercice
    def save(self, saveAs=False):
        if not self.exercise:
            self.logger.error("Save called but no exercise load")
            return

        if saveAs or self.exercise.get_output_save_path() == None:
            outputSavePath = self.gui_controller.ask_save_path()
            if not outputSavePath:
                return
            self.exercise.set_output_save_path(outputSavePath + ".perroquet")

        save_exercise(self.exercise, self.exercise.get_output_save_path())

        self.config.set("lastopenfile", self.exercise.get_output_save_path())

        #lastopenfileS
        l = self.config.get("lastopenfiles")
        path = self.exercise.get_output_save_path()
        name = self.exercise.get_name() or path
        self.config.set("lastopenfiles", [[path, name]] + [p for p in l if p[0] != path][:10])

        self.set_can_save(False)

    #load the exercice at path
    def load_exercise(self, path):
        self.gui_controller.activate("closed")
        if self.exercise:
            self.save()
        try:
            self.exercise = load_exercise(path)
            self.exercise.set_media_change_callback(self.media_change_call_back)
        except IOError:
            self.logger.exception("No file at " + path)
            return
        if not self.exercise:
            return


        validPaths, errorList = self.exercise.is_paths_valid()
        if not validPaths:
            for error in errorList:
                self.gui_controller.signal_exercise_bad_path(error)

            self.set_can_save(False)
            self.gui_controller.activate("load_failed")
            self.gui_controller.ask_properties()
            return

        self._reload(False)
        if self.exercise.get_output_save_path() == None:
            self.set_can_save(True)
        else:
            self.set_can_save(False)
        self._activate_sequence()
        self.goto_sequence_begin(True)
        if self.exercise.get_repeat_count_limit_by_sequence() == 0:
            #Auto start play only if repeat is not limited
            self.play()

    #Change paths of current exercice and reload subtitles and video
    def _update_paths(self, videoPath, exercisePath, translationPath):
        self.exercise.set_video_path(videoPath)
        self.exercise.set_exercise_path(exercisePath)
        self.exercise.set_translation_path(translationPath)

        validPaths, errorList = self.exercise.is_paths_valid()
        if not validPaths:
            for error in errorList:
                self.gui_controller.signal_exercise_bad_path(error)
            self.gui_controller.activate("load_failed")
            self.set_can_save(False)
            return

        self._set_paths(videoPath, exercisePath, translationPath)
        self._reload(True)
        self.set_can_save(True)
        self._activate_sequence()
        self.goto_sequence_begin(True)
        if self.exercise.get_repeat_count_limit_by_sequence() == 0:
            #Auto start play only if repeat is not limited
            self.play()

    def update_properties(self):
        self.exercise.initialize()
        self._reload(True)
        self.set_can_save(True)
        self._activate_sequence()
        self.goto_sequence_begin(True)
        if self.exercise.get_repeat_count_limit_by_sequence() == 0:
            #Auto start play only if repeat is not limited
            self.play()

    #get paths of current exercise
    def get_paths(self):
        return (self.exercise.get_video_path(), self.exercise.get_exercise_path(), self.exercise.get_translation_path())

    #Udpates vocabulary list in interface
    def _update_word_list(self):
        self.gui_controller.set_word_list(self.exercise.extract_word_list())

    #Notify the user use the repeat command (for stats)
    def user_repeat(self):
        self.exercise.increment_repeat_count()
        self.set_can_save(True)

    #Signal to the gui that the exercise has unsaved changes
    def set_can_save(self, save):
        self.gui_controller.set_can_save(save)

        if self.exercise == None:
            title = ""
        elif self.exercise.get_name() != None:
            title = self.exercise.get_name()
        elif self.exercise.get_output_save_path() != None:
            title = self.exercise.get_output_save_path()
        else:
            title = _("Untitled exercise")

        self.last_save = save
        self.gui_controller.set_title(title, save)

    def get_can_save(self):
        return self.last_save

    def get_exercise(self):
        return self.exercise

    def get_player(self):
        return self.player

    def media_change_call_back(self):
        self.logger.info("new media : " + self.exercise.get_video_path())
        """self.Pause()
        self.player.open(self.exercise.get_video_path())
        """
        self._reload(True)
        self._activate_sequence()
        self.goto_sequence_begin(True)
        if self.exercise.get_repeat_count_limit_by_sequence() == 0:
            #Auto start play only if repeat is not limited
            self.play()

    def export_as_template(self):
        self.gui_controller.ask_properties_advanced()
        path = self.gui_controller.ask_export_as_template_path()
        if path:
            self.exercise.set_template(True)
            save_exercise(self.exercise, path)
            self.exercise.set_template(False)

    def export_as_package(self):
        self.gui_controller.ask_properties_advanced()
        path = self.gui_controller.ask_export_as_package_path()
        if path:
            repoManager = ExerciseRepositoryManager()
            repoManager.export_as_package(self.exercise, path)
            self.logger.info("Export done")
        else:
            self.logger.warn("No valid path to export??")


    def import_package(self):
        import_path = self.gui_controller.ask_import_package()

        if import_path is not None:
            repo_manager = ExerciseRepositoryManager()
            error = repo_manager.import_package(import_path)
            if error is None:
                self.gui_controller.display_message(_("Import finish succesfully. Use the exercises manager to use the newly installed exercise."))
            else:
                self.gui_controller.display_message(_("Import failed." + " " + error))