コード例 #1
0
ファイル: models.py プロジェクト: thanhtd91/proso-apps
def current_custom_configs():
    result = []
    global _custom_configs
    global _custom_config_filters
    if _custom_configs.get(currentThread()) is None:
        user_id = get_user_id()
        _custom_configs[currentThread(
        )] = CustomConfig.objects.current_custom_configs(user_id)

    def _filter_config(config):
        c_key, c_value = next(iter(config['condition'].items()))
        if c_key is None:
            return True
        all_nones = True
        for config_filter in _custom_config_filters.get(currentThread(),
                                                        {}).values():
            filter_result = config_filter(c_key, c_value)
            if filter_result is not None:
                all_nones = False
                if not filter_result:
                    return False
        return not all_nones

    customs = _custom_configs.get(currentThread())
    if customs is not None:
        for key, configs in customs.items():
            valid_configs = [c for c in configs if _filter_config(c)]
            if len(valid_configs):
                result.append((key, valid_configs[0]['content']))
    return result
コード例 #2
0
ファイル: views.py プロジェクト: MatheusArrudaLab/proso-apps
def read(request, key):
    if 'user' in request.GET:
        user = get_user_id(request)
    else:
        user = None
    item = int(request.GET['item']) if 'item' in request.GET else None
    item_secondary = int(request.GET['item_secondary']) if 'item_secondary' in request.GET else None
    time = get_time(request)
    environment = get_environment()
    if is_time_overridden(request):
        environment.shift_time(time)
    value = environment.read(key, user=user, item=item, item_secondary=item_secondary)
    if value is None:
        return render_json(
            request,
            {'error': 'value with key "%s" not found' % key},
            template='models_json.html', status=404)
    else:
        return render_json(
            request,
            {
                'object_type': 'value',
                'key': key,
                'item_primary_id': item,
                'item_secondary_id': item_secondary,
                'user_id': user,
                'value': value
            },
            template='models_json.html'
        )
コード例 #3
0
ファイル: views.py プロジェクト: MatheusArrudaLab/proso-apps
def practice_image(request):
    user_id = get_user_id(request)
    limit = min(int(request.GET.get('limit', 10)), 100)
    item_ids = Item.objects.filter_all_reachable_leaves(get_filter(request), get_language(request))
    answers = Answer.objects.filter(user_id=user_id).filter(item_asked_id__in=item_ids).order_by('-id')[:limit]
    predictive_model = get_predictive_model()
    environment = get_environment()
    predictions = predictive_model.predict_more_items(environment, user=-1, items=item_ids, time=datetime.datetime.now())
    items_in_order = list(zip(*sorted(zip(predictions, item_ids), reverse=True)))[1] if len(item_ids) > 1 else []
    item_prediction = dict(list(zip(item_ids, predictions)))
    item_position = dict(list(zip(items_in_order, list(range(len(item_ids))))))
    svg = proso.svg.Printer()
    answers = sorted(list(answers), key=lambda a: a.id)
    SQUARE_SIZE = 10
    OFFSET_X = SQUARE_SIZE
    OFFSET_Y = SQUARE_SIZE * 3
    for i, item in enumerate(items_in_order):
        svg.print_square(OFFSET_X + SQUARE_SIZE * i, OFFSET_Y - SQUARE_SIZE, SQUARE_SIZE, int(255 * item_prediction[item]))
    for i, answer in enumerate(answers):
        for j in range(len(items_in_order)):
            svg.print_square(OFFSET_X + SQUARE_SIZE * j, OFFSET_Y + SQUARE_SIZE * i, SQUARE_SIZE, 255, border_color=200)
        color = 'green' if answer.item_asked_id == answer.item_answered_id else 'red'
        svg.print_square(
            OFFSET_X + SQUARE_SIZE * item_position[answer.item_asked_id],
            OFFSET_Y + SQUARE_SIZE * i, SQUARE_SIZE, color, border_color=0)
        svg.print_text(OFFSET_X + SQUARE_SIZE * (len(items_in_order) + 1), OFFSET_Y + SQUARE_SIZE * i + 0.8 * SQUARE_SIZE, answer.time.strftime('%H:%M:%S %Y-%m-%d'), font_size=10)
    return HttpResponse(str(svg), content_type="image/svg+xml")
コード例 #4
0
ファイル: views.py プロジェクト: MatheusArrudaLab/proso-apps
def audit(request, key):
    if 'user' in request.GET:
        user = get_user_id(request)
    else:
        user = None
    limit = 100
    if request.user.is_staff:
        limit = request.GET.get('limit', limit)
    item = int(request.GET['item']) if 'item' in request.GET else None
    item_secondary = int(request.GET['item_secondary']) if 'item_secondary' in request.GET else None
    time = get_time(request)
    environment = get_environment()
    if is_time_overridden(request):
        environment.shift_time(time)
    values = environment.audit(
        key, user=user, item=item, item_secondary=item_secondary, limit=limit)

    def _to_json_audit(audit):
        (time, value) = audit
        return {
            'object_type': 'value',
            'key': key,
            'item_primary_id': item,
            'item_secondary_id': item_secondary,
            'user_id': user,
            'value': value,
            'time': time.strftime('%Y-%m-%d %H:%M:%S')
        }
    return render_json(request, list(map(_to_json_audit, values)), template='models_json.html')
