Esempio n. 1
0
class KnownWordProbability(db.Model):
    __table_args__ = {'mysql_collate': 'utf8_bin'}
    __tablename__ = 'known_word_probability'
    id = db.Column(db.Integer, primary_key=True)
    user_id = db.Column(db.Integer, db.ForeignKey("user.id"), nullable=False)
    user = db.relationship("User")
    user_word_id = db.Column(db.Integer,
                             db.ForeignKey('user_word.id'),
                             nullable=True)
    user_word = db.relationship("UserWord")
    ranked_word_id = db.Column(db.Integer,
                               db.ForeignKey("ranked_word.id"),
                               nullable=True)
    ranked_word = db.relationship("RankedWord")
    probability = db.Column(db.DECIMAL(10, 9), nullable=False)
    db.CheckConstraint('probability>=0', 'probability<=1')

    def __init__(self, user, user_word, ranked_word, probability):
        self.user = user
        self.user_word = user_word
        self.ranked_word = ranked_word
        self.probability = probability

    def word_has_just_beek_bookmarked(self):
        self.probability /= 2

    @classmethod
    def calculateKnownWordProb(cls, exerciseProb, encounterProb):
        return 0.8 * float(exerciseProb) + 0.2 * float(encounterProb)

    @classmethod
    def find(cls, user, user_word, ranked_word, probability=None):
        try:
            return cls.query.filter_by(user=user,
                                       user_word=user_word,
                                       ranked_word=ranked_word).one()
        except sqlalchemy.orm.exc.NoResultFound:
            return cls(user, user_word, ranked_word, probability)

    @classmethod
    def find_all_by_user(cls, user):
        return cls.query.filter_by(user=user).all()

    @classmethod
    def find_all_by_user_cached(cls, user):
        known_probabilities_cache = {}
        known_probabilities = cls.find_all_by_user(user)
        for known_probability in known_probabilities:
            user_word = known_probability.user_word
            # TODO: Why are there many KnownWordProbabilities with no user word in the database?
            if user_word is not None:
                known_probabilities_cache[
                    user_word.word] = known_probability.probability
        return known_probabilities_cache

    @classmethod
    def find_all_by_user_with_rank(cls, user):
        known_probs = cls.query.filter_by(user=user).all()
        for p in known_probs:
            if p.ranked_word is None:
                known_probs.remove(p)
        return known_probs

    @classmethod
    def exists(cls, user, user_word, ranked_word):
        try:
            cls.query.filter_by(user=user,
                                user_word=user_word,
                                ranked_word=ranked_word).one()
            return True
        except sqlalchemy.orm.exc.NoResultFound:
            return False

    @classmethod
    def get_probably_known_words(cls, user):
        return cls.query.filter(cls.user == user).filter(
            cls.probability >= 0.9).all()
Esempio n. 2
0
class EncounterBasedProbability(db.Model):
    __tablename__ = 'encounter_based_probability'
    __table_args__ = {'mysql_collate': 'utf8_bin'}

    DEFAULT_PROBABILITY = 0.5

    id = db.Column(db.Integer, primary_key=True)
    user_id = db.Column(db.Integer, db.ForeignKey("user.id"), nullable=False)
    user = db.relationship("User")
    ranked_word_id = db.Column(db.Integer,
                               db.ForeignKey("ranked_word.id"),
                               nullable=False)
    ranked_word = db.relationship("RankedWord")
    not_looked_up_counter = db.Column(db.Integer, nullable=False)
    probability = db.Column(db.DECIMAL(10, 9), nullable=False)
    db.UniqueConstraint(user_id, ranked_word_id)
    db.CheckConstraint('probability>=0', 'probability<=1')

    def __init__(self, user, ranked_word, not_looked_up_counter, probability):
        self.user = user
        self.ranked_word = ranked_word
        self.not_looked_up_counter = not_looked_up_counter
        self.probability = probability

    @classmethod
    def find(cls, user, ranked_word, default_probability=None):
        try:
            return cls.query.filter_by(user=user,
                                       ranked_word=ranked_word).one()
        except sqlalchemy.orm.exc.NoResultFound:
            return cls(user, ranked_word, 1, default_probability)

    @classmethod
    def find_all(cls):
        return cls.query.all()

    @classmethod
    def find_all_by_user(cls, user):
        return cls.query.filter_by(user=user).all()

    @classmethod
    def exists(cls, user, ranked_word):
        try:
            cls.query.filter_by(user=user, ranked_word=ranked_word).one()
            return True
        except sqlalchemy.orm.exc.NoResultFound:
            return False

    @classmethod
    def find_or_create(cls, word, user, language):
        ranked_word = RankedWord.find(word.lower(), language)
        if EncounterBasedProbability.exists(user, ranked_word):
            enc_prob = EncounterBasedProbability.find(user, ranked_word)
            enc_prob.not_looked_up_counter += 1
            enc_prob.boost_prob()
        else:
            enc_prob = EncounterBasedProbability.find(
                user, ranked_word,
                EncounterBasedProbability.DEFAULT_PROBABILITY)
        return enc_prob

    def reset_prob(self):
        # Why is this 0.5? Should be lower! I just looked up the word...
        # ugh...
        self.probability = 0.5

    def word_has_just_beek_bookmarked(self):
        """
            the user can't know this word very well if he's
            bookmarking it again
        :return:
        """

        self.probability /= 2

