DZone Snippets is a public source code repository. Easily build up your personal collection of code snippets, categorize them with tags / keywords, and share them with the world

Snippets has posted 5883 posts at DZone. View Full User Profile

Tranny_sprocket.py

04.07.2010
| 2276 views |
  • submit to reddit
        
#!/usr/bin/python3
# tranny_sprocket.py rev14
# by xlforum.net/paul618
# PM me there or post to thread 773940 with data problems or suggestions

# Thanks to xlforum.net/Folkie for helping out.
# Thanks to xlforum.net/billeuze for testing on Vista.

# This builds a chart of MPH per RPM for any tire size and supported sprocket set.
# If your machine is not listed you can add a record to the dataset.

# This runs on python3.x on any platform you can imagine.
# Tested on a Mac (v. 10.6.3)
# Tested on Vista by xlforum.net/billeuze

# To run this on a Mac, Gnu/Linux or PC:
# 0) download python3.1
# 1) paste this program into a file called tranny_sprocket.py
# 2) fire up the IDE called IDLE that came with python3.1
# 3) File/Open tranny_sprocket.py
# 4) hit F5 to Run
# 5) click in the IDLE window and hit F5 to run again
# 6) there may be a bug in IDLE that causes it to dump the mouse buffer
#    into the FIRST answer field. If that happens, hit ctrl-c and
#    click in the other window. hit F5 to run again.

# history:
# April 10, stored rev7 at http://snippets.dzone.com/posts/show/10957
# April 13, stored rev9 at http://snippets.dzone.com/posts/show/10957
# April 16, more data from billeuze
# April 17, posted rev9
# April 23, posted rev11
# April 30, posted rev12
# June 6, posted rev14

# bugs:
# I need to improve the data. Send me some.

# data format:
#  ("year model",
#   (clutch, eng, wheel, trans),
#   (1st, 2nd, 3rd, 4th, 5th...), redline, flag),  # overall ratios, redline, trusted_flag
#  # sources

# for example:
#   ("1973-83 1000cc Ironhead", 
#     (59, 34, 52, 21),    
#     (10.00, 7.25, 5.48, 3.966), 6000, True),
     # source: xlforum/billeuze; Clymers isbn:1-59969-149-3, p302

# the data structure is not in natural order because the equation is:
#     (clutch/eng) * (wheel/trans) = overall_ratio

# if you only know the internal ratios multiply each by the overall ratio
# to establish your dataset


testing = False  # records flagged "False" appear for testing if True
                 # make it "True" if you are running a BT, etc
                 
