Skip to content

strava competitor - idk if it works at all -- we be vibing #315

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions StravaCompetitor/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
haversine==2.8.0
typing-extensions==4.8.0
183 changes: 183 additions & 0 deletions StravaCompetitor/utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
import haversine
import datetime
import json
import os
from typing import Dict, List, Tuple, Optional, Union, Any

def calculate_distance(coords: List[Tuple[float, float]]) -> float:
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Distance Calculation with Single Coordinate
The function should return 0.0 when the list of coordinates contains only one point, as there are no consecutive points to calculate a distance between.

Outcome Example Input # Inputs % of Total
coords=[(0.0, 0.0)] 200 100.0%

view all inputs
The property-based test has passed, indicating that the calculate_distance function behaves as expected when given a list containing a single GPS coordinate, returning a distance of 0.0 as there are no consecutive points to calculate a distance between, with the test using the argument coords=[(0.0, 0.0)]. This result aligns with the described property that the function should return 0.0 for a single point. The test confirms the function's correctness for this specific scenario.

Unit Tests
# Unit Test for "Distance Calculation with Single Coordinate": The function should return 0.0 when the list of coordinates contains only one point, as there are no consecutive points to calculate a distance between.
def benchify_test_single_coordinate_returns_zero(coords):
    distance = calculate_distance(coords)
    assert distance == 0.0

def benchify_test_single_coordinate_returns_zero_exec_test_passing_0():
    coords=[(0.0, 0.0)]
    benchify_test_single_coordinate_returns_zero(coords)

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Non-decreasing Distance with Additional Coordinates
Adding more coordinates to the list should not decrease the total distance calculated by the function.

