def update_problem_score(user_id, user_skill_level, updated_categories):
    app.logger.info(f'update_problem_score called for: {user_id}, with skill: {user_skill_level}')
    problem_score_generator = ProblemScoreGenerator()
    problem_list = search_problems_filtered_by_categories(updated_categories)
    app.logger.info(f'problem_list found of size {len(problem_list)}')

    for problem in problem_list:
        problem_id = problem['id']
        up_edge = get_user_problem_status(user_id, problem_id)
        app.logger.info(f'initial up_edge {up_edge}')

        if up_edge is None:
            up_edge = {
                "problem_id": problem_id,
                "user_id": user_id,
                "relevant_score": 0,
                "status": "UNSOLVED"
            }

        if up_edge['status'] == "SOLVED":
            continue

        app.logger.info(f'after non check, up_edge {up_edge}')
        dcat_list = problem.get('categories', [])
        dcat_level_list = []
        app.logger.info(f'dcat_list: {dcat_list}')

        for cat in dcat_list:
            app.logger.info(f'cat: {cat}')
            category_id = cat['category_id']
            if category_id in updated_categories:
                uc_edge = updated_categories[category_id]
            else:
                uc_edge = get_user_category_data(user_id, category_id)
                if uc_edge is None:
                    uc_edge = {
                        "category_id": category_id,
                        "category_root": cat['category_root'],
                        "user_id": user_id,
                        "skill_value": 0,
                        "skill_level": 0,
                        "old_skill_level": 0,
                        "relevant_score": 0,
                        "solve_count": 0,
                        "skill_value_by_percentage": 0,
                    }
                    for d in range(1, 11):
                        key = 'scd_' + str(d)
                        uc_edge[key] = 0
                updated_categories[category_id] = uc_edge
            app.logger.info(f'uc_edge: {uc_edge}')
            dcat_level_list.append(uc_edge['skill_level'])
        app.logger.info(f'dcat_level_list: {dcat_level_list}')
        relevant_score = problem_score_generator.generate_score(int(float(problem['problem_difficulty'])), dcat_level_list, user_skill_level)
        up_edge['relevant_score'] = relevant_score['score']
        up_edge.pop('id', None)
        app.logger.info(f'final up_edge {up_edge}')
        add_user_problem_status(user_id, problem_id, up_edge)
        app.logger.info(f'user problem status added')
def generate_sync_data_for_problem(user_id, user_skill_level, problem):
    try:
        dependent_categories = find_problem_dependency_list(problem['id'])
        problem_score_generator = ProblemScoreGenerator()
        if problem['problem_type'] == 'classical':
            dependent_category_id_list = []
            for category in dependent_categories:
                category_id = category['category_id']
                dependent_category_id_list.append(category_id)
            dependent_dependent_category_list = find_category_dependency_list_for_multiple_categories(
                dependent_category_id_list)
            category_level_list = []
            for category_id in dependent_dependent_category_list:
                category_details = get_user_category_data(user_id, category_id)
                category_level = 0
                if category_details:
                    category_level = category_details.get('skill_level', 0)
                category_level_list.append(category_level)
            relevant_score = problem_score_generator.generate_score(
                int(float(problem['problem_difficulty'])), category_level_list,
                user_skill_level)
        else:
            category_level_list = []
            for category in dependent_categories:
                category_id = category['category_id']
                category_details = get_user_category_data(user_id, category_id)
                category_level = 0
                if category_details:
                    category_level = category_details.get('skill_level', 0)
                category_level_list.append(category_level)
            relevant_score = problem_score_generator.generate_score(
                int(float(problem['problem_difficulty'])), category_level_list,
                user_skill_level)
        data = {
            'problem_id': problem['id'],
            'relevant_score': relevant_score['score'],
            'user_id': user_id,
            'status': 'UNSOLVED'
        }
        return data
    except Exception as e:
        raise e