data = (
    
    # if your bike is not supported put it here and remove the hash mark
    #("model", (0,0,0,0), (0,0,0,0,0), 0, True),  # template

    #("1973-85 XL, 'W' ratios", 
    # (27, 17, 49, xxx),  # "27, 17" from Andrews; 49 is xbar at dragsp and kic123.  Would somebody tell me what the trannysprocketT is? 21??
    # (2.52, 1.83, 1.38, 1.00), 6000, False), #(1st, 2nd, 3rd, 4th, 5th) , redline, flag),
    # source: andrews:33_IronSportGear.pdf; dragspecialties: 49 guess

    #("1973-85 XL, 'C' ratios", 
    # (27, 17, 49, xxx),    # "27, 17" from Andrews; 49 is xbar at drag and kic123  
    # (xxx), 5500, False),  # Would somebody tell me what the tranny sprocketT is? 21??
    # gearbox: 2.52, 1.83, 1.38, 1.00
    # source: andrews:33_IronSportGear.pdf; dragspecialties I guess wheel is 49
 
    ("Ironheads w rear drum brakes", 
     (59, 34, 51, 21),    
     (9.807, 7.111, 5.816, 3.890), 5500, True), # from internals (rev 10)
    # (10.62, 7.670, 5.373, 4.214), 6000, True), # with 23T (test)
    # xxx internal: (2.327, 1.6873, 1.275, .923) xxx
    # internal: (2.52, 1.82, 1.38, 1.00)  # billeuze
    # source: xlforum/billeuze; Clymers isbn:1-59969-149-3, p302
    
    ("billeuze's wide ratio 1985 XL Ironhead",
    (59, 34, 48, 23),
    (9.7319, 6.609, 5.0112, 3.6313), 5500, True),
    # billeuze

    #("billeuze's stock ratio 1985 XL Ironhead",
    #(59, 34, 48, 23),
    #(9.1509, 6.609, 5.0112, 3.6313), 5500, True),
    # billeuzes is below as 1985 XL Ironhead

    # msg recv 4.16:
    # "Internal ratios of gearbox of all ironheads is same as 1986 evo:
    # 1st 2.52, 2nd 1.82, 3rd 1.38, 4th 1.00
    # Then when multiplied by (crank/clutch) * (trany/rear wheel), for 82-85 it becomes:
    # 1) 2.52 10.022, 2) 1.82 7.238, 3) 1.38 5.488, 4) 1 3.977

    # "1981 and earlier with 51 tooth sprocket it's
    # 1) 2.52 10.649,  2) 1.82 7.691, 3) 1.38 5.831, 4) 1.00 4.226
    
    # The Andrews wide ratio 1st gear is 2.68, rather than stock 2.52
    # The Andrews close ratio gearset is: 1st 2.29 2nd 1.66 3rd 1.26 4th 1.00
    
    # "As for redline of the ironheads. I,m sure it is more than 5500.
    # I can't find any authoritative documentation. looking online
    # I find some references for "around 6,000" and one for 7,000" --billeuze

    ("1982-85 1000cc Ironhead", 
     (59, 34, 48, 21),    
     (10.026, 7.270, 5.496, 3.966), 5500, False), # rev10 xxx
    # 10.022, 7.238, 5.488, 3.977)  # with trans=23T: xlforum/billeuze
    # internal: (2.521, 1.828, 1.382, 1.000) "same IR as the 86 evo" --billeuze
    # bill"s tire d = 24.35
    # source: Clymers isbn:1-59969-149-3, p302

    ("1973-85 XL Ironhead, Andrews wide 1st",
     (59, 34, 48, 21),
     (9.7319, 6.609, 5.0112, 3.6313), 5500, False),  # rev10 xxx
     # (9.7319, 6.609, 5.0112, 3.6313), 6000, True), # xxx trans w 23T (rev9)
     # internals: (2.68, 1.82, 1.38, 1.00)  # billeuze

    ("1973-85 XL Ironhead, Andrews close set",
     (59, 34, 48, 21),
     (9.7319, 6.609, 5.0112, 3.6313), 5500, False),  # rev10 xxx
     # (8.293, 6.012, 4.563, 3.621), 6000, True), # xxx trans w 23T? (rev9)
     # internals: (2.29, 1.66, 1.26, 1.00)  # billeuze

    # "First is not quite a low as the stock 1200 giving you more MPH in first" --jessearias
    # http://xlforum.net/vbportal/forums/archive/index.php/t-291765.html
    
    # xlforum/billeuze:: "9.732 is lower than the oem gear, not taller"
    # the one with 9.7319 ratio is the andrews wide ratio although
    # its lower than the oem gear, not taller. But it is important
    # to designate it as Andrews close ratio because Andrews
    # stock ratio is same as OEM stock ratio. Andrews also makes
    # a close ratio gearset. this is not just the first gear, it
    # is 1st, 2nd & third. This would be (8.3157, 6.028, 4.5754, 3.6313).
    # Reference for this is 2008 sporty Specialties catalogue, page 39.
    # You also asked me if I have a manual here, I think it was about which
    # year exactly they switched from 52 tooth rear wheel sprocket to
    # 48 tooth. Oops I was Wrong, it was 51 tooth. 1981 was last year
    # of 51. 1982 was first year of 48 tooth."

    ("1982-85 XL Ironhead",
     (59, 34, 48, 23),
     (9.130, 6.620, 5.005, 3.6215), 6000, True),
    # internal: 1st 2.521, 2nd 1.828, 3rd 1.382, 4th 1.00
    # xlforum/billeuze
    
    ("1986 XL Evo US", 
     (59, 34, 48, 21),                          
     (10.026, 7.270, 5.496, 3.966), 6000, True), # --billeuze
    # internal: (2.521, 1.828, 1.382, 1.000)
    # "same internal ratios as the 82-85 1000cc Ironhead" --billeuze, 83XLX t=815214
    # (10.00, 7.25, 5.48, 3.97), 6000, True), # Clymer. close enuf for jazz
    # source: xlforum/Clymers isbn:1-59969-149-3, p302

    ("late 1986-90 XL Evo US", 
     (59, 34, 48, 21),                           # FinalDriveRatios.doc
     (9.12, 6.59, 4.98, 3.97), 5500, True),
    # internal: (2.29, 1.66, 1.25, 1.00) # Clymers Sportster 86-03 p301-302
    
    #("1987-1990 4-speed XL US",
    # (0,0,0,24),
    # (9.12, 6.59, 4.98, 3.97, 0), 6000, False),
    # inner: 2.29, 1.66, 1.25, 1.00 --Buzzelli, p151
    # [1936-79?], source: Clymers isbn:1-59969-149-3, p302
    
    ("late 1986-90 1200 US",
     (56, 35, 61, 29),
     (9.043, 6.630, 4.826, 3.968, 3.366), 5500, False), # xxx see thread 815285
     # 1st: 2.687 2nd: 1.970 3rd: 1.434 4th: 1.179 5th: 1.000  # Folkie
    
    ("late 1986-90 883 US",
     (56, 35, 61, 27),
     (9.713, 7.121, 5.184, 4.262, 3.615), 5500, False), # xxx see thread 815285
     # 1st: 2.687 2nd: 1.970 3rd: 1.434 4th: 1.179 5th: 1.000  # Folkie

    #("1991-2003 1200 US",
     #(56, 35, 61, 29),  # xxx
     #(9.35, 6.82, 5.01, 4.09, 3.36), 5500, False),
     # inner: 2.78, 2.03, 1.49, 1.22, 1.00 --Buzzelli, p151
     # Kwest187 used tire D= 25 inches
     # source: xlforum/Kwest187, Sportster Performance Handbook (Buzzelli, p151)

    #("1991-2003 883 US",
     #(56, 35, 61, 27),  # xxx
     #(10.04, 7.32, 5.38, 4.39, 3.61), 5500, False),
     # Kwest187 used tire D= 25 inches
     # source: xlforum/Kwest187, Sportster Performance Handbook (Buzzelli, p151)
    
    ("1997 883 Hugger",
    (56, 35, 61, 27),
    (9.732, 7.121, 5.184, 4.26, 3.615), 5500, False),
    # cc rider with 3rd digit added from 1996-1999 883 Sportster US

    ("1996-1999 1200 Sportster US",
     (56, 35, 61, 29),   
    (9.043, 6.630, 4.826, 6.024, 3.3655), 5500, False),
    # internal: 2.687, 1.97, 1.434, 1.79, 1.00 # nightrider.com

    ("1996-1999 883 Sportster US",
     (56, 35, 61, 27),   
    (9.713, 7.121, 5.184, 6.47, 3.615), 5500, False),
    # internal: 2.687, 1.97, 1.434, 1.79, 1.00 # nightrider.com
     
    ("2000-2002 1200 Sportster US",
     (56, 35, 61, 29),   
     (9.05, 6.22, 4.82, 3.97, 3.3655), 5500, True),    
    # 2002 Sportster owner"s manual, mine; groovemeisterus; bikernet says
    # "the Evolution 1200 redline [went] from 5500 to 6000" in 2004
    # groovemeisterus
    
    # 128T belt: 40022-91, page 45
    # 35T engine spocket: # 40235-89A, page 45
    # 56T clutch sprocket: # 36790-91, page 43
    # 1200: 29T tranny sprocket: # 40205-95, 40202-91B kit, pages 37, 45
    #  883: 27T tranny sprocket: # 40288-95, 40285-91B kit, pages 37, 45
    # 30T tranny sprocket: # xxx Andrews?
    # 61T wheel sprocket, black: # 40213-00, pages 45, 63
    # 61T wheel sprocket, silver: # 40227-00, pages 45, 63
    # 96T belt: # 40147-04. xxx
    # -- 2001 XLH Parts Catalog

    # I put the 30 tooth front pulley on my '05 883. The stock belt works fine. -kc5gxc
    
    ("2000  883 Sportster US",     
     (56, 35, 61, 27), 
     (9.71, 7.12, 5.18, 4.26, 3.61), 6000, True),        
    # 2000 Sportster owner"s manual, groovemeisterus
    
    ("2002  883 Sportster US",     
     (56, 35, 61, 27), 
     (9.71, 6.69, 5.18, 4.27, 3.615), 6000, True),        
    # 2002 Sportster owner"s manual, mine
    
    # xlforum/sleeper has different data for 2002:
    # ------- 883 ----- 1200
    # 1st --- 9.724 --- 9.053
    # 2nd --- 7.085 --- 6.957
    # 3rd --- 5.169 --- 4.813
    # 4th --- 4.265 --- 3.971
    # 5th --- 3.615 --- 3.366

    ("2004-05 1200 Sportster US",  
     (57, 38, 68, 29), 
     (9.454, 6.500, 5.040, 4.153, 3.517), 6000, True),   
    # 2004 - 2005 Gearbox ratios: 1st: 2.6880 2nd: 1.8480 3rd: 1.4329 4th: 1.1807 5th: 1.0000    # Folkie, Buzzelli, p151
    # Folkie, Clymer 

    ("2004-05 1200 Sportster HDI",  
     (57, 38, 68, 30), 
     (9.139, 6.283, 4.872, 4.014, 3.40), 6000, True),   
    # 2004 - 2005 Gearbox ratios: 1st: 2.6880 2nd: 1.8480 3rd: 1.4329 4th: 1.1807 5th: 1.0000    # Folkie
    # Folkie, Clymer 

    ("2004-05  883 Sportster US",  
     (57, 34, 68, 28), 
     (10.944, 7.524, 5.834, 4.807, 4.071), 6000, True),  
    # Folkie, Clymer on books.google.co
    # If you change the 34T engine sprocket to the 38T you will need to
    # swap from the 94T to the 96T chain.--Folkie
    
    # 29T tranny sprocket: # 480409-04,
    # 30T tranny sprocket: # 40380-04,
    # 137T belt : 40571-04 (might get away without this with the 29T, but I'm sure you need it for the 30T),
    # 38T engine spocket: # 40290-04,
    # 96T chain: # 40147-04. --Folkie, t=787711

    ("2004-05  883 Sportster HDI",  
     (57, 38, 68, 28), 
     (9.792, 6.732, 5.220, 4.301, 3.643), 6000, True),  # geared for the Autobaun
    # 2004 - 2005 Gearbox ratios: 1st: 2.6880 2nd: 1.8480 3rd: 1.4329 4th: 1.1807 5th: 1.0000    # Folkie
    # Folkie, Clymer on books.google.co

    ("2006+ 1200 Sportster US",    
     (57, 38, 68, 29), 
     (9.3147, 6.6532, 4.9484, 4.1018, 3.5172), 6000, True),  
    # 2006+ Gearbox ratios: 1st: 2.6483 2nd: 1.8916 3rd: 1.4069 4th: 1.1662 5th: 1.0000   # Folkie
    # Folkie, Clymer and it agrees w nightrider.com
    
    # 29T tranny sprocket: # 40409-04,
    # 30T tranny sprocket: # 40380-04,
    # 137T belt : 40571-04 (might get away without this with the 29T, but I'm sure you need it for the 30T),
    # 38T engine spocket: # 40290-04,
    # 96T chain: # 40147-04. --Folkie, thread=787711

    ("2006+  883 Sportster US",    
     (57, 34, 68, 28),  # xxx
     (10.782, 7.7015, 5.7281, 4.7481, 4.0714), 6000, True),  
    # Folkie, Clymer (on books.google.com) and it agrees w nightrider.com
    # If you change the 34T engine sprocket to the 38T you
    # will need to swap from the 94T to the 96T chain. --Folkie

    #("2006+  1200 Sportster HDI",    
    #(),
     #(9.004, 6.431, 4.783, 3.965, 3.400), 6000, False),  # Folkie

     #("2006+ 883 Sportster HDI",
     #(),
     #(9.647, 6.891, 5.125, 4.248, 3.643), 6000, False),  # Folkie

    #("2009- 883 Sportster US", (0,0,0,0), (9.004, 6.432, 4.783, 3.965, 3.40), 0, 6000, False),    # xlforum/tater, motorcycle.com

    ("2009+ XR1200 US/HDI",           
     (57, 34, 68, 29),   # totalmotorcycle.com says 28
     (10.782, 7.702, 5.728, 4.748, 4.071), 7000, True),   # 9000 ~ getty xxx; d=24.84    
    # internal: 
    # HD xr1200.pdf; 180/55 ZR17 is  inches (nightrider.com/biketech/calc_speed_rpm.htm)

    ("2009+ XR1200 JPN",             
     (57, 38, 68, 29),  # totalmotorcycle.com says 28
     (9.647, 6.891, 5.125, 4.248, 3.642), 7000, True),   # 9000 ~ getty xxx   
    # internal: 
    # HD xr1200.pdf; 180/55 ZR17 is  inches (nightrider.com/biketech/calc_speed_rpm.htm)
    
    ("Shu's late EVO US",
     (56, 35, 61, 27),  # xxx
     (9.717, 6.687, 5.180, 4.4265, 3.6148), 6000, False),
    # http://xlforum.net/vbportal/forums/showthread.php?t=216181

    #
    # non-Sporty/Buells only show up in test mode, so from here to the Buells the flag is False
    #
    
    # 2010 gearbox ratios: 1st:3.76 2nd:2.75 3rd:2.06 4th:1.41 5th:1.18 6th:1.00    # Bakerdrivetrain.com
    # xxx test xxx
    ("2010 Dyna US",               
     (46, 34, 43, 21), 
     (9.311, 6.454, 4.793, 3.882, 3.307, 2.790), 5500, False),
    # HD site  xxx 2.79 != (46/34) * (43/21)  [should be 2.7703] xxx

    #("1980 Softail US",       (37, 24, 70, 32), (xxx), 5500, False),   # hdforums.com
    #("1995-1999 Softail US",  (36, 25, 65, 32), (xxx), 5500, False),   # FinalDriveRatios.doc

    ("2005 Softail US",
     (36, 25, 70, 32),
     (10.110, 6.958, 4.953, 3.862, 3.150), 5500, False),
    # motorcycle.com, kic132.com

    ("2000 Dyna US",               
     (36, 25, 70, 32), 
     (10.111, 6.955, 4.945, 3.874, 3.153), 5500, False),       
    # source: _Build a Torque Monster_, page 76


    # 2010 gearbox ratios: 3.76, 2.75, 2.06, 1.55, 1.27, 1.10, 7th:1.00
    ("BT w Baker 7-speed US",               
     (46, 34, 43, 21), 
     (11.844, 8.6625, 6.489, 4.8825, 4.0005, 3.465, 3.150), 5500, False),
    # bakerdrivetrain.com
    
    ("Bill Rook's BT US",          
     (36, 24, 70, 30), 
     (11.224, 7.720, 5.489, 4.300, 3.500), 5500, False),       
    # delta_from_stock = 3.5/3.153 = 1.11
    # source: _How to Build a HD Torque Monster_ by Bill Rook, page 78

    ("2005 FXDC/I US",             
     (70, 32, 36, 25), 
     (10.110, 6.958, 4.953, 3.862, 3.150), 5500, False),  
    # motorcycle.com

    ("2010 VRSCAW US",             
     (117, 64, 72, 28), 
     (10.98, 7.38, 5.88, 5.10, 4.57), 9000, False),         
    # HD.com, harley-motorcycles.com

    ("2009 VRSCAW V-Rod US",        
    (117, 64, 72, 28),  # xxx
    (11.752, 7.898, 6.322, 5.459, 4.889), 9000, False),     
    # HD: 2009PRGVRSC.pdf

    ("2009 VRSCAW V-Rod HDI/JPN",        
    (117, 64, 72, 28),  # xxx
    (10.969, 7.371, 5.900, 5.905, 4.563), 9000, False),     
    # HD: 2009PRGVRSC.pdf


    #
    # ---- Buells
    #
    
    ("2010 Buell 1125CR US",       
     (65, 36, 76, 27), 
     (12.516, 8.897, 7.021, 5.968, 5.297, 4.880), 9800, True), 
    # buell.com

    ("2010 Firebolt XB12R US",     
     (57, 38, 65, 27), 
     (9.561, 6.831, 5.080, 4.210, 3.610), 6800, True),       
    # 1203 buell.comen_us/tools/compare-bikes

    ("2010 Lightning XB12Ss US",   
     (57, 38, 65, 27), 
     (9.561, 6.831, 5.080, 4.210, 3.610), 7500, True),       
    # 1203 buell.com, sandiegoharley.com

    ("2010 Ulysses XB12X/XT US",   
     (57, 38, 65, 27), 
     (9.561, 6.831, 5.080, 4.210, 3.610), 7500, True),     
    # 1203 buell.com, sandiegoharley.com


    # if your bike is not supported just put it here and remove ONE hash mark
    # and please send me data for your model/year
    #("model", (0,0,0,0), (0,0,0,0,0), 0, True),

    # future: let the user put in any damn numbers he wants 
    #("unlisted", (0,0,0,0), (0,0,0,0,0), 0, True),
    
    ("2009 Star VMax",
     (0,0,0,0),
     (11.045, 8.418, 6.511, 5.186, 4.348), 9000, False),
    # sentinal. ((KLUDGE ALERT: this does not appear in the menu. Thats ok...))  amadirectlink.com
    )

