Skip to content

Instantly share code, notes, and snippets.

@ahaxu
Last active February 2, 2025 06:29
Show Gist options
  • Save ahaxu/c86de34e19be44a5c61483dcbdd0c083 to your computer and use it in GitHub Desktop.
Save ahaxu/c86de34e19be44a5c61483dcbdd0c083 to your computer and use it in GitHub Desktop.
98_runners_tet_2025.py
def f(activities):
"""
customize rule for 98 runners
challenge Tet 2025
"""
import math
from datetime import datetime
white_list_acts = [
]
act_by_date = dict()
for act in activities:
dt_str = act.get('start_date_local') # 2021-02-12T20:40:00Z
dt_obj = datetime.strptime(dt_str, '%Y-%m-%dT%H:%M:%SZ')
# key for ac_by_date dict
dt_ymd = int("{}{}{}".format(dt_obj.year, dt_obj.month, dt_obj.day))
# check if act has minimum 1km
min_km = math.floor(act["distance"]/1000)
if min_km < 1:
print('act id {} with km {} not satisfied'.format(
act.get('id'), min_km))
continue
# check gps
start_latlng = act.get('start_latlng')
end_latlng = act.get('end_latlng')
# print('debug latlong {} {} {}'.format(act.get('id'), start_latlng, end_latlng))
if len(start_latlng) == 0 or len(end_latlng) == 0:
print('act id {} has no GPS'.format(act.get('id')))
continue
# round with 2 decimal
km = round(act["distance"] / 1000, 2)
# check if act over 42.2km
if km > 42.2:
print('act id {} with km {} over 42.2 km'.format(
act.get('id'), km))
continue
if act.get('id') in white_list_acts:
act["block"] = km
act["km"] = km
act["point"] = km
if dt_ymd in act_by_date:
act_by_date[dt_ymd].append(act)
else:
act_by_date[dt_ymd] = [act]
print("whitelist act id {} - name {}".format(act.get('id'), act.get('name')))
continue
# check rest time
gap_time_in_minutes = abs(
act.get('elapsed_time', 0) - act.get('moving_time', 0)) / 60
if gap_time_in_minutes > 30:
print("act_id {}: over 30 mins".format(act.get('id')))
continue
# check avg_pace first
avg_pace = round((1000/act.get('average_speed', 0))/60, 1)
if act.get('type') == "Run" \
and (3 <= avg_pace <= 12):
# check valid split pace via splits_metric
if act.get('splits_metric') is None:
print('act id {} has no splits_metric info'.format(act.get('id')))
continue
is_valid_split_pace = True
for split in act.get('splits_metric'):
print('split {}'.format(split))
if split.get('distance') < 100:
print(
'consider valid pace for distance less than 100m {}'.format(split))
continue
if int(split.get('average_speed')) == 0:
is_valid_split_pace = False
print('invalid average speed')
print(split)
break
split_pace = round(
(1000/split.get('average_speed', 0))/60, 1)
if split_pace < 3 or split_pace > 12:
is_valid_split_pace = False
print('act id {} has in valid split pace, split no: {}, split_pace: {}'.format(
act.get('id'), split.get('split'), split_pace))
break
# if valid split pace add to act_by_date
if is_valid_split_pace:
act['block'] = km
act['km'] = km
act['point'] = km
if dt_ymd in act_by_date:
act_by_date[dt_ymd].append(act)
else:
act_by_date[dt_ymd] = [act]
valid_acts = []
for d in sorted(act_by_date):
print("debug act by date {}".format(d))
print("debug act by date len {}".format(len(act_by_date.get(d))))
# sort by start_date_local
aacts = sorted(act_by_date.get(
d), key=lambda x: x.get('start_date_local'), reverse=True)
for a in aacts:
# x2 km/point
if d in [202521, 202522, 202528, 202529, 2025215, 2025216]:
print('x2 day {} - {}'.format(d, km))
a['block'] = 2 * a.get('block')
a['km'] = 1 * a.get('km')
a['point'] = 2 * a.get('point')
valid_acts.append(a)
print('valid_acts len: {}'.format(len(valid_acts)))
return valid_acts
acts = f(activities)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment