home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Simtel MSDOS 1992 September
/
Simtel20_Sept92.cdr
/
msdos
/
plot
/
bike31.arc
/
BIKE31.PAS
< prev
Wrap
Pascal/Delphi Source File
|
1988-02-20
|
17KB
|
412 lines
{ BIKEGEAR - Copyright 1988 by Dave Tutelman. All rights reserved
You may:
- Modify this program for your own use, or
- Distribute UNMODIFIED copies of the source
(optionally including the executable),
provided no charge is made without my written permission.
Dave Tutelman
16 Tilton Drive
Wayside, NJ 07712 (201) 922-9576
}
{ BIKEGEAR is a program in Turbo Pascal to plot the gear ratios }
{ for a given set of sprockets. It works for up to a 21-speed }
{ bicycle. The program is controlled by cursor keys and }
{ numerics, in an obvious way. }
{ Dave Tutelman 11/86 }
{ HISTORY:
BIKEGEAR Private use and "a few close friends". 08/85.
BIKE2 First "publication". Distributed on usenet 11/86.
BIKE3 Added cadence charts. 06/87.
BIKE3.1 Ported to Turbo 4.0. Significant speedup. Slight
changes of logic. Posted to usenet. 02/88.
}
program bikegear;
uses DOS,CRT;
const rear : array [1..7] of integer = (13, 15, 17, 20, 24, 28, 33);
front : array [1..3] of integer = (52, 40, 26);
rmax : integer = 5; { number of rear sprockets }
fmax : integer = 2; { number of front sprockets }
quit : boolean = FALSE;
done : boolean = FALSE;
wheel : integer = 27; { wheel diameter in inches }
crow : integer = 1; { input cursor row (0=max entry) }
ccol : integer = 1; { input cursor col (1=front, 2=rear) }
c_lo : real = 77.0; { range of acceptable cadence }
c_hi : real = 87.0;
d_lo = '<'; { display "tracer" characters }
d_hi = '>';
KEY_UP = 'H'; { what comes after NULL for special keys }
KEY_DOWN = 'P';
KEY_LEFT = 'K';
KEY_RIGHT = 'M';
g1:string[30] = ' Shows GEAR in inches';
g2:string[30] = ' for each sprocket pair';
s1:string[30] = ' Shows SPEED in m.p.h.';
s2:string[30] = ' for low-high cadence';
c1:string[30] = ' Shading shows speed range';
c2:string[30] = ' for <low - high> cadence ';
var r,f : integer; { index for sprockets }
fbig, fsmall, rbig, rsmall : integer; { biggest & smallest sprockets }
mode : char; { which mode? gear design or cadence charts? }
o_spd, d_spd, d_col : integer;
{ display parameters for cadence chart }
{ o_spd = origin speed }
{ d_spd = speed difference per tickmark }
{ d_col = columns difference per tickmark }
scrtitle1,scrtitle2 : string[30];
procedure BELL;
begin
write (^G);
end;
function diff : integer; { COMPUTES MAXIMUM TOOTH DIFFERENCE }
var i : integer;
begin
fbig:=front[1]; fsmall:=fbig;
rbig:=rear[1]; rsmall:=rbig;
for i:=2 to fmax do
begin
if front[i] > fbig then fbig:=front[i];
if front[i] < fsmall then fsmall:=front[i];
end;
for i:=2 to rmax do
begin
if rear[i] > rbig then rbig:=rear[i];
if rear[i] < rsmall then rsmall:=rear[i];
end;
diff := fbig - fsmall + rbig - rsmall;
end;
procedure bannerscreen; { DISPLAY FIRST SCREEN, & CHOOSE MODE }
{ INTERNAL FUNCTION TO INPUT AN INTEGER }
function GetCadence (xx, yy : integer) : real;
var c : char;
i : integer;
sum : real;
begin
repeat
gotoxy (xx,yy); write(' '); gotoxy (xx,yy);
sum := 0;
repeat
c := readKey;
if (c>='0') and (c<='9') then
begin
write (c);
sum := 10*sum + integer(c) - integer('0');
end;
until c=^M;
until (sum>40) and (sum<130);
GetCadence := sum;
end;
var i : integer;
begin
ClrScr;
HighVideo;
gotoxy (32,6); write ('B I K E G E A R');
gotoxy (23,9); write ('Copyright 1988 - Dave Tutelman');
gotoxy (30,11); write ('All rights reserved');
LowVideo;
gotoxy (22,18); write ('Press ');
HighVideo; write ('G');
LowVideo; write (' for gearing design chart');
gotoxy (22,19); write ('Press ');
HighVideo; write ('C');
LowVideo; write (' for cadence / speed graph');
gotoxy (22,20); write ('Press ');
HighVideo; write ('S');
LowVideo; write (' for design chart with cadence/speed');
gotoxy (22,24); write ('Press ');
HighVideo; write ('ESC');
LowVideo; write (' to quit');
repeat
mode := ReadKey;
if mode>='a' then { convert to upper case }
mode := char (byte(mode) -$20);
BELL;
until (mode='G') or (mode='S') or (mode='C')or (mode=^[);
case mode of
'G':
begin scrtitle1:=g1; scrtitle2:=g2; end;
'S':
begin scrtitle1:=s1; scrtitle2:=s2; end;
'C':
begin scrtitle1:=c1; scrtitle2:=c2; end;
^[:
done := TRUE;
end;
if (mode='S') or (mode='C') then
begin
gotoxy (1,22);
for i:=1 to 24 do
write (' ');
gotoxy (22,22); write ('Enter your cadence range:');
gotoxy (27,23); write ('Low cadence in RPM = ');
gotoxy (27,24); write ('High cadence in RPM = ');
c_lo := GetCadence (49,23);
c_hi := GetCadence (49,24);
end;
end;
procedure initscreen; { DRAW INITIAL PART OF WORKING SCREEN }
begin
ClrScr;
HighVideo;
gotoxy (52,1); write (scrtitle1);
gotoxy (52,2); write (scrtitle2);
LowVideo;
gotoxy (57,4); write ('Press ESC to EXIT');
gotoxy (52,6); write (' To change design of bike,');
gotoxy (52,7); write ('use cursor keys and numbers.');
HighVideo;
gotoxy (64,9); write ('FRONT REAR');
gotoxy (64,10); write ('(',fmax,') (',rmax,')');
for f:=1 to fmax do
begin
gotoxy (65,10+2*f); write (front [f]);
end;
for r:=1 to rmax do
begin
gotoxy (72,10+2*r); write (rear [r]);
end;
LowVideo;
gotoxy (52, 12+2*fmax); write ('Wheel Size = ',wheel:2);
gotoxy (52, 16+2*fmax); write ('Tooth Diff = ',diff:2);
HighVideo;
end;
procedure plotgear; { PLOTS THE CURRENT SPROCKET ARRAY }
var gear, maxgear, mingear : real;
s_lo,s_hi : real; { speeds for low and high cadence }
scale : real; { scale factor for display }
offset : integer; { subtract scaled value from offset ... }
row : integer; { row on which to plot the point }
tickmark : string[2];
begin
{ First get a good scale factor }
maxgear := wheel / rsmall * fbig;
mingear := wheel / rbig * fsmall;
scale := 23.0 / (ln(maxgear) - ln(mingear));
offset := trunc (ln(maxgear) * scale) + 1;
for f:=1 to fmax do
for r:=1 to rmax do
begin
gear := wheel / rear[r] * front[f]; { definition of GEAR }
{ The next couple of rows are "magic", to get the display pretty. }
{ It displays the gears logarithmically, as they should be. }
row := trunc ( ln(gear) * scale * 2.0 );
if (row mod 2 = 0) then tickmark:='__' else tickmark:='--';
row := offset - (row div 2);
if row>24 then begin row:=24; tickmark:='__'; end;
if row<1 then begin row:=1; tickmark:='^^'; end;
if mode='G' then gotoxy (9*f, row)
else gotoxy (16*f-14, row);
{ Now write something at this carfully computed place on screen }
if (fmax>1) and (rmax>1) then { crossing combination? dim }
if (f=1) and (r=rmax) or (r=1) and (f=fmax) then lowVideo;
if mode='G' then write (tickmark,gear:4:1,tickmark)
else begin
s_lo := gear * c_lo / 336.0;
s_hi := gear * c_hi / 336.0;
write (tickmark,s_lo:4:1,'-',s_hi:4:1,tickmark);
end;
highVideo;
end;
end;
procedure PlotCadLine; { PLOT THE GRAPHICS FOR ONE CADENCE LINE }
{ Based on Speed in MPH = Gear * RPM / 336 }
var gear : real;
s_lo, s_hi : real;
{ speeds at low and high cadence }
is_lo,is_hi : integer; { indices for s_lo & s_hi on speed line }
speed : integer; { index along the speed line }
begin
{ Compute the position on the speed line of the cadence extremes }
gear := wheel / rear[r] * front[f];
s_lo := gear * c_lo / 336.0;
s_hi := gear * c_hi / 336.0;
is_lo := round (((s_lo - o_spd) * d_col) / d_spd );
is_hi := round (((s_hi - o_spd) * d_col) / d_spd );
{ Now plot the line }
for speed:=0 to 40 do
begin
{ Regular or reverse video? }
if (speed < is_lo) then TextAttr := $07
else if (speed > is_hi) then TextAttr := $07
else TextAttr := $70;
{ Draw a "tickmark" on the graph }
if (speed > is_hi) and (speed mod d_col = 0)
then write ('+')
else if (speed > is_hi) then write (' ')
else if speed mod d_col = 0 then write ('+')
else write ('-');
end;
TextAttr := $07;
end;
procedure plotcadence; { PLOT A WHOLE CADENCE CHART }
{ INTERNAL: CHOOSE A GOOD SCALE, AND SET o_spd,d_spd, & d_col }
procedure set_display_parms;
var mingear, maxgear, minspeed, maxspeed : real;
{ min/max gear and speed to display }
s_min : integer; { int version of minspeed }
begin
mingear := wheel / rbig * fsmall;
maxgear := wheel / rsmall * fbig;
minspeed := mingear * c_lo / 336.0;
maxspeed := maxgear * c_hi / 350.0;
s_min := round (minspeed);
case round (maxspeed-minspeed) of
0..9:
begin o_spd:=s_min; d_spd:=1; d_col:=4; end;
10..12:
begin o_spd:=s_min; d_spd:=1; d_col:=3; end;
13..15:
begin o_spd:=s_min; d_spd:=2; d_col:=5; end;
16..19:
begin o_spd:=s_min; d_spd:=2; d_col:=4; end;
20..25:
begin o_spd:=s_min; d_spd:=2; d_col:=3; end;
else
begin o_spd:=0; d_spd:=5; d_col:=5; end;
end;
end;
var i,ispd : integer;
c : char;
begin
set_display_parms;
gotoxy (1,1); write (' SPEED');
for i:=0 to 40 do { put speed headings on columns }
if (i mod d_col)=0 then
begin
ispd := (i div d_col)*d_spd + o_spd;
gotoxy (9+i,1); write ((ispd div 10):1);
gotoxy (9+i,2); write ((ispd mod 10):1);
end;
gotoxy (10,24); HighVideo; write(d_lo,' ');
LowVideo; write(c_lo:4:1,' RPM ------- ',c_hi:4:1,' RPM ');
HighVideo; write(d_hi);
for f:=1 to fmax do { plot a line for each gear combination }
for r:=1 to rmax do
begin
gotoxy (1, (f-1)*rmax + (r-1) +3); HighVideo;
if r=1 then write (front[f]:2) else write (' ');
write (' ',rear[r],' ');
PlotCadLine ;
end;
end;
procedure getkey; { GET THE NEXT KEYSTROKE, AND ACT ON IT }
var c : char;
n,i : integer;
got : boolean;
begin
got := FALSE;
repeat
gotoxy (58 + ccol*7, 10 + crow*2);
c :=readKey;
case c of
^[: { ESC }
begin got:=true; quit:=true; end;
'0'..'9': { input a new value }
begin
n := integer (c) - 48; { ASCII to integer }
if (crow=0) and (ccol=1) then { new fmax }
if (n>0) and (n<=3) then
begin
write (c);
fmax := n;
for i:=fmax+1 to 3 do
begin gotoxy(65,12+2*i); write(' '); end;
got := TRUE;
end
else BELL;
if (crow=0) and (ccol=2) then { new rmax }
if (n>0) and (n<=7) then
begin
write (c);
rmax := n;
for i:=rmax+1 to 6 do
begin gotoxy(72,12+2*i); write(' '); end;
got := TRUE;
end
else BELL;
if crow>0 then { new sprocket value, get next digit }
begin
write (c);
c := readKey; { get next character }
if (c>='0') and (c<='9') then { yup, a digit }
begin
n := 10*n + integer(c) - 48;
if (ccol=1) and (crow=fmax+1) then wheel:=n;
if (ccol=1) and (crow<=fmax)
then front [crow] := n;
if ccol=2 then rear [crow] := n;
got := TRUE; { leave getkey and replot }
end
else begin BELL; got:=TRUE; end;
end;
end;
^L: { Repaint screen }
got := TRUE;
else
if integer(c)=0 then { beginning of control key sequence }
begin
c := readKey;
case c of
KEY_UP: { arrow up }
if crow=0 then BELL
else crow := crow-1;
KEY_DOWN: { arrow down }
begin
if ccol=1 then if crow=fmax+1 then BELL
else crow := crow+1;
if ccol=2 then if crow=rmax then BELL
else crow := crow+1;
end;
KEY_LEFT: { arrow left }
if (ccol=1) or (crow>fmax+1) then BELL else ccol:=1;
KEY_RIGHT: { arrow right }
if (ccol=2) or (crow>rmax) then BELL else ccol:=2;
else BELL;
end;
end
else BELL;
end;
until got;
end;
{ Main program is pretty trivial. Procs do all the work. }
begin
done :=FALSE;
repeat
bannerscreen;
if not done then
begin
quit := FALSE;
repeat
initscreen;
if mode='C' then plotcadence
else plotgear;
getkey;
until quit;
end;
until done;
ClrScr;
end.