#
# ---- limits for sanity checks. turned off...
#
eng_min = 21
eng_max = 64

clu_min = 36
clu_max = 117

tra_min = 21
tra_max = 32

whe_min = 36
whe_max = 76


# ---- dont change anything past this line ----


import sys, math, platform, pprint, unicodedata

#
# ---- check for python 3
#
if platform.python_version_tuple()[0] == '2':
    print("""This is written in python3.1. Go ahead and install it; its not a big deal.
    To convert this to python2.x the only changes I am aware of are:
    1) replace "input()" with "raw_input()"
    2) change "try/except" stmts to python2 format.
    2) replace format stmts near lines 449 and 722.
    Exiting...\n\n""")
    sys.exit(0)
    
prin = sys.stdout.write  # prin() stmts run under python2 and python3

#
# ---- subscripts
#
MODEL = 0
SPROCKETS = 1
RATIOS = 2
REDLN = 3
TRUSTED = 4


# these are ordered as in the equation:
# (clutch/eng) * (wheel/trans) = overall_ratio
# not in the natural order
CLUTCH = 0
ENGINE = 1
WHEEL  = 2
TRANNY = 3


#
# ---- subroutines
#

def newline():
    prin("\n")
    
def exitq(inp):
    if inp[0] in ("Q", "q"): prin("Goodbye.\n\n"); sys.exit(0)


