コード例 #1
0
ファイル: handlers.py プロジェクト: peterbe/tornado_gkc
    def _get_question(self, force_refresh=False,
                      cache_for=settings.DEFAULT_WIDGET_CACHE_TIME):
        search = {'state': PUBLISHED}
        global _last_question
        if _last_question and not force_refresh:
            ts, question_id = _last_question
            if ts > time.time():
                print "Reusing same old question"
                question = (self.db.Question.collection
                             .one({'_id': question_id}))
                return dict_plus(question)

        #'_id':{'$nin': [x._id for x in battle.sent_questions]}
        count = self.db.Question.find(search).count()
        while True:
            skip = random.randint(0, count - 1)
            for question in (self.db.Question.collection
                             .find(search)
                             .skip(skip)
                             .limit(1)):
                if (self.db.QuestionImage
                    .one({'question.$id': question['_id']})):
                    if '_id' not in search:
                        search['_id'] = {'$nin': []}
                    search['_id']['$nin'].append(question['_id'])
                    continue
                question = dict_plus(question)
                #logging.info("New widget question: %r (%s)"%
                #             (question.text, question._id))
                _last_question = (time.time() + cache_for, question._id)
                return question
コード例 #2
0
ファイル: handlers.py プロジェクト: peterbe/tornado_gkc
    def _get_question(self,
                      force_refresh=False,
                      cache_for=settings.DEFAULT_WIDGET_CACHE_TIME):
        search = {'state': PUBLISHED}
        global _last_question
        if _last_question and not force_refresh:
            ts, question_id = _last_question
            if ts > time.time():
                print "Reusing same old question"
                question = (self.db.Question.collection.one(
                    {'_id': question_id}))
                return dict_plus(question)

        #'_id':{'$nin': [x._id for x in battle.sent_questions]}
        count = self.db.Question.find(search).count()
        while True:
            skip = random.randint(0, count - 1)
            for question in (self.db.Question.collection.find(search).skip(
                    skip).limit(1)):
                if (self.db.QuestionImage.one(
                    {'question.$id': question['_id']})):
                    if '_id' not in search:
                        search['_id'] = {'$nin': []}
                    search['_id']['$nin'].append(question['_id'])
                    continue
                question = dict_plus(question)
                #logging.info("New widget question: %r (%s)"%
                #             (question.text, question._id))
                _last_question = (time.time() + cache_for, question._id)
                return question
コード例 #3
0
ファイル: models.py プロジェクト: peterbe/tornado_gkc
    def calculate(user, rules_id):
        db = user.db
        search = {
            'users.$id': user._id,
            'finished': {
                '$ne': None
            },
            'rules': rules_id,
        }

        from mongokit import MultipleResultsFound
        try:
            play_points = db.PlayPoints.one({
                'user.$id': user._id,
                'rules': rules_id
            })
        except MultipleResultsFound:
            # Temporary hack!
            for pp in db.PlayPoints.find({
                    'user.$id': user._id,
                    'rules': rules_id
            }).sort('add_date').limit(1):
                pp.delete()
                raise Exception("Try again")

        if not play_points:
            play_points = db.PlayPoints()
            play_points.rules = rules_id
            play_points.user = user
        # reset all because we're recalculating
        play_points.points = 0
        play_points.wins = 0
        play_points.losses = 0
        play_points.draws = 0

        for play in db.Play.collection.find(search):
            play = dict_plus(play)

            if play.winner and play.winner.id == user._id:
                play_points.wins += 1
            elif play.draw:
                play_points.draws += 1
            else:
                try:
                    assert play.winner
                    assert play.winner.id != user._id
                except AssertionError:  # pragma: no cover
                    # This happens because of a past bug in the game, where a
                    # draw wassn't saved properly.
                    points = defaultdict(int)
                    for u_ref in play.users:
                        u = db.User.one({'_id': u_ref.id})
                        for pq in (db.PlayedQuestion.collection.find({
                                'play.$id':
                                play._id,
                                'user.$id':
                                u._id
                        })):
                            pq = dict_plus(pq)
                            if pq.right:
                                if pq.alternatives:
                                    p = 1
                                else:
                                    p = 3
                            else:
                                p = 0
                            points[u.username] += p

                    if sum(points.values()) == 0:
                        for pq in (db.PlayedQuestion.find(
                            {'play.$id': play._id})):
                            pq.delete()

                        play = db.Play.one({'_id': play._id})
                        play.delete()
                        continue

                    if len(points) == 2 and len(set(points.values())):
                        play = db.Play.one({'_id': play._id})
                        play.delete()

                        play.draw = True
                        play.save()
                        play_points.draws += 1
                        continue

                    print "WINNER", repr(play.winner)
                    print "USERS", [x.username for x in play.users]
                    print "DRAW", repr(play.draw)
                    print "FINISHED", repr(play.finished)
                    print "HALTED", repr(play.halted)
                    print "\n"
                    continue

                play_points.losses += 1
            try:
                for played in (user.db.PlayedQuestion.collection.find({
                        'play.$id':
                        play._id,
                        'user.$id':
                        user._id
                })):
                    played = dict_plus(played)
                    if played.right:
                        if played.alternatives:
                            play_points.points += 1
                        else:
                            play_points.points += 3
            except:  # pragma: no cover
                print "BROKEN!!!"
                print user.username,
                print "Against", play.get_other_user(user).username
                print "PLAY", play._id
                print "USER", user._id
                raise

                return play_points
        play_points.save()
        return play_points