コード例 #5
0
def user_stats(request):
    """
    JSON of user stats of the user

    GET parameters:
      html (bool):
        turn on the HTML version of the API, defaults to false
      user (int):
        identifier of the user, defaults to logged user
      concepts (list):
        list of identifiers of concepts, defaults to all concepts
      lang (str):
        language of requested concepts, defaults to language from django
    """
    user = get_user_id(request)
    language = get_language(request)

    concepts = None  # meaning all concept
    if "concepts" in request.GET:
        concepts = Concept.objects.filter(lang=language,
                                          active=True,
                                          identifier__in=load_query_json(
                                              request.GET, "concepts"))
    data = UserStat.objects.get_user_stats(user, language, concepts)
    return render_json(request,
                       data,
                       template='concepts_json.html',
                       help_text=user_stats.__doc__)
コード例 #6
0
def current_custom_configs():
    result = []
    global _custom_configs
    global _custom_config_filters
    if _custom_configs.get(currentThread()) is None:
        user_id = get_user_id()
        _custom_configs[currentThread()] = CustomConfig.objects.current_custom_configs(user_id)

    def _filter_config(config):
        c_key, c_value = next(iter(config['condition'].items()))
        if c_key is None:
            return True
        all_nones = True
        for config_filter in _custom_config_filters.get(currentThread(), {}).values():
            filter_result = config_filter(c_key, c_value)
            if filter_result is not None:
                all_nones = False
                if not filter_result:
                    return False
        return not all_nones

    customs = _custom_configs.get(currentThread())
    if customs is not None:
        for key, configs in customs.items():
            valid_configs = [c for c in configs if _filter_config(c)]
            if len(valid_configs):
                result.append((key, valid_configs[0]['content']))
    return result
コード例 #7
0
ファイル: views.py プロジェクト: matheus-arruda/proso-apps
def read(request, key):
    if 'user' in request.GET:
        user = get_user_id(request)
    else:
        user = None
    item = int(request.GET['item']) if 'item' in request.GET else None
    item_secondary = int(request.GET['item_secondary']
                         ) if 'item_secondary' in request.GET else None
    time = get_time(request)
    environment = get_environment()
    if is_time_overridden(request):
        environment.shift_time(time)
    value = environment.read(key,
                             user=user,
                             item=item,
                             item_secondary=item_secondary)
    if value is None:
        return render_json(request,
                           {'error': 'value with key "%s" not found' % key},
                           template='models_json.html',
                           status=404)
    else:
        return render_json(request, {
            'object_type': 'value',
            'key': key,
            'item_primary_id': item,
            'item_secondary_id': item_secondary,
            'user_id': user,
            'value': value
        },
                           template='models_json.html')
コード例 #8
0
ファイル: views.py プロジェクト: MatheusArrudaLab/proso-apps
def status(request):
    user_id = get_user_id(request)
    time = get_time(request)
    environment = get_environment()
    if is_time_overridden(request):
        environment.shift_time(time)
    return render_json(request, {
        'object_type': 'status',
        'number_of_answers': environment.number_of_answers(user=user_id),
        'number_of_correct_answers': environment.number_of_correct_answers(user=user_id),
        'environment_info': get_active_environment_info(),
    }, template='models_json.html')