tranny_count_labels = ("1st", "2nd", "3rd", "4th", "5th", "6th", "7th" )

def print_ratios(preamble, f, L):
    prin("%s" % (preamble))
    i=0
    for r in L:
        prin("%s:%5.3f  " % (tranny_count_labels[i], r * f))
        i += 1
    newline()

#
# ---- ask a sprocket question
#
def sprocketq(sprocket_name, low, high):
    while 1:
        try:
            inp = input("are you changing the %s sprocket? (y/n): " % (sprocket_name))[0].lower()
            newline()
            exitq(inp)
            assert inp in ("y", "n")
            break
        except (ValueError, AssertionError) as e:
            prin("\nYou entered %r. I need a yes or no." % (inp))

    custom_T = 0
    if inp == "y":
        while 1:
            try:
                inp = input("how many teeth on your %s sprocket? " % (sprocket_name))
                newline()
                exitq(inp)
                custom_T = float(inp)
                #assert custom_T in range(low, high)
                break
            except (ValueError, AssertionError) as e:
                prin("You entered %s. I need a reasonable number of teeth (%d, %d).\n" % (inp, low, high))
                
    return custom_T

# ---- end subroutines


#
# ---- intro
#
prin("""
--------------------------------------------------
|
| 
|......This builds a chart of MPH per RPM 
|.......for any tire size and gear set. 
| 
|...** This is not complete or authoritative. **
|
|
--------------------------------------------------\n""")
     