コード例 #4
0
ファイル: handlers.py プロジェクト: peterbe/tornado_gkc
    def post(self):
        _id = self.get_argument('id')
        try:
            question = self.db.Question.one({'_id': ObjectId(_id)})
        except InvalidId:
            raise HTTPError(400, "Invalid ID")
        if not question:
            raise HTTPError(404, "Question not found")
        if self.get_argument('answer', ''):
            answer = self.get_argument('answer')
            alternatives = False
        else:
            answer = self.get_argument('alt_answer', '')
            alternatives = True

        right = question.check_answer(answer)
        qk = (self.db.QuestionKnowledge.collection
              .one({'question.$id': question._id}))
        qk_comment = qk_alternatives_comment = None
        if qk:
            qk = dict_plus(qk)
            p_right = min(99, 100 * qk.right * 1.5)
            p_right = int(p_right)
            if right:
                if p_right < 50:
                    qk_comment = TEMPLATES[0] % dict(p_right=p_right)
                    if p_right < 20:
                        qk_comment += "You're really smart!"
                    else:
                        qk_comment += "You're smart!"
                else:
                    qk_comment = TEMPLATES[2] % dict(p_right=p_right)
            else:
                if p_right < 50:
                    qk_comment = TEMPLATES[1] % dict(p_right=p_right)
                else:
                    qk_comment = TEMPLATES[3] % dict(p_right=p_right)

        options = self.get_base_options()
        if answer:
            if right:
                if alternatives:
                    options['page_title'] = 'Very good!'
                else:
                    options['page_title'] = 'Excellent!'
            else:
                options['page_title'] = 'Sorry, better luck next time'
        else:
            options['page_title'] = 'No answer :('

        options['right'] = right
        options['alternatives'] = alternatives
        options['question'] = question
        options['knowledge_comment'] = qk_comment
        options['qk_alternatives_comment'] = qk_alternatives_comment

        _log = "Widget answer: %r " % answer
        if alternatives:
            _log += ' (alternatives)'
        if right:
            _log += ' RIGHT!'
        else:
            _log += ' WRONG'
        _log += ' Question: %r' % question.text
        _log += ' knowledge_comment: %r' % qk_comment
        logging.info(_log)
        self.render('widget/answer.html', **options)
