def __init__(self): self.strava_resource = StravaResource() self.app_constants = AppConstants() self.app_variables = AppVariables() self.operations = Operations() self.database_resource = DatabaseResource() self.telegram_resource = TelegramResource() self.iron_cache_resource = IronCacheResource() self.athlete_resource = AthleteResource()
def __init__(self): self.bot_constants = AppConstants() self.bot_variables = AppVariables() self.operations = Operations() self.aes_cipher = AESCipher(self.bot_variables.crypt_key_length, self.bot_variables.crypt_key) self.telegram_resource = TelegramResource() self.database_resource = DatabaseResource() self.strava_resource = StravaResource() self.athlete_resource = AthleteResource() self.iron_cache_resource = IronCacheResource() self.auto_update_indoor_ride = AutoUpdateIndoorRide() self.activity_summary = ActivitySummary()
from flask import Flask, request, jsonify from scout_apm.flask import ScoutApm from app.commands.challenges import CalculateChallengesStats, Challenges from app.common.constants_and_variables import AppVariables, AppConstants from app.common.execution_time import execution_time from app.processor import update_stats, handle_webhook, telegram_send_message, challenges_api_hits, \ telegram_send_approval_message from app.resources.athlete import AthleteResource from app.resources.database import DatabaseResource from app.resources.iron_cache import IronCacheResource from app.resources.strava import StravaResource app_variables = AppVariables() app_constants = AppConstants() strava_resource = StravaResource() athlete_resource = AthleteResource() database_resource = DatabaseResource() iron_cache_resource = IronCacheResource() calculate_challenge_stats = CalculateChallengesStats() challenges = Challenges() app = Flask(__name__) app.config.from_object(__name__) ScoutApm(app) app.config['SCOUT_MONITOR'] = app_variables.scout_monitor app.config['SCOUT_KEY'] = app_variables.scout_key app.config['SCOUT_NAME'] = app_variables.scout_name
class Process: def __init__(self): self.bot_constants = AppConstants() self.bot_variables = AppVariables() self.operations = Operations() self.aes_cipher = AESCipher(self.bot_variables.crypt_key_length, self.bot_variables.crypt_key) self.telegram_resource = TelegramResource() self.database_resource = DatabaseResource() self.strava_resource = StravaResource() self.athlete_resource = AthleteResource() self.iron_cache_resource = IronCacheResource() self.auto_update_indoor_ride = AutoUpdateIndoorRide() self.activity_summary = ActivitySummary() def calculate_stats(self, athlete_details): calculate_stats = CalculateStats(athlete_details['athlete_token']) calculated_stats = calculate_stats.calculate() name = calculated_stats['athlete_name'] calculated_stats = ujson.dumps(calculated_stats) self.database_resource.write_operation( self.bot_constants.QUERY_UPDATE_STRAVA_DATA.format( name=name, strava_data=calculated_stats, athlete_id=athlete_details['athlete_id'])) self.iron_cache_resource.put_cache( "stats", athlete_details['telegram_username'], calculated_stats) self.telegram_resource.send_message( self.bot_constants.MESSAGE_UPDATED_STATS.format(athlete_name=name)) logging.info("Updated stats for https://www.strava.com/athletes/%s", athlete_details['athlete_id']) def process_update_stats(self, athlete_id): athlete_details = self.athlete_resource.get_athlete_details(athlete_id) if athlete_details: self.calculate_stats(athlete_details) self.telegram_resource.send_message( chat_id=athlete_details['chat_id'], message="Updated stats. Click /stats to check.", shadow=False) else: message = "Old athlete [Athlete](https://www.strava.com/athletes/{athlete_id}). Not registered anymore.".format( athlete_id=athlete_id) logging.info(message) self.telegram_resource.send_message(message) def process_update_all_stats(self): athlete_ids = self.database_resource.read_all_operation( self.bot_constants.QUERY_FETCH_ALL_ATHLETE_IDS) for athlete_id in athlete_ids: athlete_details = self.athlete_resource.get_athlete_details( athlete_id[0]) if athlete_details: logging.info("Updating stats for %s", athlete_id[0]) self.calculate_stats(athlete_details) logging.info("Updated stats for all the athletes.") def alert_webhook_event_of_athlete(self, event, athlete_details): event_type = "New Activity" if event['aspect_type'] == "delete": event_type = "Activity Deleted" message = self.bot_constants.MESSAGE_ACTIVITY_ALERT.format( callback_type=event_type, activity_id=event['object_id'], athlete_name=athlete_details['name']) self.telegram_resource.send_message(message) def handle_aspect_type_update(self, event, athlete_details): athlete_id = event['owner_id'] if 'authorized' in event['updates'] and event['updates'][ 'authorized'] == "false": if athlete_details: if self.database_resource.write_operation( self.bot_constants.QUERY_DEACTIVATE_ATHLETE.format( athlete_id=athlete_id)): message = self.bot_constants.MESSAGE_DEAUTHORIZE_SUCCESS.format( name=athlete_details['name'], athlete_id=athlete_id) else: message = self.bot_constants.MESSAGE_DEAUTHORIZE_FAILURE.format( name=athlete_details['name'], athlete_id=athlete_id) self.telegram_resource.send_message(message) def handle_aspect_type_create(self, event, athlete_details): activity_id = event['object_id'] object_type = event['object_type'] activity = self.strava_resource.get_strava_activity( athlete_details['athlete_token'], activity_id) if activity: if self.operations.supported_activities(activity): self.calculate_stats(athlete_details) if object_type == "activity": self.auto_update_indoor_ride.main(activity, athlete_details) self.activity_summary.main(activity, athlete_details) else: message = self.bot_constants.MESSAGE_UNSUPPORTED_ACTIVITY.format( activity_type=activity.type) logging.info(message) self.telegram_resource.send_message(message) else: message = "Triggering update stats as something went wrong. Exception: {exception}".format( exception=traceback.format_exc()) logging.error(message) self.telegram_resource.send_message(message) self.calculate_stats(athlete_details) def process_webhook(self, event): aspect_type = event['aspect_type'] athlete_id = event['owner_id'] activity_id = event['object_id'] athlete_details = self.athlete_resource.get_athlete_details(athlete_id) if aspect_type == "update": self.handle_aspect_type_update(event, athlete_details) else: if athlete_details: self.alert_webhook_event_of_athlete(event, athlete_details) if aspect_type == "create": self.handle_aspect_type_create(event, athlete_details) elif aspect_type == "delete": self.calculate_stats(athlete_details) else: logging.info( "Old Athlete: [Athlete](https://www.strava.com/athletes/%s) | [Activity](https://www.strava.com/activities/%s)", athlete_id, activity_id)
def __init__(self): self.app_constants = AppConstants() self.operations = Operations() self.strava_resource = StravaResource() self.telegram_resource = TelegramResource()
def __init__(self, athlete_token): self.athlete_token = athlete_token self.operations = Operations() self.strava_resource = StravaResource()
class CalculateStats: def __init__(self, athlete_token): self.athlete_token = athlete_token self.operations = Operations() self.strava_resource = StravaResource() @staticmethod def get_rider_stats(): return { "updated": "", "athlete_name": "", "athlete_strava_joined_date": "", "athlete_followers": 0, "athlete_following": 0, "ride_at_total": 0, "ride_at_indoor_total": 0, "ride_at_distance": 0, "ride_at_indoor_distance": 0, "ride_at_moving_time": 0, "ride_at_indoor_moving_time": 0, "ride_at_elevation_gain": 0, "ride_at_fifty": 0, "ride_at_hundred": 0, "ride_at_biggest_ride": 0, "ride_at_max_elevation_gain": 0, "ride_at_achievements": 0, "ride_at_commutes": 0, "ride_at_pr": 0, "ride_at_calories": 0, "ride_ytd_total": 0, "ride_ytd_indoor_total": 0, "ride_ytd_distance": 0, "ride_ytd_indoor_distance": 0, "ride_ytd_moving_time": 0, "ride_ytd_indoor_moving_time": 0, "ride_ytd_elevation_gain": 0, "ride_ytd_fifty": 0, "ride_ytd_hundred": 0, "ride_ytd_biggest_ride": 0, "ride_ytd_max_elevation_gain": 0, "ride_ytd_achievements": 0, "ride_ytd_commutes": 0, "ride_ytd_pr": 0, "ride_ytd_calories": 0, "ride_py_total": 0, "ride_py_indoor_total": 0, "ride_py_distance": 0, "ride_py_indoor_distance": 0, "ride_py_moving_time": 0, "ride_py_indoor_moving_time": 0, "ride_py_elevation_gain": 0, "ride_py_fifty": 0, "ride_py_hundred": 0, "ride_py_biggest_ride": 0, "ride_py_max_elevation_gain": 0, "ride_py_achievements": 0, "ride_py_commutes": 0, "ride_py_pr": 0, "ride_py_calories": 0, "ride_cm_total": 0, "ride_cm_indoor_total": 0, "ride_cm_distance": 0, "ride_cm_indoor_distance": 0, "ride_cm_moving_time": 0, "ride_cm_indoor_moving_time": 0, "ride_cm_elevation_gain": 0, "ride_cm_fifty": 0, "ride_cm_hundred": 0, "ride_cm_biggest_ride": 0, "ride_cm_max_elevation_gain": 0, "ride_cm_achievements": 0, "ride_cm_commutes": 0, "ride_cm_pr": 0, "ride_cm_calories": 0, "ride_pm_total": 0, "ride_pm_indoor_total": 0, "ride_pm_distance": 0, "ride_pm_indoor_distance": 0, "ride_pm_moving_time": 0, "ride_pm_indoor_moving_time": 0, "ride_pm_elevation_gain": 0, "ride_pm_fifty": 0, "ride_pm_hundred": 0, "ride_pm_biggest_ride": 0, "ride_pm_max_elevation_gain": 0, "ride_pm_achievements": 0, "ride_pm_commutes": 0, "ride_pm_pr": 0, "ride_pm_calories": 0, "run_at_total": 0, "run_at_indoor_total": 0, "run_at_distance": 0, "run_at_indoor_distance": 0, "run_at_moving_time": 0, "run_at_indoor_moving_time": 0, "run_at_elevation_gain": 0, "run_at_five": 0, "run_at_ten": 0, "run_at_hm": 0, "run_at_fm": 0, "run_at_ultra": 0, "run_at_biggest_run": 0, "run_at_max_elevation_gain": 0, "run_at_achievements": 0, "run_at_commutes": 0, "run_at_pr": 0, "run_at_calories": 0, "run_ytd_total": 0, "run_ytd_indoor_total": 0, "run_ytd_distance": 0, "run_ytd_indoor_distance": 0, "run_ytd_moving_time": 0, "run_ytd_indoor_moving_time": 0, "run_ytd_elevation_gain": 0, "run_ytd_five": 0, "run_ytd_ten": 0, "run_ytd_hm": 0, "run_ytd_fm": 0, "run_ytd_ultra": 0, "run_ytd_biggest_run": 0, "run_ytd_max_elevation_gain": 0, "run_ytd_achievements": 0, "run_ytd_commutes": 0, "run_ytd_pr": 0, "run_ytd_calories": 0, "run_py_total": 0, "run_py_indoor_total": 0, "run_py_distance": 0, "run_py_indoor_distance": 0, "run_py_moving_time": 0, "run_py_indoor_moving_time": 0, "run_py_elevation_gain": 0, "run_py_five": 0, "run_py_ten": 0, "run_py_hm": 0, "run_py_fm": 0, "run_py_ultra": 0, "run_py_biggest_run": 0, "run_py_max_elevation_gain": 0, "run_py_achievements": 0, "run_py_commutes": 0, "run_py_pr": 0, "run_py_calories": 0, "run_cm_total": 0, "run_cm_indoor_total": 0, "run_cm_distance": 0, "run_cm_indoor_distance": 0, "run_cm_moving_time": 0, "run_cm_indoor_moving_time": 0, "run_cm_elevation_gain": 0, "run_cm_five": 0, "run_cm_ten": 0, "run_cm_hm": 0, "run_cm_fm": 0, "run_cm_ultra": 0, "run_cm_biggest_run": 0, "run_cm_max_elevation_gain": 0, "run_cm_achievements": 0, "run_cm_commutes": 0, "run_cm_pr": 0, "run_cm_calories": 0, "run_pm_total": 0, "run_pm_indoor_total": 0, "run_pm_distance": 0, "run_pm_indoor_distance": 0, "run_pm_moving_time": 0, "run_pm_indoor_moving_time": 0, "run_pm_elevation_gain": 0, "run_pm_five": 0, "run_pm_ten": 0, "run_pm_hm": 0, "run_pm_fm": 0, "run_pm_ultra": 0, "run_pm_biggest_run": 0, "run_pm_max_elevation_gain": 0, "run_pm_achievements": 0, "run_pm_commutes": 0, "run_pm_pr": 0, "run_pm_calories": 0, "swim_at_total": 0, "swim_at_distance": 0, "swim_at_moving_time": 0, "swim_at_50": 0, "swim_at_100": 0, "swim_at_200": 0, "swim_at_400": 0, "swim_at_800": 0, "swim_at_1500": 0, "swim_at_biggest_swim": 0, "swim_at_achievements": 0, "swim_at_pr": 0, "swim_at_calories": 0, "swim_ytd_total": 0, "swim_ytd_distance": 0, "swim_ytd_moving_time": 0, "swim_ytd_50": 0, "swim_ytd_100": 0, "swim_ytd_200": 0, "swim_ytd_400": 0, "swim_ytd_800": 0, "swim_ytd_1500": 0, "swim_ytd_biggest_swim": 0, "swim_ytd_achievements": 0, "swim_ytd_pr": 0, "swim_ytd_calories": 0, "swim_py_total": 0, "swim_py_distance": 0, "swim_py_moving_time": 0, "swim_py_50": 0, "swim_py_100": 0, "swim_py_200": 0, "swim_py_400": 0, "swim_py_800": 0, "swim_py_1500": 0, "swim_py_biggest_swim": 0, "swim_py_achievements": 0, "swim_py_pr": 0, "swim_py_calories": 0, "swim_cm_total": 0, "swim_cm_distance": 0, "swim_cm_moving_time": 0, "swim_cm_50": 0, "swim_cm_100": 0, "swim_cm_200": 0, "swim_cm_400": 0, "swim_cm_800": 0, "swim_cm_1500": 0, "swim_cm_biggest_swim": 0, "swim_cm_achievements": 0, "swim_cm_pr": 0, "swim_cm_calories": 0, "swim_pm_total": 0, "swim_pm_distance": 0, "swim_pm_moving_time": 0, "swim_pm_50": 0, "swim_pm_100": 0, "swim_pm_200": 0, "swim_pm_400": 0, "swim_pm_800": 0, "swim_pm_1500": 0, "swim_pm_biggest_swim": 0, "swim_pm_achievements": 0, "swim_pm_pr": 0, "swim_pm_calories": 0, } def calculate(self): logging.info("Calculating stats..") athlete_info = self.strava_resource.get_athlete_info( self.athlete_token) activities = self.strava_resource.get_strava_activities_after_date( self.athlete_token, "1970-01-01T00:00:00Z") today_date = date.today() current_month = today_date.month previous_month = (current_month - 1) if (current_month > 1) else 12 current_year = date.today().year previous_year = today_date.year - 1 rider_stats = self.get_rider_stats() rider_stats["updated"] = datetime.now().strftime("%d-%m-%Y %H:%M:%S") rider_stats["athlete_name"] = "{first_name} {last_name}".format( first_name=athlete_info.firstname, last_name=athlete_info.lastname) rider_stats[ "athlete_strava_joined_date"] = athlete_info.created_at.date( ).strftime('%Y-%m-%d') rider_stats["athlete_followers"] = athlete_info.follower_count rider_stats["athlete_following"] = athlete_info.friend_count for activity in activities: if not self.operations.is_flagged(activity): distance = float(activity.distance) moving_time = unithelper.timedelta_to_seconds( activity.moving_time) total_elevation_gain = float(activity.total_elevation_gain) activity_year = activity.start_date_local.year activity_month = activity.start_date_local.month if self.operations.is_activity_a_ride(activity): rider_stats["ride_at_total"] += 1 rider_stats["ride_at_distance"] += distance rider_stats["ride_at_moving_time"] += moving_time rider_stats[ "ride_at_elevation_gain"] += total_elevation_gain rider_stats[ "ride_at_achievements"] += activity.achievement_count rider_stats["ride_at_pr"] += activity.pr_count if activity.kilojoules: rider_stats["ride_at_calories"] += activity.kilojoules if self.operations.is_indoor(activity): rider_stats["ride_at_indoor_total"] += 1 rider_stats["ride_at_indoor_distance"] += distance rider_stats[ "ride_at_indoor_moving_time"] += moving_time if activity.commute: rider_stats["ride_at_commutes"] += 1 if distance > rider_stats["ride_at_biggest_ride"]: rider_stats["ride_at_biggest_ride"] = distance if total_elevation_gain > rider_stats[ "ride_at_max_elevation_gain"]: rider_stats[ "ride_at_max_elevation_gain"] = total_elevation_gain if 50000.0 <= distance < 100000.0: rider_stats["ride_at_fifty"] += 1 elif distance > 100000.0: rider_stats["ride_at_hundred"] += 1 elif self.operations.is_activity_a_run(activity): rider_stats["run_at_total"] += 1 rider_stats["run_at_distance"] += distance rider_stats["run_at_moving_time"] += moving_time rider_stats[ "run_at_elevation_gain"] += total_elevation_gain rider_stats[ "run_at_achievements"] += activity.achievement_count rider_stats["run_at_pr"] += activity.pr_count if activity.kilojoules: rider_stats["run_at_calories"] += activity.kilojoules if self.operations.is_indoor(activity): rider_stats["run_at_indoor_total"] += 1 rider_stats["run_at_indoor_distance"] += distance rider_stats["run_at_indoor_moving_time"] += moving_time if activity.commute: rider_stats["run_at_commutes"] += 1 if distance > rider_stats["run_at_biggest_run"]: rider_stats["run_at_biggest_run"] = distance if total_elevation_gain > rider_stats[ "run_at_max_elevation_gain"]: rider_stats[ "run_at_max_elevation_gain"] = total_elevation_gain if 5000.0 <= distance < 10000.0: rider_stats["run_at_five"] += 1 elif 10000.0 <= distance < 21000.0: rider_stats["run_at_ten"] += 1 elif 21000.0 <= distance < 42000.0: rider_stats["run_at_hm"] += 1 elif 42000.0 <= distance < 44000.0: rider_stats["run_at_fm"] += 1 elif distance > 44000.0: rider_stats["run_at_ultra"] += 1 elif self.operations.is_activity_a_swim(activity): rider_stats["swim_at_total"] += 1 rider_stats["swim_at_distance"] += distance rider_stats["swim_at_moving_time"] += moving_time rider_stats[ "swim_at_achievements"] += activity.achievement_count rider_stats["swim_at_pr"] += activity.pr_count if activity.kilojoules: rider_stats["swim_at_calories"] += activity.kilojoules if distance > rider_stats["swim_at_biggest_swim"]: rider_stats["swim_at_biggest_swim"] = distance if 50.0 <= distance < 100.0: rider_stats["swim_at_50"] += 1 elif 100.0 <= distance < 200.0: rider_stats["swim_at_100"] += 1 elif 200.0 <= distance < 400.0: rider_stats["swim_at_200"] += 1 elif 400.0 <= distance < 800.0: rider_stats["swim_at_400"] += 1 elif 800.0 <= distance < 1500.0: rider_stats["swim_at_800"] += 1 elif distance > 1500.0: rider_stats["swim_at_1500"] += 1 if activity_year == current_year: if self.operations.is_activity_a_ride(activity): rider_stats["ride_ytd_total"] += 1 rider_stats["ride_ytd_distance"] += distance rider_stats["ride_ytd_moving_time"] += moving_time rider_stats[ "ride_ytd_elevation_gain"] += total_elevation_gain rider_stats[ "ride_ytd_achievements"] += activity.achievement_count rider_stats["ride_ytd_pr"] += activity.pr_count if activity.kilojoules: rider_stats[ "ride_ytd_calories"] += activity.kilojoules if self.operations.is_indoor(activity): rider_stats["ride_ytd_indoor_total"] += 1 rider_stats["ride_ytd_indoor_distance"] += distance rider_stats[ "ride_ytd_indoor_moving_time"] += moving_time if activity.commute: rider_stats["ride_ytd_commutes"] += 1 if distance > rider_stats["ride_ytd_biggest_ride"]: rider_stats["ride_ytd_biggest_ride"] = distance if total_elevation_gain > rider_stats[ "ride_ytd_max_elevation_gain"]: rider_stats[ "ride_ytd_max_elevation_gain"] = total_elevation_gain if 50000.0 <= distance < 100000.0: rider_stats["ride_ytd_fifty"] += 1 elif distance > 100000.0: rider_stats["ride_ytd_hundred"] += 1 elif self.operations.is_activity_a_run(activity): rider_stats["run_ytd_total"] += 1 rider_stats["run_ytd_distance"] += distance rider_stats["run_ytd_moving_time"] += moving_time rider_stats[ "run_ytd_elevation_gain"] += total_elevation_gain rider_stats[ "run_ytd_achievements"] += activity.achievement_count rider_stats["run_ytd_pr"] += activity.pr_count if activity.kilojoules: rider_stats[ "run_ytd_calories"] += activity.kilojoules if self.operations.is_indoor(activity): rider_stats["run_ytd_indoor_total"] += 1 rider_stats["run_ytd_indoor_distance"] += distance rider_stats[ "run_ytd_indoor_moving_time"] += moving_time if activity.commute: rider_stats["run_ytd_commutes"] += 1 if distance > rider_stats["run_ytd_biggest_run"]: rider_stats["run_ytd_biggest_run"] = distance if total_elevation_gain > rider_stats[ "run_ytd_max_elevation_gain"]: rider_stats[ "run_ytd_max_elevation_gain"] = total_elevation_gain if 5000.0 <= distance < 10000.0: rider_stats["run_ytd_five"] += 1 elif 10000.0 <= distance < 21000.0: rider_stats["run_ytd_ten"] += 1 elif 21000.0 <= distance < 42000.0: rider_stats["run_ytd_hm"] += 1 elif 42000.0 <= distance < 44000.0: rider_stats["run_ytd_fm"] += 1 elif distance > 44000.0: rider_stats["run_ytd_ultra"] += 1 elif self.operations.is_activity_a_swim(activity): rider_stats["swim_ytd_total"] += 1 rider_stats["swim_ytd_distance"] += distance rider_stats["swim_ytd_moving_time"] += moving_time rider_stats[ "swim_ytd_achievements"] += activity.achievement_count rider_stats["swim_ytd_pr"] += activity.pr_count if activity.kilojoules: rider_stats[ "swim_ytd_calories"] += activity.kilojoules if distance > rider_stats["swim_ytd_biggest_swim"]: rider_stats["swim_ytd_biggest_swim"] = distance if 50.0 <= distance < 100.0: rider_stats["swim_ytd_50"] += 1 elif 100.0 <= distance < 200.0: rider_stats["swim_ytd_100"] += 1 elif 200.0 <= distance < 400.0: rider_stats["swim_ytd_200"] += 1 elif 400.0 <= distance < 800.0: rider_stats["swim_ytd_400"] += 1 elif 800.0 <= distance < 1500.0: rider_stats["swim_ytd_800"] += 1 elif distance > 1500.0: rider_stats["swim_ytd_1500"] += 1 if activity_year == previous_year: if self.operations.is_activity_a_ride(activity): rider_stats["ride_py_total"] += 1 rider_stats["ride_py_distance"] += distance rider_stats["ride_py_moving_time"] += moving_time rider_stats[ "ride_py_elevation_gain"] += total_elevation_gain rider_stats[ "ride_py_achievements"] += activity.achievement_count rider_stats["ride_py_pr"] += activity.pr_count if activity.kilojoules: rider_stats[ "ride_py_calories"] += activity.kilojoules if self.operations.is_indoor(activity): rider_stats["ride_py_indoor_total"] += 1 rider_stats["ride_py_indoor_distance"] += distance rider_stats[ "ride_py_indoor_moving_time"] += moving_time if activity.commute: rider_stats["ride_py_commutes"] += 1 if distance > rider_stats["ride_py_biggest_ride"]: rider_stats["ride_py_biggest_ride"] = distance if total_elevation_gain > rider_stats[ "ride_py_max_elevation_gain"]: rider_stats[ "ride_py_max_elevation_gain"] = total_elevation_gain if 50000.0 <= distance < 100000.0: rider_stats["ride_py_fifty"] += 1 elif distance > 100000.0: rider_stats["ride_py_hundred"] += 1 elif self.operations.is_activity_a_run(activity): rider_stats["run_py_total"] += 1 rider_stats["run_py_distance"] += distance rider_stats["run_py_moving_time"] += moving_time rider_stats[ "run_py_elevation_gain"] += total_elevation_gain rider_stats[ "run_py_achievements"] += activity.achievement_count rider_stats["run_py_pr"] += activity.pr_count if activity.kilojoules: rider_stats[ "run_py_calories"] += activity.kilojoules if self.operations.is_indoor(activity): rider_stats["run_py_indoor_total"] += 1 rider_stats["run_py_indoor_distance"] += distance rider_stats[ "run_py_indoor_moving_time"] += moving_time if activity.commute: rider_stats["run_py_commutes"] += 1 if distance > rider_stats["run_py_biggest_run"]: rider_stats["run_py_biggest_run"] = distance if total_elevation_gain > rider_stats[ "run_py_max_elevation_gain"]: rider_stats[ "run_py_max_elevation_gain"] = total_elevation_gain if 5000.0 <= distance < 10000.0: rider_stats["run_py_five"] += 1 elif 10000.0 <= distance < 21000.0: rider_stats["run_py_ten"] += 1 elif 21000.0 <= distance < 42000.0: rider_stats["run_py_hm"] += 1 elif 42000.0 <= distance < 44000.0: rider_stats["run_py_fm"] += 1 elif distance > 44000.0: rider_stats["run_py_ultra"] += 1 elif self.operations.is_activity_a_swim(activity): rider_stats["swim_py_total"] += 1 rider_stats["swim_py_distance"] += distance rider_stats["swim_py_moving_time"] += moving_time rider_stats[ "swim_py_achievements"] += activity.achievement_count rider_stats["swim_py_pr"] += activity.pr_count if activity.kilojoules: rider_stats[ "swim_py_calories"] += activity.kilojoules if distance > rider_stats["swim_py_biggest_swim"]: rider_stats["swim_py_biggest_swim"] = distance if 50.0 <= distance < 100.0: rider_stats["swim_py_50"] += 1 elif 100.0 <= distance < 200.0: rider_stats["swim_py_100"] += 1 elif 200.0 <= distance < 400.0: rider_stats["swim_py_200"] += 1 elif 400.0 <= distance < 800.0: rider_stats["swim_py_400"] += 1 elif 800.0 <= distance < 1500.0: rider_stats["swim_py_800"] += 1 elif distance > 1500.0: rider_stats["swim_py_1500"] += 1 if activity_month == current_month and activity_year == current_year: if self.operations.is_activity_a_ride(activity): rider_stats["ride_cm_total"] += 1 rider_stats["ride_cm_distance"] += distance rider_stats["ride_cm_moving_time"] += moving_time rider_stats[ "ride_cm_elevation_gain"] += total_elevation_gain rider_stats[ "ride_cm_achievements"] += activity.achievement_count rider_stats["ride_cm_pr"] += activity.pr_count if activity.kilojoules: rider_stats[ "ride_cm_calories"] += activity.kilojoules if self.operations.is_indoor(activity): rider_stats["ride_cm_indoor_total"] += 1 rider_stats["ride_cm_indoor_distance"] += distance rider_stats[ "ride_cm_indoor_moving_time"] += moving_time if activity.commute: rider_stats["ride_cm_commutes"] += 1 if distance > rider_stats["ride_cm_biggest_ride"]: rider_stats["ride_cm_biggest_ride"] = distance if total_elevation_gain > rider_stats[ "ride_cm_max_elevation_gain"]: rider_stats[ "ride_cm_max_elevation_gain"] = total_elevation_gain if 50000.0 <= distance < 100000.0: rider_stats["ride_cm_fifty"] += 1 elif distance > 100000.0: rider_stats["ride_cm_hundred"] += 1 elif self.operations.is_activity_a_run(activity): rider_stats["run_cm_total"] += 1 rider_stats["run_cm_distance"] += distance rider_stats["run_cm_moving_time"] += moving_time rider_stats[ "run_cm_elevation_gain"] += total_elevation_gain rider_stats[ "run_cm_achievements"] += activity.achievement_count rider_stats["run_cm_pr"] += activity.pr_count if activity.kilojoules: rider_stats[ "run_cm_calories"] += activity.kilojoules if self.operations.is_indoor(activity): rider_stats["run_cm_indoor_total"] += 1 rider_stats["run_cm_indoor_distance"] += distance rider_stats[ "run_cm_indoor_moving_time"] += moving_time if activity.commute: rider_stats["run_cm_commutes"] += 1 if distance > rider_stats["run_cm_biggest_run"]: rider_stats["run_cm_biggest_run"] = distance if total_elevation_gain > rider_stats[ "run_cm_max_elevation_gain"]: rider_stats[ "run_cm_max_elevation_gain"] = total_elevation_gain if 5000.0 <= distance < 10000.0: rider_stats["run_cm_five"] += 1 elif 10000.0 <= distance < 21000.0: rider_stats["run_cm_ten"] += 1 elif 21000.0 <= distance < 42000.0: rider_stats["run_cm_hm"] += 1 elif 42000.0 <= distance < 44000.0: rider_stats["run_cm_fm"] += 1 elif distance > 44000.0: rider_stats["run_cm_ultra"] += 1 elif self.operations.is_activity_a_swim(activity): rider_stats["swim_cm_total"] += 1 rider_stats["swim_cm_distance"] += distance rider_stats["swim_cm_moving_time"] += moving_time rider_stats[ "swim_cm_achievements"] += activity.achievement_count rider_stats["swim_cm_pr"] += activity.pr_count if activity.kilojoules: rider_stats[ "swim_cm_calories"] += activity.kilojoules if distance > rider_stats["swim_cm_biggest_swim"]: rider_stats["swim_cm_biggest_swim"] = distance if 50.0 <= distance < 100.0: rider_stats["swim_cm_50"] += 1 elif 100.0 <= distance < 200.0: rider_stats["swim_cm_100"] += 1 elif 200.0 <= distance < 400.0: rider_stats["swim_cm_200"] += 1 elif 400.0 <= distance < 800.0: rider_stats["swim_cm_400"] += 1 elif 800.0 <= distance < 1500.0: rider_stats["swim_cm_800"] += 1 elif distance > 1500.0: rider_stats["swim_cm_1500"] += 1 # TODO This condition fails for January. Fix it. if activity_month == previous_month and activity_year == current_year: if self.operations.is_activity_a_ride(activity): rider_stats["ride_pm_total"] += 1 rider_stats["ride_pm_distance"] += distance rider_stats["ride_pm_moving_time"] += moving_time rider_stats[ "ride_pm_elevation_gain"] += total_elevation_gain rider_stats[ "ride_pm_achievements"] += activity.achievement_count rider_stats["ride_pm_pr"] += activity.pr_count if activity.kilojoules: rider_stats[ "ride_pm_calories"] += activity.kilojoules if self.operations.is_indoor(activity): rider_stats["ride_pm_indoor_total"] += 1 rider_stats["ride_pm_indoor_distance"] += distance rider_stats[ "ride_pm_indoor_moving_time"] += moving_time if activity.commute: rider_stats["ride_pm_commutes"] += 1 if distance > rider_stats["ride_pm_biggest_ride"]: rider_stats["ride_pm_biggest_ride"] = distance if total_elevation_gain > rider_stats[ "ride_pm_max_elevation_gain"]: rider_stats[ "ride_pm_max_elevation_gain"] = total_elevation_gain if 50000.0 <= distance < 100000.0: rider_stats["ride_pm_fifty"] += 1 elif distance > 100000.0: rider_stats["ride_pm_hundred"] += 1 elif self.operations.is_activity_a_run(activity): rider_stats["run_pm_total"] += 1 rider_stats["run_pm_distance"] += distance rider_stats["run_pm_moving_time"] += moving_time rider_stats[ "run_pm_elevation_gain"] += total_elevation_gain rider_stats[ "run_pm_achievements"] += activity.achievement_count rider_stats["run_pm_pr"] += activity.pr_count if activity.kilojoules: rider_stats[ "run_pm_calories"] += activity.kilojoules if self.operations.is_indoor(activity): rider_stats["run_pm_indoor_total"] += 1 rider_stats["run_pm_indoor_distance"] += distance rider_stats[ "run_pm_indoor_moving_time"] += moving_time if activity.commute: rider_stats["run_pm_commutes"] += 1 if distance > rider_stats["run_pm_biggest_run"]: rider_stats["run_pm_biggest_run"] = distance if total_elevation_gain > rider_stats[ "run_pm_max_elevation_gain"]: rider_stats[ "run_pm_max_elevation_gain"] = total_elevation_gain if 5000.0 <= distance < 10000.0: rider_stats["run_pm_five"] += 1 elif 10000.0 <= distance < 21000.0: rider_stats["run_pm_ten"] += 1 elif 21000.0 <= distance < 42000.0: rider_stats["run_pm_hm"] += 1 elif 42000.0 <= distance < 44000.0: rider_stats["run_pm_fm"] += 1 elif distance > 44000.0: rider_stats["run_pm_ultra"] += 1 elif self.operations.is_activity_a_swim(activity): rider_stats["swim_pm_total"] += 1 rider_stats["swim_pm_distance"] += distance rider_stats["swim_pm_moving_time"] += moving_time rider_stats[ "swim_pm_achievements"] += activity.achievement_count rider_stats["swim_pm_pr"] += activity.pr_count if activity.kilojoules: rider_stats[ "swim_pm_calories"] += activity.kilojoules if distance > rider_stats["swim_pm_biggest_swim"]: rider_stats["swim_pm_biggest_swim"] = distance if 50.0 <= distance < 100.0: rider_stats["swim_pm_50"] += 1 elif 100.0 <= distance < 200.0: rider_stats["swim_pm_100"] += 1 elif 200.0 <= distance < 400.0: rider_stats["swim_pm_200"] += 1 elif 400.0 <= distance < 800.0: rider_stats["swim_pm_400"] += 1 elif 800.0 <= distance < 1500.0: rider_stats["swim_pm_800"] += 1 elif distance > 1500.0: rider_stats["swim_pm_1500"] += 1 return rider_stats
class AutoUpdateIndoorRide: def __init__(self): self.app_constants = AppConstants() self.operations = Operations() self.strava_resource = StravaResource() self.telegram_resource = TelegramResource() @staticmethod def get_indoor_activity_name(athlete_details, activity): if athlete_details['update_indoor_ride_data']['name'] == 'Automatic': activity_hour = activity.start_date_local.hour if 3 <= activity_hour <= 11: athlete_details['update_indoor_ride_data'][ 'name'] = "Morning Ride" elif 12 <= activity_hour <= 15: athlete_details['update_indoor_ride_data'][ 'name'] = "Afternoon Ride" elif 16 <= activity_hour <= 18: athlete_details['update_indoor_ride_data'][ 'name'] = "Evening Ride" elif (19 <= activity_hour <= 23) or (0 <= activity_hour <= 2): athlete_details['update_indoor_ride_data'][ 'name'] = "Night Ride" return athlete_details def get_configured_update_indoor_ride_data(self, athlete_details): configured_data = self.app_constants.MESSAGE_UPDATED_INDOOR_RIDE if athlete_details['update_indoor_ride_data']['name']: configured_data += "\nActivity Name: {activity_name}".format( activity_name=athlete_details['update_indoor_ride_data'] ['name']) if athlete_details['update_indoor_ride_data']['gear_id']: bike_name = self.strava_resource.get_gear_name( athlete_details['athlete_token'], athlete_details['update_indoor_ride_data']['gear_id']) configured_data += "\nBike: {bike_name}".format( bike_name=bike_name) return configured_data def main(self, activity, athlete_details): if self.operations.is_activity_a_ride(activity): if self.operations.is_indoor(activity): if athlete_details['update_indoor_ride']: athlete_details = self.get_indoor_activity_name( athlete_details, activity) result = self.strava_resource.update_strava_activity( athlete_details['athlete_token'], activity.id, athlete_details['update_indoor_ride_data']['name'], athlete_details['update_indoor_ride_data']['gear_id']) if result: message = self.get_configured_update_indoor_ride_data( athlete_details) else: message = "Error auto updating indoor ride." self.telegram_resource.send_message( chat_id=athlete_details['chat_id'], message=message) else: logging.info("Auto update indoor ride is not enabled.") else: logging.info("Activity is not an indoor ride.") else: logging.info("Activity Type is not Ride.")
class ToKOddMonth: def __init__(self): self.strava_resource = StravaResource() self.app_constants = AppConstants() self.app_variables = AppVariables() self.operations = Operations() self.database_resource = DatabaseResource() self.telegram_resource = TelegramResource() self.iron_cache_resource = IronCacheResource() self.athlete_resource = AthleteResource() @staticmethod def get_activity_type(activity): activity_type = None if activity.type == 'VirtualRide' or activity.type == 'Ride': activity_type = "Ride" elif activity.type == 'Run' or activity.type == 'VirtualRun': activity_type = "Run" elif activity.type == 'Swim': activity_type = "Swim" return activity_type def get_activities_calendar(self, athlete_details): activities_calendar = { "calendar": { "2019916": { "result": False, "data": { "activities": [] } }, "2019917": { "result": False, "data": { "activities": [] } }, "2019918": { "result": False, "data": { "activities": [] } }, "2019919": { "result": False, "data": { "activities": [] } }, "2019920": { "result": False, "data": { "activities": [] } }, "2019921": { "result": False, "data": { "activities": [] } }, "2019922": { "result": False, "data": { "activities": [] } }, "2019923": { "result": False, "data": { "activities": [] } }, "2019924": { "result": False, "data": { "activities": [] } }, "2019925": { "result": False, "data": { "activities": [] } }, "2019926": { "result": False, "data": { "activities": [] } }, "2019927": { "result": False, "data": { "activities": [] } }, "2019928": { "result": False, "data": { "activities": [] } }, "2019929": { "result": False, "data": { "activities": [] } }, "2019930": { "result": False, "data": { "activities": [] } }, "2019101": { "result": False, "data": { "activities": [] } }, "2019102": { "result": False, "data": { "activities": [] } }, "2019103": { "result": False, "data": { "activities": [] } }, "2019104": { "result": False, "data": { "activities": [] } }, "2019105": { "result": False, "data": { "activities": [] } }, "2019106": { "result": False, "data": { "activities": [] } }, "2019107": { "result": False, "data": { "activities": [] } }, "2019108": { "result": False, "data": { "activities": [] } }, "2019109": { "result": False, "data": { "activities": [] } }, "20191010": { "result": False, "data": { "activities": [] } }, "20191011": { "result": False, "data": { "activities": [] } }, "20191012": { "result": False, "data": { "activities": [] } }, "20191013": { "result": False, "data": { "activities": [] } }, "20191014": { "result": False, "data": { "activities": [] } }, "20191015": { "result": False, "data": { "activities": [] } }, "20191016": { "result": False, "activities": [] }, "20191017": { "result": False, "data": { "activities": [] } }, "20191018": { "result": False, "data": { "activities": [] } }, "20191019": { "result": False, "data": { "activities": [] } }, "20191020": { "result": False, "data": { "activities": [] } }, "20191021": { "result": False, "data": { "activities": [] } }, "20191022": { "result": False, "data": { "activities": [] } }, "20191023": { "result": False, "data": { "activities": [] } }, "20191024": { "result": False, "data": { "activities": [] } }, "20191025": { "result": False, "data": { "activities": [] } }, "20191026": { "result": False, "data": { "activities": [] } }, "20191027": { "result": False, "data": { "activities": [] } }, "20191028": { "result": False, "data": { "activities": [] } }, "20191029": { "result": False, "data": { "activities": [] } }, "20191030": { "result": False, "data": { "activities": [] } }, "20191031": { "result": False, "data": { "activities": [] } }, "2019111": { "result": False, "data": { "activities": [] } }, "2019112": { "result": False, "data": { "activities": [] } }, "2019113": { "result": False, "data": { "activities": [] } }, "2019114": { "result": False, "data": { "activities": [] } }, "2019115": { "result": False, "data": { "activities": [] } }, "2019116": { "result": False, "data": { "activities": [] } }, "2019117": { "result": False, "data": { "activities": [] } }, "2019118": { "result": False, "data": { "activities": [] } }, "2019119": { "result": False, "data": { "activities": [] } }, "20191110": { "result": False, "data": { "activities": [] } }, "20191111": { "result": False, "data": { "activities": [] } }, "20191112": { "result": False, "data": { "activities": [] } }, "20191113": { "result": False, "data": { "activities": [] } }, "20191114": { "result": False, "data": { "activities": [] } }, "20191115": { "result": False, "data": { "activities": [] } }, "20191116": { "result": False, "data": { "activities": [] } }, "20191117": { "result": False, "data": { "activities": [] } }, "20191118": { "result": False, "data": { "activities": [] } }, "20191119": { "result": False, "data": { "activities": [] } }, "20191120": { "result": False, "data": { "activities": [] } }, "20191121": { "result": False, "data": { "activities": [] } }, "20191122": { "result": False, "data": { "activities": [] } }, "20191123": { "result": False, "data": { "activities": [] } }, "20191124": { "result": False, "data": { "activities": [] } } } } try: for activity in self.strava_resource.get_strava_activities_after_date_before_date( athlete_details['athlete_token'], self.app_variables.tok_odd_challenges_from_date, self.app_variables.tok_odd_challenges_to_date): activity_type = activity.type activity_year = activity.start_date_local.year activity_month = activity.start_date_local.month activity_day = activity.start_date_local.day activity_distance = float(activity.distance) activity_elevation = float( activity.total_elevation_gain ) if not self.operations.is_indoor(activity) else 0.0 activity_time = unithelper.timedelta_to_seconds( activity.moving_time) calendar_key = "{activity_year}{activity_month}{activity_day}".format( activity_year=activity_year, activity_month=activity_month, activity_day=activity_day) logging.info( "Type: %s | Year: %s | Month: %s | Day: %s | Distance: %s | Time: %s | Elevation: %s, Calendar Key: %s", activity_type, activity_year, activity_month, activity_day, activity_distance, activity_time, activity_elevation, calendar_key) if self.operations.supported_activities_for_tok_challenges( activity ) and activity_month in self.app_variables.tok_odd_challenges_month and activity_year in self.app_variables.tok_odd_challenges_year: logging.info("Activity considered.") activities_calendar["calendar"][calendar_key][ "result"] = True activities_calendar["calendar"][calendar_key]["data"][ "activities"].append({ "type": self.get_activity_type(activity), "distance": activity_distance, "elevation": activity_elevation }) except ValueError as exception_message: if str(exception_message) == "day is out of range for month": logging.info("Future date") else: logging.info(exception_message) except Exception: logging.info(traceback.format_exc()) finally: return ujson.dumps(activities_calendar) @staticmethod def cap_ride_distance_and_elevation(activities_calendar): for activity_day in activities_calendar["calendar"]: if activities_calendar["calendar"][activity_day]["result"]: for activity in activities_calendar["calendar"][activity_day][ "data"]["activities"]: if activity["type"] == "Ride": activity[ "distance"] = activity["distance"] if activity[ "distance"] < 150000.0 else 150000.0 activity[ "elevation"] = activity["elevation"] if activity[ "elevation"] < 2000.0 else 2000.0 return activities_calendar @staticmethod def calculate_activity_points(activities_calendar): for activity_day in activities_calendar["calendar"]: if activities_calendar["calendar"][activity_day]["result"]: for activity in activities_calendar["calendar"][activity_day][ "data"]["activities"]: if activity["type"] == "Ride": activity["activity_points"] = 1 if activity[ "distance"] >= 10000.0 else 0 elif activity["type"] == "Run": activity["activity_points"] = 0 elif activity["type"] == "Swim": activity["activity_points"] = 0 return activities_calendar @staticmethod def calculate_distance_bonus(activities_calendar): for activity_day in activities_calendar["calendar"]: if activities_calendar["calendar"][activity_day]["result"]: for activity in activities_calendar["calendar"][activity_day][ "data"]["activities"]: if activity["type"] == "Ride": if activity["distance"] >= 100000.0: activity["distance_bonus_points"] = 35 elif activity["distance"] >= 50000.0: activity["distance_bonus_points"] = 15 elif activity["distance"] >= 25000.0: activity["distance_bonus_points"] = 5 else: activity["distance_bonus_points"] = 0 elif activity["type"] == "Run": if activity["distance"] >= 40000.0: activity["distance_bonus_points"] = 35 elif activity["distance"] >= 20000.0: activity["distance_bonus_points"] = 16 elif activity["distance"] >= 15000.0: activity["distance_bonus_points"] = 12 elif activity["distance"] >= 10000.0: activity["distance_bonus_points"] = 7 elif activity["distance"] >= 5000.0: activity["distance_bonus_points"] = 3 else: activity["distance_bonus_points"] = 0 elif activity["type"] == "Swim": if activity["distance"] >= 2000.0: activity["distance_bonus_points"] = 10 elif activity["distance"] >= 1500.0: activity["distance_bonus_points"] = 5 elif activity["distance"] >= 1000.0: activity["distance_bonus_points"] = 3 else: activity["distance_bonus_points"] = 0 return activities_calendar @staticmethod def calculate_elevation_bonus(activities_calendar): for activity_day in activities_calendar["calendar"]: if activities_calendar["calendar"][activity_day]["result"]: for activity in activities_calendar["calendar"][activity_day][ "data"]["activities"]: if activity["type"] == "Ride": if activity["elevation"] >= 2000.0: activity["elevation_bonus_points"] = 60 elif activity["elevation"] >= 1500.0: activity["elevation_bonus_points"] = 40 elif activity["elevation"] >= 1000.0: activity["elevation_bonus_points"] = 25 elif activity["elevation"] >= 500.0: activity["elevation_bonus_points"] = 10 else: activity["elevation_bonus_points"] = 0 elif activity["type"] == "Run": activity["elevation_bonus_points"] = 0 elif activity["type"] == "Swim": activity["elevation_bonus_points"] = 0 return activities_calendar @staticmethod def calculate_total_distance_and_elevation_for_the_day( activities_calendar): for activity_day in activities_calendar["calendar"]: if activities_calendar["calendar"][activity_day]["result"]: activities_calendar["calendar"][activity_day]["data"].update( {"distance": { "Ride": 0.0, "Run": 0.0, "Swim": 0.0 }}) activities_calendar["calendar"][activity_day]["data"].update( {"elevation": { "Ride": 0.0, "Run": 0.0, "Swim": 0.0 }}) for activity in activities_calendar["calendar"][activity_day][ "data"]["activities"]: if activity["type"] == "Ride": activities_calendar["calendar"][activity_day]["data"][ "distance"]["Ride"] += activity["distance"] activities_calendar["calendar"][activity_day]["data"][ "elevation"]["Ride"] += activity["elevation"] elif activity["type"] == "Run": activities_calendar["calendar"][activity_day]["data"][ "distance"]["Run"] += activity["distance"] activities_calendar["calendar"][activity_day]["data"][ "elevation"]["Run"] += activity["elevation"] elif activity["type"] == "Swim": activities_calendar["calendar"][activity_day]["data"][ "distance"]["Swim"] += activity["distance"] activities_calendar["calendar"][activity_day]["data"][ "elevation"]["Swim"] += activity["elevation"] return activities_calendar @staticmethod def calculate_max_distance_and_elevation_for_the_day(activities_calendar): for activity_day in activities_calendar["calendar"]: if activities_calendar["calendar"][activity_day]["result"]: activities_calendar["calendar"][activity_day]["data"].update( {"max_distance": { "Ride": 0.0, "Run": 0.0, "Swim": 0.0 }}) activities_calendar["calendar"][activity_day]["data"].update( {"max_elevation": { "Ride": 0.0, "Run": 0.0, "Swim": 0.0 }}) list_max_distance_ride = list() list_max_distance_run = list() list_max_distance_swim = list() list_max_elevation_ride = list() list_max_elevation_run = list() list_max_elevation_swim = list() for activity in activities_calendar["calendar"][activity_day][ "data"]["activities"]: if activity["type"] == "Ride": list_max_distance_ride.append(activity["distance"]) list_max_elevation_ride.append(activity["elevation"]) elif activity["type"] == "Run": list_max_distance_run.append(activity["distance"]) list_max_elevation_run.append(activity["elevation"]) elif activity["type"] == "Swim": list_max_distance_swim.append(activity["distance"]) list_max_elevation_swim.append(activity["elevation"]) activities_calendar["calendar"][activity_day]["data"][ "max_distance"]["Ride"] = max( list_max_distance_ride ) if len(list_max_distance_ride) > 0 else 0 activities_calendar["calendar"][activity_day]["data"][ "max_distance"]["Run"] = max(list_max_distance_run) if len( list_max_distance_run) > 0 else 0 activities_calendar["calendar"][activity_day]["data"][ "max_distance"]["Swim"] = max( list_max_distance_swim ) if len(list_max_distance_swim) > 0 else 0 activities_calendar["calendar"][activity_day]["data"][ "max_elevation"]["Ride"] = max( list_max_elevation_ride ) if len(list_max_elevation_ride) > 0 else 0 activities_calendar["calendar"][activity_day]["data"][ "max_elevation"]["Run"] = max( list_max_elevation_run ) if len(list_max_elevation_run) > 0 else 0 activities_calendar["calendar"][activity_day]["data"][ "max_elevation"]["Swim"] = max( list_max_elevation_swim ) if len(list_max_elevation_swim) > 0 else 0 return activities_calendar @staticmethod def calculate_total_distance_and_elevation(activities_calendar): activities_calendar.update( {"total_distance": { "Ride": 0.0, "Run": 0.0, "Swim": 0.0 }}) activities_calendar.update( {"total_elevation": { "Ride": 0.0, "Run": 0.0, "Swim": 0.0 }}) for activity_day in activities_calendar["calendar"]: if activities_calendar["calendar"][activity_day]["result"]: activities_calendar["total_distance"]["Ride"] += \ activities_calendar["calendar"][activity_day]["data"]["distance"]["Ride"] activities_calendar["total_distance"]["Run"] += \ activities_calendar["calendar"][activity_day]["data"]["distance"]["Run"] activities_calendar["total_distance"]["Swim"] += \ activities_calendar["calendar"][activity_day]["data"]["distance"]["Swim"] activities_calendar["total_elevation"]["Ride"] += \ activities_calendar["calendar"][activity_day]["data"]["elevation"]["Ride"] activities_calendar["total_elevation"]["Run"] += \ activities_calendar["calendar"][activity_day]["data"]["elevation"]["Run"] activities_calendar["total_elevation"]["Swim"] += \ activities_calendar["calendar"][activity_day]["data"]["elevation"]["Swim"] return activities_calendar @staticmethod def calculate_consecutive_fifties_and_hundreds(activities_calendar): activities_calendar.update({ "consecutives": { "hundreds": { "three": 0, "two": 0 }, "fifties": { "five": 0, "three": 0 } } }) hundreds_streak = 0 fifties_streak = 0 for activity_day in activities_calendar["calendar"]: if activities_calendar["calendar"][activity_day]["result"]: max_distance = activities_calendar["calendar"][activity_day][ "data"]["max_distance"]["Ride"] if max_distance >= 100000.0: hundreds_streak += 1 fifties_streak += 1 else: hundreds_streak = 0 if max_distance >= 50000.0: fifties_streak += 1 else: fifties_streak = 0 if hundreds_streak == 2: activities_calendar["consecutives"]["hundreds"]["two"] += 1 elif hundreds_streak == 3: activities_calendar["consecutives"]["hundreds"][ "three"] += 1 activities_calendar["consecutives"]["hundreds"]["two"] -= 1 hundreds_streak = 0 elif fifties_streak == 3: activities_calendar["consecutives"]["fifties"][ "three"] += 1 elif fifties_streak == 5: activities_calendar["consecutives"]["fifties"]["five"] += 1 activities_calendar["consecutives"]["fifties"][ "three"] -= 1 fifties_streak = 0 else: hundreds_streak = 0 fifties_streak = 0 return activities_calendar def calculate_base_points(self, points, activities_calendar): points["base"]["Ride"]["distance"] = int( self.operations.meters_to_kilometers( activities_calendar["total_distance"]["Ride"] / 10)) * 2 points["base"]["Run"]["distance"] = int( self.operations.meters_to_kilometers( activities_calendar["total_distance"]["Run"])) points["base"]["Swim"]["distance"] = int( activities_calendar["total_distance"]["Swim"] / 500) points["base"]["Ride"]["elevation"] = int( activities_calendar["total_elevation"]["Ride"] / 100) for activity_day in activities_calendar["calendar"]: if activities_calendar["calendar"][activity_day]["result"]: for activity in activities_calendar["calendar"][activity_day][ "data"]["activities"]: points["base"]["Ride"]["activities"] += activity[ "activity_points"] return points @staticmethod def calculate_bonus_points(points, activities_calendar): if activities_calendar["total_distance"]["Ride"] >= 3000000.0: points["bonus"]["Ride"]["total_distance"] = 500 if activities_calendar["total_elevation"]["Ride"] >= 35000.0: points["bonus"]["Ride"]["total_elevation"] = 500 for activity_day in activities_calendar["calendar"]: if activities_calendar["calendar"][activity_day]["result"]: for activity in activities_calendar["calendar"][activity_day][ "data"]["activities"]: if activity["type"] == "Ride": points["bonus"]["Ride"]["distance"] += activity[ "distance_bonus_points"] points["bonus"]["Ride"]["elevation"] += activity[ "elevation_bonus_points"] # elif activity["type"] == "Run": # points["bonus"]["Run"]["distance"] += activity["distance_bonus_points"] # elif activity["type"] == "Swim": # points["bonus"]["Swim"]["distance"] += activity["distance_bonus_points"] points["bonus"]["Ride"][ "three_consecutive_hundreds"] = 100 * activities_calendar[ "consecutives"]["hundreds"]["three"] points["bonus"]["Ride"][ "two_consecutive_hundreds"] = 50 * activities_calendar[ "consecutives"]["hundreds"]["two"] points["bonus"]["Ride"][ "five_consecutive_fifties"] = 50 * activities_calendar[ "consecutives"]["fifties"]["five"] points["bonus"]["Ride"][ "three_consecutive_fifties"] = 25 * activities_calendar[ "consecutives"]["fifties"]["three"] return points @staticmethod def calculate_total_points(points): total_points = list() total_points.append(sum(list(points["base"]["Ride"].values()))) total_points.append(sum(list(points["base"]["Run"].values()))) total_points.append(sum(list(points["base"]["Swim"].values()))) total_points.append(sum(list(points["bonus"]["Ride"].values()))) total_points.append(sum(list(points["bonus"]["Run"].values()))) total_points.append(sum(list(points["bonus"]["Swim"].values()))) return sum(total_points) @staticmethod def prepare_challenge_summary(points, total_points, athlete_details): challenge_summary = "*ToK Challenge Summary*:\n\n" challenge_summary += "Athlete Name: {}\n".format( athlete_details["name"]) challenge_summary += "Total Points: {}\n\n".format(total_points) # if points["base"]["Ride"]["distance"] > 0: challenge_summary += "*Ride*:\n\n" challenge_summary += "_Base Points_:\n\n" challenge_summary += "Distance: {}\n".format( points["base"]["Ride"]["distance"]) challenge_summary += "Elevation: {}\n".format( points["base"]["Ride"]["elevation"]) challenge_summary += "Activities: {}\n\n".format( points["base"]["Ride"]["activities"]) challenge_summary += "_Bonus Points_:\n\n" challenge_summary += "Distance slots: {}\n".format( points["bonus"]["Ride"]["distance"]) challenge_summary += "Elevation slots: {}\n".format( points["bonus"]["Ride"]["elevation"]) challenge_summary += "3 consecutive 50s: {}\n".format( points["bonus"]["Ride"]["three_consecutive_fifties"]) challenge_summary += "5 consecutive 50s: {}\n".format( points["bonus"]["Ride"]["five_consecutive_fifties"]) challenge_summary += "2 consecutive 100s: {}\n".format( points["bonus"]["Ride"]["two_consecutive_hundreds"]) challenge_summary += "3 consecutive 100s: {}\n".format( points["bonus"]["Ride"]["three_consecutive_hundreds"]) challenge_summary += "3000 km total: {}\n".format( points["bonus"]["Ride"]["total_distance"]) challenge_summary += "35000 meters total: {}\n\n".format( points["bonus"]["Ride"]["total_elevation"]) # if points["base"]["Run"]["distance"] > 0: challenge_summary += "*Run*:\n\n" challenge_summary += "Base Points: {}\n\n".format( points["base"]["Run"]["distance"]) # challenge_summary += "Bonus Points: {}\n\n".format(points["bonus"]["Run"]["distance"]) # if points["base"]["Swim"]["distance"] > 0: challenge_summary += "*Swim*:\n\n" challenge_summary += "Base Points: {}\n".format( points["base"]["Swim"]["distance"]) # challenge_summary += "Bonus Points: {}".format(points["bonus"]["Swim"]["distance"]) return challenge_summary def send_challenges_summary(self, athlete_details, challenges_summary, notify=False): if notify and athlete_details['enable_activity_summary']: self.telegram_resource.send_message( chat_id=athlete_details['chat_id'], message=challenges_summary) logging.info("Sent challenge summary.") def tok_odd_challenges(self, athlete_details): logging.info("Calculating ToK odd challenges..") activities_calendar = ujson.loads( self.get_activities_calendar(athlete_details)) # logging.info("Activities Calendar: %s", activities_calendar) activities_calendar = self.cap_ride_distance_and_elevation( activities_calendar) # logging.info("Activities Calendar with capped distance and elevation for Rides: %s", activities_calendar) activities_calendar = self.calculate_activity_points( activities_calendar) # logging.info("Activities Calendar with activity points: %s", activities_calendar) activities_calendar = self.calculate_distance_bonus( activities_calendar) # logging.info("Activities Calendar with distance bonus: %s", activities_calendar) activities_calendar = self.calculate_elevation_bonus( activities_calendar) # logging.info("Activities Calendar with elevation bonus: %s", activities_calendar) activities_calendar = self.calculate_total_distance_and_elevation_for_the_day( activities_calendar) # logging.info("Activities Calendar with total distance and elevation for the day: %s", activities_calendar) activities_calendar = self.calculate_max_distance_and_elevation_for_the_day( activities_calendar) # logging.info("Activities Calendar with max distance slot for the day: %s", activities_calendar) activities_calendar = self.calculate_total_distance_and_elevation( activities_calendar) # logging.info("Activities Calendar with total distance and elevation: %s", activities_calendar) activities_calendar = self.calculate_consecutive_fifties_and_hundreds( activities_calendar) logging.info("Activities Calendar: %s", activities_calendar) points = { "base": { "Ride": { "distance": 0, "elevation": 0, "activities": 0 }, "Run": { "distance": 0 }, "Swim": { "distance": 0 } }, "bonus": { "Ride": { "distance": 0, "elevation": 0, "total_distance": 0, "total_elevation": 0, "three_consecutive_hundreds": 0, "two_consecutive_hundreds": 0, "five_consecutive_fifties": 0, "three_consecutive_fifties": 0 }, "Run": { "distance": 0 }, "Swim": { "distance": 0 } } } points = self.calculate_base_points(points, activities_calendar) points = self.calculate_bonus_points(points, activities_calendar) logging.info("Points with bonus: %s", points) total_points = self.calculate_total_points(points) logging.info("Total points: %s", total_points) if self.database_resource.write_operation( self.app_constants.QUERY_UPDATE_TOK_ODD_CHALLENGES_DATA.format( challenges_data=ujson.dumps({ 'athlete_id': athlete_details['athlete_id'], 'points': total_points }), athlete_id=athlete_details['athlete_id'])): self.telegram_resource.send_message( "Updated ToK odd challenges data for {name}.".format( name=athlete_details['name'])) else: self.telegram_resource.send_message( "Failed to update ToK odd challenges data for {name}".format( name=athlete_details['name'])) athlete_details_from_bot = self.athlete_resource.get_athlete_details( athlete_details['athlete_id']) if athlete_details_from_bot: challenge_summary = self.prepare_challenge_summary( points, total_points, athlete_details_from_bot) self.send_challenges_summary(athlete_details_from_bot, challenge_summary, True) def consolidate_tok_odd_challenges_result(self): odd_challenge = list() results = self.database_resource.read_all_operation( self.app_constants.QUERY_GET_TOK_ODD_CHALLENGES_DATA) for result in results: name = result[0] challenges = result[1] challenges_data = result[2] if challenges: odd_challenge.append({ 'name': name, 'value': challenges_data['points'] }) odd_challenge_temp = sorted(odd_challenge, key=operator.itemgetter('value'), reverse=True) odd_challenge_sorted = list() rank = 1 for athlete in odd_challenge_temp: odd_challenge_sorted.append({ 'rank': rank, 'name': athlete['name'], 'value': athlete['value'] }) rank += 1 if len(odd_challenge_sorted) == 0: odd_challenge_sorted.append({'rank': '', 'name': '', 'value': ''}) self.iron_cache_resource.put_cache("tok_odd_challenges_result", "leaderboard", ujson.dumps(odd_challenge_sorted)) self.telegram_resource.send_message( "Updated cache for ToK odd month challenge.")