if testing:
    prin("...............................................(engine, clutch, tranny, wheel, trust)\n\n")
else:
    prin("...............................................(engine, clutch, tranny, wheel)\n\n")
    
    data = [data[rec] for rec in range(len(data)) if data[rec][TRUSTED]]  # cull flagged records
    if 0:
        pp = pprint.PrettyPrinter(indent=4)
        pp.pprint(data)
        sys.exit(0) # testing
            
#
# ---- main menu
#
MAX_MENU = len(data) - 1  # xxx  zero-based  xxx
for i in range(MAX_MENU):
    #if data[i][TRUSTED]:
    #prin("%2d) %-36s" % (i, data[i][MODEL]))
    print("{0:.<4n}{1:.<40}".format(i, data[i][MODEL]), end="")  # _Python 3_ by mark summerfield, page 83-85

    if data[i][TRUSTED]:
        prin("...(%2d, %7d, %7d, %7d)\n" % (data[i][SPROCKETS][ENGINE],
                                        data[i][SPROCKETS][CLUTCH],
                                        data[i][SPROCKETS][TRANNY],
                                        data[i][SPROCKETS][WHEEL]))
    else:
        #print("{0:.<4n}{1:.<40}".format(i, data[i][MODEL]), end="")  # _Python 3_ by mark summerfield, page 83-85
        prin("...(%2d, %7d, %7d, %7d)  xxx\n" % (data[i][SPROCKETS][ENGINE],
                                        data[i][SPROCKETS][CLUTCH],
                                        data[i][SPROCKETS][TRANNY],
                                        data[i][SPROCKETS][WHEEL]))


#
# ---- enter model (future: support "unlisted")
#
while 1:
    try:
        inp = input("\nenter digit(s) 0-%d or 'quit': " % (MAX_MENU - 1))
        newline()
        exitq(inp)
        SEL = int(inp) 
        assert SEL in range(MAX_MENU)
        prin("You have selected %s.\n" % (data[SEL][MODEL]))
        inp = input("if that is correct enter 'y' to continue: ")
        newline()
        if inp[0] in ("Y", "y"): break  
    except (ValueError, AssertionError) as e:
        prin("\nYou entered %r. I need an answer 0-%d.\n" % (inp, MAX_MENU-1))

        

#if data[SEL][MODEL] == "unlisted":
#   # future
#else:

# 
# ---- constants
#
selected_model = data[SEL][MODEL]
selected_ratios = data[SEL][RATIOS]
selected_sprockets = data[SEL][SPROCKETS]

#
# ---- early reporting
#
# if data[SEL][TRUSTED]:
prin("primary---------------------  secondary------------\n")
prin("stock engine: %d, clutch: %d, tranny: %d, wheel: %d\n\n" % (data[SEL][SPROCKETS][ENGINE],
                                                                 data[SEL][SPROCKETS][CLUTCH],
                                                                 data[SEL][SPROCKETS][TRANNY],
                                                                 data[SEL][SPROCKETS][WHEEL]))


#
# ---- enter tire diameter
#
while 1:
    try:
        #prin("enter your tire diameter in inches (eg. 25.3 for a 130/90B-16).\n")
        #inp = input("  If you dont know your tire diameter visit\n  nightrider.com/biketech/calc_speed_rpm.html: ")
        # Folkie said to simplify the user interface, and I am listening
        
        inp = input("enter your tire diameter in inches (abt 25.3 for a 130/90B-16): ")
        exitq(inp)
        DIAMETER = float(inp)
        newline()
        assert DIAMETER >= 12 and DIAMETER <= 36
        break
    except (ValueError, AssertionError) as e:
        prin("You entered %r. I need a reasonable tire size (12-36 inches).\n" % (inp))

if DIAMETER >= 26:
    prin("That's a big tire!\n\n")
elif DIAMETER <= 24.6:
    prin("That's a lil tire!\n\n")

circumference = DIAMETER * 3.1415926 / 12  # wheel travel converted to feet


#
# ---- the big questions --------------------------
#
USER_ENGINE = sprocketq("engine", eng_min, eng_max)
USER_CLUTCH = sprocketq("clutch", clu_min, clu_max)  
USER_TRANNY = sprocketq("tranny", tra_min, tra_max) 
USER_WHEEL  = sprocketq("wheel",  whe_min, whe_max)
#
# ---- 
#


#
# ---- find the conversion factor between a stock and custom set of sprockets
#
if USER_CLUTCH:
    clu_f = data[SEL][SPROCKETS][CLUTCH] / USER_CLUTCH
else:
    USER_CLUTCH = data[SEL][SPROCKETS][CLUTCH]
    clu_f = 1
    
if USER_ENGINE:
    eng_f = data[SEL][SPROCKETS][ENGINE] / USER_ENGINE
else:
    USER_ENGINE = data[SEL][SPROCKETS][ENGINE] 
    eng_f = 1
    
if USER_WHEEL:
    whe_f = data[SEL][SPROCKETS][WHEEL]  / USER_WHEEL
else:
    USER_WHEEL = data[SEL][SPROCKETS][WHEEL]
    whe_f = 1
    
if USER_TRANNY:
    tra_f = data[SEL][SPROCKETS][TRANNY] / USER_TRANNY
else:
    USER_TRANNY = data[SEL][SPROCKETS][TRANNY]
    tra_f = 1
    
