first commit

This commit is contained in:
2025-12-11 06:26:12 -08:00
commit 4662fe2d3b
2327 changed files with 114173 additions and 0 deletions

View 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()