def generate_sync_data_for_category(user_id, category):
    try:
        category_skill_generator = CategorySkillGenerator()
        factor = float(category.get('factor', 1))
        skill_stat = category_skill_generator.generate_skill(
            category['solved_stat']['difficulty_wise_count'], factor)

        dependent_skill_level = []
        dependent_categories = find_category_dependency_list(
            category['category_id'])
        for dcat in dependent_categories:
            category_details = get_user_category_data(user_id,
                                                      dcat['category_id'])
            category_level = 0
            if category_details:
                category_level = category_details.get('skill_level', 0)
            dependent_skill_level.append(category_level)

        category_score_generator = CategoryScoreGenerator()
        cat_score = category_score_generator.generate_score(
            dependent_skill_level, skill_stat['level'])
        skill_obj = Skill()

        category_percentage = float(category.get('score_percentage', 100))

        data = {
            'relevant_score':
            cat_score['score'],
            'skill_value':
            skill_stat['skill'],
            'skill_value_by_percentage':
            float(skill_stat['skill']) * category_percentage / 100.0,
            'skill_level':
            skill_stat['level'],
            'skill_title':
            skill_obj.get_skill_title(skill_stat['skill']),
            'solve_count':
            category['solved_stat']['total_count'],
            'category_root':
            category['category_root'],
        }

        return data
    except Exception as e:
        raise e
Beispiel #4
0
def get_category_details(cat_id, user_id=None):
    app.logger.info(
        f'get_category_details function called for cat_id: {cat_id}, user_id: {user_id}'
    )
    try:
        rs = requests.session()
        search_url = 'http://{}/{}/{}/{}'.format(app.config['ES_HOST'],
                                                 _es_index_category, _es_type,
                                                 cat_id)
        response = rs.get(url=search_url, headers=_http_headers).json()
        if 'found' in response:
            if response['found']:
                data = response['_source']
                data['category_id'] = response['_id']
                data['comment_list'] = get_comment_list(response['_id'])
                data['vote_count'] = get_vote_count_list(response['_id'])
                data['comment_count'] = get_comment_count(response['_id'])
                data['resource_list'] = search_resource(
                    {'resource_ref_id': response['_id']}, 0, _es_size)
                data['problem_count'] = 0
                if data['category_root'] == 'root':
                    data['problem_count'] = get_problem_count_for_category(
                        {'category_root': data['category_name']})
                else:
                    data['problem_count'] = get_problem_count_for_category(
                        {'category_name': data['category_name']})

                if user_id:
                    cat_info = get_user_category_data(user_id,
                                                      data['category_id'])
                    if cat_info:
                        skill_value = float(cat_info.get('skill_value', 0))
                        data['skill_value'] = "{:.2f}".format(skill_value)
                        skill = Skill()
                        data['skill_title'] = skill.get_skill_title(
                            skill_value)
                    else:
                        data['skill_value'] = 0
                        data['skill_title'] = "NA"
                app.logger.info('get_category_details completed')
                return data
        return None
    except Exception as e:
        raise e
