first commit
This commit is contained in:
206
assets/bicycle_gear_calculator_withsummary_1746460243216_0.py
Normal file
206
assets/bicycle_gear_calculator_withsummary_1746460243216_0.py
Normal file
@@ -0,0 +1,206 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Bicycle Gear Calculator
|
||||
|
||||
This script calculates and generates markdown tables for:
|
||||
- Gear inches for combinations of chainring and rear cog
|
||||
- Cadence for combinations of chainring and rear cog at different target speeds
|
||||
- Speeds in MPH for combinations of chainring and rear cog at different target cadences
|
||||
|
||||
The script also provides an option to save each table as a separate file.
|
||||
"""
|
||||
|
||||
import os
|
||||
import math
|
||||
|
||||
def calculate_gear_inches(chainring, cog, wheel_size, tire_width):
|
||||
"""Calculate gear inches for a given combination."""
|
||||
# Calculate wheel diameter in inches (including tire)
|
||||
wheel_diameter = wheel_size / 25.4 + 2 * tire_width / 25.4
|
||||
return (chainring / cog) * wheel_diameter
|
||||
|
||||
def calculate_speed(chainring, cog, wheel_size, tire_width, cadence):
|
||||
"""Calculate speed in MPH for a given combination and cadence."""
|
||||
# Calculate wheel circumference in meters
|
||||
wheel_diameter_m = (wheel_size + 2 * tire_width) / 1000
|
||||
wheel_circumference_m = wheel_diameter_m * math.pi
|
||||
|
||||
# Calculate distance traveled per pedal revolution in meters
|
||||
distance_per_revolution = wheel_circumference_m * (chainring / cog)
|
||||
|
||||
# Calculate speed in MPH (cadence is in RPM)
|
||||
# distance_per_minute = distance_per_revolution * cadence (meters/minute)
|
||||
# Convert to meters/hour and then to miles/hour
|
||||
meters_per_hour = distance_per_revolution * cadence * 60
|
||||
miles_per_hour = meters_per_hour / 1609.34
|
||||
|
||||
return miles_per_hour
|
||||
|
||||
def calculate_cadence(chainring, cog, wheel_size, tire_width, speed_mph):
|
||||
"""Calculate cadence in RPM for a given combination and speed."""
|
||||
# Calculate wheel circumference in meters
|
||||
wheel_diameter_m = (wheel_size + 2 * tire_width) / 1000
|
||||
wheel_circumference_m = wheel_diameter_m * math.pi
|
||||
|
||||
# Calculate distance traveled per pedal revolution in meters
|
||||
distance_per_revolution = wheel_circumference_m * (chainring / cog)
|
||||
|
||||
# Calculate cadence in RPM
|
||||
# speed_mph converted to meters/minute
|
||||
meters_per_minute = speed_mph * 1609.34 / 60
|
||||
cadence = meters_per_minute / distance_per_revolution
|
||||
|
||||
return cadence
|
||||
|
||||
def create_gear_inches_table(chainrings, cogs, wheel_size, tire_width):
|
||||
"""Create a markdown table showing gear inches for all combinations."""
|
||||
header = "| Chainring / Cog | " + " | ".join([str(cog) for cog in cogs]) + " |\n"
|
||||
separator = "| --- | " + " | ".join(["---" for _ in cogs]) + " |\n"
|
||||
|
||||
rows = ""
|
||||
for chainring in chainrings:
|
||||
row = f"| {chainring} | "
|
||||
row += " | ".join([f"{calculate_gear_inches(chainring, cog, wheel_size, tire_width):.1f}" for cog in cogs])
|
||||
row += " |\n"
|
||||
rows += row
|
||||
|
||||
return header + separator + rows
|
||||
|
||||
def create_cadence_table(chainrings, cogs, wheel_size, tire_width, speed_mph):
|
||||
"""Create a markdown table showing cadence for all combinations at a specific speed."""
|
||||
header = f"| Cadence at {speed_mph} MPH | " + " | ".join([str(cog) for cog in cogs]) + " |\n"
|
||||
separator = "| --- | " + " | ".join(["---" for _ in cogs]) + " |\n"
|
||||
|
||||
rows = ""
|
||||
for chainring in chainrings:
|
||||
row = f"| {chainring} | "
|
||||
row += " | ".join([f"{calculate_cadence(chainring, cog, wheel_size, tire_width, speed_mph):.1f}" for cog in cogs])
|
||||
row += " |\n"
|
||||
rows += row
|
||||
|
||||
return header + separator + rows
|
||||
|
||||
def create_speed_table(chainrings, cogs, wheel_size, tire_width, cadence):
|
||||
"""Create a markdown table showing speed for all combinations at a specific cadence."""
|
||||
header = f"| Speed at {cadence} RPM | " + " | ".join([str(cog) for cog in cogs]) + " |\n"
|
||||
separator = "| --- | " + " | ".join(["---" for _ in cogs]) + " |\n"
|
||||
|
||||
rows = ""
|
||||
for chainring in chainrings:
|
||||
row = f"| {chainring} | "
|
||||
row += " | ".join([f"{calculate_speed(chainring, cog, wheel_size, tire_width, cadence):.1f}" for cog in cogs])
|
||||
row += " |\n"
|
||||
rows += row
|
||||
|
||||
return header + separator + rows
|
||||
|
||||
def save_to_file(content, filename):
|
||||
"""Save content to a file."""
|
||||
with open(filename, 'w') as f:
|
||||
f.write(content)
|
||||
print(f"Saved to {filename}")
|
||||
|
||||
def create_summary_table(chainrings, cogs, wheel_size, tire_width):
|
||||
"""Create a comprehensive summary table with multiple metrics for each combination."""
|
||||
# Define reference values
|
||||
reference_speed = 20.0 # mph
|
||||
reference_cadence = 100.0 # rpm
|
||||
|
||||
header = "| Chainring | Cog | Ratio | Gear Inches | Cadence at 20mph | Speed at 100rpm |\n"
|
||||
separator = "| --- | --- | --- | --- | --- | --- |\n"
|
||||
|
||||
rows = ""
|
||||
for chainring in chainrings:
|
||||
for cog in cogs:
|
||||
# Calculate all metrics
|
||||
ratio = round(chainring / cog, 2)
|
||||
gear_inches = calculate_gear_inches(chainring, cog, wheel_size, tire_width)
|
||||
cadence_at_20mph = calculate_cadence(chainring, cog, wheel_size, tire_width, reference_speed)
|
||||
speed_at_100rpm = calculate_speed(chainring, cog, wheel_size, tire_width, reference_cadence)
|
||||
|
||||
# Format the row
|
||||
row = f"| {chainring} | {cog} | {ratio:.2f} | {gear_inches:.1f} | {cadence_at_20mph:.1f} | {speed_at_100rpm:.1f} |\n"
|
||||
rows += row
|
||||
|
||||
return header + separator + rows
|
||||
|
||||
def main():
|
||||
# User input for variables
|
||||
print("Bicycle Gear Calculator")
|
||||
print("======================\n")
|
||||
|
||||
# Get tire and wheel specifications
|
||||
tire_width = float(input("Enter tire width in mm (e.g., 23): ") or 25)
|
||||
wheel_size = float(input("Enter wheel size in mm (e.g., 622 for 700c): ") or 622)
|
||||
|
||||
# Get chainring and cog specifications
|
||||
chainring_input = input("Enter list of chainring teeth, separated by commas (e.g., 34,36,38,40): ") or "34,36,38,40,42"
|
||||
chainrings = [int(x.strip()) for x in chainring_input.split(",")]
|
||||
|
||||
cog_input = input("Enter list of rear cog teeth, separated by commas (e.g., 11,12,13,14,16,18,20,22,25,28,32): ") or "11,12,13,14,16,18,20,22,25,28,32"
|
||||
cogs = [int(x.strip()) for x in cog_input.split(",")]
|
||||
|
||||
# Get target cadences and speeds
|
||||
cadence_input = input("Enter list of target cadences in RPM, separated by commas (e.g., 80,90,100): ") or "80,90,100"
|
||||
cadences = [int(x.strip()) for x in cadence_input.split(",")]
|
||||
|
||||
speed_input = input("Enter list of target speeds in MPH, separated by commas (e.g., 15,18,20,25): ") or "15,18,20,25"
|
||||
speeds = [float(x.strip()) for x in speed_input.split(",")]
|
||||
|
||||
# Generate tables
|
||||
print("\nGenerating tables...\n")
|
||||
|
||||
# Gear inches table
|
||||
gear_inches_table = create_gear_inches_table(chainrings, cogs, wheel_size, tire_width)
|
||||
print("Gear Inches Table:")
|
||||
print(gear_inches_table)
|
||||
|
||||
# Cadence tables for each target speed
|
||||
cadence_tables = []
|
||||
for speed in speeds:
|
||||
table = create_cadence_table(chainrings, cogs, wheel_size, tire_width, speed)
|
||||
cadence_tables.append((speed, table))
|
||||
print(f"\nCadence Table for {speed} MPH:")
|
||||
print(table)
|
||||
|
||||
# Speed tables for each target cadence
|
||||
speed_tables = []
|
||||
for cadence in cadences:
|
||||
table = create_speed_table(chainrings, cogs, wheel_size, tire_width, cadence)
|
||||
speed_tables.append((cadence, table))
|
||||
print(f"\nSpeed Table for {cadence} RPM:")
|
||||
print(table)
|
||||
|
||||
# Summary table with multiple metrics
|
||||
summary_table = create_summary_table(chainrings, cogs, wheel_size, tire_width)
|
||||
print("\nSummary Table (all metrics):")
|
||||
print(summary_table)
|
||||
|
||||
# Option to save tables
|
||||
save_option = input("\nDo you want to save tables to files? (y/n): ").lower().strip()
|
||||
if save_option == 'y':
|
||||
# Create a directory for the files if it doesn't exist
|
||||
output_dir = "gear_tables"
|
||||
if not os.path.exists(output_dir):
|
||||
os.makedirs(output_dir)
|
||||
|
||||
# Save gear inches table
|
||||
gear_inches_filename = os.path.join(output_dir, "gear_inches.md")
|
||||
save_to_file(gear_inches_table, gear_inches_filename)
|
||||
|
||||
# Save cadence tables
|
||||
for speed, table in cadence_tables:
|
||||
cadence_filename = os.path.join(output_dir, f"cadence_at_{speed}mph.md")
|
||||
save_to_file(table, cadence_filename)
|
||||
|
||||
# Save speed tables
|
||||
for cadence, table in speed_tables:
|
||||
speed_filename = os.path.join(output_dir, f"speed_at_{cadence}rpm.md")
|
||||
save_to_file(table, speed_filename)
|
||||
|
||||
# Save summary table
|
||||
summary_filename = os.path.join(output_dir, "summary_table.md")
|
||||
save_to_file(summary_table, summary_filename)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user