Ejemplo n.º 1
0
class UserWord(db.Model, util.JSONSerializable):
    __tablename__ = 'user_words'
    __table_args__ = {'mysql_collate': 'utf8_bin'}

    id = db.Column(db.Integer, primary_key=True)
    word = db.Column(db.String(255), nullable=False, unique=True)
    language_id = db.Column(db.String(2), db.ForeignKey("language.id"))
    language = db.relationship("Language")
    rank_id = db.Column(db.Integer,
                        db.ForeignKey("word_ranks.id"),
                        nullable=True)
    rank = db.relationship("WordRank")
    db.UniqueConstraint(word, language_id)

    IMPORTANCE_LEVEL_STEP = 1000
    IMPOSSIBLE_RANK = 1000000
    IMPOSSIBLE_IMPORTANCE_LEVEL = IMPOSSIBLE_RANK / IMPORTANCE_LEVEL_STEP

    def __init__(self, word, language, rank=None):
        self.word = word
        self.language = language
        self.rank = rank

    def __repr__(self):
        return '<UserWord %r>' % (self.word)

    def serialize(self):
        return self.word

    # returns a number between
    def importance_level(self):
        if self.rank is not None:
            return max((10 - self.rank.rank / UserWord.IMPORTANCE_LEVEL_STEP),
                       0)
        else:
            return 0

    # we use this in the bookmarks.html to show the rank.
    # for words in which there is no rank info, we don't display anything
    def importance_level_string(self):
        if self.rank == None:
            return ""
        b = "|"
        return b * self.importance_level()

    @classmethod
    def find(cls, word, language, rank=None):
        try:
            return (cls.query.filter(cls.word == word).filter(
                cls.language == language).one())
        except sqlalchemy.orm.exc.NoResultFound:
            return cls(word, language, rank)

    @classmethod
    def find_rank(cls, word, language):
        return WordRank.find(word, language)

    @classmethod
    def find_all(cls):
        return cls.query.all()
Ejemplo n.º 2
0
class RankedWord(db.Model, util.JSONSerializable):
    __tablename__ = 'ranked_word'
    __table_args__ = {'mysql_collate': 'utf8_bin'}

    id = db.Column(db.Integer, primary_key=True)
    word = db.Column(db.String(255), nullable=False, unique=True, index=True)

    language_id = db.Column(db.String(2), db.ForeignKey("language.id"))
    language = db.relationship("Language")
    rank = db.Column(db.Integer)
    db.UniqueConstraint(word, language_id)

    def __init__(self, word, language, rank):
        self.word = word
        self.language = language
        self.rank = rank

    @classmethod
    def find(cls, word, language):
        word = word.lower()
        try:
            return (cls.query.filter(cls.word == word).filter(
                cls.language == language).one())
        except sqlalchemy.orm.exc.NoResultFound:
            return None

    @classmethod
    def find_all(cls, language):
        return cls.query.filter(cls.language == language).all()

    @classmethod
    def exists(cls, word, language):
        word = word.lower()
        try:
            (cls.query.filter(cls.word == word).filter(
                cls.language == language).one())
            return True
        except sqlalchemy.orm.exc.NoResultFound:
            return False

    @classmethod
    def words_list(cls):
        words_list = []
        for word in cls.find_all():
            words_list.append(word.word)
        return words_list
Ejemplo n.º 3
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
Ejemplo n.º 4
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')