custom_sprockets = (USER_CLUTCH, USER_ENGINE, USER_WHEEL, USER_TRANNY)

factor = (clu_f / eng_f) * (whe_f / tra_f)  # this is the main equation
    
#
# ---- debug
#
#if 0 and not data[SEL][MODEL] == "unlisted":
#    prin("\n----\n")                v--- THESE ARE REVERSED
#    prin(">>>CL = STOCK_CLUTCH:%dT / USER_CLUTCH:%dT<<<\n" % (data[SEL][SPROCKETS][CLUTCH], USER_CLUTCH))
#    prin(">>>EN = STOCK_ENGINE:%dT / USER_ENGINE:%dT<<<\n" % (data[SEL][SPROCKETS][ENGINE], USER_ENGINE))
#    prin(">>>WH = STOCK_WHEEL:%dT  / USER_WHEEL:%dT<<<\n"  % (data[SEL][SPROCKETS][WHEEL],  USER_WHEEL))
#    prin(">>>TR = STOCK_TRANNY:%dT / USER_TRANNY:%dT<<<\n" % (data[SEL][SPROCKETS][TRANNY], USER_TRANNY))
#    prin(">>>factor = ((CL:%5.3f / EN:%5.3f) * (WH:%5.3f / TR:%5.3f)<<<\n" % (CL, EN, WH, TR))

#
# ---- end 
#


#
# ---- enter redline
#
min_redline = 5000
max_redline = 10000  # Buell 1125CR is mfr9800

while 1:
    try:
        inp = input("enter your redline (msr:%d): " % (data[SEL][REDLN]))
        REDLINE = int(inp)
        newline()
        assert REDLINE < max_redline and REDLINE > min_redline  
        break
    except (ValueError, AssertionError) as e:
        prin("You entered %s. I need digits %d - %d." % (inp, min_redline, max_redline))
    
if REDLINE > data[SEL][REDLN]:
    prin("(If the mfr redline is not %d please send me a bug report.)\n\n" % (data[SEL][REDLN]))
    

#
# ---- enter interval
#
while 1:
    try:
        inp = input("enter RPM interval for charting (eg. 1000) or 'h' for hertz: ")  
        if inp[0] == "h":  # setup easteregg
            RPM_INTERVAL = 0
        else:
            RPM_INTERVAL = int(inp)
        newline()
        break
    except (ValueError, AssertionError) as e:
        prin("You entered %r. I need something like 500 or 1000." % (inp))


#
# ---- print header
#
prin("-----\n\nmodel: %s\n" % (selected_model))

q, r, s, t = selected_sprockets
prin("ratios for (%d, %d, %d, %d):\n" % (q, r, s, t))
print_ratios("", 1, selected_ratios)

if factor != 1:
    #custom_ratios = map(lambda x: x*factor, selected_ratios)
    prin("\nfactor = %5.4f\n" % (factor))
    q, r, s, t = custom_sprockets
    prin("ratios for (%d, %d, %d, %d):\n" % (q, r, s, t))
    #print_ratios("", factor, custom_ratios)
    print_ratios("", factor, map(lambda x: x*factor, selected_ratios))
newline()


#
# ---- print tranny ratios
#
DIRECTDRIVE = len(selected_ratios)-1  # BUG IF THERES AN OVERDRIVE ANYWHERE
T = map(lambda x: x/selected_ratios[DIRECTDRIVE], selected_ratios)

#prin("%s gear is direct drive.\n\n" % (tranny_count_labels[DIRECTDRIVE]))

print("tranny ratios:")
print_ratios("           ", 1, T)

# looks like:
#................1st:3.337  2nd:2.313  3rd:1.718  4th:1.391  5th:1.185  6th:1.000  


#
# ---- chart
#
feet_per_mile = 5280.0
KPH = False
if RPM_INTERVAL:
    if 0 and len(selected_ratios) >= 6:
        prin("----            |          |          |          |          |          |\n")
        prin("----            V          V          V          V          V          V\n")
    elif 0:
        prin("----            |          |          |          |          |\n")
        prin("----            V          V          V          V          V\n")

    rpm = 1000
    while rpm <= REDLINE: 
        prin("%4.0f\t" % (rpm))
        for ratio in selected_ratios:
            travel_per_minute_in_feet = rpm / ratio * circumference
            mph = travel_per_minute_in_feet * 60 / feet_per_mile
            if KPH:
                prin("%10.1f " % (mph * factor * 1.6093)) 
            else:
                prin("%10.1f " % (mph * factor))
        if KPH:
            prin(" KPH")    
        else:
            prin(" MPH")    
        newline()
        rpm += RPM_INTERVAL
        
    # add a line for his redline if we shot past it
    if rpm != REDLINE+RPM_INTERVAL:
        prin("%4.0f\t" % (REDLINE))
        for ratio in selected_ratios:
            travel_per_minute_in_feet = REDLINE / ratio * circumference
            mph = travel_per_minute_in_feet * 60 / feet_per_mile
            if KPH:
                prin("%10.1f " % (mph * factor * 1.6093)) 
            else:
                prin("%10.1f " % (mph * factor))
        if KPH:
            prin(" KPH")    
        else:
            prin(" MPH")    
        newline()
    prin("done\n")
        
else:
    # easteregg
    
    # mine comes on strong at 3500 (by ear only, no tach)
    # and thats with no real mods to the engine --flathead45
    
    rpm = 1962.1917  # humans usually can"t hear anything below 1962 as a pitch. And if you
                     # set this lower it will break because the notelist starts with C

    twelvth_root_of_two = math.pow(2, 1/12)  # the factor for climbing a chromatic scale

    notelist = ("C", "Db", "D", "Eb", "E", "F", "Gb", "G", "Ab", "A", "Bb", "B")