def sync_problems(user_id, oj_problem_set):
    app.logger.info(f'sync_problems called for {user_id}')
    try:
        category_score_generator = CategoryScoreGenerator()
        updated_categories = {}
        root_category_solve_count = {}

        for problem_set in oj_problem_set:
            # Change here
            for problem in problem_set['problem_list']:
                problem_stat = problem_set['problem_list'][problem]
                submission_list = problem_stat['submission_list']
                problem_db = search_problems({'problem_id': problem, 'oj_name': problem_set['oj_name'], 'active_status': approved}, 0, 1)
                if len(problem_db) == 0:
                    continue
                problem_id = problem_db[0]['id']
                if len(problem_db) > 1:
                    app.logger.error('Multiple problem with same id found')
                apply_solved_problem_for_user(user_id, problem_id, problem_db[0], submission_list, updated_categories, root_category_solve_count)

        app.logger.info('apply_solved_problem_for_user completed for all problems')
        marked_categories = dict(updated_categories)

        for category_id in marked_categories:
            app.logger.info(f'category id inside marked_categories: {category_id}')
            uc_edge = marked_categories[category_id]
            app.logger.info(f'uc_edge 1: {uc_edge}')
            # UPDATE OWN CONTRIBUTION
            old_cont = category_score_generator.get_own_difficulty_based_score(uc_edge['old_skill_level'])
            new_cont = category_score_generator.get_own_difficulty_based_score(uc_edge['skill_level'])
            cont_dx = new_cont - old_cont
            uc_edge['relevant_score'] += cont_dx
            app.logger.info(f'uc_edge 2: {uc_edge}')
            updated_categories[category_id] = uc_edge
            # UPDATE DEPENDENT CATEGORY CONTRIBUTION
            dependent_cat_list = find_dependent_category_list(category_id)
            app.logger.info(f'dependent_cat_list: {dependent_cat_list}')
            for dcat in dependent_cat_list:
                dcat_id = dcat['category_id']
                dcat_category_root = dcat['category_info']['category_root']
                app.logger.info(f'dcat_category_root: {dcat_category_root}')
                if dcat_id in updated_categories:
                    dcat_uc_edge = updated_categories[dcat_id]
                else:
                    dcat_uc_edge = get_user_category_data(user_id, dcat_id)

                if dcat_uc_edge is None:
                    dcat_uc_edge = {
                        "category_id": dcat_id,
                        "category_root": dcat_category_root,
                        "user_id": user_id,
                        "skill_value": 0,
                        "skill_level": 0,
                        "old_skill_level": 0,
                        "relevant_score": 0,
                        "solve_count": 0,
                        "skill_value_by_percentage": 0,
                    }
                    for d in range(1, 11):
                        key = 'scd_' + str(d)
                        dcat_uc_edge[key] = 0

                dependency_percentage = float(dcat['dependency_percentage'])
                old_cont = category_score_generator.get_dependent_score(uc_edge['old_skill_level'], dependency_percentage)
                new_cont = category_score_generator.get_dependent_score(uc_edge['skill_level'], dependency_percentage)
                cont_dx = new_cont - old_cont
                dcat_uc_edge['relevant_score'] += cont_dx

                app.logger.info(f'dcat_uc_edge: {dcat_uc_edge}')
                updated_categories[dcat_id] = dcat_uc_edge

        app.logger.info('process of mark categories completed')

        for category_id in updated_categories:
            uc_edge = updated_categories[category_id]
            uc_edge.pop('old_skill_level', None)
            uc_edge.pop('id', None)
            add_user_category_data(user_id, category_id, uc_edge)

        app.logger.info('updated root categories')
        root_category_list = search_categories({"category_root": "root"}, 0, _es_size)
        skill = Skill()
        user_skill = update_root_category_skill_for_user(user_id, root_category_list, root_category_solve_count)
        user_skill_level = skill.get_skill_level_from_skill(user_skill)
        app.logger.info(f'Final user_skill: {user_skill}, user_skill_level: {user_skill_level}')
        sync_overall_stat_for_user(user_id, user_skill)
        app.logger.info('sync_overall_stat_for_user completed')
        if len(updated_categories) > 0:
            update_problem_score(user_id, user_skill_level, updated_categories)
        app.logger.info(f'sync_problems completed for {user_id}')
    except Exception as e:
        raise e
Beispiel #6
0
def search_categories(param, from_value, size_value, heavy=False):
    try:
        query_json = {'query': {'match_all': {}}}
        rs = requests.session()

        must = []
        keyword_fields = ['category_title', 'category_root']
        user_id = param.get('user_id', None)
        print('search_categories: body: ', param)
        param.pop('user_id', None)

        minimum_difficulty = 0
        maximum_difficulty = 100

        if 'minimum_difficulty' in param and param['minimum_difficulty']:
            minimum_difficulty = int(param['minimum_difficulty'])

        if 'maximum_difficulty' in param and param['maximum_difficulty']:
            maximum_difficulty = int(param['maximum_difficulty'])

        param.pop('minimum_difficulty', None)
        param.pop('maximum_difficulty', None)

        for f in param:
            if f in keyword_fields:
                if param[f]:
                    must.append({'term': {f: param[f]}})
            else:
                if param[f]:
                    must.append({'match': {f: param[f]}})

        must.append({
            "range": {
                "category_difficulty": {
                    "gte": minimum_difficulty,
                    "lte": maximum_difficulty
                }
            }
        })

        if len(must) > 0:
            query_json = {'query': {'bool': {'must': must}}}

        if 'category_root' not in param:
            if 'query' in query_json and 'bool' in query_json['query']:
                query_json['query']['bool']['must_not'] = [{
                    'term': {
                        'category_root': 'root'
                    }
                }]
            else:
                query_json = {
                    'query': {
                        'bool': {
                            'must_not': [{
                                'term': {
                                    'category_root': 'root'
                                }
                            }]
                        }
                    }
                }

        query_json['from'] = from_value
        query_json['size'] = size_value
        print('query_json: ', json.dumps(query_json))
        search_url = 'http://{}/{}/{}/_search'.format(app.config['ES_HOST'],
                                                      _es_index_category,
                                                      _es_type)
        response = rs.post(url=search_url,
                           json=query_json,
                           headers=_http_headers).json()
        # print('response: ', response)
        item_list = []
        if 'hits' in response:
            for hit in response['hits']['hits']:
                category = hit['_source']
                category['category_id'] = hit['_id']
                category['problem_count'] = 0
                category['solve_count'] = 0
                if category['category_root'] == 'root':
                    category['problem_count'] = get_problem_count_for_category(
                        {'category_root': category['category_name']})
                else:
                    category['problem_count'] = get_problem_count_for_category(
                        {'category_name': category['category_name']})

                if user_id:
                    cat_info = get_user_category_data(user_id,
                                                      category['category_id'])
                    if cat_info is not None:
                        category['solve_count'] = cat_info.get(
                            'solve_count', 0)
                if heavy:
                    category[
                        'category_dependency_list'] = find_category_dependency_list(
                            category['category_id'])

                item_list.append(category)
            return item_list
        app.logger.error('Elasticsearch down, response: ' + str(response))
        return item_list
    except Exception as e:
        raise e