コード例 #9
0
def answer_question(request):
    if request.method == 'GET':
        return render(request, 'user_answer.html', {}, help_text=answer_question.__doc__)
    elif request.method == 'POST':
        with transaction.atomic():
            user_id = get_user_id(request)
            to_save = json_body(request.body.decode("utf-8"))
            for answer in to_save['answers']:
                question = get_object_or_404(UserQuestion, pk=answer['question'])
                if 'open_answer' in answer and 'closed_answer' in answer:
                    return render_json(request, {
                        'error': _('The answer can not contain both open and closed part'),
                        'error_type': 'answer_closed_open_both'
                    }, template='user_json.html', status=400)
                if 'open_answer' not in answer and 'closed_answer' not in answer:
                    return render_json(request, {
                        'error': _('The answer has to contain either open, or closed part.'),
                        'error_type': 'answer_closed_open_missing'
                    }, template='user_json.html', status=400)
                if question.answer_type == UserQuestion.TYPE_CLOSED and 'closed_answer' not in answer:
                    return render_json(request, {
                        'error': _('The answer has to contain closed part.'),
                        'error_type': 'answer_closed_missing'
                    }, template='user_json.html', status=400)
                if question.answer_type == UserQuestion.TYPE_OPEN and 'open_answer' not in answer:
                    return render_json(request, {
                        'error': _('The answer has to contain open part.'),
                        'error_type': 'answer_open_missing'
                    }, template='user_json.html', status=400)

                user_answer = None
                if not question.repeat:
                    user_answer = UserQuestionAnswer.objects.filter(user_id=user_id, question__identifier=question.identifier).first()
                    status = 202
                if user_answer is None:
                    status = 201
                    user_answer = UserQuestionAnswer(user_id=user_id, question=question)
                if 'closed_answer' in answer:
                    user_answer.closed_answer = get_object_or_404(UserQuestionPossibleAnswer, pk=answer['closed_answer'])
                    if user_answer.closed_answer.question_id != question.id:
                        return render_json(request, {
                            'error': _('The given question and question for the given closed answer does not match.'),
                            'error_type': 'closed_answer_no_match'
                        }, template='user_json.html', status=400)
                else:
                    user_answer.closed_answer = None
                user_answer.open_answer = answer['open_answer'] if 'open_answer' in answer else None
                user_answer.save()
            return HttpResponse('ok', status=status)
    else:
        return HttpResponseBadRequest("method %s is not allowed".format(request.method))
コード例 #10
0
ファイル: views.py プロジェクト: adaptive-learning/proso-apps
def answer_question(request):
    if request.method == 'GET':
        return render(request, 'user_answer.html', {}, help_text=answer_question.__doc__)
    elif request.method == 'POST':
        with transaction.atomic():
            user_id = get_user_id(request)
            to_save = json_body(request.body.decode("utf-8"))
            for answer in to_save['answers']:
                question = get_object_or_404(UserQuestion, pk=answer['question'])
                if 'open_answer' in answer and 'closed_answer' in answer:
                    return render_json(request, {
                        'error': _('The answer can not contain both open and closed part'),
                        'error_type': 'answer_closed_open_both'
                    }, template='user_json.html', status=400)
                if 'open_answer' not in answer and 'closed_answer' not in answer:
                    return render_json(request, {
                        'error': _('The answer has to contain either open, or closed part.'),
                        'error_type': 'answer_closed_open_missing'
                    }, template='user_json.html', status=400)
                if question.answer_type == UserQuestion.TYPE_CLOSED and 'closed_answer' not in answer:
                    return render_json(request, {
                        'error': _('The answer has to contain closed part.'),
                        'error_type': 'answer_closed_missing'
                    }, template='user_json.html', status=400)
                if question.answer_type == UserQuestion.TYPE_OPEN and 'open_answer' not in answer:
                    return render_json(request, {
                        'error': _('The answer has to contain open part.'),
                        'error_type': 'answer_open_missing'
                    }, template='user_json.html', status=400)

                user_answer = None
                if not question.repeat:
                    user_answer = UserQuestionAnswer.objects.filter(user_id=user_id, question__identifier=question.identifier).first()
                    status = 202
                if user_answer is None:
                    status = 201
                    user_answer = UserQuestionAnswer(user_id=user_id, question=question)
                if 'closed_answer' in answer:
                    user_answer.closed_answer = get_object_or_404(UserQuestionPossibleAnswer, pk=answer['closed_answer'])
                    if user_answer.closed_answer.question_id != question.id:
                        return render_json(request, {
                            'error': _('The given question and question for the given closed answer does not match.'),
                            'error_type': 'closed_answer_no_match'
                        }, template='user_json.html', status=400)
                else:
                    user_answer.closed_answer = None
                user_answer.open_answer = answer['open_answer'] if 'open_answer' in answer else None
                user_answer.save()
            return HttpResponse('ok', status=status)
    else:
        return HttpResponseBadRequest("method %s is not allowed".format(request.method))
コード例 #11
0
def user_answers(request, json_list, nested):
    if nested:
        return
    user_id = get_user_id(request)
    user_answers = defaultdict(list)
    for user_answer in UserQuestionAnswer.objects.select_related('question', 'closed_answer').filter(user_id=user_id):
        user_answers[user_answer.question.identifier].append(user_answer)
    for question in json_list:
        possible_answers = {ans['identifier']: ans for ans in question['possible_answers']}
        question_user_answers = [ans.to_json(nested=True) for ans in user_answers[question['identifier']]]
        for ans in question_user_answers:
            if 'closed_answer' in ans:
                ans['closed_answer'] = possible_answers[ans['closed_answer']['identifier']]
        question['user_answers'] = question_user_answers