#    if len(selected_ratios) >= 6:
#        prin("----..............|        |          |          |          |          |\n")
#    else:
#        prin("----..............|       |          |          |          |\n")

    i = 0
    while rpm <= REDLINE: 
        #note = notelist[i].replace("b", unicodedata.lookup("MUSIC FLAT SIGN")) # Summerf p94 not
        note = notelist[i].replace("b", "\u266d")
        prin("%-5.0f %-3s\t" % (rpm, note))
        for ratio in selected_ratios:
            travel_per_minute_in_feet = rpm / ratio * circumference
            mph = travel_per_minute_in_feet * 60 / feet_per_mile
            
            m = mph * factor
            # this will break in python2.x
            print("{0:.^9.1f}".format(m), end="")  # _Python 3_ by mark summerfield, page 83-85
            
        newline()
        rpm *= twelvth_root_of_two
        i += 1
        if i > 11: i = 0
    prin("done\n")


##################
#
# ---- tests:
#
##################

# ---- testing w 2002 883 (mine)
# 2002 883 w 27 T tranny sprocket (stock):
# 6000	 46.5  67.5  87.2 106.0 124.9
# rev 9: baseline

# 2002 883 w 26 T tranny sprocket (stock is 27):
# rev 6: 6000	 44.8  65.0  84.0 102.1 120.5
# PASS
# rev 9: 6000	44.8  65.0  84.0  102.1 120.3
# data changed
# PASS

# rev 9.1: 6000  43.1  62.5  80.7  98.2  115.7 
# do the math by hand for:
# 25/27 * 124.9 = 115.65
# PASS


# 2002 883 w 34T engine sprocket (stock is 35T):
# rev 6: 6000	45.2  65.6  84.7 103.0 121.5 
# PASS
# rev 9: 6000	45.2  65.6  84.7  103.0 121.4 
# PASS


# 2002 883 w 54T clutch sprocket (stock is 56T):
# rev 6: 6000  48.2  70.0  90.4  109.9  129.7 
# PASS
# rev 9: 6000  48.2  70.0  90.4  109.9  129.6
# PASS


# rev 1: 3300    27T::23  34  43  53  62
# rev 1: 3300    26T::22  32  42  51  60
# 
# rev 7: 3300   27T::25.6 37.1 48.0 58.3 68.7 
# rev 7: 3300	26T::24.6 35.8 46.2 56.1 66.2
# FAIL, the older rev was wrong because...
# rev 9: 27T: 3300  A  	...25.6......37.1......48.0......58.3......68.7...
# rev 9: 26T: 3300  A  	...24.6......35.8......46.2......56.1......66.2...
# PASS


# rev 7: 2002 883 w 35T stock engine sprocket:
# rev 7: 6000	      46.5       67.5       87.2      106.0      124.9 
# rev 7: 2002 883 w 33T custom engine sprocket:
# rev 7: 6000	      43.9       63.6       82.2      100.0      117.8 
# do the math by hand for:
# 33/35 * 124.9 = 117.8
# PASS


# I sent Folkie some results for rev 6, got this response:
# Hi Paul
# Yes, when I put your primary sprockets (59T/36T) in my program, I get the same speeds 
# at each rpm point.  By the way, redline on the rubber mounts is 6,000 rpm.
# rev 6:
# PASS


# testing gearbox ratios report:
# 2010 BT w Baker 7-speed
# source: bakerdrivetrain.com
# rev 7: 3.76, 2.75, 2.06, 1.55, 1.27, 1.10, 7th:1.00
# PASS
# rev 9: 1st:3.760  2nd:2.750  3rd:2.060  4th:1.550  5th:1.270  6th:1.100  7th:1.000 
# PASS


# Bill Rook says in _How to Build a HD Torque Monster_ page 76:
# 2000 Dyna "in fifth gear at 2200rpm = 50 miles per hour"
# He doesnt tell you the tire diameter...
# rev 7: 2200	      16.4       23.8       33.5       42.7       52.5
# rev 7: I get 52.5@2200 with a 25.3 tire diameter. He"s got a smaller tire than that.
# rev 7: PASS


# rev 9: 2200	      14.6       21.2       29.8       38.1       46.7
# rev 9: I get 46.7@2200 with a 25.0 tire diameter. He"s got a bigger tire than that.

# rev 9: 2200	      14.7       21.3       30.0       38.3       47.0 
# rev 9: I get 47.0@2200 with a 25.15 tire diameter. He"s got a bigger tire than that. 
# rev 9: PASS


# hdforums says, "1980 softail w custom 65T at 70 MPH engine RPM drops 235 rpm"
# stock sprockets:
# rev 7: 3000	 22.3  32.5  45.7  58.3  71.6
# 
# rev 7: w custom 65T wheel sprocket
# rev 7: 2775	 22.2  32.3  45.5  58.1  71.3 
# rev 7: 2800	 22.4  32.6  45.9  58.6  72.0
# so 71.6 would occur at 2785.7, dropping 214.3 RPM from 3000
# rev 7: give it a PASS


# xlforum/Mikel_NY says:
# the rubber 883's are about 3200 @ 60.
# rev 7: 3200	      22.0       32.0       41.2       50.1       59.2 
# rev 9: 3200	      22.0       32.0       41.2       50.1       59.2 
# PASS


# Kwest187 1993 883/1200  he says:
# tire diameter: 6.5 feet * 12 / pi = 24.83 inches
# 1st, 5000rpm  36.78 mph
# 2nd, 5000rpm  50.45 mph
# 3rd, 5000rpm  68.65 mph
# 4th, 5000rpm  84.13 mph
# 5th, 5000rpm 102.03
# rev 9: 5000  36.8  50.5  68.7  84.1  102.3 
# PASS


# Kwest187, I took the gear ratios you quoted, and came up with this:
# XL883 1993 US            
 
# Gear   Ratio  ←                          Engine Revs                         →
#               1000  1500  2000  2500  3000  3500  4000  4500  5000  5500  6000
 
# 1     10.040   7.5  11.3  15.1  18.8  22.6  26.3  30.1  33.9  37.6  41.4  45.2
# 2      7.320  10.3  15.5  20.6  25.8  31.0  36.1  41.3  46.5  51.6  56.8  61.9
# 3      5.380  14.0  21.1  28.1  35.1  42.1  49.2  56.2  63.2  70.2  77.3  84.3
# 4      4.390  17.2  25.8  34.4  43.0  51.6  60.2  68.9  77.5  86.1  94.7 103.3
# 5      3.610  20.9  31.4  41.9  52.3  62.8  73.3  83.7  94.2 104.7 115.1 125.6
# --Folkie [maybe he used a different tire diameter]
# PASS