Beispiel #7
0
def apply_solved_problem_for_user(user_id, problem_id, problem_details,
                                  submission_list, updated_categories,
                                  root_category_solve_count):
    app.logger.info(
        f'apply_solved_problem_for_user for user_id: {user_id}, problem_id: {problem_id}'
    )
    app.logger.info('current updated_categories: ' +
                    json.dumps(updated_categories))
    try:
        skill_info = Skill()
        up_edge = get_user_problem_status(user_id, problem_id)
        if up_edge is not None and up_edge['status'] == SOLVED:
            return
        rs = requests.session()
        data = {
            'user_id': user_id,
            'problem_id': problem_id,
            'submission_list': submission_list,
            'status': SOLVED
        }
        # Insert User Problem Solved Status Here
        post_url = 'http://{}/{}/{}'.format(app.config['ES_HOST'],
                                            _es_index_problem_user, _es_type)
        response = rs.post(url=post_url, json=data,
                           headers=_http_headers).json()

        if 'result' not in response:
            raise Exception('Internal server error')

        # Update dependent category skill
        problem_difficulty = problem_details['problem_difficulty']
        app.logger.info(f'problem_difficulty: {problem_difficulty}')
        dep_cat_list = problem_details.get('categories', [])
        cat_skill_model = CategorySkillGenerator()
        marked_roots = {}
        for cat in dep_cat_list:
            app.logger.info(f'dept cat: {cat}')
            category_id = cat['category_id']
            category_details = get_category_details(category_id)
            category_root = category_details['category_root']
            app.logger.info(f'category_root: {category_root}')
            if category_root not in marked_roots:
                if category_root not in root_category_solve_count:
                    root_category_solve_count[category_root] = 0
                root_category_solve_count[category_root] += 1
                marked_roots[category_root] = 1
            if category_id in updated_categories:
                uc_edge = updated_categories[category_id]
            else:
                uc_edge = get_user_category_data(user_id, category_id)
                if uc_edge:
                    uc_edge['old_skill_level'] = uc_edge['skill_level']
                    uc_edge.pop('id', None)
            app.logger.info(f'uc_edge from es: {uc_edge}')
            if uc_edge is None:
                uc_edge = {
                    "category_id": category_id,
                    "category_root": category_root,
                    "user_id": user_id,
                    "skill_value": 0,
                    "skill_level": 0,
                    "old_skill_level": 0,
                    "relevant_score": 0,
                    "solve_count": 0,
                    "skill_value_by_percentage": 0,
                }
                for d in range(1, 11):
                    key = 'scd_' + str(d)
                    uc_edge[key] = 0

            app.logger.info(f'current uc_edge: {uc_edge}')
            dif_key = 'scd_' + str(int(problem_difficulty))
            uc_edge[dif_key] += 1
            problem_factor = category_details.get('factor', 1)
            added_skill = cat_skill_model.get_score_for_latest_solved_problem(
                problem_difficulty, uc_edge[dif_key], problem_factor)
            uc_edge['skill_value'] += added_skill
            uc_edge['solve_count'] += 1
            uc_edge['skill_title'] = skill_info.get_skill_title(
                uc_edge['skill_value'])
            uc_edge['skill_level'] = skill_info.get_skill_level_from_skill(
                uc_edge['skill_value'])
            score_percentage = float(category_details['score_percentage'])
            uc_edge['skill_value_by_percentage'] = uc_edge[
                'skill_value'] * score_percentage / 100
            app.logger.info(f'add uc_edge: {uc_edge}')
            updated_categories[category_id] = uc_edge
            app.logger.info(f'saved at category_id: {category_id}')
    except Exception as e:
        app.logger.error(f'Exception occurred: {e}')
        raise Exception('Internal server error')