def new_question(self, L, H):
        """
        Return values:
        OK: new question created, all ok
        ERR_NO_INTERVALLS: no new question because no intervals are selected
        ERR_PICKY: you have to solve this question before you are allowed to create new
        """
        if self.m_timeout_handle:
            gobject.source_remove(self.m_timeout_handle)
            self.m_timeout_handle = None

        if solfege.app.m_test_mode:
            old_tonika = self.m_tonika
            if old_tonika:
                old_toptone = old_tonika + self.m_interval
            self.m_P.next_test_question()
            self.m_interval = self.m_P.m_test_questions[self.m_P.m_test_idx]
            # FIXME use tone pitch range from preferences window.
            self.m_tonika = mpd.MusicalPitch()
            # Do this loop to make sure two questions in a row does not have
            # the same top or bottom tone.
            while True:
                self.m_tonika.randomize("f", "f'")
                if not old_tonika:
                    break
                if old_tonika != self.m_tonika and self.m_tonika + self.m_interval != old_toptone:
                    break
            self.q_status = self.QSTATUS_NEW
            return self.OK

        if self.get_bool("config/picky_on_new_question") and self.q_status in [self.QSTATUS_NEW, self.QSTATUS_WRONG]:
            return Teacher.ERR_PICKY

        if self.get_list("intervals") == []:
            self.q_status = self.QSTATUS_NO
            return Teacher.ERR_NO_INTERVALLS
        last_question = self.m_interval
        last_tonika = self.m_tonika
        L, H = utils.adjust_low_high_to_irange(L, H, self.get_list("intervals"))
        while 1:
            # in this loop we will try to make a question that is not the
            # same that the last one.
            self.m_tonika, self.m_interval = utils.random_tonika_and_interval(L, H, self.get_list("intervals"))
            if last_question is None:
                break
            if (self.m_interval == last_question and self.m_tonika == last_tonika) and (
                len(self.get_list("intervals")) > 1 or (H - L) > 1
            ):
                continue
            break
        assert self.m_tonika
        self.q_status = self.QSTATUS_NEW
        return Teacher.OK
Beispiel #2
0
    def new_question(self, L, H):
        assert isinstance(L, basestring)
        assert isinstance(H, basestring)
        if self.get_list('ask_for_intervals_0') == []:
            return self.ERR_CONFIGURE
        L, H = utils.adjust_low_high_to_irange(L, H,
                     self.get_list('ask_for_intervals_0'))

        if self.m_timeout_handle:
            gobject.source_remove(self.m_timeout_handle)
            self.m_timeout_handle = None

        if solfege.app.m_test_mode:
            old_tonika = self.m_tonika
            if old_tonika:
                old_toptone = old_tonika + self.m_question[0]
            self.m_P.next_test_question()
            self.m_question = [self.m_P.m_test_questions[self.m_P.m_test_idx]]
            #FIXME use tone pitch range from preferences window.
            self.m_tonika = mpd.MusicalPitch()
            # Do this loop to make sure two questions in a row does not have
            # the same top or bottom tone.
            while True:
                self.m_tonika.randomize("f", "f'")
                if not old_tonika:
                    break
                if old_tonika != self.m_tonika and self.m_tonika + self.m_question[0] != old_toptone:
                    break
            self.q_status = self.QSTATUS_NEW
            return self.OK

        if self.get_bool('config/picky_on_new_question') \
              and self.q_status in [self.QSTATUS_NEW, self.QSTATUS_WRONG]:
            return self.ERR_PICKY

        self.q_status = self.QSTATUS_NO
        last_tonika = self.m_tonika
        last_question = self.m_question
        for x in range(10):# we try max 10 times to get a question that
                           # is different from the last one.
            self.m_tonika, i = utils.random_tonika_and_interval(L, H,
                            self.get_list('ask_for_intervals_0'))
            self.m_question = [i]
            t = self.m_tonika + i
            for x in range(1, self.get_int('number_of_intervals=1')):
                if not self.get_list('ask_for_intervals_%i' % x):
                    return self.ERR_CONFIGURE
                i = utils.random_interval(t, L, H,
                               self.get_list('ask_for_intervals_%i' % x))
                if not i:
                    # if we can't find an interval that is with the range
                    # we, find the interval that is closest to the range
                    # of notes the user want. This mean that the questions
                    # are not necessarily that random.
                    low = mpd.MusicalPitch.new_from_int(L)
                    high = mpd.MusicalPitch.new_from_int(H)
                    off = 1000
                    best = None
                    for interval in self.get_list('ask_for_intervals_%i'%x):
                        try:
                            if t + interval > high:
                                if t + interval - high < off:
                                    off = t + interval - high
                                    best = interval
                            if t + interval < low:
                                if low - (t + interval) < off:
                                    off = low - (t + interval)
                                    best = interval
                        except ValueError:
                            return self.ERR_CONFIGURE
                    i = best
                self.m_question.append(i)
                t = t + i
            if last_tonika is not None \
                    and last_tonika == self.m_tonika \
                    and last_question == self.m_question:
                continue
            break
        self.q_status = self.QSTATUS_NEW
        return self.OK