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
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
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
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')