/*

The C Source for Paul W. Laudon's bicycle gear shift program

*/

/* From: speed@etecnw.com (Paul W. Laudon x7241 (sun)) Date: 17 Aug 1994 23:21:36 GMT Newsgroups: rec.bicycles.tech Subject: Gear Shift Tables Made Easy ... When I was recently in the market for a new toy I wanted an easy way to compare the various combinations of ring/cog gears that I was looking at. So naturally I wrote a program to help me. The following code should be extremely portable (famous last words) to a whole host of platforms. One caveat, the code is ANSI C, not K&R C. Compile the program shift.c using whatever means necessary. Name the executable shift. Then you can run the program (of course) thusly: shift gears The result is two tables. The first table is a 2-D table of ring gears versus cog gears and their resulting distance merit figures. The second table is a shifting pattern table and a listing of the distance merit figures steps between each gear shift. These steps are given in two forms. The first is useful if you shift monotonically. The second is useful if (like me) you do a lot of your shifting by changing cogs more frequently than you change rings. The distance merit figures are calculated with the following formula: (ring_gear_teeth / cog_gear_teeth) * 27.0 If you want true distance figures replace the 27.0 in the above expression with your actual measured wheel circumference. (Sounds like a feature to add.) If you have any comments or fixes please send them to me. I am interested in any and all feedback. I will NOT provide executables to anyone!! - ------------------------------------------------------------------------------ When someone asks you why you have that 60 tooth ring gear look them square in the eyes and snarl "Because gravity is NOT ENOUGH"! - ------ Cut Here --- File name gears ------------------------------------------ 52 42 30 11 13 15 18 21 24 28 - ------ Cut Here --- File name shift.c - (file has been de-tabbed) ------------ */ /* * Calculate the gear ratios and shifting patterns for bicycles. * * This programs expects an input file as an argument. * * The file needs to have pairs of lines of numbers. Blank lines or lines * that start with a '#' are allowed before or after the line pairs. * * The first line of a pair specifies the number of teeth on the ring gears. * The second line of a pair specifies the number of teeth on the cog gears. * * The numbers in the set of numbers on either line can appear in any order, * including random, as long as the numbers are delimited by spaces. * * This program supports up to three ring gears and up to eight cog gears. * If you specify more than this the excess will be ignored! * * If you do not want each gear spec to appear on a separate page you can * comment out the printf that prints a 'Ctl-L' on line 127. */ #include #define RATIO_CONSTANT 27.0 /* MAGIC RATIO Multiplier */ char lbuf[128]; /* Input Line Buffer */ int rings[3]; /* Main Ring Gear Teeth Counts */ int cogs[8]; /* Cog Gear Teeth Counts */ struct ratio { int gear; /* Initialize from 1 to 24 */ float value; /* Gear Ratio times RATIO_CONSTANT */ } ratios[24]; char *spc = " "; /* Printing Spaces */ char *dsh = "------------------------"; /* Printing Dashes */ int int_compare( int *a, int *b ) { return( *a - *b ); } int rat_compare( struct ratio *a, struct ratio *b ) { if ( a->value > b->value ) return( 1 ); else if ( a->value < b->value ) return( -1 ); else return( 0 ); } int main( int argc, char *argv[ ] ) { FILE *fs; /* File Stream Pointer */ int num_rings, num_cogs; /* Number of rings & cogs */ int i, j, k; /* Loopers */ int t, z; /* Temp Vars */ int first = 0; /* Have we printed first page? */ if ( argc != 2 ) { fprintf( stderr, "Usage: %s gear_file\n", argv[0] ); exit( -5 ); } if ( (fs = fopen( argv[1], "r" )) == (FILE *)NULL ) { fprintf( stderr, "Could not open gear spec file '%s'\n", argv[1] ); exit( -1 ); } while ( fgets( &lbuf[0], 128, fs ) != (char *)NULL ) { if ( lbuf[0] == '#' || lbuf[0] == '\n' ) continue; rings[0] = rings[1] = rings[2] = 0; cogs[0] = cogs[1] = cogs[2] = cogs[3] = cogs[4] = cogs[5] = cogs[6] = cogs[7] = 0; for ( i = 0; i < 24; i++ ) { ratios[i].gear = 0; ratios[i].value = 0.0; } num_rings = sscanf( &lbuf[0], "%d%d%d", &rings[0], &rings[1], &rings[2] ); if ( num_rings == 0 ) { fprintf( stderr, "Could not parse the ring gear spec\n" ); exit( -2 ); } if ( fgets( &lbuf[0], 80, fs ) == (char *)NULL ) { fprintf( stderr, "Missing cog gear spec\n" ); exit( -3 ); } num_cogs = sscanf( &lbuf[0], "%d%d%d%d%d%d%d%d", &cogs[0], &cogs[1], &cogs[2], &cogs[3], &cogs[4], &cogs[5], &cogs[6], &cogs[7] ); if ( num_cogs == 0 ) { fprintf( stderr, "Could not parse the cog gear spec\n" ); exit( -4 ); } qsort( &rings[0], num_rings, sizeof(int), int_compare ); qsort( &cogs[0], num_cogs, sizeof(int), int_compare ); for ( j = 0; j < num_rings; j++ ) for ( i = 0; i < num_cogs; i++ ) { ratios[(j*num_cogs)+i].gear = ((j + 1) * num_cogs) - i; ratios[(j*num_cogs)+i].value = ((float)rings[j] / (float)cogs[i]) * RATIO_CONSTANT; } if ( first == 0 ) first = 1; else printf( "\014" ); /* Ctl-L */ printf( "\n\n Gear Ratio Chart\n\n" ); printf( " |" ); for ( i = 0; i < num_cogs; i++ ) printf( " %2d", cogs[i] ); printf( "\n----+" ); for ( i = 0; i < num_cogs; i++ ) printf( "%0.6s", dsh ); printf( "-\n" ); for ( j = (num_rings - 1); j >= 0; j-- ) { printf( " %2d |", rings[j] ); for ( i = 0; i < num_cogs; i++ ) printf( " %5.1f", ratios[(j*num_cogs)+i].value ); printf( "\n" ); } qsort( &ratios[0], (num_cogs * num_rings), sizeof(struct ratio), rat_compare ); printf( "\n Shift Pattern Chart (with ratio value changes)\n\n" ); t = (num_rings - 1) * 2; printf( " |%0.*s Gear %0.*s Value Step", t, spc, t, spc ); if ( num_rings > 1 ) printf( " Main Ring Steps" ); printf( "\n----+------%0.*s", ((t * 2) + 16), dsh ); if ( num_rings > 1 ) printf( "----%0.*s", (num_rings * 7), dsh ); printf( "\n" ); for ( j = 0; j < num_rings; j++ ) for ( i = 0; i < num_cogs; i++ ) { z = (j * num_cogs) + i; t = ratios[z].gear; printf( " %2d | %0.*s %2d %0.*s %5.1f", (z + 1), (((t - 1) / num_cogs) * 4), spc, t, (((num_rings - 1) * 4) - (((t - 1) / num_cogs) * 4)), spc, ratios[z].value ); if ( ((j + 1) * (i + 1)) != (num_rings * num_cogs) ) printf( " %4.1f", (ratios[z + 1].value - ratios[z].value) ); if ( (num_rings > 1) && ((ratios[z].gear % num_cogs) != 0) ) { for ( k = z + 1; k < 24; k++ ) if ( (ratios[z].gear + 1) == ratios[k].gear ) break; printf( "%0.*s%4.1f", (((ratios[z].gear / num_cogs) + 1) * 7), spc, (ratios[k].value - ratios[z].value) ); } printf( "\n" ); } } exit( 0 ); }