def process_closest_to_bull(game, score_value, computer=False): if score_value > 60: return closest_to_bull_json = json.loads(game.closest_to_bull_json) # local game if game.player1 == game.player2: player = '2' if (len(closest_to_bull_json['1']) % 3 == 0) and \ (len(closest_to_bull_json['1']) > len(closest_to_bull_json['2'])) else '1' # computer game elif computer: player = '2' # online game else: player = '1' if game.player1 == current_user.id else '2' other_player = '1' if player == '2' else '2' # check if player has to wait for other player if len(closest_to_bull_json[player]) % 3 == 0 \ and len(closest_to_bull_json[player]) > len(closest_to_bull_json[other_player]): return # append score if score_value in (25, 50): closest_to_bull_json[player].append(score_value) else: closest_to_bull_json[player].append(0) game.closest_to_bull_json = json.dumps(closest_to_bull_json) db.session.commit() # check if both threw 3 darts if len(closest_to_bull_json[player]) % 3 == 0 \ and (len(closest_to_bull_json[player]) == len(closest_to_bull_json[other_player])): # check if done for i in range(len(closest_to_bull_json[player])): if closest_to_bull_json['1'][i] > closest_to_bull_json['2'][i]: # player 1 won game.p1_next_turn = True game.closest_to_bull = False db.session.commit() emit('closest_to_bull_completed', { 'hashid': game.hashid, 'p1_won': game.p1_next_turn, 'p1_score': closest_to_bull_json['1'][-3:], 'p2_score': closest_to_bull_json['2'][-3:] }, room=game.hashid, broadcast=True) socketio.sleep(0) return elif closest_to_bull_json['1'][i] < closest_to_bull_json['2'][i]: # player 2 won game.p1_next_turn = False game.closest_to_bull = False db.session.commit() emit('closest_to_bull_completed', { 'hashid': game.hashid, 'p1_won': game.p1_next_turn, 'p1_score': closest_to_bull_json['1'][-3:], 'p2_score': closest_to_bull_json['2'][-3:] }, room=game.hashid, broadcast=True) socketio.sleep(0) return # draw, next round emit('closest_to_bull_draw', { 'hashid': game.hashid, 'p1_score': closest_to_bull_json['1'][-3:], 'p2_score': closest_to_bull_json['2'][-3:] }, room=game.hashid, broadcast=True) socketio.sleep(0) return # emit throw score to players if len(closest_to_bull_json['1']) % 3 == 1: p1_score = closest_to_bull_json['1'][-1:] elif len(closest_to_bull_json['1']) % 3 == 2: p1_score = closest_to_bull_json['1'][-2:] elif len(closest_to_bull_json['1']) % 3 == 0 \ and len(closest_to_bull_json['1']) > len(closest_to_bull_json['2']): p1_score = closest_to_bull_json['1'][-3:] else: p1_score = [] if len(closest_to_bull_json['2']) % 3 == 1: p2_score = closest_to_bull_json['2'][-1:] elif len(closest_to_bull_json['2']) % 3 == 2: p2_score = closest_to_bull_json['2'][-2:] elif len(closest_to_bull_json['2']) % 3 == 0 \ and len(closest_to_bull_json['2']) > len(closest_to_bull_json['1']): p2_score = closest_to_bull_json['2'][-3:] else: p2_score = [] emit('closest_to_bull_score', { 'hashid': game.hashid, 'p1_score': p1_score, 'p2_score': p2_score }, room=game.hashid, broadcast=True) socketio.sleep(0) return
def create_statistics(user, form, use_custom_filter_last_games, use_custom_filter_date_range): """ this function builds the statistics for the given games and filter criterias """ # build the query and select the the games games = create_statistics_query(user, form).all() # create the stats object stats = { 'today': create_stats_object(), 'currentweek': create_stats_object(), 'currentmonth': create_stats_object(), 'currentyear': create_stats_object(), 'overall': create_stats_object(), 'custom': create_stats_object(), 'averagepergame': [] } # get the dates for date related statistics today_date = datetime.today().date() start_current_week = today_date - timedelta(days=today_date.weekday()) start_current_month = today_date.replace(day=1) number_of_games = 0 # iterate through each game for game in games: socketio.sleep(0) # hack for legacy games on lidarts.org which do not have double-missed and finish darts if game.id < 18: continue game_begin_date = game.begin.date() player = '1' if not user.id == game.player1: player = '2' number_of_games += 1 # check if game is valid for the current custom filter settings valid_game_for_custom_filter = False if use_custom_filter_last_games and number_of_games <= form.number_of_games.data: valid_game_for_custom_filter = True elif use_custom_filter_date_range and form.date_from.data <= game_begin_date <= form.date_to.data: valid_game_for_custom_filter = True # custom filter if valid_game_for_custom_filter: calculate_overall_stats_from_game(stats['custom'], game, player) # use for today statistics? if game_begin_date == today_date: calculate_overall_stats_from_game(stats['today'], game, player) # use current week statistics? if game_begin_date >= start_current_week: calculate_overall_stats_from_game(stats['currentweek'], game, player) # use current month statistics? if game_begin_date >= start_current_month: calculate_overall_stats_from_game(stats['currentmonth'], game, player) # use current year statistics? if game_begin_date.year >= today_date.year: calculate_overall_stats_from_game(stats['currentyear'], game, player) # overall stats calculate_overall_stats_from_game(stats['overall'], game, player) match_json = json.loads(game.match_json) # calculate current game stats current_game_stats = {'darts_thrown': 0, 'total_score': 0} # iterate through each set/leg and calculate the corresponding statistics calculate_set_leg_statistics(match_json, player, current_game_stats, valid_game_for_custom_filter, stats, game_begin_date, today_date, start_current_week, start_current_month) # sum up average per game stats game_average = round((current_game_stats['total_score'] / (current_game_stats['darts_thrown'])) * 3, 2) \ if current_game_stats['darts_thrown'] else 0 stats['averagepergame'].append(game_average) # sum up all the stats sum_up_stats(stats['custom']) sum_up_stats(stats['today']) sum_up_stats(stats['currentweek']) sum_up_stats(stats['currentmonth']) sum_up_stats(stats['currentyear']) sum_up_stats(stats['overall']) # invert the list for averagepergame (we need the date from the oldest game to newest game) stats['averagepergame'].reverse() return stats
def send_score(message): hashid = message['hashid'] game = Game.query.filter_by(hashid=hashid).first() if 'computer' in message and not game.p1_next_turn: # calculate computer's score message['score'], message['double_missed'], message[ 'to_finish'] = get_computer_score(message['hashid']) socketio.sleep(0) elif 'score' not in message or not message['score']: return # players may throw simultaneously at closest to bull # exception needed for undoing score if it's not your turn elif int(message['user_id']) != current_turn_user_id(message['hashid']) and not game.closest_to_bull \ and not message['undo_active']: return # spectators should never submit scores :-) elif int(message['user_id']) not in (game.player1, game.player2): return try: score_value = int(message['score']) impossible_numbers = [179, 178, 176, 175, 173, 172, 169] if not 0 <= score_value <= 180 or score_value in impossible_numbers: return except: return # Closest to bull handler to determine starting player if game.closest_to_bull: process_closest_to_bull(game, score_value) if game.opponent_type.startswith('computer'): # computer's attempt at double bullseye score = get_computer_score(game.hashid) process_closest_to_bull(game, score, computer=True) return match_json = json.loads(game.match_json) # undo input handler if 'undo_active' in message and message['undo_active'] is True: current_set = str(game.p1_sets + game.p2_sets + 1) current_leg = str(game.p1_legs + game.p2_legs + 1) if current_user.id == game.player1 and current_user.id == game.player2: undo_player = '2' if game.p1_next_turn else '1' elif current_user.id == game.player1: undo_player = '1' else: undo_player = '2' # if no checkout just change score silently if sum(match_json[current_set][current_leg][undo_player]['scores'] [:-1]) + score_value > game.type: match_json[current_set][current_leg][undo_player]['scores'][-1] = 0 match_json[current_set][current_leg][undo_player]['double_missed'][ -1] = int(message['double_missed']) if undo_player == '1': game.p1_score = game.type - sum( match_json[current_set][current_leg][undo_player] ['scores']) else: game.p2_score = game.type - sum( match_json[current_set][current_leg][undo_player] ['scores']) game.match_json = json.dumps(match_json) db.session.commit() send_score_response(game, broadcast=False) return elif sum(match_json[current_set][current_leg][undo_player]['scores'] [:-1]) + score_value < game.type: match_json[current_set][current_leg][undo_player]['scores'][ -1] = score_value match_json[current_set][current_leg][undo_player]['double_missed'][ -1] = int(message['double_missed']) if undo_player == '1': game.p1_score = game.type - sum( match_json[current_set][current_leg][undo_player] ['scores']) else: game.p2_score = game.type - sum( match_json[current_set][current_leg][undo_player] ['scores']) game.match_json = json.dumps(match_json) db.session.commit() send_score_response(game, broadcast=False) return # checkout - revert scores and proceed normally else: # rollback to handle end of leg if (undo_player == '1' and game.p1_next_turn) or (undo_player == '2' and not game.p1_next_turn): # other player already entered score - rollback both, don't change p1_next_turn match_json[current_set][current_leg]['1']['scores'].pop() match_json[current_set][current_leg]['1']['double_missed'].pop( ) match_json[current_set][current_leg]['2']['scores'].pop() match_json[current_set][current_leg]['2']['double_missed'].pop( ) game.p1_score = game.type - sum( match_json[current_set][current_leg]['1']['scores']) game.p2_score = game.type - sum( match_json[current_set][current_leg]['2']['scores']) else: # other player did not enter score - rollback undo player, toggle p1_next_turn match_json[current_set][current_leg][undo_player][ 'scores'].pop() match_json[current_set][current_leg][undo_player][ 'double_missed'].pop() game.p1_next_turn = not game.p1_next_turn if undo_player == '1': game.p1_score = game.type - sum( match_json[current_set][current_leg][undo_player] ['scores']) else: game.p2_score = game.type - sum( match_json[current_set][current_leg][undo_player] ['scores']) game.match_json = json.dumps(match_json) db.session.commit() # keep old score to display game shot if finish old_score = game.p1_score if game.p1_next_turn else game.p2_score old_set_count = len(match_json) old_leg_count = len(match_json[str(len(match_json))]) socketio.sleep(0) game = process_score(game, score_value, int(message['double_missed']), int(message['to_finish'])) socketio.sleep(0) # check for match_json updates match_json = json.loads(game.match_json) if game.status == 'completed': last_set = match_json[str(len(match_json))] last_leg = last_set[str(len(last_set))] p1_last_leg = last_leg['1']['scores'] p2_last_leg = last_leg['2']['scores'] p1_won = sum(p1_last_leg) == game.type # calculate cached stats if game.type == 501 and game.in_mode == 'si' and game.out_mode == 'do': rq_job = current_app.task_queue.enqueue( 'lidarts.tasks.calc_cached_stats', game.player1) if game.player2 and game.player1 != game.player2: rq_job = current_app.task_queue.enqueue( 'lidarts.tasks.calc_cached_stats', game.player2) emit('game_completed', { 'hashid': game.hashid, 'p1_last_leg': p1_last_leg, 'p2_last_leg': p2_last_leg, 'p1_won': p1_won, 'type': game.type, 'p1_sets': game.p1_sets, 'p2_sets': game.p2_sets, 'p1_legs': game.p1_legs, 'p2_legs': game.p2_legs, 'to_finish': message['to_finish'], }, room=game.hashid, broadcast=True, namespace='/game') elif old_set_count < len(match_json) or old_leg_count < len(match_json[str( len(match_json))]): if len(match_json[str(len(match_json))]) == 1: # new set last_set = match_json[str(len(match_json) - 1)] last_leg = last_set[str(len(last_set))] else: # no new set last_set = match_json[str(len(match_json))] last_leg = last_set[str(len(last_set) - 1)] p1_last_leg = last_leg['1']['scores'] p2_last_leg = last_leg['2']['scores'] p1_won = sum(p1_last_leg) == game.type emit('game_shot', { 'hashid': game.hashid, 'p1_last_leg': p1_last_leg, 'p2_last_leg': p2_last_leg, 'p1_won': p1_won, 'type': game.type, 'p1_sets': game.p1_sets, 'p2_sets': game.p2_sets, 'p1_legs': game.p1_legs, 'p2_legs': game.p2_legs, 'to_finish': message['to_finish'], }, room=game.hashid, broadcast=True, namespace='/game') else: send_score_response(game, old_score, broadcast=True)
def send_score(message): hashid = message['hashid'] game = CricketGame.query.filter_by(hashid=hashid).first() if 'computer' in message and not game.p1_next_turn: if game.confirmation_needed: confirm_score(message, computer=True) return # calculate computer's score message['score'] = get_computer_score(message['hashid']) elif message['score'] == '': # confirm function for keyboard confirm_score(message) return elif game.confirmation_needed: return # players may throw simultaneously at closest to bull elif int(message['user_id']) != current_turn_user_id( message['hashid'], True) and not game.closest_to_bull: return # spectators should never submit scores :-) elif int(message['user_id']) not in (game.player1, game.player2): return score_value = int(message['score']) if score_value not in (15, 16, 17, 18, 19, 20, 25, 30, 32, 34, 36, 38, 40, 45, 48, 50, 51, 54, 57, 60): score_value = 0 # Closest to bull handler to determine starting player if game.closest_to_bull: process_closest_to_bull(game, score_value) if game.opponent_type.startswith('computer'): # computer's attempt at double bullseye score = get_computer_score(game.hashid) process_closest_to_bull(game, score, computer=True) return match_json = json.loads(game.match_json) # keep old score to display game shot if finish p1_old_score = game.p1_score p2_old_score = game.p2_score old_set_count = len(match_json) old_leg_count = len(match_json[str(len(match_json))]) socketio.sleep(0) game = process_score(game, score_value) socketio.sleep(0) # check for match_json updates match_json = json.loads(game.match_json) if game.status == 'completed': last_set = match_json[str(len(match_json))] last_leg = last_set[str(len(last_set))] p1_last_score = last_leg['1']['points'] p2_last_score = last_leg['2']['points'] p1_won = last_leg['1']['points'] > last_leg['2']['points'] # determine dart count in last round winning_player = '1' if p1_won else '2' to_finish = len(last_leg[winning_player]['scores'][-1]) stats = calculate_footer_stats(match_json) emit('game_completed', { 'hashid': game.hashid, 'p1_won': p1_won, 'p1_last_score': p1_last_score, 'p2_last_score': p2_last_score, 'p1_old_score': p1_old_score, 'p2_old_score': p2_old_score, 'p1_sets': game.p1_sets, 'p2_sets': game.p2_sets, 'p1_legs': game.p1_legs, 'p2_legs': game.p2_legs, 'p1_next_turn': game.p1_next_turn, 'p1_current_leg': stats['p1_current_leg_scores'], 'p2_current_leg': stats['p2_current_leg_scores'], 'p1_current_fields': stats['p1_current_leg_fields'], 'p2_current_fields': stats['p2_current_leg_fields'], 'p1_leg_mpr': stats['p1_leg_mpr'], 'p2_leg_mpr': stats['p2_leg_mpr'], 'to_finish': to_finish, 'p1_match_mpr': stats['p1_match_mpr'], 'p2_match_mpr': stats['p2_match_mpr'], }, room=game.hashid, broadcast=True, namespace='/game/cricket') elif old_set_count < len(match_json) or old_leg_count < len(match_json[str( len(match_json))]): if len(match_json[str(len(match_json))]) == 1: # new set last_set = match_json[str(len(match_json) - 1)] last_leg = last_set[str(len(last_set))] else: # no new set last_set = match_json[str(len(match_json))] last_leg = last_set[str(len(last_set) - 1)] p1_last_score = last_leg['1']['points'] p2_last_score = last_leg['2']['points'] p1_won = last_leg['1']['points'] > last_leg['2']['points'] stats = calculate_footer_stats(match_json, last_leg=True) # determine dart count in last round winning_player = '1' if p1_won else '2' to_finish = len(last_leg[winning_player]['scores'][-1]) emit('game_shot', { 'hashid': game.hashid, 'p1_last_score': p1_last_score, 'p2_last_score': p2_last_score, 'p1_old_score': p1_old_score, 'p2_old_score': p2_old_score, 'p1_won': p1_won, 'p1_sets': game.p1_sets, 'p2_sets': game.p2_sets, 'p1_legs': game.p1_legs, 'p2_legs': game.p2_legs, 'p1_next_turn': game.p1_next_turn, 'p1_current_leg': stats['p1_current_leg_scores'], 'p2_current_leg': stats['p2_current_leg_scores'], 'p1_current_fields': stats['p1_current_leg_fields'], 'p2_current_fields': stats['p2_current_leg_fields'], 'p1_leg_mpr': stats['p1_leg_mpr'], 'p2_leg_mpr': stats['p2_leg_mpr'], 'p1_match_mpr': stats['p1_match_mpr'], 'p2_match_mpr': stats['p2_match_mpr'], 'to_finish': to_finish, }, room=game.hashid, broadcast=True, namespace='/game/cricket') else: send_score_response(game, p1_old_score, p2_old_score, broadcast=True)
def send_score_response(game, old_score=0, broadcast=False): match_json = json.loads(game.match_json) current_set = str(len(match_json)) current_leg = str(len(match_json[str(len(match_json))])) p1_current_leg_scores = match_json[current_set][current_leg]['1']['scores'] p2_current_leg_scores = match_json[current_set][current_leg]['2']['scores'] # various statistics for footer p1_leg_avg = round( sum(p1_current_leg_scores) / len(p1_current_leg_scores), 2) if len(p1_current_leg_scores) else 0 p2_leg_avg = round( sum(p2_current_leg_scores) / len(p2_current_leg_scores), 2) if len(p2_current_leg_scores) else 0 p1_180 = 0 p2_180 = 0 p1_140 = 0 p2_140 = 0 p1_100 = 0 p2_100 = 0 p1_scores = [] p2_scores = [] p1_first9_scores = [] p2_first9_scores = [] p1_high_finish = 0 p2_high_finish = 0 p1_short_leg = 0 p2_short_leg = 0 p1_darts_thrown = 0 p1_darts_thrown_double = 0 p1_legs_won = 0 p2_darts_thrown = 0 p2_darts_thrown_double = 0 p2_legs_won = 0 for set in match_json: for leg in match_json[set]: socketio.sleep(0) p1_darts_thrown_double += sum( match_json[set][leg]['1']['double_missed']) p2_darts_thrown_double += sum( match_json[set][leg]['2']['double_missed']) p1_darts_thrown_this_leg = len( match_json[set][leg]['1']['scores']) * 3 p2_darts_thrown_this_leg = len( match_json[set][leg]['2']['scores']) * 3 if sum(match_json[set][leg]['1']['scores']) == game.type: if 'to_finish' in match_json[set][leg]['1']: p1_darts_thrown_this_leg -= ( 3 - match_json[set][leg]['1']['to_finish']) p1_darts_thrown_double += 1 p1_legs_won += 1 p1_short_leg = p1_darts_thrown_this_leg if p1_short_leg == 0 else p1_short_leg p1_short_leg = p1_darts_thrown_this_leg \ if p1_darts_thrown_this_leg < p1_short_leg else p1_short_leg p1_high_finish = match_json[set][leg]['1']['scores'][-1] \ if match_json[set][leg]['1']['scores'][-1] > p1_high_finish else p1_high_finish if sum(match_json[set][leg]['2']['scores']) == game.type: if 'to_finish' in match_json[set][leg]['2']: p2_darts_thrown_this_leg -= ( 3 - match_json[set][leg]['2']['to_finish']) p2_darts_thrown_double += 1 # better: p2_darts_thrown_double = legs_won + double_missed p2_legs_won += 1 p2_short_leg = p2_darts_thrown_this_leg if p2_short_leg == 0 else p2_short_leg p2_short_leg = p2_darts_thrown_this_leg \ if p2_darts_thrown_this_leg < p2_short_leg else p2_short_leg p2_high_finish = match_json[set][leg]['2']['scores'][-1] \ if match_json[set][leg]['2']['scores'][-1] > p2_high_finish else p2_high_finish p1_darts_thrown += p1_darts_thrown_this_leg p2_darts_thrown += p2_darts_thrown_this_leg for i, score in enumerate(match_json[set][leg]['1']['scores']): p1_scores.append(score) if i <= 2: p1_first9_scores.append(score) if score == 180: p1_180 += 1 elif score >= 140: p1_140 += 1 elif score >= 100: p1_100 += 1 for i, score in enumerate(match_json[set][leg]['2']['scores']): p2_scores.append(score) if i <= 2: p2_first9_scores.append(score) if score == 180: p2_180 += 1 elif score >= 140: p2_140 += 1 elif score >= 100: p2_100 += 1 p1_match_avg = round(sum(p1_scores) * 3 / (p1_darts_thrown), 2) if p1_scores else 0 p2_match_avg = round(sum(p2_scores) * 3 / (p2_darts_thrown), 2) if p2_scores else 0 p1_first9_avg = round(sum(p1_first9_scores) / len(p1_first9_scores), 2) if p1_first9_scores else 0 p2_first9_avg = round(sum(p2_first9_scores) / len(p2_first9_scores), 2) if p2_first9_scores else 0 p1_doubles = int( p1_legs_won / p1_darts_thrown_double * 10000) / 100 if p1_legs_won and p1_darts_thrown_double else 0 p2_doubles = int( p2_legs_won / p2_darts_thrown_double * 10000) / 100 if p2_legs_won and p2_darts_thrown_double else 0 p1_started_leg = (len(p1_current_leg_scores) > len(p2_current_leg_scores) or (len(p1_current_leg_scores) == len(p2_current_leg_scores) and game.p1_next_turn)) p2_started_leg = not p1_started_leg p1_checkout_suggestion = checkout_suggestions[game.p1_score].replace( '-', ' ') if game.p1_score in checkout_suggestions else None p2_checkout_suggestion = checkout_suggestions[game.p2_score].replace( '-', ' ') if game.p2_score in checkout_suggestions else None computer_game = game.opponent_type.startswith('computer') room = game.hashid if broadcast else request.sid emit( 'score_response', { 'hashid': game.hashid, 'p1_score': game.p1_score, 'p2_score': game.p2_score, 'p1_sets': game.p1_sets, 'p2_sets': game.p2_sets, 'p1_legs': game.p1_legs, 'p2_legs': game.p2_legs, 'p1_next_turn': game.p1_next_turn, 'p1_current_leg': p1_current_leg_scores, 'p2_current_leg': p2_current_leg_scores, 'old_score': old_score, 'p1_leg_avg': p1_leg_avg, 'p2_leg_avg': p2_leg_avg, 'p1_match_avg': p1_match_avg, 'p2_match_avg': p2_match_avg, 'p1_first9_avg': p1_first9_avg, 'p2_first9_avg': p2_first9_avg, 'p1_100': p1_100, 'p2_100': p2_100, 'p1_140': p1_140, 'p2_140': p2_140, 'p1_180': p1_180, 'p2_180': p2_180, 'p1_doubles': p1_doubles, 'p2_doubles': p2_doubles, 'p1_legs_won': p1_legs_won, 'p2_legs_won': p2_legs_won, 'p1_darts_thrown_double': p1_darts_thrown_double, 'p2_darts_thrown_double': p2_darts_thrown_double, 'p1_high_finish': p1_high_finish, 'p2_high_finish': p2_high_finish, 'p1_short_leg': p1_short_leg, 'p2_short_leg': p2_short_leg, 'computer_game': computer_game, 'p1_id': game.player1, 'p2_id': game.player2, 'p1_started_leg': p1_started_leg, 'p2_started_leg': p2_started_leg, 'p1_checkout_suggestion': p1_checkout_suggestion, 'p2_checkout_suggestion': p2_checkout_suggestion, 'new_score': broadcast # needed for score sound output }, room=room) socketio.sleep(0)