コード例 #12
0
ファイル: json_enrich.py プロジェクト: thanhtd91/proso-apps
def number_of_correct_answers(request, json_list, nested):
    if 'stats' not in request.GET:
        return
    object_item_ids = [x['item_id'] for x in json_list]
    user = get_user_id(request)
    leaves = models.Item.objects.get_leaves(object_item_ids, language=get_language(request))
    all_leaves = set(flatten(leaves.values()))
    number_of_correct_answers = _environment(request).number_of_correct_answers_more_items(
        user=user, items=all_leaves)
    for object_json in json_list:
        num = sum([number_of_correct_answers[leave] for leave in leaves[object_json['item_id']]])
        object_json['number_of_correct_answers'] = num
        object_json['practiced_correctly'] = num > 0
    return json_list
コード例 #13
0
ファイル: json_enrich.py プロジェクト: thanhtd91/proso-apps
def prediction(request, json_list, nested):
    if 'stats' not in request.GET:
        return
    object_item_ids = [x['item_id'] for x in json_list]
    user = get_user_id(request)
    time = models.get_time_for_knowledge_overview(request)
    predictions = _predictive_model().predict_more_items(_environment(request), user, object_item_ids, time)
    mastery_threshold = get_mastery_trashold()
    for object_json, prediction in zip(json_list, predictions):
        object_json['prediction'] = float("{0:.2f}".format(prediction))
        object_json['mastered'] = prediction >= mastery_threshold
    if "new_user_predictions" in request.GET:
        user = -1
        predictions = _predictive_model().predict_more_items(_environment(request), user, object_item_ids, time)
        for object_json, prediction in zip(json_list, predictions):
            object_json['new_user_prediction'] = float("{0:.2f}".format(prediction))
    return json_list
コード例 #14
0
ファイル: views.py プロジェクト: matheus-arruda/proso-apps
def status(request):
    user_id = get_user_id(request)
    time = get_time(request)
    environment = get_environment()
    if is_time_overridden(request):
        environment.shift_time(time)
    return render_json(request, {
        'object_type':
        'status',
        'number_of_answers':
        environment.number_of_answers(user=user_id),
        'number_of_correct_answers':
        environment.number_of_correct_answers(user=user_id),
        'environment_info':
        get_active_environment_info(),
    },
                       template='models_json.html')
コード例 #15
0
ファイル: views.py プロジェクト: matheus-arruda/proso-apps
def practice_image(request):
    user_id = get_user_id(request)
    limit = min(int(request.GET.get('limit', 10)), 100)
    item_ids = Item.objects.filter_all_reachable_leaves(
        get_filter(request), get_language(request))
    answers = Answer.objects.filter(user_id=user_id).filter(
        item_asked_id__in=item_ids).order_by('-id')[:limit]
    predictive_model = get_predictive_model()
    environment = get_environment()
    predictions = predictive_model.predict_more_items(
        environment, user=-1, items=item_ids, time=datetime.datetime.now())
    items_in_order = list(
        zip(*sorted(zip(predictions, item_ids),
                    reverse=True)))[1] if len(item_ids) > 1 else []
    item_prediction = dict(list(zip(item_ids, predictions)))
    item_position = dict(list(zip(items_in_order, list(range(len(item_ids))))))
    svg = proso.svg.Printer()
    answers = sorted(list(answers), key=lambda a: a.id)
    SQUARE_SIZE = 10
    OFFSET_X = SQUARE_SIZE
    OFFSET_Y = SQUARE_SIZE * 3
    for i, item in enumerate(items_in_order):
        svg.print_square(OFFSET_X + SQUARE_SIZE * i, OFFSET_Y - SQUARE_SIZE,
                         SQUARE_SIZE, int(255 * item_prediction[item]))
    for i, answer in enumerate(answers):
        for j in range(len(items_in_order)):
            svg.print_square(OFFSET_X + SQUARE_SIZE * j,
                             OFFSET_Y + SQUARE_SIZE * i,
                             SQUARE_SIZE,
                             255,
                             border_color=200)
        color = 'green' if answer.item_asked_id == answer.item_answered_id else 'red'
        svg.print_square(OFFSET_X +
                         SQUARE_SIZE * item_position[answer.item_asked_id],
                         OFFSET_Y + SQUARE_SIZE * i,
                         SQUARE_SIZE,
                         color,
                         border_color=0)
        svg.print_text(OFFSET_X + SQUARE_SIZE * (len(items_in_order) + 1),
                       OFFSET_Y + SQUARE_SIZE * i + 0.8 * SQUARE_SIZE,
                       answer.time.strftime('%H:%M:%S %Y-%m-%d'),
                       font_size=10)
    return HttpResponse(str(svg), content_type="image/svg+xml")