コード例 #5
0
ファイル: handlers.py プロジェクト: peterbe/tornado_gkc
    def get(self, play_id):
        options = self.get_base_options()
        play = self.must_find_play(play_id, options['user'])
        play = self.find_play(play_id)
        options['play'] = play
        player_names_lookup = {}
        for user in play.users:
            player_names_lookup[user._id] = unicode(user)
        player_names = player_names_lookup.values()

        def sort_me_first(x, y):
            if x == unicode(options['user']):
                return -1
            else:
                return 1
        player_names.sort(sort_me_first)
        options['player_names'] = player_names
        played_questions = (self.db.PlayedQuestion.collection
          .find({'play.$id': play._id}).sort('add_date', ASCENDING))

        questions = []
        outcomes = defaultdict(dict)
        totals = defaultdict(int)
        series = defaultdict(list)  # to use for the graph
        for played_question in played_questions:
            if played_question['question'].id not in questions:
                questions.append(played_question['question'].id)
            player_name = player_names_lookup[played_question['user'].id]
            outcomes[played_question['question'].id][player_name] = \
              dict_plus(played_question)
            if played_question['right']:
                if played_question['alternatives']:
                    totals[player_name] += 1
                else:
                    totals[player_name] += 3
            series[player_name].append(
              totals[player_name]
            )
        # now turn this series dict into a list
        series = [dict(name=k, data=[0] + v) for (k, v) in series.items()]
        options['series_json'] = tornado.escape.json_encode(series)

        questions = [dict_plus(self.db.Question.collection.one({'_id':x}))
                      for x in questions]
        genres = {}
        images = {}
        for q in questions:
            if q._id in genres:
                name = genres[q._id]
            else:
                genres[q._id] = u'xxx'
            q.genre = dict_plus(dict(name=genres[q._id]))
        for question_image in (self.db.QuestionImage
          .find({'question.$id': {'$in': [x._id for x in questions]}})):
            images[question_image.question._id] = question_image
        options['images'] = images
        options['questions'] = questions
        options['outcomes'] = outcomes
        options['totals'] = totals
        options['page_title'] = ' vs. '.join(player_names)
        options['message_sent'] = None
        options['can_send_message'] = not options['user'].anonymous
        if settings.COMPUTER_USERNAME in player_names:
            options['can_send_message'] = False

        options['play_messages'] = (self.db.PlayMessage
                               .find({'play.$id': play._id})
                               .sort('add_date'))

        self.render("play/replay.html", **options)
コード例 #6
0
ファイル: __init__.py プロジェクト: peterbe/tornado_gkc
    def render(self, question):
        db = connection[settings.DATABASE_NAME]
        difficulties = {
          0: 0, # about right
          1: 0, # easy
          -1: 0 # hard
        }
        ratings = {
          0: 0, # ok
          1: 0, # good
          -1: 0 # bad
        }
        count = 0
        search = {'question.$id': question._id}
        for review in db.QuestionReview.collection.find(search):
            review = dict_plus(review)
            difficulties[review['difficulty']] += 1
            rating = review['rating']
            if rating == 2: # legacy
                if isinstance(review.difficulty, float):
                    review.delete()
                    continue
                review.rating = 1
                review.save()
                rating = 1
            ratings[rating] += 1
            count += 1

        count = rights = alternatives = wrongs = tooslows = 0
        for qp in db.PlayedQuestion.collection.find(search):
            play = db.Play.collection.one({'_id': qp['play'].id})
            if not play:
                db.PlayedQuestion.collection.remove({'play.$id':qp['play'].id})
                continue

            if play['finished']:
                if qp['answer']:
                    count += 1
                    if qp['right']:
                        rights += 1
                    else:
                        wrongs += 1
                    if qp['alternatives']:
                        alternatives += 1
                else:
                    tooslows += 1

        answers = {
          'right': 0,
          'wrong': 0,
          'alternatives': 0,
        }
        if count:
            answers['right'] = int(100. * rights /count)
            answers['wrong'] = int(100. * wrongs /count)
            answers['alternatives'] = int(100. * alternatives /count)

        return dict(difficulties=difficulties,
                    ratings=ratings,
                    answers=answers,
                    )
        return dict(difficulties_json=tornado.escape.json_encode(difficulties),
                    ratings_json=tornado.escape.json_encode(ratings),
                    )