Outcome Example Input # Inputs % of Total
coords=[(0.0, 0.0), (0.0, 0.0)... view full input 200 100.0%

view all inputs
The property-based test has passed, indicating that adding more coordinates to the list does not decrease the total distance calculated by the function. With the provided arguments, coords=[(0.0, 0.0), (0.0, 0.0)], the test confirmed that the total distance remains non-decreasing when a new coordinate is added. This suggests that the calculate_distance function is behaving as expected, and the test has validated the property that adding more coordinates does not decrease the total distance.

Unit Tests
# Unit Test for "Non-decreasing Distance with Additional Coordinates": Adding more coordinates to the list should not decrease the total distance calculated by the function.
def benchify_test_distance_non_decreasing_with_more_coords(coords):
    initial_distance = calculate_distance(coords)
    new_coord = (0.0, 0.0)
    new_distance = calculate_distance(coords + [new_coord])
    assert new_distance >= initial_distance

def benchify_test_distance_non_decreasing_with_more_coords_exec_test_passing_0():
    coords=[(0.0, 0.0), (0.0, 0.0)]
    benchify_test_distance_non_decreasing_with_more_coords(coords)

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Non-negative Distance Calculation
The function should always return a non-negative distance, regardless of the input coordinates.

Outcome Example Input # Inputs % of Total
coords=[(0.0, 0.0), (0.0, 0.0)... view full input 200 100.0%

view all inputs
The property-based test has passed, indicating that the calculate_distance function correctly returns a non-negative distance for the given input coordinates [(0.0, 0.0), (0.0, 0.0)]. This suggests that the function behaves as expected, returning a distance of 0.0 kilometers for identical coordinates. With no error type or trace reported, the test result confirms the function's correctness for this specific input scenario.

Unit Tests
# Unit Test for "Non-negative Distance Calculation": The function should always return a non-negative distance, regardless of the input coordinates.
def benchify_test_distance_is_non_negative(coords):
    distance = calculate_distance(coords)
    assert distance >= 0.0

def benchify_test_distance_is_non_negative_exec_test_passing_0():
    coords=[(0.0, 0.0), (0.0, 0.0)]
    benchify_test_distance_is_non_negative(coords)

"""
Calculate total distance in kilometers given a list of GPS coordinates.

Args:
coords: List of (latitude, longitude) tuples

Returns:
Total distance in kilometers
"""
total_distance = 0.0

for i in range(len(coords) - 1):
# Calculate distance between consecutive points using haversine formula
distance = haversine.haversine(coords[i], coords[i+1], unit='km')
total_distance += distance

return total_distance

def calculate_elevation_gain(elevation_data: List[float]) -> float:
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Elevation gain is non-negative
The function calculate_elevation_gain should always return a non-negative value, as it only sums positive elevation differences.

Outcome Example Input # Inputs % of Total
elevation_data=[0.0, 0.0] 200 100.0%

view all inputs
The test for the calculate_elevation_gain function has passed, indicating that it correctly returns a non-negative value for the given elevation data [0.0, 0.0]. This aligns with the expected property that the function should only sum positive elevation differences, resulting in a non-negative total elevation gain. The test result confirms that the function behaves as intended, with no errors or exceptions encountered during execution.

Unit Tests
# Unit Test for "Elevation gain is non-negative": The function `calculate_elevation_gain` should always return a non-negative value, as it only sums positive elevation differences.
def benchify_test_elevation_gain_non_negative(elevation_data):
    result = calculate_elevation_gain(elevation_data)
    assert result >= 0

def benchify_test_elevation_gain_non_negative_exec_test_passing_0():
    elevation_data=[0.0, 0.0]
    benchify_test_elevation_gain_non_negative(elevation_data)

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Zero gain for non-increasing elevation
If all elements in elevation_data are the same or in non-increasing order, the function should return zero, as there would be no positive elevation gain.

Outcome Example Input # Inputs % of Total
elevation_data=[0.0, 0.0] 200 100.0%

view all inputs
The test has passed, indicating that the calculate_elevation_gain function behaves as expected when given elevation data with no positive gain, such as [0.0, 0.0]. The function correctly returns zero, confirming that it handles non-increasing elevation data as described in the property. This result suggests that the function is working correctly for this specific scenario, with no errors or issues encountered during the test.

Unit Tests
# Unit Test for "Zero gain for non-increasing elevation": If all elements in `elevation_data` are the same or in non-increasing order, the function should return zero, as there would be no positive elevation gain.
def benchify_test_zero_gain_for_non_increasing_elevation(elevation_data):
    sorted_data = sorted(elevation_data, reverse=True)
    result = calculate_elevation_gain(sorted_data)
    assert result == 0

def benchify_test_zero_gain_for_non_increasing_elevation_exec_test_passing_0():
    elevation_data=[0.0, 0.0]
    benchify_test_zero_gain_for_non_increasing_elevation(elevation_data)

"""
Calculate total elevation gain in meters from a list of elevation points.

Args:
elevation_data: List of elevation values in meters

Returns:
Total elevation gain in meters
"""
gain = 0.0

for i in range(len(elevation_data) - 1):
# Only count positive elevation changes
diff = elevation_data[i+1] - elevation_data[i]
if diff > 0:
gain += diff

return gain

def calculate_pace(distance_km: float, duration_seconds: int) -> Tuple[int, int]:
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

calculate_pace returns (0, 0) for non-positive distance
If distance_km is zero or negative, calculate_pace should return a tuple (0, 0), indicating an invalid or undefined pace.

Outcome Example Input # Inputs % of Total
distance_km=0.0
duration_seconds=0
200 100.0%

view all inputs
The property-based test has passed, confirming that the calculate_pace function behaves as expected when given a non-positive distance, such as distance_km=0.0 and duration_seconds=0. The function correctly returns a tuple of (0, 0) in this case, indicating an invalid or undefined pace. This result aligns with the described property, which states that a zero or negative distance_km should yield a return value of (0, 0).

Unit Tests
# Unit Test for "`calculate_pace` returns (0, 0) for non-positive distance": If `distance_km` is zero or negative, `calculate_pace` should return a tuple (0, 0), indicating an invalid or undefined pace.
def benchify_test_calculate_pace_non_positive_distance(distance_km, duration_seconds):
    assert calculate_pace(distance_km, duration_seconds) == (0, 0)

def benchify_test_calculate_pace_non_positive_distance_exec_test_passing_0():
    distance_km=0.0
    duration_seconds=0
    benchify_test_calculate_pace_non_positive_distance(distance_km, duration_seconds)

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

calculate_pace returns non-negative minutes and seconds
For positive distance_km, calculate_pace should return a tuple where both minutes and seconds are non-negative integers.

Outcome Example Input # Inputs % of Total
distance_km=0.0001
duration_seconds=0
200 100.0%

view all inputs
The property-based test has passed, indicating that the calculate_pace function behaves as expected for positive distance_km values, returning non-negative integers for both minutes and seconds. With input arguments distance_km=0.0001 and duration_seconds=0, the function correctly handled this edge case. The test result confirms that the function adheres to its specified property, providing a tuple of non-negative minutes and seconds for the given input.

Unit Tests
# Unit Test for "`calculate_pace` returns non-negative minutes and seconds": For positive `distance_km`, `calculate_pace` should return a tuple where both `minutes` and `seconds` are non-negative integers.
def benchify_test_calculate_pace_non_negative_output(distance_km, duration_seconds):
    minutes, seconds = calculate_pace(distance_km, duration_seconds)
    assert minutes >= 0 and seconds >= 0

def benchify_test_calculate_pace_non_negative_output_exec_test_passing_0():
    distance_km=0.0001
    duration_seconds=0
    benchify_test_calculate_pace_non_negative_output(distance_km, duration_seconds)

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

calculate_pace calculates correct pace
For positive distance_km, the sum of minutes * 60 + seconds should equal duration_seconds / distance_km.

Outcome Example Input # Inputs % of Total
distance_km=0.0001
duration_seconds=0
192 96.0%
distance_km=1.5
duration_seconds=7984612441624... view full input
8 4.0%

view all inputs
The test test_calculate_pace_correctness failed with an AssertionError due to a mismatch between the calculated pace and the expected value, specifically when distance_km=1.5 and duration_seconds=7984612441624629471. The error occurred because the calculated minutes and seconds (88717916018051424 * 60 + 24) did not equal the expected value (int(7984612441624629471 / 1.5)), indicating a potential issue with the calculate_pace function.

Stack Trace
Traceback (most recent call last):
  File "/app/repo/StravaCompetitor/pver_0c6eaacc-73d7-4f9e-a55d-e457e52e1ef7-test.py", line 319, in wrapper
    ret = func(*args, **kwargs)
  File "/app/repo/StravaCompetitor/pver_0c6eaacc-73d7-4f9e-a55d-e457e52e1ef7-test.py", line 482, in test_calculate_pace_correctness
    assert minutes * 60 + seconds == int(duration_seconds / distance_km)
AssertionError: assert ((88717916018051424 * 60) + 24) == 5323074961083085824
 +  where 5323074961083085824 = int((7984612441624629471 / 1.5))

"""
Calculate pace in minutes per kilometer.

Args:
distance_km: Distance in kilometers
duration_seconds: Duration in seconds

Returns:
Tuple of (minutes, seconds) per kilometer
"""
if distance_km <= 0:
return (0, 0)

# Calculate seconds per kilometer
seconds_per_km = duration_seconds / distance_km

# Convert to minutes and seconds
minutes = int(seconds_per_km // 60)
seconds = int(seconds_per_km % 60)

return (minutes, seconds)

def save_activity(user_id: str, activity_data: Dict[str, Any],
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

❌ Unique Activity ID Generation
The function save_activity should generate a unique activity ID for each call, assuming user_id and the current timestamp are unique at the time of the call.

Outcome Example Input # Inputs % of Total
user_id='0'
activity_data={}
200 100.0%

view all inputs
The property-based test failed with an AssertionError because the save_activity function generated the same activity ID '0_20250319165819' for two consecutive calls with the same user_id='0' and empty activity_data dictionary. This suggests that the function's reliance on the current timestamp to generate unique IDs may not be sufficient when multiple calls are made in quick succession, resulting in duplicate IDs.

Stack Trace
Traceback (most recent call last):
  File "/app/repo/StravaCompetitor/pver_d7a188d6-7e47-410d-bd00-c72fbdcfe2e4-test.py", line 319, in wrapper
    ret = func(*args, **kwargs)
  File "/app/repo/StravaCompetitor/pver_d7a188d6-7e47-410d-bd00-c72fbdcfe2e4-test.py", line 492, in test_unique_activity_id
    assert activity_id1 != activity_id2
AssertionError: assert '0_20250319165819' != '0_20250319165819'
Unit Tests
# Unit Test for "Unique Activity ID Generation": The function `save_activity` should generate a unique activity ID for each call, assuming `user_id` and the current timestamp are unique at the time of the call.
def benchify_test_unique_activity_id(user_id, activity_data):
    activity_id1 = save_activity(user_id, activity_data.copy())
    activity_id2 = save_activity(user_id, activity_data.copy())
    assert activity_id1 != activity_id2

def benchify_test_unique_activity_id_exec_test_failing_0():
    user_id='0'
    activity_data={}
    benchify_test_unique_activity_id(user_id, activity_data)

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

❌ Directory Creation and JSON File Saving
The function save_activity should create a directory for the user if it does not already exist, and save the activity_data as a JSON file in that directory.

Outcome Example Input # Inputs % of Total
user_id='0'
activity_data={}
180 90.0%
user_id='P³\U0003d448\tÜ/'
activity_data={}
20 10.0%

view all inputs
The test failed due to a FileNotFoundError when attempting to save an activity as a JSON file, with the error occurring when trying to open the file at path 'test_data/activities/P³\U0003d448\tÜ/_20250319165741.json'. This issue arose when the save_activity function was called with a user_id of 'P³\U0003d448\tÜ/' and an empty activity_data dictionary, suggesting that the function is not properly handling directory creation for user IDs with special characters.

Stack Trace
Traceback (most recent call last):
  File "/app/repo/StravaCompetitor/pver_1ced1198-cbd4-4626-ba55-72c6310cd914-test.py", line 319, in wrapper
    ret = func(*args, **kwargs)
  File "/app/repo/StravaCompetitor/pver_1ced1198-cbd4-4626-ba55-72c6310cd914-test.py", line 491, in test_directory_creation_and_json_saving
    activity_id = save_activity(user_id, activity_data.copy(), base_dir)
  File "/app/repo/StravaCompetitor/utils.py", line 95, in save_activity
    with open(file_path, "w") as f:
FileNotFoundError: [Errno 2] No such file or directory: 'test_data/activities/P³\U0003d448\tÜ/P³\U0003d448\tÜ/_20250319165741.json'

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

❌ Activity Data Modification
The function save_activity should add an 'id' key with the generated activity ID and a 'timestamp' key with the current timestamp to the activity_data dictionary before saving it.

Outcome Example Input # Inputs % of Total
user_id='0'
activity_data={}
200 100.0%

view all inputs
The test failed with an AssertionError because the activity_data dictionary was empty, causing the assertion 'id' in activity_data to fail. The error occurred when user_id='0' and activity_data={} were passed to the test_activity_data_modification function, indicating that the save_activity function did not add the 'id' key to the activity_data dictionary as expected. The issue may be due to the fact that the activity_data dictionary was not modified by the save_activity function before the assertion was made.

Stack Trace
Traceback (most recent call last):
  File "/app/repo/StravaCompetitor/pver_fb14676c-49b7-4f06-aa43-d18f7ea2619e-test.py", line 319, in wrapper
    ret = func(*args, **kwargs)
  File "/app/repo/StravaCompetitor/pver_fb14676c-49b7-4f06-aa43-d18f7ea2619e-test.py", line 491, in test_activity_data_modification
    assert "id" in activity_data
AssertionError: assert 'id' in {}
Unit Tests
# Unit Test for "Activity Data Modification": The function `save_activity` should add an 'id' key with the generated activity ID and a 'timestamp' key with the current timestamp to the `activity_data` dictionary before saving it.
def benchify_test_activity_data_modification(user_id, activity_data):
    activity_id = save_activity(user_id, activity_data.copy())
    assert "id" in activity_data
    assert activity_data["id"] == activity_id
    assert "timestamp" in activity_data

def benchify_test_activity_data_modification_exec_test_failing_0():
    user_id='0'
    activity_data={}
    benchify_test_activity_data_modification(user_id, activity_data)

base_dir: str = "data/activities") -> str:
"""
Save activity data to disk and return the activity ID.

Args:
user_id: Unique identifier for the user
activity_data: Dictionary containing activity information
base_dir: Base directory for storing activity data

Returns:
Activity ID
"""
# Generate a unique activity ID
activity_id = f"{user_id}_{datetime.datetime.now().strftime('%Y%m%d%H%M%S')}"

# Add activity ID and timestamp to the data
activity_data["id"] = activity_id
activity_data["timestamp"] = datetime.datetime.now().isoformat()

# Create user directory if it doesn't exist
user_dir = os.path.join(base_dir, user_id)
os.makedirs(user_dir, exist_ok=True)

# Save activity data as JSON
file_path = os.path.join(user_dir, f"{activity_id}.json")
with open(file_path, "w") as f:
json.dump(activity_data, f, indent=2)

return activity_id

def get_user_activities(user_id: str, limit: Optional[int] = None,
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Returns empty list if user directory does not exist
The function should return an empty list if the directory corresponding to the user_id does not exist.

Outcome Example Input # Inputs % of Total
user_id=''
limit=1
activity_type=''
base_dir=''
194 100.0%

view all inputs
The property-based test has passed, confirming that the get_user_activities function returns an empty list when the directory corresponding to the user_id does not exist, as specified by the property description. With input arguments such as user_id='', limit=1, activity_type='', and base_dir='', the function behaves as expected. This passing result indicates that the function is working correctly under these conditions, with no errors or exceptions encountered during the test.

Unit Tests
# Unit Test for "Returns empty list if user directory does not exist": The function should return an empty list if the directory corresponding to the user_id does not exist.
def benchify_test_get_user_activities_no_directory(user_id, limit, activity_type, base_dir):
    
    result = get_user_activities(user_id, limit, activity_type, base_dir)
    assert result == []

def benchify_test_get_user_activities_no_directory_exec_test_passing_0():
    user_id=''
    limit=1
    activity_type=''
    base_dir=''
    benchify_test_get_user_activities_no_directory(user_id, limit, activity_type, base_dir)

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

❌ Returns activities sorted by timestamp
The function should return a list of activities sorted by the 'timestamp' key in descending order.

Outcome Example Input # Inputs % of Total
user_id=''
limit=1
activity_type=''
base_dir=''
8 4.0%
user_id='TAJgi'
limit=1
activity_type=''
base_dir=''
192 96.0%

view all inputs
The test failed due to a FileNotFoundError when attempting to create a directory with an empty path, as indicated by the args showing user_id='' and base_dir=''. This error occurred because the os.makedirs function was called with an empty string, which is not a valid directory path. To resolve this issue, the function should be modified to handle empty or invalid input values for user_id and base_dir.

Stack Trace
Traceback (most recent call last):
  File "/app/repo/StravaCompetitor/pver_7fab035c-e229-4298-8fd2-f08c7d9d8c26-test.py", line 319, in wrapper
    ret = func(*args, **kwargs)
  File "/app/repo/StravaCompetitor/pver_7fab035c-e229-4298-8fd2-f08c7d9d8c26-test.py", line 489, in test_get_user_activities_sorted_by_timestamp
    os.makedirs(user_dir, exist_ok=True)
  File "/usr/lib/python3.10/os.py", line 225, in makedirs
    mkdir(name, mode)
FileNotFoundError: [Errno 2] No such file or directory: ''
Unit Tests
# Unit Test for "Returns activities sorted by timestamp": The function should return a list of activities sorted by the 'timestamp' key in descending order.
def benchify_test_get_user_activities_sorted_by_timestamp(user_id, limit, activity_type, base_dir):
    user_dir = os.path.join(base_dir, user_id)
    os.makedirs(user_dir, exist_ok=True)
    activities = [
        {'timestamp': '2023-10-01T12:00:00', 'type': 'run'},
        {'timestamp': '2023-10-02T12:00:00', 'type': 'ride'},
        {'timestamp': '2023-10-03T12:00:00', 'type': 'swim'}
    ]
    for i, activity in enumerate(activities):
        with open(os.path.join(user_dir, f'activity_{i}.json'), 'w') as f:
            json.dump(activity, f)
    result = get_user_activities(user_id, limit, activity_type, base_dir)
    assert result == sorted(result, key=lambda x: x['timestamp'], reverse=True)

def benchify_test_get_user_activities_sorted_by_timestamp_exec_test_failing_0():
    user_id=''
    limit=1
    activity_type=''
    base_dir=''
    benchify_test_get_user_activities_sorted_by_timestamp(user_id, limit, activity_type, base_dir)

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

❌ Respects limit on number of activities returned
The function should return at most 'limit' number of activities if 'limit' is provided and is a positive integer.

Outcome Example Input # Inputs % of Total
user_id=''
limit=1
activity_type=''
base_dir=''
6 3.0%
user_id='l7'
limit=1
activity_type=''
base_dir=''
194 97.0%

view all inputs
The test test_get_user_activities_respects_limit failed due to a FileNotFoundError when attempting to create a directory with an empty path, as indicated by the args user_id='' and base_dir=''. This error occurred because the os.makedirs function was called with an empty string, which is not a valid directory path. To resolve this issue, the function should be modified to handle empty or invalid input values for user_id and base_dir.

Stack Trace
Traceback (most recent call last):
  File "/app/repo/StravaCompetitor/pver_057c4ce3-08e6-44c7-8caa-f0f6ce502678-test.py", line 319, in wrapper
    ret = func(*args, **kwargs)
  File "/app/repo/StravaCompetitor/pver_057c4ce3-08e6-44c7-8caa-f0f6ce502678-test.py", line 487, in test_get_user_activities_respects_limit
    os.makedirs(user_dir, exist_ok=True)
  File "/usr/lib/python3.10/os.py", line 225, in makedirs
    mkdir(name, mode)
FileNotFoundError: [Errno 2] No such file or directory: ''
Unit Tests
# Unit Test for "Respects limit on number of activities returned": The function should return at most 'limit' number of activities if 'limit' is provided and is a positive integer.
def benchify_test_get_user_activities_respects_limit(user_id, limit, activity_type, base_dir):
    user_dir = os.path.join(base_dir, user_id)
    os.makedirs(user_dir, exist_ok=True)
    activities = [
        {'timestamp': '2023-10-01T12:00:00', 'type': 'run'},
        {'timestamp': '2023-10-02T12:00:00', 'type': 'ride'},
        {'timestamp': '2023-10-03T12:00:00', 'type': 'swim'}
    ]
    for i, activity in enumerate(activities):
        with open(os.path.join(user_dir, f'activity_{i}.json'), 'w') as f:
            json.dump(activity, f)
    result = get_user_activities(user_id, limit, activity_type, base_dir)
    assert len(result) <= limit

def benchify_test_get_user_activities_respects_limit_exec_test_failing_0():
    user_id=''
    limit=1
    activity_type=''
    base_dir=''
    benchify_test_get_user_activities_respects_limit(user_id, limit, activity_type, base_dir)

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

❌ Filters activities by type
The function should only include activities where the 'type' key matches the 'activity_type' if 'activity_type' is provided.

Outcome Example Input # Inputs % of Total
user_id=''
limit=1
activity_type='run'
base_dir=''
22 11.0%
user_id='I0wXJRS2'
limit=1
activity_type='run'
base_dir=''
178 89.0%

view all inputs
The test failed due to a FileNotFoundError when attempting to create a directory with an empty path, as indicated by the args showing base_dir='' and user_id=''. This error occurred because the os.makedirs function was called with an empty string, which is not a valid directory path. The test case was generated with empty strings for user_id and base_dir, which caused the function to fail when trying to create the directory.

Stack Trace
Traceback (most recent call last):
  File "/app/repo/StravaCompetitor/pver_8d5a61d7-845c-4404-be84-c0df0adee08a-test.py", line 319, in wrapper
    ret = func(*args, **kwargs)
  File "/app/repo/StravaCompetitor/pver_8d5a61d7-845c-4404-be84-c0df0adee08a-test.py", line 487, in test_get_user_activities_filters_by_type
    os.makedirs(user_dir, exist_ok=True)
  File "/usr/lib/python3.10/os.py", line 225, in makedirs
    mkdir(name, mode)
FileNotFoundError: [Errno 2] No such file or directory: ''
Unit Tests
# Unit Test for "Filters activities by type": The function should only include activities where the 'type' key matches the 'activity_type' if 'activity_type' is provided.
def benchify_test_get_user_activities_filters_by_type(user_id, limit, activity_type, base_dir):
    user_dir = os.path.join(base_dir, user_id)
    os.makedirs(user_dir, exist_ok=True)
    activities = [
        {'timestamp': '2023-10-01T12:00:00', 'type': 'run'},
        {'timestamp': '2023-10-02T12:00:00', 'type': 'ride'},
        {'timestamp': '2023-10-03T12:00:00', 'type': 'swim'}
    ]
    for i, activity in enumerate(activities):
        with open(os.path.join(user_dir, f'activity_{i}.json'), 'w') as f:
            json.dump(activity, f)
    result = get_user_activities(user_id, limit, activity_type, base_dir)
    assert all(activity['type'] == activity_type for activity in result)

def benchify_test_get_user_activities_filters_by_type_exec_test_failing_0():
    user_id=''
    limit=1
    activity_type='run'
    base_dir=''
    benchify_test_get_user_activities_filters_by_type(user_id, limit, activity_type, base_dir)

activity_type: Optional[str] = None,
base_dir: str = "data/activities") -> List[Dict[str, Any]]:
"""
Retrieve a user's activities with optional filtering.

Args:
user_id: Unique identifier for the user
limit: Maximum number of activities to return (newest first)
activity_type: Filter by activity type (e.g., "run", "ride", "swim")
base_dir: Base directory for storing activity data

Returns:
List of activity data dictionaries
"""
user_dir = os.path.join(base_dir, user_id)

# Return empty list if user directory doesn't exist
if not os.path.exists(user_dir):
return []

activities = []

# Get all JSON files in the user directory
for filename in os.listdir(user_dir):
if filename.endswith(".json"):
file_path = os.path.join(user_dir, filename)
with open(file_path, "r") as f:
activity = json.load(f)

# Apply activity type filter if provided
if activity_type is None or activity.get("type") == activity_type:
activities.append(activity)

# Sort activities by timestamp (newest first)
activities.sort(key=lambda x: x.get("timestamp", ""), reverse=True)

# Apply limit if provided
if limit is not None and limit > 0:
activities = activities[:limit]

return activities

def calculate_statistics(activities: List[Dict[str, Any]]) -> Dict[str, Any]:
"""
Calculate summary statistics for a list of activities.

Args:
activities: List of activity dictionaries

Returns:
Dictionary with summary statistics
"""
if not activities:
return {
"total_activities": 0,
"total_distance": 0,
"total_elevation_gain": 0,
"total_duration": 0,
"activity_types": {}
}

stats = {
"total_activities": len(activities),
"total_distance": 0,
"total_elevation_gain": 0,
"total_duration": 0,
"activity_types": {}
}

for activity in activities:
# Accumulate totals
stats["total_distance"] += activity.get("distance", 0)
stats["total_elevation_gain"] += activity.get("elevation_gain", 0)
stats["total_duration"] += activity.get("duration", 0)

# Count by activity type
activity_type = activity.get("type", "unknown")
if activity_type in stats["activity_types"]:
stats["activity_types"][activity_type] += 1
else:
stats["activity_types"][activity_type] = 1

return stats