コード例 #16
0
ファイル: json_enrich.py プロジェクト: thanhtd91/proso-apps
def avg_prediction(request, json_list, nested):
    if 'stats' not in request.GET:
        return
    object_item_ids = [x['item_id'] for x in json_list]
    leaves = models.Item.objects.get_leaves(object_item_ids, language=get_language(request))
    all_leaves = list(set(flatten(leaves.values())))
    user = get_user_id(request)
    time = models.get_time_for_knowledge_overview(request)
    predictions = dict(list(zip(all_leaves, _predictive_model().predict_more_items(
        _environment(request),
        user,
        all_leaves,
        time
    ))))
    mastery_threshold = get_mastery_trashold()
    for object_json in json_list:
        leaf_predictions = [predictions[leave] for leave in leaves[object_json['item_id']]]
        object_json['avg_predicton'] = numpy.mean(leaf_predictions)
        object_json['mastered'] = sum([p > mastery_threshold for p in leaf_predictions])
コード例 #17
0
ファイル: json_enrich.py プロジェクト: thanhtd91/proso-apps
def user_answers(request, json_list, nested):
    if nested:
        return
    user_id = get_user_id(request)
    user_answers = defaultdict(list)
    for user_answer in UserQuestionAnswer.objects.select_related(
            'question', 'closed_answer').filter(user_id=user_id):
        user_answers[user_answer.question.identifier].append(user_answer)
    for question in json_list:
        possible_answers = {
            ans['identifier']: ans
            for ans in question['possible_answers']
        }
        question_user_answers = [
            ans.to_json(nested=True)
            for ans in user_answers[question['identifier']]
        ]
        for ans in question_user_answers:
            if 'closed_answer' in ans:
                ans['closed_answer'] = possible_answers[ans['closed_answer']
                                                        ['identifier']]
        question['user_answers'] = question_user_answers
コード例 #18
0
ファイル: views.py プロジェクト: MatheusArrudaLab/proso-apps
def user_stats(request):
    """
    JSON of user stats of the user

    GET parameters:
      html (bool):
        turn on the HTML version of the API, defaults to false
      user (int):
        identifier of the user, defaults to logged user
      concepts (list):
        list of identifiers of concepts, defaults to all concepts
      lang (str):
        language of requested concepts, defaults to language from django
    """
    user = get_user_id(request)
    language = get_language(request)

    concepts = None    # meaning all concept
    if "concepts" in request.GET:
        concepts = Concept.objects.filter(lang=language, active=True,
                                          identifier__in=load_query_json(request.GET, "concepts"))
    data = UserStat.objects.get_user_stats(user, language, concepts)
    return render_json(request, data, template='concepts_json.html', help_text=user_stats.__doc__)
コード例 #19
0
ファイル: views.py プロジェクト: matheus-arruda/proso-apps
def audit(request, key):
    if 'user' in request.GET:
        user = get_user_id(request)
    else:
        user = None
    limit = 100
    if request.user.is_staff:
        limit = request.GET.get('limit', limit)
    item = int(request.GET['item']) if 'item' in request.GET else None
    item_secondary = int(request.GET['item_secondary']
                         ) if 'item_secondary' in request.GET else None
    time = get_time(request)
    environment = get_environment()
    if is_time_overridden(request):
        environment.shift_time(time)
    values = environment.audit(key,
                               user=user,
                               item=item,
                               item_secondary=item_secondary,
                               limit=limit)

    def _to_json_audit(audit):
        (time, value) = audit
        return {
            'object_type': 'value',
            'key': key,
            'item_primary_id': item,
            'item_secondary_id': item_secondary,
            'user_id': user,
            'value': value,
            'time': time.strftime('%Y-%m-%d %H:%M:%S')
        }

    return render_json(request,
                       list(map(_to_json_audit, values)),
                       template='models_json.html')
