REM Mpg utility - a fuel economy
REM database for Psion Series 3.
REM Rick Andrews Dec 92

APP Mpg
TYPE 4
ICON "\pic\mpg.pic"
PATH "\mpg"
EXT "mpg"
ENDA

PROC Mpg:
GLOBAL g%,k%
GLOBAL gFile$(128)
GLOBAL GSCRHT%
GLOBAL gMile%,gGallon%
GLOBAL gKFactor,gLFactor
GLOBAL gEconomy,gTotDist,gTotVol
GLOBAL gOpen%
LOCAL exit%,delta%,wId%
LOCAL finger%,oldFing%,oldCoun%
LOCAL ctrl%,choice%
LOCAL action$(1)
REM Init.
TRAP MKDIR "\MPG"
gUPDATE OFF
GSCRHT%=7 REM Screen height in lines.
gOpen%=0
gMile%=-1 :gGallon%=-1
gLFactor=4.546099 REM Ltrs in gallon.
gKFactor=1.609344 REM Kms in mile.
wId%=gCREATE(0,0,240,gSCRHT%*9+17,1)
gBORDER 0 REM Natural.
gSTYLE 0 REM prop.
gTMODE 3 REM Replace.
gAT 0,12 :gLINEBY 240,0
gAT 15,10 :gPRINT "Date"
gAT 58,10 :gPRINT "Odometer"
UnitHead:
gFile$=CMD$(2)
REM Handle initial actions.
action$=CMD$(3)
HandAct:(action$)
oldFing%=0
oldCoun%=0
delta%=-1
finger%=COUNT-GSCRHT%+1
exit%=0
DO
IF finger%<>oldFing% OR COUNT<>oldCoun%
delta%=-1
oldFing%=finger%
oldCoun%=COUNT
ENDIF
IF finger%>COUNT-GSCRHT%+1
finger%=COUNT-GSCRHT%+1
ENDIF
IF finger%<1
finger%=1
ENDIF
IF delta%
Screen:(finger%)
delta%=0
ENDIF
GetEv:
IF (k% AND 4)
ctrl%=-1
ENDIF
IF (g%=$122 OR (g% AND $200)) REM Menu/Hot.
IF g%=$122 REM Menu.
LOCK ON
mINIT
mCARD "File", "New file",%N, "Open file",%O, "Save as",%A
mCARD "Changes", "Enter data",%E,"Update",%U,"Delete last",%D
mCARD "Economy","Calculate",%C,"Evalulate",%V
mCARD "Special", "Options",%Q, "Version",%Z, "Exit",%X
choice%=MENU
LOCK OFF
ELSE REM Hotkey.
choice%=g%-$200
ENDIF
choice%=choice% AND $FFDF REM Uppercase.
IF choice%<32 REM Delete key etc.
choice%=choice%+32
ENDIF
IF choice%=%C :ShowEcon:
ELSEIF choice%=%E :Insert: :finger%=COUNT
ELSEIF choice%=%U :Update: :delta%=-1
ELSEIF choice%=%D :Delete:
ELSEIF choice%=%N :New:(1) REM User.
ELSEIF choice%=%O :Open:(1) REM User.
ELSEIF choice%=%A :Saveas:
ELSEIF choice%=%Q :Option: :delta%=-1
ELSEIF choice%=%V :Eval:
ELSEIF choice%=%X :exit%=-1
ELSEIF choice%=%Z :Version:
ENDIF
ELSEIF g%=8 REM <-Delete.
Delete:
ELSEIF g%=291 REM Help.
Help:
ELSEIF g%=256 REM Up.
finger%=finger%-GSCRHT%
ELSEIF g%=257 REM Down.
finger%=finger%+GSCRHT%
ELSEIF g%=260 REM Psion Up.
IF ctrl%
finger%=1
ELSE
finger%=finger%-GSCRHT%
ENDIF
ELSEIF g%=261 REM Psion Down.
IF ctrl%
finger%=COUNT
ELSE
finger%=finger%+GSCRHT%
ENDIF
ENDIF
UNTIL exit%
CLOSE
gCLOSE wId%
gUPDATE ON
RETURN REM To system.
ENDP

PROC GetEv:
LOCAL t$(1),a%(6)
DO
GETEVENT a%()
IF a%(1)=$404 REM Sys event
gFile$=GETCMD$
t$=LEFT$(gFile$,1)
gFile$=MID$(gFile$,2,128)
IF t$="X"
REM Simulate user quiting.
a%(1)=632 REM Psion+X.
BREAK
ELSEIF t$="C" OR t$="O"
HandAct:(t$)
ENDIF
ELSE
BREAK
ENDIF
UNTIL 0
g%=a%(1) REM Key.
k%=a%(2) AND $00FF REM KMOD.
RETURN
ENDP