コード例 #7
0
    def get(self, play_id):
        options = self.get_base_options()
        play = self.must_find_play(play_id, options['user'])
        play = self.find_play(play_id)
        options['play'] = play
        player_names_lookup = {}
        for user in play.users:
            player_names_lookup[user._id] = unicode(user)
        player_names = player_names_lookup.values()

        def sort_me_first(x, y):
            if x == unicode(options['user']):
                return -1
            else:
                return 1

        player_names.sort(sort_me_first)
        options['player_names'] = player_names
        played_questions = (self.db.PlayedQuestion.collection.find({
            'play.$id':
            play._id
        }).sort('add_date', ASCENDING))

        questions = []
        outcomes = defaultdict(dict)
        totals = defaultdict(int)
        series = defaultdict(list)  # to use for the graph
        for played_question in played_questions:
            if played_question['question'].id not in questions:
                questions.append(played_question['question'].id)
            player_name = player_names_lookup[played_question['user'].id]
            outcomes[played_question['question'].id][player_name] = \
              dict_plus(played_question)
            if played_question['right']:
                if played_question['alternatives']:
                    totals[player_name] += 1
                else:
                    totals[player_name] += 3
            series[player_name].append(totals[player_name])
        # now turn this series dict into a list
        series = [dict(name=k, data=[0] + v) for (k, v) in series.items()]
        options['series_json'] = tornado.escape.json_encode(series)

        questions = [
            dict_plus(self.db.Question.collection.one({'_id': x}))
            for x in questions
        ]
        genres = {}
        images = {}
        for q in questions:
            if q._id in genres:
                name = genres[q._id]
            else:
                genres[q._id] = u'xxx'
            q.genre = dict_plus(dict(name=genres[q._id]))
        for question_image in (self.db.QuestionImage.find(
            {'question.$id': {
                '$in': [x._id for x in questions]
            }})):
            images[question_image.question._id] = question_image
        options['images'] = images
        options['questions'] = questions
        options['outcomes'] = outcomes
        options['totals'] = totals
        options['page_title'] = ' vs. '.join(player_names)
        options['message_sent'] = None
        options['can_send_message'] = not options['user'].anonymous
        if settings.COMPUTER_USERNAME in player_names:
            options['can_send_message'] = False

        options['play_messages'] = (self.db.PlayMessage.find({
            'play.$id':
            play._id
        }).sort('add_date'))

        self.render("play/replay.html", **options)
コード例 #8
0
def calculate_knowledge(db, question):
    bot_ids = [
        bot['_id'] for bot in (
            db.User.collection.find({'username': settings.COMPUTER_USERNAME}))
    ]
    users = defaultdict(set)
    tally = {
        'right': 0,
        'wrong': 0,
        'alternatives_wrong': 0,
        'alternatives_right': 0,
        'too_slow': 0,
        'timed_out': 0,
        'users': 0,
    }
    finished_plays = {}
    for played_question in (db.PlayedQuestion.collection.find({
            'question.$id':
            question._id,
            'user.$id': {
                '$nin': bot_ids
            }
    }).sort('add_date', 1)):
        played_question = dict_plus(played_question)
        #print "PQ"
        #pprint(dict(play=played_question.play.id,
        #           user=played_question.user.id,
        #           right=played_question.right,
        #           question=played_question.question.id,
        #           alternatives=played_question.alternatives,
        #           timed_out=played_question.timed_out,
        #           answer=played_question.answer))

        # only bother with played questions in a play that finished
        play_id = played_question.play.id
        if play_id not in finished_plays:
            # need to figure out if it was finished
            play = db.Play.collection.one({'_id': play_id})
            assert play, play_id
            finished_plays[play_id] = bool(play['finished'])
        if not finished_plays[play_id]:
            continue
        user_id = played_question['user'].id
        if played_question['question'].id in users[user_id]:
            continue
        users[user_id].add(played_question['question'].id)

        tally['users'] += 1
        if played_question.right:
            # means, this user nailed it!
            if played_question.alternatives:
                # ...but had to load alternatives
                tally['alternatives_right'] += 1
                #print "ALTERNATIVES RIGHT"
            else:
                # ...by knowing the answer
                tally['right'] += 1
                #print "RIGHT"
        elif played_question.answer:
            if played_question.alternatives:
                tally['alternatives_wrong'] += 1
                #print "ALTERNATIVES WRONG"
            else:
                tally['wrong'] += 1
                #print "WRONG"
        else:
            # that means that this user was either
            # too slow (ie. beaten) or timed out

            # To find out what happened we need to find out how the other
            # opponent faired
            others_right = []
            others_wrong = []
            others_alternatives = []
            others_right_alternatives = []
            others_too_slow = []
            others_timed_out = []
            for other in (db.PlayedQuestion.collection.find({
                    'question.$id':
                    question._id,
                    'play.$id':
                    played_question['play'].id,
                    'user.$id': {
                        '$ne': user_id
                    }
            })):
                # always assume N opponents
                others_right.append(other['right'])
            if any(others_right):
                # in some way, the opponent beat you to it
                tally['too_slow'] += 1
                #print "TOO SLOW"
            else:
                # opponent didn't get it right and you no answer
                tally['timed_out'] += 1
                #print "TIMED OUT"

    if not tally['users']:
        if options.verbose:
            print "NO ANSWERS!"
            print repr(question.text), repr(question.answer)
            print question.publish_date
    else:
        if options.verbose:
            print repr(question.text), repr(question.answer)
            pprint(tally)
        check = (tally['right'] + tally['alternatives_right'] +
                 tally['wrong'] + tally['alternatives_wrong'] +
                 tally['too_slow'] + tally['timed_out'])
        if check != tally['users']:
            raise ValueError(tally)
        # save all of this!
        knowledge = db.QuestionKnowledge.one({'question.$id': question._id})
        if not knowledge:
            knowledge = db.QuestionKnowledge()
            knowledge.question = question
        users = float(tally['users'])
        knowledge.users = tally['users']
        knowledge.right = tally['right'] / users
        knowledge.wrong = tally['wrong'] / users
        knowledge.alternatives_right = tally['alternatives_right'] / users
        knowledge.alternatives_wrong = tally['alternatives_wrong'] / users
        knowledge.too_slow = tally['too_slow'] / users
        knowledge.timed_out = tally['timed_out'] / users
        knowledge.save()