コード例 #20
0
ファイル: views.py プロジェクト: matheus-arruda/proso-apps
def user_stats(request):
    """
    Get user statistics for selected groups of items

    time:
      time in format '%Y-%m-%d_%H:%M:%S' used for practicing
    user:
      identifier of the user (only for stuff users)
    username:
      username of user (only for users with public profile)
    filters:                -- use this or body
      json as in BODY
    mastered:
      use model to compute number of mastered items - can be slowed
    language:
      language of the items

    BODY
      json in following format:
      {
        "#identifier": []         -- custom identifier (str) and filter
        ...
      }
    """
    timer('user_stats')
    response = {}
    data = None
    if request.method == "POST":
        data = json.loads(request.body.decode("utf-8"))["filters"]
    if "filters" in request.GET:
        data = load_query_json(request.GET, "filters")
    if data is None:
        return render_json(request, {},
                           template='models_user_stats.html',
                           help_text=user_stats.__doc__)
    environment = get_environment()
    if is_time_overridden(request):
        environment.shift_time(get_time(request))
    user_id = get_user_id(request)
    language = get_language(request)
    filter_names, filter_filters = list(zip(*sorted(data.items())))
    reachable_leaves = Item.objects.filter_all_reachable_leaves_many(
        filter_filters, language)
    all_leaves = flatten(reachable_leaves)
    answers = dict(
        list(
            zip(all_leaves,
                environment.number_of_answers_more_items(all_leaves,
                                                         user_id))))
    correct_answers = dict(
        list(
            zip(
                all_leaves,
                environment.number_of_correct_answers_more_items(
                    all_leaves, user_id))))
    if request.GET.get("mastered"):
        timer('user_stats_mastered')
        mastery_threshold = get_mastery_trashold()
        predictions = get_predictive_model().predict_more_items(
            environment, user_id, all_leaves, get_time(request))
        mastered = dict(
            list(zip(all_leaves,
                     [p >= mastery_threshold for p in predictions])))
        LOGGER.debug(
            "user_stats - getting predictions for flashcards took %s seconds",
            (timer('user_stats_mastered')))
    for identifier, items in zip(filter_names, reachable_leaves):
        if len(items) == 0:
            response[identifier] = {
                "filter": data[identifier],
                "number_of_flashcards": 0,
            }
        else:
            response[identifier] = {
                "filter":
                data[identifier],
                "number_of_flashcards":
                len(items),
                "number_of_practiced_flashcards":
                sum(answers[i] > 0 for i in items),
                "number_of_answers":
                sum(answers[i] for i in items),
                "number_of_correct_answers":
                sum(correct_answers[i] for i in items),
            }
            if request.GET.get("mastered"):
                response[identifier]["number_of_mastered_flashcards"] = sum(
                    mastered[i] for i in items)
    return render_json(request,
                       response,
                       template='models_user_stats.html',
                       help_text=user_stats.__doc__)
コード例 #21
0
ファイル: views.py プロジェクト: adaptive-learning/proso-apps
def questions_to_ask(request):
    language = get_language(request)
    user_id = get_user_id(request)
    questions = UserQuestion.objects.questions_to_ask(user_id, language)
    return render_json(request, list(questions), template='user_json.html')
コード例 #22
0
ファイル: views.py プロジェクト: adaptive-learning/proso-apps
def profile(request, status=200):
    """
    Get the user's profile. If the user has no assigned profile, the HTTP 404
    is returned. Make a POST request to modify the user's profile.

    GET parameters:
        html
            turn on the HTML version of the API
        username:
            username of user (only for users with public profile)
        stats:
            attache addition user statistics

    POST parameters (JSON):
        send_emails:
            switcher turning on sending e-mails to user
        public:
            swicher making the user's profile publicly available
        user:
            password:
                user's password
            password_check:
                user's password again to check it
            first_name (optional):
                user's first name
            last_name (optional):
                user's last name
    """
    if request.method == 'GET':
        if request.GET.get("username", False):
            try:
                user_profile = User.objects.get(username=request.GET.get("username"),
                                                userprofile__public=True).userprofile
            except ObjectDoesNotExist:
                raise Http404("user not found or have not public profile")
        else:
            user_id = get_user_id(request)
            if get_config('proso_user', 'google.openid.migration', default=True) and not is_user_id_overridden(request):
                migrated_user = migrate_google_openid_user(request.user)
                if migrated_user is not None:
                    auth.logout(request)
                    migrated_user.backend = 'social.backends.google.GoogleOAuth2'
                    auth.login(request, migrated_user)
            user_profile = get_object_or_404(UserProfile, user_id=user_id)
        return render_json(
            request, user_profile, status=status,
            template='user_profile.html', help_text=profile.__doc__)
    elif request.method == 'POST':
        with transaction.atomic():
            to_save = json_body(request.body.decode("utf-8"))
            user_id = get_user_id(request)
            user_profile = get_object_or_404(UserProfile, user_id=user_id)
            user = to_save.get('user', None)
            if 'send_emails' in to_save:
                user_profile.send_emails = bool(to_save['send_emails'])
            if 'public' in to_save:
                user_profile.public = bool(to_save['public'])
            if user:
                error = _save_user(request, user, new=False)
                if error:
                    return render_json(request, error, template='user_json.html', status=400)
            if 'properties' in to_save:
                user_profile.save_properties(to_save['properties'])
            user_profile.save()
        request.method = "GET"
        return profile(request, status=202)
    else:
        return HttpResponseBadRequest("method %s is not allowed".format(request.method))