PROC Open:(user%)
LOCAL okay%
okay%=-1
IF user%
IF GetName:("Open",0)
ELSE
RETURN
ENDIF
ENDIF
IF gOpen%
CLOSE
gOpen%=0
ENDIF
SETNAME gFile$
IF NOT EXIST(gFile$)
ALERT ("Failed to find",gFile$)
okay%=0
ELSE
TRAP OPEN gFile$,A,date&,dist,vol,note$
IF ERR
ALERT ("Failed to open",gFile$)
okay%=0
ELSE
gOpen%=-1
Screen:(1)
IF COUNT=0
Insert:
Screen:(1)
ENDIF
ENDIF
ENDIF
IF NOT okay%
STOP
ENDIF
ENDP

PROC New:(user%)
LOCAL okay%
okay%=-1
IF user%
IF GetName:("Create new ",1+16)
ELSE
RETURN
ENDIF
ENDIF
SETNAME gFile$
IF gOpen%
CLOSE
gOpen%=0
ENDIF
IF EXIST(gFile$)
TRAP DELETE gFile$
ENDIF
TRAP CREATE gFile$,A,date&,dist,vol,note$
IF ERR
ALERT ("Failed to create",gFile$)
okay%=0
ELSE
gOpen%=-1
Screen:(1)
Insert:
Screen:(1)
ENDIF
IF NOT okay%
STOP
ENDIF
ENDP

PROC Screen:(finger%)
REM Update screen.
LOCAL prevd,back1%
LOCAL place$(7)
back1%=finger%-1
IF back1%<1
prevd=-1
ELSE
POSITION back1%
prevd=A.dist
NEXT
ENDIF
POSITION finger%
Row:(prevd)
POSITION finger%
IF COUNT=0
place$="0/0"
ELSE
place$=GEN$(POS,3)+"/"
place$=place$+GEN$(COUNT,3)
ENDIF
gAT 200,10
gPRINTB place$,37
ENDP

PROC Row:(prevdst)
LOCAL row%,r%,dist,trip
LOCAL vol
dist=prevdst
row%=1
DO
r%=row%*9+12
gAT 3,r%
IF EOF
gPRINTB "",234
ELSE
gPRINT Day2Str$:(A.date&)
gAT 55,r%
gPRINT FIX$(a.dist,1,-8)
gAT 105,r%
IF dist=-1
gPRINTB "   -",38
ELSE
trip=A.dist-dist
IF trip<0
trip=trip+1000000
ENDIF
IF NOT gMile%
trip=trip*gKFactor
ENDIF
gPRINT FIX$(trip,1,-6)
ENDIF
dist=A.dist
gAT 144,r%
vol=a.vol
IF gGallon%
vol=a.vol
ELSE
vol=a.vol*gLFactor
ENDIF
gPRINT FIX$(vol,1,-5)
gAT 177,r%
gSTYLE 0 REM Proportional.
gPRINTB A.note$,60
gSTYLE 16 REM Non-prop.
ENDIF
row%=row%+1
NEXT
UNTIL row%>GSCRHT%
ENDP

PROC Day2Str$:(day&)
REM Convert days-date to a
REM formatted string e.g. 29/02/84
LOCAL y%,m%,d%,d$(8),lday&
LOCAL u% REM An unused parameter.
lday&=day&-25567
lday&=lday&*86400
SECSTODATE lday&,y%,m%,d%,u%,u%,u%,u%
d$=RIGHT$("0"+GEN$(d%,2),2)+"/"
d$=d$+RIGHT$("0"+GEN$(m%,2),2)+"/"
d$=d$+RIGHT$("0"+GEN$(y%-1900,2),2)
RETURN d$
ENDP

PROC Insert:
Entry:(-1) REM Append.
ENDP

PROC Delete:
LOCAL choice%
IF COUNT=0
GIPRINT "No entries to delete!"
RETURN
ENDIF
dINIT "Delete last entry ?"
dBUTTONS "No",-%N,"Yes",%Y
choice%=DIALOG
IF choice%=%y
LAST
ERASE
GIPRINT "Deleted"
ENDIF
ENDP

PROC ShowEcon:
LOCAL dType%,vType%,econ$(30)
IF COUNT<2
GIPRINT "Need more readings!"
RETURN
ENDIF
CalcEcon:
IF gMile%
dType%=1
ELSE
dType%=2
ENDIF
IF gGallon%
vType%=3
ELSE
vType%=4
ENDIF
econ$=GEN$(gEconomy,5)+" "+Type$:(dType%)
econ$=econ$+" per "+LEFT$(Type$:(vType%),6)
dINIT 
dTEXT "","The fuel economy is",2
dTEXT "",econ$,$302
dTEXT "","(Total distance is "+GEN$(gTotDist,6)+" "+Type$:(dType%)+")",2
dTEXT "","(Total fuel is "+GEN$(gTotVol,6)+" "+Type$:(vType%)+")",2
DIALOG
ENDP