コード例 #9
0
def calculate_knowledge(db, question):
    bot_ids = [bot["_id"] for bot in (db.User.collection.find({"username": settings.COMPUTER_USERNAME}))]
    users = defaultdict(set)
    tally = {
        "right": 0,
        "wrong": 0,
        "alternatives_wrong": 0,
        "alternatives_right": 0,
        "too_slow": 0,
        "timed_out": 0,
        "users": 0,
    }
    finished_plays = {}
    for played_question in db.PlayedQuestion.collection.find(
        {"question.$id": question._id, "user.$id": {"$nin": bot_ids}}
    ).sort("add_date", 1):
        played_question = dict_plus(played_question)
        # print "PQ"
        # pprint(dict(play=played_question.play.id,
        #           user=played_question.user.id,
        #           right=played_question.right,
        #           question=played_question.question.id,
        #           alternatives=played_question.alternatives,
        #           timed_out=played_question.timed_out,
        #           answer=played_question.answer))

        # only bother with played questions in a play that finished
        play_id = played_question.play.id
        if play_id not in finished_plays:
            # need to figure out if it was finished
            play = db.Play.collection.one({"_id": play_id})
            assert play, play_id
            finished_plays[play_id] = bool(play["finished"])
        if not finished_plays[play_id]:
            continue
        user_id = played_question["user"].id
        if played_question["question"].id in users[user_id]:
            continue
        users[user_id].add(played_question["question"].id)

        tally["users"] += 1
        if played_question.right:
            # means, this user nailed it!
            if played_question.alternatives:
                # ...but had to load alternatives
                tally["alternatives_right"] += 1
                # print "ALTERNATIVES RIGHT"
            else:
                # ...by knowing the answer
                tally["right"] += 1
                # print "RIGHT"
        elif played_question.answer:
            if played_question.alternatives:
                tally["alternatives_wrong"] += 1
                # print "ALTERNATIVES WRONG"
            else:
                tally["wrong"] += 1
                # print "WRONG"
        else:
            # that means that this user was either
            # too slow (ie. beaten) or timed out

            # To find out what happened we need to find out how the other
            # opponent faired
            others_right = []
            others_wrong = []
            others_alternatives = []
            others_right_alternatives = []
            others_too_slow = []
            others_timed_out = []
            for other in db.PlayedQuestion.collection.find(
                {"question.$id": question._id, "play.$id": played_question["play"].id, "user.$id": {"$ne": user_id}}
            ):
                # always assume N opponents
                others_right.append(other["right"])
            if any(others_right):
                # in some way, the opponent beat you to it
                tally["too_slow"] += 1
                # print "TOO SLOW"
            else:
                # opponent didn't get it right and you no answer
                tally["timed_out"] += 1
                # print "TIMED OUT"

    if not tally["users"]:
        if options.verbose:
            print "NO ANSWERS!"
            print repr(question.text), repr(question.answer)
            print question.publish_date
    else:
        if options.verbose:
            print repr(question.text), repr(question.answer)
            pprint(tally)
        check = (
            tally["right"]
            + tally["alternatives_right"]
            + tally["wrong"]
            + tally["alternatives_wrong"]
            + tally["too_slow"]
            + tally["timed_out"]
        )
        if check != tally["users"]:
            raise ValueError(tally)
        # save all of this!
        knowledge = db.QuestionKnowledge.one({"question.$id": question._id})
        if not knowledge:
            knowledge = db.QuestionKnowledge()
            knowledge.question = question
        users = float(tally["users"])
        knowledge.users = tally["users"]
        knowledge.right = tally["right"] / users
        knowledge.wrong = tally["wrong"] / users
        knowledge.alternatives_right = tally["alternatives_right"] / users
        knowledge.alternatives_wrong = tally["alternatives_wrong"] / users
        knowledge.too_slow = tally["too_slow"] / users
        knowledge.timed_out = tally["timed_out"] / users
        knowledge.save()