コード例 #23
0
ファイル: views.py プロジェクト: matheus-arruda/proso-apps
def practice(request):
    """
    Return the given number of questions to practice adaptively. In case of
    POST request, try to save the answer(s).

    GET parameters:
        filter:
            list of lists of identifiers (may be prefixed by minus sign to
            mark complement)
        language:
            language (str) of flashcards
        avoid:
            list of item ids to avoid
        limit:
            number of returned questions (default 10, maximum 100)
        time:
            time in format '%Y-%m-%d_%H:%M:%S' used for practicing
        user:
            identifier for the practicing user (only for stuff users)
        stats:
            turn on the enrichment of the objects by some statistics
        html:
            turn on the HTML version of the API

    BODY:
        see answer resource
    """
    if request.user.id is None:  # Google Bot
        return render_json(
            request, {
                'error': _('There is no user available for the practice.'),
                'error_type': 'user_undefined'
            },
            status=400,
            template='models_json.html')

    limit = min(int(request.GET.get('limit', 10)), 100)
    # prepare
    user = get_user_id(request)
    time = get_time(request)
    avoid = load_query_json(request.GET, "avoid", "[]")
    practice_filter = get_filter(request)
    practice_context = PracticeContext.objects.from_content(practice_filter)
    environment = get_environment()
    item_selector = get_item_selector()
    if is_time_overridden(request):
        environment.shift_time(time)

    # save answers
    if request.method == 'POST':
        _save_answers(request, practice_context)

    if len(practice_filter) > 0:
        item_ids = Item.objects.filter_all_reachable_leaves(
            practice_filter, get_language(request))
    else:
        item_ids = Item.objects.get_all_available_leaves()
    item_ids = list(set(item_ids) - set(avoid))
    if len(item_ids) == 0:
        return render_json(
            request, {
                'error':
                _('There is no item for the given filter to practice.'),
                'error_type': 'empty_practice'
            },
            status=404,
            template='models_json.html')
    selected_items, meta = item_selector.select(environment,
                                                user,
                                                item_ids,
                                                time,
                                                practice_context.id,
                                                limit,
                                                items_in_queue=len(avoid))
    result = []
    for item, item_meta in zip(selected_items, meta):
        question = {
            'object_type': 'question',
            'payload': Item.objects.item_id_to_json(item),
        }
        if item_meta is not None:
            question['meta'] = item_meta
        result.append(question)

    return render_json(request,
                       result,
                       template='models_json.html',
                       help_text=practice.__doc__)
コード例 #24
0
ファイル: views.py プロジェクト: MatheusArrudaLab/proso-apps
def user_stats(request):
    """
    Get user statistics for selected groups of items

    time:
      time in format '%Y-%m-%d_%H:%M:%S' used for practicing
    user:
      identifier of the user (only for stuff users)
    username:
      username of user (only for users with public profile)
    filters:                -- use this or body
      json as in BODY
    mastered:
      use model to compute number of mastered items - can be slowed
    language:
      language of the items

    BODY
      json in following format:
      {
        "#identifier": []         -- custom identifier (str) and filter
        ...
      }
    """
    timer('user_stats')
    response = {}
    data = None
    if request.method == "POST":
        data = json.loads(request.body.decode("utf-8"))["filters"]
    if "filters" in request.GET:
        data = load_query_json(request.GET, "filters")
    if data is None:
        return render_json(request, {}, template='models_user_stats.html', help_text=user_stats.__doc__)
    environment = get_environment()
    if is_time_overridden(request):
        environment.shift_time(get_time(request))
    user_id = get_user_id(request)
    language = get_language(request)
    filter_names, filter_filters = list(zip(*sorted(data.items())))
    reachable_leaves = Item.objects.filter_all_reachable_leaves_many(filter_filters, language)
    all_leaves = flatten(reachable_leaves)
    answers = dict(list(zip(all_leaves, environment.number_of_answers_more_items(all_leaves, user_id))))
    correct_answers = dict(list(zip(all_leaves, environment.number_of_correct_answers_more_items(all_leaves, user_id))))
    if request.GET.get("mastered"):
        timer('user_stats_mastered')
        mastery_threshold = get_mastery_trashold()
        predictions = get_predictive_model().predict_more_items(environment, user_id, all_leaves, get_time(request))
        mastered = dict(list(zip(all_leaves, [p >= mastery_threshold for p in predictions])))
        LOGGER.debug("user_stats - getting predictions for flashcards took %s seconds", (timer('user_stats_mastered')))
    for identifier, items in zip(filter_names, reachable_leaves):
        if len(items) == 0:
            response[identifier] = {
                "filter": data[identifier],
                "number_of_flashcards": 0,
            }
        else:
            response[identifier] = {
                "filter": data[identifier],
                "number_of_flashcards": len(items),
                "number_of_practiced_flashcards": sum(answers[i] > 0 for i in items),
                "number_of_answers": sum(answers[i] for i in items),
                "number_of_correct_answers": sum(correct_answers[i] for i in items),
            }
            if request.GET.get("mastered"):
                response[identifier]["number_of_mastered_flashcards"]= sum(mastered[i] for i in items)
    return render_json(request, response, template='models_user_stats.html', help_text=user_stats.__doc__)
