def validate(blunder_id, user_line, spent_time, task_type): blunder = postgre.blunder.getBlunderById(blunder_id) if blunder is None: return {'status': 'error', 'message': "Invalid blunder id"} date_start = postgre.blunder.getTaskStartDate(session.userID(), blunder_id, task_type) blunder_move = blunder['blunder_move'] forced_line = blunder['forced_line'] if chess.mismatchCheck(blunder_move, forced_line, user_line): return { 'status': 'error', 'message': "Remote database has been changed" } success = chess.compareLines(blunder_move, forced_line, user_line) if not postgre.blunder.closeBlunderTask(session.userID(), blunder_id, task_type): return {'status': 'error', 'message': "Validation failed"} user_id = session.userID() user_elo = postgre.user.getRating(user_id) postgre.blunder.saveBlunderHistory(user_id, user_elo, blunder_id, blunder['elo'], success, user_line, date_start, spent_time) elo = blunder['elo'] newElo, delta = changeRating(session.userID(), blunder_id, success) return {'data': {'elo': newElo, 'delta': delta}, 'status': 'ok'}
def favoriteBlunder(): logger.info("API Handler blunder/favorite") if session.isAnonymous(): return { 'status': 'error', 'message': 'Favorites allowed only for authorized user' } try: blunder_id = request.json['blunder_id'] except Exception: return {'status': 'error', 'message': 'Blunder id required'} if not postgre.blunder.favoriteBlunder(session.userID(), blunder_id): return {'status': 'error', 'message': "Can't favorite blunder"} result = postgre.blunder.getBlunderInfoById(session.userID(), blunder_id) if result is None: return { 'status': 'error', 'message': 'Invalid blunder id', } return {'status': 'ok', 'data': result}
def voteBlunderComment(): logger.info("API Handler comment/vote") if session.isAnonymous(): return { 'status': 'error', 'message': 'Voting allowed only for authorized user' } try: blunder_id = request.json['blunder_id'] comment_id = request.json['comment_id'] vote = request.json['vote'] except Exception: return { 'status': 'error', 'message': 'Blunder id, comment id and vote required' } if postgre.blunder.blunderCommentAuthor(comment_id) == session.userID(): return {'status': 'error', 'message': "Can't vote for own comments"} if not postgre.blunder.voteBlunderComment(session.userID(), comment_id, vote): return {'status': 'error', 'message': "Can't vote comment"} result = postgre.blunder.getBlunderInfoById(session.userID(), blunder_id) if result is None: return { 'status': 'error', 'message': 'Invalid blunder id', } return {'status': 'ok', 'data': result}
def createPack(blunder_ids, pack_type_name, pack_type_args, pack_caption, pack_body): pack_id = postgre.pack.createPack(session.userID(), blunder_ids, pack_type_name, pack_type_args, pack_caption, pack_body) postgre.pack.assignPack(session.userID(), pack_id) return pack_id
def reusePack(pack_type_name, pack_type_args): pack_id = postgre.pack.reusePack(session.userID(), pack_type_name, pack_type_args) if (pack_id == None): return None postgre.pack.assignPack(session.userID(), pack_id) return pack_id
def getExploreBlunder(): blunder = postgre.blunder.getAssignedBlunder(session.userID(), const.tasks.EXPLORE) if 'id' in request.json: if blunder is not None: postgre.blunder.closeBlunderTask(session.userID(), request.json['id'], const.tasks.EXPLORE) blunder = postgre.blunder.getBlunderById(request.json['id']) else: if blunder is None: blunder = assignNewBlunder(const.tasks.EXPLORE) return { 'status': 'ok', 'data': utils.jsonifyBlunder(blunder) }
def calcualteWithEngine(blunder_id, blunder_fen, data): with Engine(const.engine.path) as engine: for element in data: if 'engine' in element: continue user_line = element['user']['line'] user_move = element['user']['move'] # Mathematical equality: element['user_line'] + element['user_move'] = user_line user_fen = chess.fenAfterVariation(blunder_fen, user_line) engine.new() engine.set(user_fen) element['engine'] = engine.think(const.engine.time, move=user_move) engine_line = element['engine']['line'] engine_score = element['engine']['score'] # TODO: calculating is long procedure. In order to avoid error, checking once more # In the future, after upgrade to 9.5 please use ON CONFLICT DO NOTHING if postgre.blunder.getAnalyze(blunder_id, user_line, user_move) is None: postgre.blunder.saveAnalyze(session.userID(), blunder_id, user_line, user_move, engine_line, engine_score, const.engine.time) return data
def getPackInfo(): logger.info("API Handler pack/info") try: pass except Exception: return { 'status': 'error', 'message': 'Unknown' } if(session.isAnonymous()): return { 'status': 'error', 'message': 'Working with packs in anonymous mode is not supported' } packs, unlocked = postgre.pack.getPacks(session.userID()) packs = [ postgre.pack.idToHashId(pack_id) for pack_id in packs] return { 'status':'ok', 'data': { 'packs': packs, 'unlocked': unlocked } }
def getPack(): logger.info("API Handler pack/get") try: hash_id = request.json['pack_id'] except Exception: return {'status': 'error', 'message': 'Pack id required'} pack_id = postgre.pack.hashIdToId(hash_id) if (pack_id is None): return { 'status': 'error', 'message': 'Pack with given hash id not found' } if (session.isAnonymous()): return { 'status': 'error', 'message': 'Working with packs in anonymous mode is not supported' } pack_info = postgre.pack.getPackInfo(pack_id) if pack_info is None: return {'status': 'error', 'message': 'This pack not exist'} caption = pack_info['caption'] body = pack_info['body'] blunder_ids = postgre.pack.getAssignedBlunders(session.userID(), pack_id) if blunder_ids is None: return {'status': 'error', 'message': 'This pack not assigned to user'} blunders = [{ 'get': utils.jsonifyBlunder(postgre.blunder.getBlunderById(blunder_id)), 'info': postgre.blunder.getBlunderInfoById(session.userID(), blunder_id) } for blunder_id in blunder_ids] return { 'status': 'ok', 'data': { 'caption': caption, 'body': body, 'pack_id': postgre.pack.idToHashId(pack_id), 'blunders': blunders } }
def commentBlunder(): logger.info("API Handler comment/send") if session.isAnonymous(): return { 'status': 'error', 'message': 'Commenting allowed only for authorized user' } try: blunder_id = request.json['blunder_id'] comment_id = request.json['comment_id'] user_input = request.json['user_input'] except Exception: return { 'status': 'error', 'message': 'Blunder id, input and comment_id required' } # Frontend uses 0 to say comment is the root comment, # but backend uses None for that if comment_id == 0: comment_id = None if len(user_input) > const.comment.MAX_SIZE: return { 'status': 'error', 'message': 'Input length can\'t be greater than %d' % MAX_MESSAGE_SIZE } if not postgre.blunder.commentBlunder(session.userID(), blunder_id, comment_id, user_input): return {'status': 'error', 'message': "Can't comment blunder"} result = postgre.blunder.getBlunderInfoById(session.userID(), blunder_id) if result is None: return { 'status': 'error', 'message': 'Invalid blunder id', } return {'status': 'ok', 'data': result}
def getRatedBlunder(): blunder = postgre.blunder.getAssignedBlunder(session.userID(), const.tasks.RATED) if blunder is None: blunder = assignNewBlunder(const.tasks.RATED) return { 'status': 'ok', 'data': utils.jsonifyBlunder(blunder) }
def validateExploreBlunder(blunder_id, user_line, spent_time): #pylint: disable=unused-argument if session.isAnonymous(): return {'status': 'ok'} # In explore mode, just remove blunder from task list # It is also ok, that there is no blunder to delete postgre.blunder.closeBlunderTask(session.userID(), blunder_id, const.tasks.EXPLORE) return {'status': 'ok'}
def validatePackBlunder(blunder_id, user_line, spent_time): # In pack mode, anonymous user can't validate, this is error if session.isAnonymous(): return { 'status': 'error', 'message': "Working with packs in anonymous mode is not supported" } result = validate(blunder_id, user_line, spent_time, const.tasks.PACK) # This is optional field, client should not rely on. Gets updated info of the position # so user can update it without need of sending separate info request result['data'].update({ 'info': postgre.blunder.getBlunderInfoById(session.userID(), blunder_id) }) # Remove user asociated packs which are complatelly solved postgre.pack.gcHistoryPacks(session.userID()) return result
def getBlunderInfo(): logger.info("API Handler blunder/info") try: blunder_id = request.json['blunder_id'] except Exception: return {'status': 'error', 'message': 'Blunder id required'} result = postgre.blunder.getBlunderInfoById(session.userID(), blunder_id) if result is None: return { 'status': 'error', 'message': 'Invalid blunder id', } return {'status': 'ok', 'data': result}
def removePack(): logger.info("API Handler pack/remove") try: hash_id = request.json['pack_id'] except Exception: return {'status': 'error', 'message': 'Pack id required'} pack_id = postgre.pack.hashIdToId(hash_id) if (pack_id is None): return { 'status': 'error', 'message': 'Pack with given hash id not found' } if (session.isAnonymous()): return { 'status': 'error', 'message': 'Working with packs in anonymous mode is not supported' } postgre.pack.removePack(session.userID(), pack_id, False) return {'status': 'ok'}
def getRating(): logger.info("API Handler session/rating") return {'status': 'ok', 'rating': postgre.user.getRating(session.userID())}
def assignNewBlunder(taskType): blunder = postgre.blunder.getRandomBlunder() postgre.blunder.assignBlunderTask(session.userID(), str(blunder['id']), taskType) return blunder
def newPackReplayFailed(pack_type_args, pack_caption, pack_body): blunder_ids = postgre.blunder.getBlunderForReplayFailed( session.userID(), const.pack.DEFAULT_SIZE) return createPack(blunder_ids, const.pack_type.REPLAYFAILED, {}, pack_caption, pack_body)
def packSelector(pack_type_name, pack_type_args_user): assigned_packs, unlocked_packs = postgre.pack.getPacks(session.userID()) pack_type_unlocked = [ pack for pack in unlocked_packs if pack['type_name'] == pack_type_name ] if len(pack_type_unlocked) > 1: return { # Duplicates in pack_type_name's in unlocked array are not allowed 'status': 'error', 'message': 'Internal error in algorithm of pack creation: %s' % pack_type_name } if len(pack_type_unlocked) != 1: return { 'status': 'error', 'message': 'Pack type name is not exist or locked for user: %s' % pack_type_name } pack_type_args_unlocked = pack_type_unlocked[0][ 'args'] if 'args' in pack_type_unlocked[0] else {} if not validateSelects(pack_type_args_user, pack_type_args_unlocked): return { # User's input is illegal 'status': 'error', 'message': 'Illegal input received from user: %s' % pack_type_name } # Setting new pack's description. Can be anything, changeable by user # Currently, we create empty body for pack, reserving it for future use. # For example, user might want to edit pack body pack_caption = pack_type_unlocked[0]['caption'] pack_body = '' #pack_type_unlocked[0]['body'] # Reuse pack mechanism. This keeps database from growing too much and # give better interaction experience between users pack_id = reusePack(pack_type_name, pack_type_args_user) if (pack_id != None): return { 'status': 'ok', 'data': { 'pack_id': postgre.pack.idToHashId(pack_id) } } if pack_type_name == const.pack_type.RANDOM: pack_id = newRandomPack(pack_caption, pack_body) elif pack_type_name == const.pack_type.MATEINN: pack_id = newMateInNPack(pack_type_args_user, pack_caption, pack_body) elif pack_type_name == const.pack_type.GRANDMASTERS: pack_id = newPackByTagName(pack_type_name, pack_caption, pack_body) elif pack_type_name == const.pack_type.OPENING: pack_id = newPackByTagName(pack_type_name, pack_caption, pack_body) elif pack_type_name == const.pack_type.ENDGAME: pack_id = newPackByTagName(pack_type_name, pack_caption, pack_body) elif pack_type_name == const.pack_type.PROMOTION: pack_id = newPackByTagName(pack_type_name, pack_caption, pack_body) elif pack_type_name == const.pack_type.CLOSEDGAME: pack_id = newPackByTagName(pack_type_name, pack_caption, pack_body) elif pack_type_name == const.pack_type.DIFFICULTYLEVELS: pack_id = newPackDifficultyLevels(pack_type_args_user, pack_caption, pack_body) elif pack_type_name == const.pack_type.REPLAYFAILED: pack_id = newPackReplayFailed(pack_type_args_user, pack_caption, pack_body) else: return { 'status': 'error', 'message': 'Pack type name not supported: %s' % pack_type_name } if pack_id is None: return { 'status': 'error', 'message': 'Internal error in algorithm of pack creation: %s' % pack_type_name } return { 'status': 'ok', 'data': { 'pack_id': postgre.pack.idToHashId(pack_id) } }