コード例 #10
0
ファイル: models.py プロジェクト: peterbe/tornado_gkc
    def calculate(user, rules_id):
        db = user.db
        search = {
          'users.$id': user._id,
          'finished': {'$ne': None},
          'rules': rules_id,
        }

        from mongokit import MultipleResultsFound
        try:
            play_points = db.PlayPoints.one({'user.$id': user._id,
                                         'rules': rules_id})
        except MultipleResultsFound:
            # Temporary hack!
            for pp in db.PlayPoints.find({'user.$id': user._id,'rules': rules_id}).sort('add_date').limit(1):
                pp.delete()
                raise Exception("Try again")

        if not play_points:
            play_points = db.PlayPoints()
            play_points.rules = rules_id
            play_points.user = user
        # reset all because we're recalculating
        play_points.points = 0
        play_points.wins = 0
        play_points.losses = 0
        play_points.draws = 0

        for play in db.Play.collection.find(search):
            play = dict_plus(play)

            if play.winner and play.winner.id == user._id:
                play_points.wins += 1
            elif play.draw:
                play_points.draws += 1
            else:
                try:
                    assert play.winner
                    assert play.winner.id != user._id
                except AssertionError:  # pragma: no cover
                    # This happens because of a past bug in the game, where a
                    # draw wassn't saved properly.
                    points = defaultdict(int)
                    for u_ref in play.users:
                        u = db.User.one({'_id': u_ref.id})
                        for pq in (db.PlayedQuestion.collection
                                   .find({'play.$id': play._id,
                                          'user.$id': u._id})):
                            pq = dict_plus(pq)
                            if pq.right:
                                if pq.alternatives:
                                    p = 1
                                else:
                                    p = 3
                            else:
                                p = 0
                            points[u.username] += p

                    if sum(points.values()) == 0:
                        for pq in (db.PlayedQuestion
                                   .find({'play.$id': play._id})):
                            pq.delete()

                        play = db.Play.one({'_id': play._id})
                        play.delete()
                        continue

                    if len(points) == 2 and len(set(points.values())):
                        play = db.Play.one({'_id': play._id})
                        play.delete()

                        play.draw = True
                        play.save()
                        play_points.draws += 1
                        continue

                    print "WINNER", repr(play.winner)
                    print "USERS", [x.username for x in play.users]
                    print "DRAW", repr(play.draw)
                    print "FINISHED", repr(play.finished)
                    print "HALTED", repr(play.halted)
                    print "\n"
                    continue

                play_points.losses += 1
            try:
                for played in (user.db.PlayedQuestion.collection
                                 .find({'play.$id': play._id,
                                        'user.$id': user._id})):
                    played = dict_plus(played)
                    if played.right:
                        if played.alternatives:
                            play_points.points += 1
                        else:
                            play_points.points += 3
            except:  # pragma: no cover
                print "BROKEN!!!"
                print user.username,
                print "Against", play.get_other_user(user).username
                print "PLAY", play._id
                print "USER", user._id
                raise

                return play_points
        play_points.save()
        return play_points
