REM PROGRAM: MILEAGE 1.4.2 REM PROGRAMMER: D. ALLEN REM CREATED: MAR 14, 1984 REM UPDATED: JAN 16, 2001 REM COPYRIGHT (C) 1986 ' ' THE PURPOSE OF THIS PROGRAM IS TO HELP THE USER KEEP A RECORD ' OF GASOLINE CONSUMPTION, MILES DRIVEN, AND MPG FOR HIS/HER ' AUTOMOBILE. INPUT TO THIS PROGRAM IS BY MENU SELECTION. THE ' USER HAS THE OPTIONS OF READING, OR WRITING MILEAGE DATA TO ' A FILE. THIS FILE IS STORED IN A DIF FORMAT. HE CAN ALSO ' ADD TO, RESET, OR DISPLAY HIS MILEAGE DATA. ' ' VARIABLE TABLE: ' A,A$ - ONE CHARACTER INPUT VARIABLES ' D,D!,D$ - DUMMY VARIABLES ' DAT$ - CURRENT DATE ' DAT$() - ARRAY OF DATES ' DONE - FLAG, EXECUTION COMPLETE ' ER - ERROR CODE ' ERP - ERROR PROCESSING FLAG ' F1 - FLAG, VALID MILES DRIVEN ' F2 - FLAG, VALID ODOMETER ' FID$ - FILE IDENTIFICATION ' FLAG - FLAG, 0=FALSE,-1=TRUE ' GAL() - ARRAY OF GALLONS USED ' I,J - LOOP INDEXES ' MAX.REC - MAXIMUM NUMBER OF RECORDS ' MIL() - ARRAY OF MILES DRIVEN ' NUM - DIF DATA NUMBER ' NUM.TUP - DIF TUPLE LENGTH ' NUM.VEC - DIF VECTOR LENGTH ' OD() - ARRAY OF ODOMETER READINGS ' <0 INDICATES OIL CHANGE ' QUIT - FLAG, EXIT PROGRAM ' REC - CURRENT RECORD NUMBER ' RET$ - RETURN CHARACTER ' RPT.ROW - REPORT ROW ' STG$ - DIF DATA STRING ' TIT$ - DIF TITLE STRING ' TYP - DIF TYPE INDICATOR ' VALID - FLAG, VALID INPUT ' ' ENVIRONMENT VARIABLES: ' SET DEBUG=YES - DEBUG MODE ON ' ' DECLARATIONS: ' DIM DAT$(250) DIM GAL(250) DIM MIL(250) DIM OD(250) ' GOTO INITIALIZATION REM REM UTILITY ROUTINES SECTION. REM ' INKEY.CASE: ' ' THE PURPOSE OF THIS ROUTINE IS TO SET A$ EQUAL TO THE NEXT ' LINE OF INPUT. ALL LOWERCASE IS CONVERTED TO UPPERCASE. ' DO A$ = INKEY$ LOOP UNTIL A$ <> "" D. = ASC(A$): IF D. > 96 AND D. < 123 THEN A$ = CHR$(D. - 32) RETURN ' INPUT.CASE: ' ' THE PURPOSE OF THIS ROUTINE IS TO READ A LINE OF INPUT FROM ' A$, CONVERTING IT FROM LOWER TO UPPERCASE. ' LINE INPUT A$ FOR A. = 1 TO LEN(A$) D. = ASC(MID$(A$, A., 1)) IF D. > 96 AND D. < 123 THEN MID$(A$, A., 1) = CHR$(D. - 32) NEXT A. RETURN ' PAUSE: ' ' THE PURPOSE OF THIS ROUTINE IS TO WAIT FOR THE USER TO ' HIT ANY KEY. ' PRINT PRINT "Press anything to continue..."; GOSUB INKEY.CASE RETURN ' MESSAGES: ' ' THE PURPOSE OF THIS ROUTINE IS TO HANDLE ALL NON-FATAL ' ERRORS. ENTRY: GOSUB MESSAGES\ ' D$ = "" IF ER = 1 THEN D$ = "Invalid Command, Retype" IF ER = 2 THEN D$ = "Bad Value, Retype" IF ER = 3 THEN D$ = "Enter Miles Driven, or Odometer" IF ER = 4 THEN D$ = "Bad Date, Enter 99/99/99 Format" PRINT "** "; D$ GOSUB PAUSE RETURN ' ERRORS: ' ' THE PURPOSE OF THIS ROUTINE IS TO HANDLE ALL FATAL ' ERRORS. ENTRY: GOTO ERRORS\ ' D$ = "" IF ER = 1 THEN D$ = "Error, Bad DIF File" PRINT "** "; D$ GOSUB PAUSE RETURN ' ERROR.HANDLER: ' ' THE PURPOSE OF THIS ROUTINE IS TO HANDLE ALL PROGRAM, AND ' SYSTEM ERRORS. ENTRY: ON ERROR GOTO ERROR.HANDLER\ ' D$ = "" IF ERR < 50 THEN D$ = "Syntax Error" IF ERR = 53 THEN D$ = "File not Found" IF ERR = 64 THEN D$ = "Bad File Name" IF D$ = "" THEN D$ = "Disk Error" PRINT "** "; D$; ", ERR#"; ERR IF ERR <= 50 THEN D! = ERL IF D! <> 65535 THEN PRINT "** Error Line Number"; D! END IF IF ERP THEN PRINT "Press 'C' to continue, anything to quit." D$ = INPUT$(1) IF D$ <> "C" AND D$ <> "c" THEN STOP END IF RESUME RESUMED RESUMED: RETURN REM REM UTILITY ROUTINES EXIT. REM ' INITIALIZATION: ' DAT$ = DATE$ ON ERROR GOTO ERROR.HANDLER IF ENVIRON$("DEBUG") <> "" THEN ERP = -1 ENDIF MAX.REC = 250 NUM.VEC = 4 QUIT = 0 REC = 0 REM REM MAIN ROUTINE REM ' ' THE PURPOSE OF THIS ROUTINE IS TO CONTROL THE PROGRAM. IT ' WILL READ, VERIFY, AND PROCESS A COMMAND FROM THE USER. IT ' WILL THEN ASK FOR ANOTHER COMMAND. ENTRY: INITIALIZATION\ ' DO CLS : PRINT PRINT PRINT "MILEAGE 1.4.2" PRINT "(C) Copyright 1986-2001 by Dennis Allen" PRINT "Portions (C) Copyright" PRINT "Microsoft Corp. 1982-2001" PRINT "All Rights Reserved" PRINT PRINT " <1> Help" PRINT " <2> Read Mileage File "+FID$ PRINT " <3> Write Mileage File" PRINT " <4> Add to Mileage Table" PRINT " <5> Clear Mileage Table" PRINT " <6> Display Mileage Table" PRINT " <7> Print Mileage Table" PRINT " <8> Exit Program" PRINT PRINT " Press key corresponding to function..." PRINT PRINT "Number of Records ="; REC DO GOSUB INKEY.CASE: A = VAL(A$): IF A$ = "Q" OR A$ = "q" THEN A = 8 LOOP UNTIL A <> 0 IF A = 8 THEN QUIT = -1 ON A GOSUB HELP, READ.DIF, WRITE.DIF, ADD.REC, RESET., DISPLAY.TABLE, PRINT.TABLE LOOP UNTIL QUIT SYSTEM REM REM MAIN ROUTINES SECTION. REM ' READ.DIF: ' ' THE PURPOSE OF THIS ROUTINE IS TO READ A DIF FILE. IT WILL ' FIRST ASK THE USER FOR THE FILE NAME. IT WILL THEN OPEN THE ' THE DIF FILE, AND CHECK IT IF IT HAS A VALID DIF FORMAT. DIF ' DATA WILL THEN BE READ AND STORED IN TABLES. ENTRY & EXIT: ' THE MAIN ROUTINE. ' PRINT PRINT "What is the name of the input DIF file "; IF FID$ <> "" THEN PRINT "("+FID$+")" ; END IF PRINT " ? " ; GOSUB INPUT.CASE: IF A$ <> "" THEN FID$ = A$ IF INSTR(FID$, ".") = 0 THEN FID$ = FID$ + ".DIF" CLOSE 1: OPEN "I", 1, FID$ REC = 0 GOSUB READ.DIF.HEADER IF NOT DONE GOTO ERRORS GOSUB READ.DIF.TABLE IF NOT DONE GOTO ERRORS PRINT NUM.TUP; "Record(s) read" GOSUB PAUSE RETURN REM REM READ DIF ROUTINES SECTION. REM ' READ.DIF.HEADER: ' ' THE PURPOSE OF THIS ROUTINE IS TO RETRIEVE, AND VERIFY THE ' DIF HEADER. ENTRY & EXIT: READ.DIF\ ' DONE = 0 INPUT #1, TIT$ INPUT #1, TYP, NUM INPUT #1, STG$ IF TIT$ <> "TABLE" THEN ER = 1: RETURN WHILE NOT EOF(1) AND NOT DONE INPUT #1, TIT$ INPUT #1, TYP, NUM INPUT #1, STG$ SELECT CASE TIT$ CASE "TUPLES" IF NUM < 0 OR NUM > MAX.REC THEN ER = 1: RETURN NUM.TUP = NUM CASE "VECTORS" IF NUM < NUM.VEC THEN ER = 1: RETURN NUM.VEC = NUM CASE "DATA" DONE = -1 CASE ELSE END SELECT WEND RETURN ' READ.DIF.TABLE: ' ' THE PURPOSE OF THIS ROUTINE IS TO RETRIEVE, AND VERIFY ' DIF DATA. ENTRY & EXIT: READ.DIF\ ' DONE = 0 FOR I = 1 TO NUM.TUP INPUT #1, TYP, NUM INPUT #1, STG$ IF TYP <> -1 OR STG$ <> "BOT" THEN ER = 1: RETURN FOR J = 1 TO NUM.VEC INPUT #1, TYP, NUM INPUT #1, STG$ SELECT CASE J CASE 1 IF LEN(STG$) = 8 THEN IF VAL(RIGHT$(STG$,2)) < 50 THEN STG$ = LEFT$(STG$,6)+"20"+RIGHT$(STG$,2) ELSE STG$ = LEFT$(STG$,6)+"19"+RIGHT$(STG$,2) END IF END IF : DAT$(I) = STG$ CASE 2 : MIL(I) = NUM CASE 3 : OD(I) = NUM CASE 4 : GAL(I) = NUM CASE ELSE END SELECT NEXT J NEXT I REC = NUM.TUP INPUT #1, TYP, NUM INPUT #1, STG$ IF TYP <> -1 OR STG$ <> "EOD" THEN ER = 1: RETURN DONE = -1 RETURN REM REM READ DIF ROUTINES EXIT. REM ' WRITE.DIF: ' ' THE PURPOSE OF THIS ROUTINE IS TO WRITE A DIF FILE. IT WILL ' FIRST ASK THE USER FOR THE DIF FILE NAME. IT WILL THEN OPEN ' THE DIF FILE, AND STORE THE MILEAGE DATA IN DIF FORMAT. ' ENTRY & EXIT: THE MAIN ROUTINE. ' PRINT PRINT "What is the name of the output DIF file "; IF FID$ <> "" THEN PRINT "("+FID$+")" ; END IF PRINT " ? " ; GOSUB INPUT.CASE: IF A$ <> "" THEN FID$ = A$ IF INSTR(FID$, ".") = 0 THEN FID$ = FID$ + ".DIF" CLOSE 1: OPEN "O", 1, FID$ GOSUB WRITE.DIF.HEADER IF NOT DONE THEN RETURN GOSUB WRITE.DIF.TABLE IF NOT DONE THEN RETURN PRINT NUM.TUP; "Record(s) saved" GOSUB PAUSE RETURN REM REM WRITE DIF ROUTINES SECTION. REM ' WRITE.DIF.HEADER: ' ' THE PURPOSE OF THIS ROUTINE IS TO WRITE THE DIF HEADER TO ' FID$. ENTRY & EXIT: WRITE.DIF\ ' DONE = 0 NUM.TUP = REC NUM.VEC = 4 PRINT #1, "TABLE" PRINT #1, 0; ","; 0 PRINT #1, CHR$(34); "MILEAGE TABLE"; CHR$(34) PRINT #1, "VECTORS" PRINT #1, 0; ","; NUM.VEC PRINT #1, CHR$(34); CHR$(34) PRINT #1, "TUPLES" PRINT #1, 0; ","; NUM.TUP PRINT #1, CHR$(34); CHR$(34) PRINT #1, "LABEL" PRINT #1, 1; ","; 0 PRINT #1, CHR$(34); "DATE"; CHR$(34) PRINT #1, "LABEL" PRINT #1, 2; ","; 0 PRINT #1, CHR$(34); "MILES"; CHR$(34) PRINT #1, "LABEL" PRINT #1, 3; ","; 0 PRINT #1, CHR$(34); "ODOMETER"; CHR$(34) PRINT #1, "LABEL" PRINT #1, 4; ","; 0 PRINT #1, CHR$(34); "GALLONS"; CHR$(34) PRINT #1, "DATA" PRINT #1, 0; ","; 0 PRINT #1, CHR$(34); CHR$(34) DONE = -1 RETURN ' WRITE.DIF.TABLE: ' ' THE PURPOSE OF THIS ROUTINE IS TO WRITE THE MILEAGE DATA TO ' FID$ IN THE DIF FORMAT. ENTRY & EXIT: WRITE.DIF\ ' DONE = 0 FOR I = 1 TO REC PRINT #1, -1; ","; 0 PRINT #1, "BOT" FOR J = 1 TO NUM.VEC SELECT CASE J CASE 1 : TYP = 1: NUM = 0: STG$ = CHR$(34) + DAT$(I) + CHR$(34) CASE 2 : TYP = 0: NUM = MIL(I): STG$ = "V" CASE 3 : TYP = 0: NUM = OD(I): STG$ = "V" CASE 4 : TYP = 0: NUM = GAL(I): STG$ = "V" CASE ELSE END SELECT PRINT #1, TYP; ","; NUM PRINT #1, STG$ NEXT J NEXT I PRINT #1, -1; ","; 0 PRINT #1, "EOD" DONE = -1 RETURN REM REM WRITE DIF ROUTINES EXIT. REM ' ADD.REC: ' ' THE PURPOSE OF THIS ROUTINE IS TO ADD ANOTHER RECORD TO THE ' CURRENT MILEAGE DATA. ENTRY & EXIT: THE MAIN ROUTINE. ' DO GOSUB ADD.DATE DO F1 = 0: F2 = 0 GOSUB ADD.MILES IF NOT F1 THEN GOSUB ADD.ODOMETER IF NOT (F1 OR F2) THEN ER = 3: GOSUB MESSAGES LOOP UNTIL F1 OR F2 IF F1 THEN OD(REC + 1) = ABS(OD(REC)) + MIL(REC + 1) ELSE MIL(REC + 1) = ABS(OD(REC + 1)) - ABS(OD(REC)) END IF GOSUB ADD.OIL GOSUB ADD.GAL GOSUB ADD.DISPLAY IF VALID THEN IF REC + 1 < MAX.REC THEN REC = REC + 1 ELSE FOR D = 2 TO REC + 1 DAT$(D - 1) = DAT$(D) GAL(D - 1) = GAL(D) MIL(D - 1) = MIL(D) OD(D - 1) = OD(D) NEXT D END IF END IF LOOP UNTIL VALID RETURN REM REM ADD ROUTINES SECTION. REM ' ADD.DATE: ' ' THE PURPOSE OF THIS ROUTINE IS TO RETRIEVE A VALID DATE. ' ENTRY & EXIT: ADD.REC\ ' CLS : PRINT DAT$(REC + 1) = "" DO PRINT PRINT "Enter Date, for System Date : "; INPUT D$ IF LEN(D$) = 0 THEN D$ = DAT$ FLAG = -1 IF LEN(D$) <> 10 THEN FLAG = 0 D = VAL(D$) IF D < 1 OR D > 12 THEN FLAG = 0 D = VAL(MID$(D$, 4, 2)) IF D < 1 OR D > 31 THEN FLAG = 0 D = VAL(MID$(D$, 7, 4)) IF D < 1900 OR D > 3000 THEN FLAG = 0 IF NOT FLAG THEN ER = 4: GOSUB MESSAGES LOOP UNTIL FLAG DAT$(REC + 1) = D$ RETURN ' ADD.MILES: ' ' THE PURPOSE OF THIS ROUTINE IS TO RETRIEVE THE NUMBER OF ' MILES DRIVEN SINCE LAST FILL UP. ENTRY & EXIT: ADD.REC\ ' F1 = 0: MIL(REC + 1) = 0 DO PRINT PRINT "Enter number of Miles Driven, for Odometer Prompt "; INPUT D FLAG = -1 IF D < 0 OR D > 9999 THEN FLAG = 0 IF NOT FLAG THEN ER = 2: GOSUB MESSAGES LOOP UNTIL FLAG MIL(REC + 1) = D: IF D <> 0 THEN F1 = -1 RETURN ' ADD.ODOMETER: ' ' THE PURPOSE OF THIS ROUTINE IS TO RETRIEVE THE ODOMETER ' READING. ENTRY & EXIT: ADD.REC\ ' F2 = 0: OD(REC + 1) = 0 DO PRINT PRINT "Enter Odometer reading "; INPUT D FLAG = -1 IF D < 0 OR D > 99999 THEN FLAG = 0 IF NOT FLAG THEN ER = 2: GOSUB MESSAGES LOOP UNTIL FLAG OD(REC + 1) = D: IF D <> 0 THEN F2 = -1 RETURN ' ADD.OIL: ' ' THE PURPOSE OF THIS ROUTINE IS TO CHECK THE ODOMETER ' READING FOR OIL CHANGE. ENTRY & EXIT: ADD.REC\ ' PRINT PRINT "Did you change your Oil (Y or *N) "; GOSUB INKEY.CASE: IF A$ <> "Y" THEN A$ = "N" PRINT A$ IF LEFT$(A$, 1) = "Y" THEN OD(REC + 1) = -OD(REC + 1) RETURN ' ADD.GAL: ' ' THE PURPOSE OF THIS ROUTINE IS TO RETRIEVE THE GASOLINE ' CONSUMPTION, IN GALLONS. ENTRY & EXIT: ADD.REC\ ' DO PRINT PRINT "Enter number of Gallons, or Liters (##G OR ##L) "; GOSUB INPUT.CASE D = VAL(A$) FLAG = -1 IF D < 0 THEN FLAG = 0 IF NOT FLAG THEN ER = 2: GOSUB MESSAGES LOOP UNTIL FLAG IF INSTR(A$, "L") <> 0 THEN D = D / 3.78 GAL(REC + 1) = D RETURN ' ADD.DISPLAY: ' ' THE PURPOSE OF THIS ROUTINE IS TO DISPLAY THE CURRENT ' MILEAGE RECORD, AND TO ASK IF IT IS VALID. ENTRY & ' EXIT: ADD.REC\ ' CLS : PRINT PRINT "Input Check" PRINT PRINT " Date "; DAT$(REC + 1) PRINT " Driven "; MIL(REC + 1); "Miles" PRINT " Odometer "; ABS(OD(REC + 1)); "Miles" PRINT " Gasoline "; GAL(REC + 1); "Gallons" PRINT IF OD(REC + 1) >= 0 THEN D = REC + 1: FLAG = 0 WHILE D > 0 AND NOT FLAG IF OD(D) < 0 THEN FLAG = -1 ELSE D = D - 1 WEND IF (ABS(OD(REC + 1)) > (ABS(OD(D)) + 3000)) THEN PRINT PRINT " You need to change your Oil" END IF END IF PRINT PRINT "Input OK (*Y or N) "; GOSUB INKEY.CASE: IF A$ <> "N" THEN A$ = "Y" PRINT A$ VALID = 0 IF LEFT$(A$, 1) = "Y" THEN VALID = -1 RETURN REM REM ADD ROUTINES EXIT. REM ' RESET.: ' ' THE PURPOSE OF THIS ROUTINE IS TO CLEAR MILEAGE DATA FROM ' TABLES. ENTRY & EXIT: THE MAIN ROUTINE. ' PRINT "MILEAGE Table cleared" GOSUB PAUSE FID$ = "" REC = 0 RETURN ' DISPLAY.TABLE: ' ' THE PURPOSE OF THIS ROUTINE IS TO DISPLAY ALL CURRENT ' MILEAGE DATA, INCLUDING LITERS USED, MPG, AND LAST OIL ' CHANGE. ENTRY & EXIT: THE MAIN ROUTINE. ' RPT.ROW = 5 D$ = " #####.##" D = 1 DO WHILE D <= REC IF RPT.ROW >= 24-5 THEN GOSUB PAUSE: RPT.ROW = 5 ENDIF IF RPT.ROW = 5 THEN CLS : PRINT PRINT "Current MILEAGE Table" PRINT PRINT " DATE ODOMETER M/DRIVEN GALLONS LITERS MILES/GAL" PRINT "********** ******** ******** ******** ******** *********" ENDIF PRINT DAT$(D); PRINT USING D$; ABS(OD(D)); PRINT USING D$; MIL(D); PRINT USING D$; GAL(D); PRINT USING D$; GAL(D) * 3.78; IF GAL(D) > 0 THEN PRINT USING D$; MIL(D) / GAL(D); END IF PRINT D = D + 1 RPT.ROW = RPT.ROW + 1 LOOP D = REC: FLAG = 0 WHILE D > 0 AND NOT FLAG IF OD(D) < 0 THEN FLAG = -1 ELSE D = D - 1 WEND IF FLAG THEN PRINT PRINT "Last Oil change was at"; ABS(OD(D)) END IF GOSUB PAUSE RETURN ' PRINT.TABLE: ' ' THE PURPOSE OF THIS ROUTINE IS TO PRINT ALL CURRENT ' MILEAGE DATA, INCLUDING LITERS USED, MPG, AND LAST OIL ' CHANGE. ENTRY & EXIT: THE MAIN ROUTINE. ' OPEN "LPT1.DOS" FOR OUTPUT AS #2 PRINT #2, " " PRINT #2, "Current MILEAGE Table" PRINT #2, " " PRINT #2, " DATE ODOMETER M/DRIVEN GALLONS LITERS MILES/GAL" PRINT #2, "********** ******** ******** ******** ******** *********" D$ = " #####.##" FOR D = 1 TO REC PRINT #2, DAT$(D); PRINT #2, USING D$; ABS(OD(D)); PRINT #2, USING D$; MIL(D); PRINT #2, USING D$; GAL(D); PRINT #2, USING D$; GAL(D) * 3.78; IF GAL(D) > 0 THEN PRINT #2, USING D$; MIL(D) / GAL(D); END IF PRINT #2, " " NEXT D D = REC: FLAG = 0 WHILE D > 0 AND NOT FLAG IF OD(D) < 0 THEN FLAG = -1 ELSE D = D - 1 WEND IF FLAG THEN PRINT #2, " " PRINT #2, "Last Oil change was at"; ABS(OD(D)) END IF PRINT #2, CHR$(12) CLOSE #2 RETURN ' HELP: ' ' THE PURPOSE OF THIS ROUTINE IS TO BRIEFLY EXPLAIN THE ' SELECTIONS PROVIDED IN THE MILEAGE MENU. ENTRY & ' EXIT: THE MAIN ROUTINE. ' CLS : PRINT PRINT "The following menu is available in MILEAGE:" PRINT PRINT "MILEAGE Command Menu" PRINT PRINT " 1. Help" PRINT " 2. Read Mileage File" PRINT " 3. Write Mileage File" PRINT " 4. Add to Mileage Table" PRINT " 5. Clear Mileage Table" PRINT " 6. Display Mileage Table" PRINT " 7. Print Mileage Table" PRINT " 8. Exit Program" PRINT GOSUB PAUSE CLS : PRINT PRINT "Select 1 will get instructions." PRINT PRINT "Select 2 will read a specified file, and update the" PRINT " MILEAGE Table. The specified file must be in Data" PRINT " Interchange Format (DIF)." PRINT PRINT "Select 3 will write the current MILEAGE Table to" PRINT " the specified DIF file." PRINT PRINT "Select 4 Will add another record to the current MILEAGE" PRINT " Table. Each record in the MILEAGE Table consists of" PRINT " the Date, how many Miles Driven since the last fill" PRINT " up, the Odometer reading, and how many Gallons/Liters" PRINT " used in last fill up." GOSUB PAUSE CLS : PRINT PRINT "Select 5 will clear all records from the MILEAGE Table." PRINT PRINT "Select 6 will display all records in the MILEAGE Table." PRINT PRINT "Select 7 will send all records in table to the printer." PRINT PRINT "Select 8 will Exit back to DOS." GOSUB PAUSE RETURN REM REM MAIN ROUTINES EXIT. REM END '