コード例 #25
0
def profile(request, status=200):
    """
    Get the user's profile. If the user has no assigned profile, the HTTP 404
    is returned. Make a POST request to modify the user's profile.

    GET parameters:
        html
            turn on the HTML version of the API
        username:
            username of user (only for users with public profile)
        stats:
            attache addition user statistics

    POST parameters (JSON):
        send_emails:
            switcher turning on sending e-mails to user
        public:
            swicher making the user's profile publicly available
        user:
            password:
                user's password
            password_check:
                user's password again to check it
            first_name (optional):
                user's first name
            last_name (optional):
                user's last name
    """
    if request.method == 'GET':
        if request.GET.get("username", False):
            try:
                user_profile = User.objects.get(
                    username=request.GET.get("username"),
                    userprofile__public=True).userprofile
            except ObjectDoesNotExist:
                raise Http404("user not found or have not public profile")
        else:
            user_id = get_user_id(request)
            if get_config('proso_user',
                          'google.openid.migration',
                          default=True) and not is_user_id_overridden(request):
                migrated_user = migrate_google_openid_user(request.user)
                if migrated_user is not None:
                    auth.logout(request)
                    migrated_user.backend = 'social.backends.google.GoogleOAuth2'
                    auth.login(request, migrated_user)
            user_profile = get_object_or_404(UserProfile, user_id=user_id)
        return render_json(request,
                           user_profile,
                           status=status,
                           template='user_profile.html',
                           help_text=profile.__doc__)
    elif request.method == 'POST':
        with transaction.atomic():
            to_save = json_body(request.body.decode("utf-8"))
            user_id = get_user_id(request)
            user_profile = get_object_or_404(UserProfile, user_id=user_id)
            user = to_save.get('user', None)
            if 'send_emails' in to_save:
                user_profile.send_emails = bool(to_save['send_emails'])
            if 'public' in to_save:
                user_profile.public = bool(to_save['public'])
            if user:
                error = _save_user(request, user, new=False)
                if error:
                    return render_json(request,
                                       error,
                                       template='user_json.html',
                                       status=400)
            if 'properties' in to_save:
                user_profile.save_properties(to_save['properties'])
            user_profile.save()
        request.method = "GET"
        return profile(request, status=202)
    else:
        return HttpResponseBadRequest("method %s is not allowed".format(
            request.method))
コード例 #26
0
ファイル: views.py プロジェクト: MatheusArrudaLab/proso-apps
def practice(request):
    """
    Return the given number of questions to practice adaptively. In case of
    POST request, try to save the answer(s).

    GET parameters:
        filter:
            list of lists of identifiers (may be prefixed by minus sign to
            mark complement)
        language:
            language (str) of flashcards
        avoid:
            list of item ids to avoid
        limit:
            number of returned questions (default 10, maximum 100)
        time:
            time in format '%Y-%m-%d_%H:%M:%S' used for practicing
        user:
            identifier for the practicing user (only for stuff users)
        stats:
            turn on the enrichment of the objects by some statistics
        html:
            turn on the HTML version of the API

    BODY:
        see answer resource
    """
    if request.user.id is None:  # Google Bot
        return render_json(request, {
            'error': _('There is no user available for the practice.'),
            'error_type': 'user_undefined'
        }, status=400, template='models_json.html')

    limit = min(int(request.GET.get('limit', 10)), 100)
    # prepare
    user = get_user_id(request)
    time = get_time(request)
    avoid = load_query_json(request.GET, "avoid", "[]")
    practice_filter = get_filter(request)
    practice_context = PracticeContext.objects.from_content(practice_filter)
    environment = get_environment()
    item_selector = get_item_selector()
    if is_time_overridden(request):
        environment.shift_time(time)

    # save answers
    if request.method == 'POST':
        _save_answers(request, practice_context)

    if len(practice_filter) > 0:
        item_ids = Item.objects.filter_all_reachable_leaves(practice_filter, get_language(request))
    else:
        item_ids = Item.objects.get_all_available_leaves()
    item_ids = list(set(item_ids) - set(avoid))
    if len(item_ids) == 0:
        return render_json(request, {
            'error': _('There is no item for the given filter to practice.'),
            'error_type': 'empty_practice'
        }, status=404, template='models_json.html')
    selected_items, meta = item_selector.select(environment, user, item_ids, time, practice_context.id, limit, items_in_queue=len(avoid))
    result = []
    for item, item_meta in zip(selected_items, meta):
        question = {
            'object_type': 'question',
            'payload': Item.objects.item_id_to_json(item),
        }
        if item_meta is not None:
            question['meta'] = item_meta
        result.append(question)

    return render_json(request, result, template='models_json.html', help_text=practice.__doc__)
コード例 #27
0
def questions_to_ask(request):
    language = get_language(request)
    user_id = get_user_id(request)
    questions = UserQuestion.objects.questions_to_ask(user_id, language)
    return render_json(request, list(questions), template='user_json.html')