コード例 #11
0
ファイル: handlers.py プロジェクト: peterbe/tornado_gkc
    def post(self):
        _id = self.get_argument('id')
        try:
            question = self.db.Question.one({'_id': ObjectId(_id)})
        except InvalidId:
            raise HTTPError(400, "Invalid ID")
        if not question:
            raise HTTPError(404, "Question not found")
        if self.get_argument('answer', ''):
            answer = self.get_argument('answer')
            alternatives = False
        else:
            answer = self.get_argument('alt_answer', '')
            alternatives = True

        right = question.check_answer(answer)
        qk = (self.db.QuestionKnowledge.collection.one(
            {'question.$id': question._id}))
        qk_comment = qk_alternatives_comment = None
        if qk:
            qk = dict_plus(qk)
            p_right = min(99, 100 * qk.right * 1.5)
            p_right = int(p_right)
            if right:
                if p_right < 50:
                    qk_comment = TEMPLATES[0] % dict(p_right=p_right)
                    if p_right < 20:
                        qk_comment += "You're really smart!"
                    else:
                        qk_comment += "You're smart!"
                else:
                    qk_comment = TEMPLATES[2] % dict(p_right=p_right)
            else:
                if p_right < 50:
                    qk_comment = TEMPLATES[1] % dict(p_right=p_right)
                else:
                    qk_comment = TEMPLATES[3] % dict(p_right=p_right)

        options = self.get_base_options()
        if answer:
            if right:
                if alternatives:
                    options['page_title'] = 'Very good!'
                else:
                    options['page_title'] = 'Excellent!'
            else:
                options['page_title'] = 'Sorry, better luck next time'
        else:
            options['page_title'] = 'No answer :('

        options['right'] = right
        options['alternatives'] = alternatives
        options['question'] = question
        options['knowledge_comment'] = qk_comment
        options['qk_alternatives_comment'] = qk_alternatives_comment

        _log = "Widget answer: %r " % answer
        if alternatives:
            _log += ' (alternatives)'
        if right:
            _log += ' RIGHT!'
        else:
            _log += ' WRONG'
        _log += ' Question: %r' % question.text
        _log += ' knowledge_comment: %r' % qk_comment
        logging.info(_log)
        self.render('widget/answer.html', **options)
コード例 #12
0
    def render(self, question):
        db = connection[settings.DATABASE_NAME]
        difficulties = {
            0: 0,  # about right
            1: 0,  # easy
            -1: 0  # hard
        }
        ratings = {
            0: 0,  # ok
            1: 0,  # good
            -1: 0  # bad
        }
        count = 0
        search = {'question.$id': question._id}
        for review in db.QuestionReview.collection.find(search):
            review = dict_plus(review)
            difficulties[review['difficulty']] += 1
            rating = review['rating']
            if rating == 2:  # legacy
                if isinstance(review.difficulty, float):
                    review.delete()
                    continue
                review.rating = 1
                review.save()
                rating = 1
            ratings[rating] += 1
            count += 1

        count = rights = alternatives = wrongs = tooslows = 0
        for qp in db.PlayedQuestion.collection.find(search):
            play = db.Play.collection.one({'_id': qp['play'].id})
            if not play:
                db.PlayedQuestion.collection.remove(
                    {'play.$id': qp['play'].id})
                continue

            if play['finished']:
                if qp['answer']:
                    count += 1
                    if qp['right']:
                        rights += 1
                    else:
                        wrongs += 1
                    if qp['alternatives']:
                        alternatives += 1
                else:
                    tooslows += 1

        answers = {
            'right': 0,
            'wrong': 0,
            'alternatives': 0,
        }
        if count:
            answers['right'] = int(100. * rights / count)
            answers['wrong'] = int(100. * wrongs / count)
            answers['alternatives'] = int(100. * alternatives / count)

        return dict(
            difficulties=difficulties,
            ratings=ratings,
            answers=answers,
        )
        return dict(
            difficulties_json=tornado.escape.json_encode(difficulties),
            ratings_json=tornado.escape.json_encode(ratings),
        )