#
# ----

# Shu's EVO (late) 883:
# Engine sprocket: 35 teeth 
# clutch: 56 teeth
# transmission: 27 teeth
# rear pulley: 61 teeth
# rear tire circ: 78.5"
# 1st gear: 2.688
# 2nd gear: 1.850
# 3rd gear: 1.433
# 4th gear: 1.180
# 5th gear:1.000
# rev 7: internal ratios: (2.688, 1.850, 1.433, 1.180, 1.000), 6000, False)
#    ("Shu's late EVO", (56, 35, 61, 27),  (9.717, 6.687, 5.180, 4.4265, 3.6148), 6000, False)


# XR1200 -- at 4000 rpms you are in fifth gear running 67 mph --getty
# I get 74mph. Maybe his tire diameter is less than 25.3. Ask him...

# --- end tests ----



xlforum_folkie_sent_this = """
Hi Paul

I only have data for rubber mounts, but I can certainly fill you in on them.

'04 - '05 Gearbox ratios:1st: 2.6880
2nd: 1.8480
3rd: 1.4329
4th: 1.1807
5th: 1.0000

'06+ Gearbox ratios:1st: 2.6483
2nd: 1.8916
3rd: 1.4069
4th: 1.1662
5th: 1.0000

Now, sprockets:

# [2004 - 2005] pt
US 883s and (all, except Japan, I believe) XR1200s:Engine: 34T
Clutch: 57T
Transmission: 28T
Rear Wheel: 68T

HDI 883s:Engine: 38T
Clutch: 57T
Transmission: 28T
Rear Wheel: 68T

US 1200s:Engine: 38T
Clutch: 57T
Transmission: 29T
Rear Wheel: 68T

HDI 1200s:Engine: 38T
Clutch: 57T
Transmission: 30T
Rear Wheel: 68T

So, overall ratios:

'04 - '05 US 883:1st: 10.944
2nd: 7.524
3rd: 5.834
4th: 4.807
5th: 4.071

'04 - '05 HDI 883:1st: 9.792
2nd: 6.732
3rd: 5.220
4th: 4.301
5th: 3.643

'04 - '05 US 1200:1st: 9.454
2nd: 6.500
3rd: 5.040
4th: 4.153
5th: 3.517

'04 - '05 HDI 1200:1st: 9.139
2nd: 6.283
3rd: 4.872
4th: 4.014
5th: 3.400

'06+ US 883 & XR1200:1st: 10.782
2nd: 7.702
3rd: 5.728
4th: 4.748
5th: 4.071

'06+ HDI 883:1st: 9.647
2nd: 6.891
3rd: 5.125
4th: 4.248
5th: 3.643

'06+ US 1200:1st: 9.315
2nd: 6.653
3rd: 4.948
4th: 4.102
5th: 3.517

'06+ HDI 1200:1st: 9.004
2nd: 6.431
3rd: 4.783
4th: 3.965
5th: 3.400

Apparently the Japan XR1200 has a 38T engine sprocket, but I'm not sure if that's the only difference. If it is, the ratios are the same as an '06+ HDI 883.

----

2006 883 part numbers:
29T tranny sprocket: # 40409-04,
30T tranny sprocket: # 40380-04,
137T belt : 40571-04 (might get away without this with the 29T, but I'm sure you need it for the 30T),
38T engine spocket: # 40290-04,
96T chain: # 40147-04.

----

Re: 91-99 gear ratios
Hi Paul

I have this, which I believe applies to '86 - '03: # pt says, NO THIS APPLIES TO SOMETHING AFTER 1990 AFAIK

Gearbox ratios are:

    1st: 2.687
    2nd: 1.970
    3rd: 1.434
    4th: 1.179
    5th: 1.000

Primary is 56T/35T, secondary is 61T/27T.

This gives overall ratios of:

    1st: 9.713
    2nd: 7.121
    3rd: 5.184
    4th: 4.262
    5th: 3.615
"""

sample_output = '''
# version 14:
model: 2002  883 Sportster US
ratios for (56, 35, 61, 27):
1st:9.710  2nd:6.690  3rd:5.180  4th:4.270  5th:3.615  

tranny ratios:
           1st:2.686  2nd:1.851  3rd:1.433  4th:1.181  5th:1.000  
1000	       7.8       11.3       14.5       17.6       20.8  MPH
1250	       9.7       14.1       18.2       22.0       26.0  MPH
1500	      11.6       16.9       21.8       26.4       31.2  MPH
1750	      13.6       19.7       25.4       30.8       36.4  MPH
2000	      15.5       22.5       29.1       35.3       41.6  MPH
2250	      17.4       25.3       32.7       39.7       46.8  MPH
2500	      19.4       28.1       36.3       44.1       52.1  MPH
2750	      21.3       30.9       40.0       48.5       57.3  MPH
3000	      23.3       33.8       43.6       52.9       62.5  MPH
3250	      25.2       36.6       47.2       57.3       67.7  MPH
3500	      27.1       39.4       50.9       61.7       72.9  MPH
3750	      29.1       42.2       54.5       66.1       78.1  MPH
4000	      31.0       45.0       58.1       70.5       83.3  MPH
4250	      32.9       47.8       61.8       74.9       88.5  MPH
4500	      34.9       50.6       65.4       79.3       93.7  MPH
4750	      36.8       53.4       69.0       83.7       98.9  MPH
5000	      38.8       56.3       72.7       88.1      104.1  MPH
5250	      40.7       59.1       76.3       92.5      109.3  MPH
5500	      42.6       61.9       79.9       96.9      114.5  MPH
5750	      44.6       64.7       83.5      101.4      119.7  MPH
6000	      46.5       67.5       87.2      105.8      124.9  MPH