PROC CalcEcon:
LOCAL startD,lastD
FIRST
gTotVol=0
startD=A.dist
NEXT REM Skip first fuel reading.
DO
gTotVol=gTotVol+A.vol
NEXT
UNTIL EOF
BACK
lastD=A.dist
IF lastD>startD
gTotDist=lastD-startD
ELSE REM Clocked.
gTotDist=1000000-startD+lastD
ENDIF
IF NOT gMile%
gTotDist=gTotDist*gKFactor
ENDIF
IF NOT gGallon%
gTotVol=gTotVol*gLFactor
ENDIF
gEconomy=gTotDist/gTotVol
RETURN 
ENDP

PROC Entry:(append%)
LOCAL dDay&,today&
LOCAL done%,dial%,dial2%,write%
LOCAL eNote$(11),eDate&,eDist,eVol
LOCAL fuel$(7),title$(6)
LOCAL trip,clocked%,limit%,prevDist
IF gGallon%
fuel$=Type$:(3)
ELSE
fuel$=Type$:(4)
ENDIF
REM Get default settings.
LAST
dDay&=A.date&
today&=DAYS(DAY,MONTH,YEAR)
IF append%
title$="Enter"
eDate&=today&
ELSE
title$="Update"
eDate&=dDay&
IF COUNT=1
dDay&=0
ENDIF
eVol=A.vol
eNote$=A.note$
ENDIF
eDist=A.dist
write%=0
REM Find the odometer upper limit.
limit%=-1
IF (append% AND COUNT=0) OR (NOT append% AND COUNT<=1)
limit%=0
ELSE
IF append%
prevDist=A.dist
ELSE
BACK
prevDist=A.dist
dDay&=A.date&
LAST
ENDIF
ENDIF
IF NOT gGallon%
eVol=eVol*gLFactor
ENDIF
DO
eVol=Round2:(eVol)
dINIT title$+" reading"
dDATE eDate&,"Date",dDay&,today&
dFLOAT eDist,"Odometer",0,999999.9
dFLOAT eVol,fuel$,0.1,999.9
dEDIT eNote$,"Note",11
dial%=DIALOG
IF dial%
IF limit%
trip=eDist-prevDist
IF trip<0
trip=trip+1000000
clocked%=-1
ELSE
clocked%=0
ENDIF
IF trip>5000
GIPRINT "Invalid odometer value: Max = "+GEN$(prevDist+5000,8)
ELSEIF (trip=0 AND append%)
GIPRINT "Invalid odometer value: Min = "+GEN$(prevDist+.1,8)
ELSEIF clocked%
dINIT "Warning!"
dTEXT "","You have clocked the odometer",$102
dTEXT "","Is this correct ?",2
dBUTTONS "Yes",%Y,"No",%N
dial2%=DIALOG
IF dial2%=%y
write%=-1
ENDIF
ELSE
write%=-1
ENDIF
ELSE REM No limit
write%=-1
ENDIF
ELSE
done%=-1
ENDIF
UNTIL done% OR write%
IF write%
A.date&=eDate&
A.dist=eDist
IF gGallon%
A.vol=eVol
ELSE REM Conv to gallon.
A.vol=eVol/gLFactor
ENDIF
A.note$=eNote$
IF append%
TRAP APPEND
ELSE
TRAP UPDATE
ENDIF
IF ERR
ALERT("File function failed","Try again")
ELSE
IF append%
GIPRINT "Appended"
ELSE
GIPRINT "Updated"
ENDIF
ENDIF
ENDIF
ENDP

PROC Update:
LOCAL choice%
IF COUNT=0
GIPRINT "No entries to update!"
RETURN
ENDIF
Entry:(0) REM Update
ENDP

PROC UnitHead:
gSTYLE 0 REM Prop.
gAT 110,10
IF gMile%
gPRINTB Type$:(1),30,3
ELSE
gPRINTB Type$:(2),30,3
ENDIF
gAT 151,10
IF gGallon%
gPRINTB LEFT$(Type$:(3),4),20,3
ELSE
gPRINTB Type$:(4),20,3
ENDIF
gSTYLE 16 REM Non-prop.
ENDP

PROC Option:
LOCAL mile%,gallon%
mile%=gMile%+2
gallon%=gGallon%+2
dINIT "Set options"
dCHOICE mile%,"Trip distance shown as","Miles,Km"
dCHOICE gallon%,"Fuel volume shown as","Gallons,Litres"
IF DIALOG
gMile%=mile%-2
gGallon%=gallon%-2
UnitHead:
ENDIF
ENDP