#         This function controls if prob is already 1.0, else it adds 0.1. It maximum adds 0.1, therefore cannot exceed 1

    def boost_prob(self):
        if float(self.probability) <> 1.0:
            self.probability = float(self.probability) + 0.1
Esempio n. 3
0
class ExerciseBasedProbability(db.Model):

    __tablename__ = 'exercise_based_probability'
    __table_args__ = {'mysql_collate': 'utf8_bin'}

    id = db.Column(db.Integer, primary_key=True)
    user_id = db.Column(db.Integer, db.ForeignKey("user.id"), nullable=False)
    user = db.relationship("User")
    user_word_id = db.Column(db.Integer,
                             db.ForeignKey('user_word.id'),
                             nullable=False)
    user_word = db.relationship("UserWord")
    probability = db.Column(db.DECIMAL(10, 9), nullable=False)
    db.UniqueConstraint(user_id, user_word_id)
    db.CheckConstraint('probability>=0', 'probability<=1')

    DEFAULT_MIN_PROBABILITY = 0.1
    DEFAULT_MAX_PROBABILITY = 1.0

    def __init__(self, user, user_word, probability):
        self.user = user
        self.user_word = user_word
        self.probability = probability

    @classmethod
    def find(cls, user, user_word):
        try:
            return cls.query.filter_by(user=user, user_word=user_word).one()
        except sqlalchemy.orm.exc.NoResultFound:
            return cls(user, user_word, 0.1)

    @classmethod
    def exists(cls, user, user_word):
        try:
            cls.query.filter_by(user=user, user_word=user_word).one()
            return True

        except sqlalchemy.orm.exc.NoResultFound:
            return False

    @classmethod
    def find_all(cls):
        return cls.query.all()

    def wrong_formula(self, count_wrong_after_another):
        if self.DEFAULT_MIN_PROBABILITY * count_wrong_after_another >= float(
                self.probability):
            self.probability = decimal.Decimal('0.1')
        else:
            self.probability = (
                float(self.probability) -
                self.DEFAULT_MIN_PROBABILITY * count_wrong_after_another)

    def correct_formula(self, count_correct_after_another):
        if float(
                self.probability
        ) + self.DEFAULT_MIN_PROBABILITY * count_correct_after_another >= 1.0:
            self.probability = decimal.Decimal('1.0')
        else:
            self.probability = (
                float(self.probability) +
                self.DEFAULT_MIN_PROBABILITY * count_correct_after_another)

    def update_probability_after_adding_bookmark_with_same_word(
            self, bookmark, user):
        count_bookmarks_with_same_word = len(
            Bookmark.find_all_by_user_and_word(user, bookmark.origin))
        self.probability = (
            float(self.probability * count_bookmarks_with_same_word) + 0.1) / (
                count_bookmarks_with_same_word + 1
            )  # compute avg probability of all bookmarks with same word

    #calculates the probability of knowing a certain bookmark after a exercise_outcome.
    def calculate_known_bookmark_probability(self, bookmark):
        count_correct_after_another = 0
        count_wrong_after_another = 0
        sorted_exercise_log_after_date = sorted(bookmark.exercise_log,
                                                key=lambda x: x.time,
                                                reverse=False)
        for exercise in sorted_exercise_log_after_date:
            if exercise.outcome.outcome == ExerciseOutcome.TOO_EASY:
                self.probability = decimal.Decimal('1.0')
                count_wrong_after_another = 0
            elif exercise.outcome.outcome == ExerciseOutcome.SHOW_SOLUTION:
                self.probability //= 2
                if float(self.probability) < 0.1:
                    self.probability = decimal.Decimal('0.1')
                count_correct_after_another = 0
            elif exercise.outcome.outcome == ExerciseOutcome.CORRECT:
                count_correct_after_another += 1
                count_wrong_after_another = 0
                if float(self.probability) < 1.0:
                    self.correct_formula(count_correct_after_another)
                else:
                    self.probability = decimal.Decimal('1.0')
            elif exercise.outcome.outcome == ExerciseOutcome.WRONG:
                count_wrong_after_another += 1
                count_correct_after_another = 0
                if float(self.probability) > 0.1:
                    self.wrong_formula(count_wrong_after_another)
                else:
                    self.probability = decimal.Decimal('0.1')

    def halfProbability(self):
        self.probability /= 2
        if float(self.probability) < 0.1:
            self.probability = decimal.Decimal('0.1')