PROC HandAct:(act$)
IF act$="C"
New:(0) REM system
ELSE REM act$="O"
Open:(0) REM system
ENDIF
ENDP

PROC Help:
dINIT
dTEXT "","Help: Mpg", $302
dTEXT "","Calculates fuel economy from fuel volume"
dTEXT "","and odometer (milometer) readings."
dTEXT "","Use "+CHR$(24)+CHR$(25)+" to move around the file"
dTEXT "","The "+CHR$(2)+" and Control keys increase movement"
dTEXT "","`Save as' saves the data as Ascii text"
dTEXT "","Use `Options' to change preferences"
DIALOG
ENDP

PROC GetName:(Title$,type%)
dINIT title$+" file"
dFILE gFile$,"Name",type%
IF DIALOG
RETURN -1
ELSE
RETURN 0
ENDIF
ENDP

PROC Version:
dINIT
dTEXT "","MPG - Fuel economy database",$302
dTEXT "","Rick Andrews & IPSO FACTO",2
dTEXT "","Version 1.0 - 21 Dec 92",2
DIALOG
ENDP

PROC SaveAs:
LOCAL f$(128),dist
LOCAL trip,vol
LOCAL dType%,vType%
IF COUNT<1
GIPRINT "No entries!"
RETURN
ENDIF
dist=-1
f$="\WRD\MPG.TXT"
dINIT "Save as ASCII text"
dFILE f$,"File:",1+16
IF DIALOG
TRAP LOPEN f$
IF ERR
ALERT("Unable to open file",f$)
ELSE
BUSY "Saving"
LPRINT "MPG - Fuel economy database"
LPRINT "Filename:",gFile$
LPRINT "at",DATIM$
LPRINT
LPRINT "  Date  ",
LPRINT "Odometer ",
IF gMile%
LPRINT Type$:(1),
dType%=1
ELSE
LPRINT Type$:(2),"   ",
dType%=2
ENDIF
IF gGallon%
LPRINT Type$:(3),
vType%=3
ELSE
LPRINT Type$:(4),
vType%=4
ENDIF
LPRINT "Notes"
LPRINT
FIRST
DO
LPRINT Day2Str$:(A.date&),
LPRINT FIX$(a.dist,1,-8),
IF dist<0
LPRINT "   -  ",
ELSE
trip=A.dist-dist
IF trip<0
trip=trip+1000000
ENDIF
IF NOT gMile%
trip=trip*gKFactor
ENDIF
LPRINT FIX$(trip,1,-6),
ENDIF
dist=A.dist
vol=a.vol
IF gGallon%
vol=a.vol
ELSE
vol=a.vol*gLFactor
ENDIF
LPRINT FIX$(vol,1,-5),
LPRINT A.note$
NEXT
UNTIL EOF
LPRINT
IF COUNT<2
LPRINT "(Not enough entries to calculate economy)"
ELSE
CalcEcon:
LPRINT "Economy is",
LPRINT GEN$(gEconomy,5),
LPRINT Type$:(dType%),"per",
LPRINT LEFT$(Type$:(vType%),6)
LPRINT "Total distance is",GEN$(gTotDist,6),Type$:(dType%)
LPRINT "Total fuel is",GEN$(gTotVol,6),Type$:(vType%)
ENDIF
BUSY OFF
LCLOSE
ENDIF
ENDIF
ENDP


PROC Eval:
LOCAL convert%,type%,quantity
LOCAL factor,answer
LOCAL qType%,aType%
convert%=1
type%=1
dINIT "Evaluate units"
dCHOICE convert%,"Convert","Imperial to metric,Metric to imperial"
dCHOICE type%,"Type","Distance,Volume"
dFLOAT quantity,"Quantity",0,99999
IF DIALOG=0
RETURN
ENDIF
IF type%=1
factor=gKFactor REM Distance.
qType%=1 :aType%=1
ELSE
factor=gLFactor REM Volume.
qType%=3 :aType%=3
ENDIF
IF convert%=1
answer=quantity*factor REM I to M.
aType%=aType%+1
ELSE
answer=quantity/factor REM M to I.
qType%=qType%+1
ENDIF
dINIT "Evaluate"
dTEXT "",GEN$(quantity,6)+" "+Type$:(qType%)+" is",2
dTEXT "",GEN$(answer,6)+" "+Type$:(aType%),$102
DIALOG
ENDP

PROC Type$:(type%)
IF type%=1 :RETURN "Miles"
ELSEIF type%=2 :RETURN "Km"
ELSEIF type%=3 :RETURN "Gallons"
ELSE RETURN "Ltr"
ENDIF
ENDP

PROC Round2:(value)
LOCAL tidy
tidy=INT(value*100)
RETURN tidy/100
ENDP
