iConvert V3.3

User avatar
rbytes
Posts: 1963
Joined: Sun May 31, 2015 12:11 am
My devices: iPhone X
iPad 4
MacBook
Dell Inspiron laptop
CHUWI Plus 10 convertible Windows/Android tablet
Location: Calgary, Canada
Flag: Canada
Contact:

iConvert V3.3

Post by rbytes » Thu Nov 01, 2018 5:46 pm

A Flow Rate category has been added:
Also the animated and still title images are attached here.
iconvert3.PNG
iconvert3.PNG (14.12 KiB) Viewed 1542 times
iconvert3.GIF
iconvert3.GIF (222.71 KiB) Viewed 1542 times

Code: Select all

/*
iConvert V3.3
by rbytes and Dutchman, October 2018
Converts measurements in many categories.
A collaborative international project.

V3.3
- Flow Rate category added by rbytes
V3.2
- Angle category added by rbytes
- Energy transition category added by Dutchman
- Error trap added for Currency
V3.1
- Temperature category added by Dutchman
V3
- Currency category added by Dutchman
  DATA generated with "Update currencies.sb"
V2
- animation added to title
  (plays only once, at launch)
- measures added in most categories
- scientific notation is now used for
  results larger than 100,000,000 or
  smaller than .00000001
V1.1
- added Horsepower (Metric) to
  Power category
- eliminated >>> button;
  calculation is now automatic
  when list selections or
  input values are changed.
- code efficiency improved
*/
OPTION BASE 1
SET ORIENTATION LANDSCAPE
SET BUTTONS CUSTOM
SET TOOLBAR OFF
laun$=LAUNCHER$()
GET SCREEN SIZE sw,sh

' set to 1 to test iPhone layout on iPad
iostest=0
IF iostest THEN
  sw=568
  sh=320
  dev$=""
ENDIF
rw=sw/1024!rh=sh/740

'b'========= Constants ===================
'' *** Note - IP address may change if router is rebooted ***
'  run ipconfig on your PC to find its IP address.

URL$="192.170.61.43"   ' example of IP address
DIM h$(2)


' each line of a file sent to a PC print server must end with these characters:

cr$=CHR$(13)       ' carriage return character
lf$=CHR$(10)       ' line feed character


' interface object names

x$="guide"
y$="guide2"
n$="title"
o$="category"
p$="from"
q$="to"
pi$="from_in"
qi$="to_in"
qi2$="cover"


lf$=CHR$(10)
q$=CHR$(34)
cat=1          ' default category (angle)
invalue=1

upshift=7

'r'  conversion constants  
KwhPerYear=1000/(365.25*24)
MJperYear=1E6/(365.25*24*60*60)
''
' correction for iPad display only
IF rw=1 then shift=10

' correction for non-iPad display only
IF rw<1 then shift2=75

fm$="##,###,###,###,###,###,###.#######"    ' formats the result with commas
fm2$="####################.#######"      ' formats the result without commas


' number of measures in each category

cats=16
DIM cat$(cats)
angle=9
area=9
cook=9
curr=54
dat=8
energ=12
EnergyTrans=28
flow=17
leng=13
prefix=21
pow=14
press=13
spd=11
Tscales=8 ! Tscale$="Temperature"
timing=10
vol=12
wgt=10


' include constant 'Valuta' and 'currencies:' data
{currencies.data}



'b'============ Initialisation============
''
GRAPHICS
GRAPHICS CLEAR .9,1,1


 ' animate title if gif animation file exists

A$="iconvert3.GIF"
IF FILE_EXISTS(A$) THEN
  SPRITE N$ LOAD A$
  SPRITE N$ AT sw/3-shift2,sh/60+3*shift scale 1*rh
  SPRITE N$ SHOW
ELSE
  DRAW IMAGE "iconvert3.PNG" AT sw/2.8,sh/20 SCALE .8*rw
ENDIF
' read categories
RESTORE TO Categories

FOR t=1 TO cats
  READ cat$(t)
NEXT t

RESTORE TO angle     ' default category
items=angle
DIM measure$(items)
GOSUB setcategory


' create three lists

SET LISTS FONT SIZE 18*rw
LIST o$ TEXT cat$ AT sw*.1,260*rh SIZE 240*rw,310*rh
LIST o$ SELECT cat
LIST p$ TEXT measure$ AT sw*.385,260*rh SIZE 240*rw,310*rh
LIST p$ SELECT 1
LIST q$ TEXT measure$ AT sw*.672,260*rh SIZE 240*rw,310*rh
LIST q$ SELECT 1


' create fields and buttons

SET BUTTONS FONT SIZE 20*rw
DRAW COLOR 0,0,0
guide$="Pick from each list"&lf$&"Enter quantity here"
DRAW LINE sw*.26,168*rh TO sw*.392,168*rh
FILL COLOR 0,0,0
FILL CIRCLE sw*.39,168*rh SIZE 3*rw
FILL COLOR 1,1,1
FIELD x$ TEXT guide$ AT sw*.1,132*rh-upshift SIZE 250,60 RO ML
FIELD x$ FONT SIZE 18*rw
FIELD x$ BACK ALPHA 0
guide2$="All lists can be scrolled"
DRAW LINE sw*.096,618*rh TO sw*.38,618*rh
DRAW LINE sw*.63,618*rh TO sw*.91,618*rh
FIELD y$ TEXT guide2$ AT sw*.41,600*rh-upshift*.8 SIZE 250,60 RO ML
FIELD y$ FONT SIZE 18*rw
FIELD y$ BACK ALPHA 0
FIELD o$ TEXT "CATEGORY" AT sw*.115,210*rh SIZE 130,30 RO
FIELD o$ FONT SIZE 20*rw
FIELD o$ BACK ALPHA 0
FIELD p$ TEXT "FROM" AT sw*.405,210*rh SIZE 100,30 RO
FIELD p$ FONT SIZE 20*rw
FIELD p$ BACK ALPHA 0
FIELD q$ TEXT "TO" AT sw*.69,210*rh SIZE 70,30 RO
FIELD q$ FONT SIZE 20*rw
FIELD q$ BACK ALPHA 0
FILL ALPHA 0
BUTTON "copy" TEXT "COPY" AT 285*rw,650*rh SIZE 100*rw,50*rh
BUTTON "print" TEXT "PRINT" AT 405*rw,650*rh SIZE 100*rw,50*rh
BUTTON "save" TEXT "SAVE" AT 525*rw,650*rh SIZE 100*rw,50*rh
BUTTON "stop" TEXT "STOP" AT 645*rw,650*rh SIZE 100*rw,50*rh
FILL ALPHA 1
FIELD pi$ TEXT "1" AT sw*.400,150*rh SIZE 200*rw,30*rh
FIELD pi$ FONT SIZE 18*rw
FIELD qi$ TEXT "1" AT sw*.640,145*rh SIZE 280*rw,40*rh
FIELD qi$ FONT SIZE 22*rw
FIELD qi2$ TEXT "" AT sw*.640,145*rh SIZE 280*rw,40*rh RO
FIELD qi2$ BACK ALPHA 0
FILL COLOR .6,.8,.8
FILL RECT sw*.395,145*rh TO sw*.6,185*rh
FILL COLOR .8,.8,.8
FILL RECT sw*.635,140*rh TO sw*.92,190*rh
DRAW RECT sw*.1-1,258*rh TO sw*.1+240*rw+1,258*rh+312*rh
DRAW RECT sw*.386-2,258*rh TO sw*.386+240*rw,258*rh+312*rh
DRAW RECT sw*.673-2,258*rh TO sw*.673+240*rw,258*rh+312*rh

timer=time ()    ' set timer to stop title anim after one cycle


'b'========== main program loop ===================
''
DO

' play once, then stop animation

IF time()-timer>1 AND time()-timer <2 and not noplay THEN
  IF FILE_EXISTS(A$) THEN SPRITE N$ PLAY
  noplay=1
ENDIF
IF time()-timer>6 AND time()-timer <7 THEN
  IF FILE_EXISTS(A$) THEN SPRITE N$ STOP
ENDIF


' check which category is selected

type=LIST_SELECTED(o$)


' choose and prepare a new category if necessary

IF type<>cat THEN
  oldcat=cat
  cat=type
  changed=1

  ON cat GOTO 10,15,20,25,30,40,45,50,55,60,70,80,90,95,100,110,120
  10 RESTORE TO angle
     items=angle
     GOTO skip
  15 RESTORE TO area
     items=area
     GOTO skip
  20 RESTORE TO cooking
     items=cook
     GOTO skip
  25 RESTORE TO currencies
     if void then
       list o$ select oldcat
       type=oldcat
       gosub message
       goto skip2
     endif
     items=currencies
     GOTO skip
  30 RESTORE TO data
     items=dat
     GOTO skip
  40 RESTORE TO energy
     items=energ
     GOTO skip
  45 RESTORE TO EnergyTransition
     items=EnergyTrans
     GOTO skip
  50 RESTORE TO FlowRate
     items=flow
     GOTO skip
  55 RESTORE TO length
     items=leng
     GOTO skip
  60 RESTORE TO prefixes
     items=prefix
     GOTO skip
  70 RESTORE TO power
     items=pow
     GOTO skip
  80 RESTORE TO pressure
     items=press
     GOTO skip
  90 RESTORE TO speed
     items=SPD
     GOTO skip
  95 RESTORE TO Temperatures
     items=Tscales
     GOTO Skip
  100 RESTORE TO timing
     items=timing
     GOTO skip
  110 RESTORE TO volume
     items=vol
     GOTO skip
  120 RESTORE TO weight
     items=wgt
     GOTO skip

  skip:
  GOSUB setcategory
  LIST p$ TEXT measure$
  LIST p$ SELECT 1
  LIST q$ TEXT measure$
  LIST q$ SELECT 1
  FIELD pi$ TEXT "1"
  skip2:
ENDIF

IF LIST_SELECTED(p$)<>selp or LIST_SELECTED(q$)<>selq then changed=1


' calculate the conversion

if VAL(FIELD_TEXT$(pi$))<>invalue or changed then
  invalue=VAL(FIELD_TEXT$(pi$))
  selp=LIST_SELECTED(p$)
  selq=LIST_SELECTED(q$)
  GOSUB Convert ' calculate OutValue
  if outvalue<100000000 and outvalue>.000000001 then 
    out$=STR$(outvalue,fm$)
    out2$=STR$(outvalue,fm2$)
    format(out$)!out$=format.form$
    format(out2$)!out2$=format.form$
  else
    out$=STR$(outvalue)
  endif
  fsize=22*rw
  FIELD qi$ FONT SIZE fsize
  FIELD qi$ TEXT out$
  FIELD qi2$ TEXT ""
ENDIF

' copy the conversion info to clipboard

IF bp("copy") THEN
  GOSUB compile
  IF cp=0 THEN!CLIPBOARD CLEAR!cp=1!ENDIF
  CLIPBOARD WRITE convert$
  BEEP
ENDIF


' print the conversion info

IF bp("print") THEN
GOSUB compile
h$(1) = "content-type:text/html"   ' make header info
h$(2) = "content-length:" & LEN(convert$)

' print convert$ using Henko print technique
HTTP URL$ HEADER H$ POST convert$   ' send doc to the print server
BEEP
ENDIF


' save the conversion info to a file

IF bp("save") THEN
  GOSUB compile
  fname$="converted.txt"
  IF FILE_EXISTS(fname$) THEN FILE fname$ DELETE
  FILE fname$ WRITELINE convert$
  BEEP
ENDIF


' end the program

IF bp("stop") THEN
  IF laun$="desktop" THEN
    IF FILE_EXISTS("/launch") THEN
      RUN "/-Launch.sb"
    ELSE
      EXIT
    ENDIF
  ENDIF
  END
ENDIF
SLOWDOWN
UNTIL 0
END

'g'========== Subroutines and Functions =============

Convert:
'--- Convert via formula
'  temperature
IF Cat$(cat)=Tscale$ THEN
  Outvalue=FromCelsius(Celsius(Invalue,measureval(selp)),measureval(selq))
  RETURN
ENDIF
'--- Convert via ratio
  outvalue=invalue*1/(measureval(selq)/measureval(selp))
RETURN

' temperature conversion

DEF FromCelsius(Value,UnitPointer)
'Converts Value on 'Unit'-scale to Celsius-scale
'  to newvalue in scale of Unitpointer
ON UnitPointer GOTO 1,2,3,4,5,6,7,8
  1 RETURN Value 'Celsius
  2 RETURN Value+273.15 'Kelvin
  3 RETURN Value*9/5+32 'Fahrenheit
  4 RETURN (Value+273.15)*9/5 'Rankine
  5 RETURN (100-Value)*3/2 'Delisle
  6 RETURN Value*33/100 'Newton
  7 RETURN Value*4/5 'Réamur
  8 RETURN Value*21/40+7.5 'Rømer
END DEF
'
DEF Celsius(Value,UnitPointer)
'Converts Value in 'Unit' to new value in Celsius
ON UnitPointer GOTO 1,2,3,4,5,6,7,8
  1 RETURN Value 'Celsius
  2 RETURN Value-273.15 'Kelvin
  3 RETURN (Value-32)*5/9 'Fahrenheit
  4 RETURN (Value-491.67)*5/9 'Rankine
  5 RETURN 100-Value*2/3 'Delisle
  6 RETURN Value*100/33 'Newton
  7 RETURN Value*5/4 'Réamur
  8 RETURN (Value-7.5)*40/21 'Rømer
END DEF


' read the data for a category

setcategory:
DIM measure$(items)
FOR t=1 TO items
  READ measure$(t)
NEXT t
DIM measureval(items)
FOR t=1 TO items
  READ measureval(t)
NEXT t
RETURN


' prepare a string showing the conversion, for copying or saving to a file

compile:
  selp=LIST_SELECTED(p$)
  selq=LIST_SELECTED(q$)
  temp1$=measure$(selp)
  temp2$=measure$(selq)


  ' if a value is 1 or a fraction, change the name from plural to singular
  convin=val(FIELD_TEXT$(p$))
  temp1len=LEN(temp1$)
  IF convin=<1 AND RIGHT$(temp1$,1)="s" THEN temp1$=LEFT$(temp1$,temp1len-1)
  IF VAL(out2$)=<1 AND RIGHT$(temp2$,1)="s" THEN temp2$=LEFT$(temp2$,LEN(temp2$)-1)
  convert$&=FIELD_TEXT$(pi$)&" "&temp1$&" = "&FIELD_TEXT$(qi$)&" "&temp2$
  convert$&=cr$&lf$&FIELD_TEXT$(pi$)&" "&temp1$&" = "&out2$&" "&temp2$&cr$&lf$&cr$&lf$
RETURN


' message if user has not downloaded and run Update Currencies.sb

message:
a$="To use this category, please download the file Update Currencies.txt from the Forum at this link:"&lf$&lf$&"https://kibernetik.pro/forum/viewtopic.php?f=20&t=2280"&lf$&lf$&"Then run it. The next time you run iConvert, the Currency category will be functional."
' Example:
pw("notice","Notice!",a$,sw/2-200*rw,sh/4,400*rw,400*rw,1,1,1,1)
wait: SLOWDOWN
IF BUTTON_PRESSED("close") THEN
  PAGE pw.NAME$ HIDE ! PAGE "" SET
ELSE 
  GOTO wait
ENDIF
RETURN


' shortcut for button press

DEF bp(a$) = BUTTON_PRESSED(a$)


' remove scientific notation before displaying result

DEF format(form$)
  WHILE LEFT$(form$,1)=" " OR LEFT$(form$,1)=","
    form$=RIGHT$(form$,LEN(form$)-1)
    ' trim leading spaces and separators
  ENDWHILE
  IF INSTR (form$, ".") THEN        ' if form$ has a decimal point
    IF NOT numpad.curr THEN
    ' trim trailing zeros
    WHILE RIGHT$(form$,1)="0"
      form$=LEFT$(form$,LEN(form$)-1)
    ENDWHILE
    IF RIGHT$(form$,1)="." THEN
      form$=LEFT$(form$,LEN(form$)-1)
    ENDIF
    ENDIF
  ENDIF
END DEF

DEF pw(NAME$,title$,a$,xs,ys,ww,hh,R,G,B,ALPHA)
PAGE NAME$ SET
PAGE NAME$ SHOW
PAGE NAME$ FRAME xs,ys,ww,hh
PAGE NAME$ COLOR R,G,B,ALPHA
FIELD NAME$ TEXT a$ at 20*.rw,50*.rh size 380*.rw,360*.rh ML RO
BUTTON "close" title "❎" AT ww-30,5 SIZE 24*.rw,24*.rh
BUTTON "bottom" title "" AT -6,hh-3 SIZE ww+12,3
BUTTON "left" title "" AT 0,-6 SIZE 3,hh+12*.rh
BUTTON "right" title "" AT ww-3,-6 SIZE 3,hh+12*.rh
BUTTON "upper1" title "" AT -6,0 SIZE ww+12,3
BUTTON "upper2" title "" AT -6,30 SIZE ww+12,3
BUTTON "title" title title$ AT ww/2-50,3 SIZE 100*.rw,28*.rh
'
' other UI objects
'
'
END DEF
''

/*
Conversion Data

The technique I use to calculate conversions is to choose a reference measure in the middle of the range and set its value to 1. All other measures are then assigned numbers representing the ratio of their value to the reference measure's value.
*/

Categories:

DATA "Angle", "Area", "Cooking", "Currency "&CurrDate$ ,"Data", "Energy", "Energy Transition", "Flow Rate", "Length", "Prefixes", "Power", "Pressure", "Speed"
DATA Tscale$, "Time", "Volume", "Weight"

Angle:
DATA "Degrees", "Radians", "Gradians", "Minutes", "Seconds", "Circles", "Quadrants", "Points", "Mils"
DATA 1, 57.2957795128962, .9, .0166666666666667, .000277777777777778, 360, 90, 11.25, .05625

Area:
DATA "Acres", "Square Kilometers", "Hectares", "Square Meters", "Square Centimeters", "Square Miles", "Square Yards", "Square Feet", "Square Inches"
DATA 4046.85642, 1000000, 10000, 1, .0001, 2589988.110266, .8361273, .0929030, .000645159722

Cooking:
DATA "Centiliters", "Cups (CD)", "Fluid Ounces (CD)", "Liters", "Milliliters", "Pints (CD)", "Quarts (CD)", "Tablespoons", "Teaspoons"
DATA .35195,8,1,35.195079,.035195,20,40,.520421,.1734737

Data:
DATA "Bits", "Bytes", "Words", "Kilobytes", "Megabytes", "Gigabytes", "Terabytes", "Petabytes"
DATA .000125, .001, .008, 1, 1000, 1000000, 1000000000, 1000000000000

Energy:
DATA "BTU", "Calories", "Cubic Mile of Oil", "Foot Pounds", "Horsepower Per Hr", "Joules", "KiloJoules", "KiloCalories", "Kilowatt Hours", "Kilotons", "MegaJoules", "Therms (US)"
DATA 251.99576, 1, 38334721315564331336, .32404825, 641615.559278, .23900573, 239.00573, 1000, 860420.6501033, 999999974320, 239005.7299999, 25210420.65043

EnergyTransition:
DATA "Watt", "Kilowatt", "Kwh/y", "Kg/y Coal", "Kg/y Brown coal", "Kg/y Peat dry", "Kg/y Wood", "Kg/y Fat", "Kg Battery Li-Po, Li-Hv", "m² Solar panel", "Liter/y petrol", "Liter/y diesel oil", "Liter/y heating oil", "Liter/y Hydrogen 700bar", "Liter/y Alcohol", "Liter/y LNG", "Liter/y LPG", "Liter/day heating oil", "Liter/day LNG", "Liter/day LPG", "m³/y natural gas", "m³/y natural gas NL", "m³/y Hydrogen", "m³/day natural gas", "m³/day natural gas NL", "m³/day Hydrogen", "m³/day water to ice", "g/y Thorium"
DATA 1, 1000, 0.114077, 0.7465713, 0.4753213, 0.4753213, 0.4753213, 1.1724592, 0.0570386, 31.6564, 1.0837326, 1.2231602, 1.1819657, 0.2905798, 0.7415013, 0.7034755, 0.8143839, 431.713, 256.944, 297.454, 1.234251, 1.0583821, 0.5357, 450.81, 386.574, 195.664, 3865.74, 2516.6679

FlowRate:
DATA "Cubic Meters per Sec", "Cubic Meters per Min", "Cubic Meters per Hour", "Liters per Second", "Liters per Minute", "Liters per Hour", "Cubic Feet per Sec", "Cubic Feet per Minute", "Cubic Feet per Hour", "Gallons (US) per Sec", "Gallons (US) per Min", "Gallons (US) per Hour", "Gallons (US) per Day", "Gallons (UK) per Sec", "Gallons (UK) per Min", "Gallons (UK) per Hour", "Gallons (UK) per Day"
DATA 951019.38852, 15850.323142, 264.172052366667, 951.01938852, 15.850323142, 0.264172052366667, 26929.870147125, 448.83116911875, 7.48051948531251, 3600, 60, 1, .0416666666675429, 4323.41973193896, 72.0569955323167, 1.20094992556893, .0500395802310909

Length:
DATA "Ångströms","Centimeters", "Fathoms", "Feet", "Furlongs (US)", "Inches", "Kilometers", "Meters","Mils", "Miles", "Millimeters", "Nanometers", "Yards"
DATA .00000001, 1, 182.88, 30.48, 20116.8, 2.54, 100000, 100, .00254, 160934.39999, .1, .0000001, 91.44

Power:
DATA "Watts","Kilowatts", "Megawatts", "Gigawatts", "Terawatts", "KWh/year", "MegaJoule/year (MJ/y)","Horsepower (IT)", "Horsepower (Metric)", "Moosepower", "Calories per Hour", "BTU per Hour", "Foot Pounds per Hr", "Tons Refrigeration"
DATA 1,1000, 1E6, 1E9, 1E12, KwhPerYear,MJperYear,745.69987, 756.042476, 2438.4385749, 0.0011629, 2930710000, 3766160000, 3516.8

Prefixes:
DATA "yotta", "zetta", "exa", "peta", "tera", "giga", "mega", "kilo", "hecto", "deca", "none", "deci", "centi", "milli", "micro", "nano", "pico", "femto", "atto", "zepto", "yocto"
DATA 1000000000000000000000000, 1000000000000000000000, 1000000000000000000, 1000000000000000, 1000000000000, 1000000000, 1000000, 1000, 100, 10, 1, .1, .01, .001, .000001, .000000001, .000000000001, .000000000000001, .000000000000000001, .000000000000000000001, .000000000000000000000001

Pressure:
DATA "Bars", "Millibars", "Pascals", "HectoPascals", "KiloPascals", "MegaPascals", "Atmospheres", "Pounds per Sq. Foot", "Pounds per Sq. Inch", "Inches of Water", "Inches of Mercury", "Centimeters of Water", "Centimeters of Mercury"
DATA 1000, 1, .01, 1, 10, 10000, 1013.250099, .47880258, 68.947572, 2.490889, 33.864, .98066496, 13.332283459

Speed:
DATA "Feet per Second", "Feet per Minute", "Furlongs per Fortnight", "Inches per Second", "Kilometers per Hour", "Kilometers per Sec.", "Knots", "Miles per Hour", "Miles per Second", "Speed of Light", "Speed of Sound"
DATA 1.09728, .018288, .000598715, .09144, 1, 3600, 1.8519999, 1.609349, 5793.638399, 1079252848.794, 1225.0439999

Temperatures:
DATA "Celsius [°C]", "Delisle [°D]", "Fahrenheit [°F]", "Kelvin [K]", "Newton [°N]", "Rankine [°Ra]", "Réamur [°Re]", "Rømer [°Rø]"
DATA 1,5,3,2,6,4,7,8 ' unit-pointers

Timing:
DATA "Milliseconds", "Seconds", "Minutes", "Hours", "Days", "Weeks", "Fortnights", "Months", "Years", "Leap Years"
DATA .00001666666, .01666666, 1, 60, 1440, 10080, 20160, 43800, 525600, 527040

Volume:
DATA "Cubic Centimeters", "Cubic Feet", "Cubic Inches", "Cubic Yards", "Cups (CD)", "Fluid Ounces (CD)", "Gallons (CD)", "Gallons (US)", "Liters", "Milliliters", "Pints (CD)", "Quarts (CD)"
DATA 1,28316.84659,16.3871,764554,284.130625,28.4131,4546.08999,3785.411784,1000,1,568.26125,1136.5225

Weight:
DATA "Grams", "Kilograms", "Ounces", "Ounces (troy)", "Pounds", "Grains", "Tonnes (metric)", "Tons (US short)", "Long Tons (UK)", "Stones"
DATA .0022046226, 2.2046226, .0625, .0685714, 1, 10, 2204.62262184, 2000, 2240, 14

' this routine is used when adding a new category, until its data is entered.

TBA:
DATA "To Be Added","","","","","","","","",""
DATA 1,1,1,1,1,1,1,1,1,1
Attachments
B10B0EC2-4F52-43BE-90CE-6DB773E52011.png
B10B0EC2-4F52-43BE-90CE-6DB773E52011.png (288.42 KiB) Viewed 1585 times
Last edited by rbytes on Fri Nov 02, 2018 8:31 pm, edited 2 times in total.
Zzzzz

User avatar
Dutchman
Posts: 907
Joined: Mon May 06, 2013 9:21 am
My devices: iMac, iPad Air, iPhone
Location: Netherlands
Flag: Netherlands

Re: iConvert V3.3

Post by Dutchman » Fri Nov 02, 2018 11:17 am

I have another idea besides the comments that I have placed on https://kibernetik.pro/forum/viewtopic. ... 766#p13639
We could create a controlling 'master' program that starts "iConvert" after it has tested whether the necessary other files are present.
We consider it a refreshing mental exercise to figure out ways to circumvent foolishness (Quote from Richard)

User avatar
rbytes
Posts: 1963
Joined: Sun May 31, 2015 12:11 am
My devices: iPhone X
iPad 4
MacBook
Dell Inspiron laptop
CHUWI Plus 10 convertible Windows/Android tablet
Location: Calgary, Canada
Flag: Canada
Contact:

Re: iConvert V3.3

Post by rbytes » Fri Nov 02, 2018 2:09 pm

For my own purposes I modified a copy of Update Currencies to bypass all of the choices and hide the screen output, since I was just clicking "y" every time. The screen looks like this while the modified program is generating currencies.dat, with animated colored balls to indicate progress:

B04359D2-71F1-4FC6-8A4B-B3555C059C3C.png
B04359D2-71F1-4FC6-8A4B-B3555C059C3C.png (141.22 KiB) Viewed 1574 times
After finishing its work, it launches the iConvert program. Perhaps you could modify it further to test the currency website and print an error message if the information is unreadable. This program could be renamed iConvert Launch.

Please note - if variable "full" is set to 1, the interactive dialogue occurs. If it is set to 0, all questions and prompts are bypassed, and the data file is updated silently.

Here is the progress animation:
loader.GIF
loader.GIF (75.22 KiB) Viewed 1540 times

Code: Select all

'iConvert Launch
'Update currencies
'by Dutchman, october 2018
'modified by rbytes, october 2018
'Generate DATA-list for currency-conversion
'Launch iConvert
'
'==== Presets ====
SET ORIENTATION LANDSCAPE
SET TOOLBAR OFF
OPTION BASE 1
SET BROWSERS SCALED
GET SCREEN SIZE sw,sh
rw=sw/1024!rh=sh/768
GRAPHICS
GRAPHICS CLEAR .9,1,1
DRAW IMAGE "iconvert3.PNG" AT sw/3,sh/10 SCALE 1*rw
a$="Follow the prompts at screen top"
N$="anim"
Full=1    ' 1=interactive; 0=updates in background

'IF NOT full THEN
  A$="loader.GIF"
  IF FILE_EXISTS(A$) THEN
    SPRITE N$ LOAD A$
    SPRITE N$ AT sw/2.8,sh/3 scale 1*rw
    SPRITE N$ SHOW
    SPRITE N$ DELAY .05
    SPRITE N$ PLAY
  ENDIF
'ENDIF

' field to create black background behind FIELD "info"
FIELD "infob" TEXT "" AT sw/2-180*rw-3,sw/6-3 SIZE 350*rh+6,43*rh+3 ML RO
FIELD "infob" BACK COLOR 0,0,0

' information field
FIELD "info" TEXT a$ AT sw/2-180*rw,sw/6 SIZE 350*rw,40*rh ML RO
FIELD "info" FONT SIZE 20*rw
PAUSE 2
Test=0  ' don't ask
'
'==== Constants ======
Source$="https://www.x-rates.com/table/?from=USD&amount=1"
Count=100 ' max number of currencies
Top=sh/30 ' top space
Top$="In" ' Field for input
WebPage$="currencies.html" ' undated webpage filename

'==== Output variables
DIM Data$(count,2) ' array for extracted data
DataFile$="currencies.data" ' file with DATA-lines
'
'==== Main ====
Msg$="" ' message on exit
'
'--- Select and store source
GOSUB StoreSource
'
'---- Extract data from HTML-text
IF full THEN
  FIELD "infob" TEXT ""
  FIELD "info" TEXT " Extracting first table ..."
  FIELD "infob" SHOW
  FIELD "info" SHOW
  PAUSE 2
  FIELD "infob" HIDE
  FIELD "info" HIDE
ENDIF
ExtractData: ' from file
GOSUB ReadTableBody ' store HTML-table in 'Body$'
Msg$=""
CALL Extract(p1,p2, Body$)
IF Msg$<>"" THEN GOSUB Finish
'
'--- Sort and write to data-file
SPRITE N$ PLAY
CALL SortAndStore(DataFile$,Data$,Extract.count)
GOSUB FINISH
RUN "iConvert.sb"
END

'========== Subroutines and Functions ===========
Finish:
BROWSER "a" DELETE
IF full THEN
  FIELD "info" TEXT Msg$
  FIELD "infob" SHOW
  FIELD "info" SHOW
  PAUSE 2
ENDIF
FIELD top$ DELETE
FIELD "info" DELETE
FIELD "infob" DELETE
RETURN
'
DEF SortAndStore(File$,Data$(,),items)
Quicksort$(Data$,Extract.count,2,1)
IF FILE_EXISTS(File$) THEN FILE File$ DELETE
items+=1 'add 1 to include reference value US-dollar
FILE File$ PRINT "currencies="&items&" ' items in Currencies"
FILE File$ PRINT "CurrDate$="""&.DataDate$&""" ' download-date"
FILE File$ PRINT "Currencies:"
File File$ PRINT "DATA """&"US dollar"&"""";
FOR i=1 TO items-1
  File File$ PRINT ", """&.Data$(i,1)&"""";
NEXT i
File File$ PRINT
File File$ PRINT "DATA 1";
FOR i=1 TO items-1
  File File$ PRINT ", "&Data$(i,2);
NEXT i
File File$ SETPOS 0
.Msg$="Data written to """&File$&""""
END DEF
'
DEF Extract(first,last,a$)
'g'/* single item in HTML-text to parse:
<tr>
<td>Argentine Peso</td>
<td class='rtRates'><a href='… url …/?from=USD&amp;to=ARS'>36.446414</a></td>
<td class='rtRates'><a href='… url …/?from=ARS&amp;to=USD'>0.027438</a></td> 
</tr>
''*/

count=0
'--- Store HTML table-rows
p1=INSTR(a$,"<tr",first)
WHILE p1>0 AND count<.count
 p2=INSTR(a$,"/tr>",p1)
  first=p2 
  IF first>0 THEN
    count+=1
    .Data$(count,1)=SUBSTR$(a$,p1,p2)
  ENDIF
  p1=INSTR(a$,"<tr",first)
END WHILE
'--- Check table-size
IF count>=.count THEN
  FIELD "infob" TEXT ""
  FIELD "info" TEXT " Data-array is too small. Increase constant 'count'"
  FIELD "infob" SHOW
  FIELD "info" SHOW
  PAUSE 2
  FIELD "infob" HIDE
  FIELD "info" HIDE
  RETURN
ENDIF
'--- extract valuta and value
FOR i=1 TO count
  p1=INSTR(.Data$(i,1),"<td>",1)+4
  p2=INSTR(.Data$(i,1),"<",p1)-1
  Valuta$=SUBSTR$(.Data$(i,1),p1,p2)
  p1=INSTR(.Data$(i,1),"to=USD'>",p2)+8
  p2=INSTR(.Data$(i,1),"</a",p1)-1
  Value$= SUBSTR$(.Data$(i,1),p1,p2)
  .Data$(i,1)=Valuta$ ! .Data$(i,2)=Value$
NEXT i
END DEF
'
ReadTableBody:
'--- Extract date from filename
year$=CURRENT_YEAR()
year$=RIGHT$(year$,2)
hour$=CURRENT_HOUR()
if val(hour$)<10 then hour$="0"&hour$
min$=CURRENT_MINUTE()
if val(min$)<10 then min$="0"&min$
DataDate$=year$&" "&RIGHT$(TRIM$(web$),4)&" "&hour$&min$
'--- Find second table
IF full THEN
  FIELD "infob" TEXT ""
  FIELD "info" TEXT " Extracting second table ..."
  FIELD "infob" SHOW
  FIELD "info" SHOW
  PAUSE 2
  FIELD "infob" HIDE
  FIELD "info" HIDE
ENDIF
FILE Web$ SETPOS 0
Msg$="Second marker """&"tbody"&""" not found."
FOR i=1 TO 2
  DO
    FILE Web$ READLINE Line$
    IF Line$<>"" THEN p1=INSTR(Line$,"<tbody",1)
  UNTIL p1>0 OR FILE_END(Web$)
  IF FILE_END(web$) THEN GOSUB Finish ' Msg$ is preset
NEXT i
IF p1<1  THEN GOSUB Finish ' Msg$ is preset
'--- Read table-body
Body$=Line$
DO
  FILE web$ READLINE Line$
  Body$&=Line$
  p2=INSTR(Body$,"/tbody",1)
UNTIL FILE_END(web$) OR p2>0
Msg$&=" (no end-marker)"
IF p2<1 THEN GOSUB Finish ' Msg$ is preset
RETURN
'
StoreSource:
IF NOT full then shift=sh else shift=0    
BROWSER "a" AT 0,top-shift SIZE sw,sh-top
BROWSER "a" HIDE
Update=1
web$=LatestFile$(webpage$)
IF web$<>"" THEN
  IF Test THEN RETURN
  prompt$ ="Latest date: "
  prompt$&= LatestFile$.date$
  prompt$&=". Download new? (Y/N)"
  IF full=1 THEN
    DO 
      Answer$=TRIM$(LOWSTR$(Input$(0,0,sw,top,top$, prompt$)))
    UNTIL Answer$="y" OR Answer$="n"
  ELSE
    Answer$="y"
  ENDIF
  
  FIELD top$ DELETE
  IF Answer$="n" OR Test THEN
    Update=0
    FIELD "infob" TEXT ""
    Field "info" TEXT " Reading data ..."
    PAUSE 2
    BROWSER "a" SHOW
    BROWSER "a" TEXT PageContent$(web$)
  ELSE
    Update=1
 ENDIF
ENDIF

'----  Update webdata
IF Update THEN
  web$=webpage$&" "&ISO_date$
IF full THEN
  FIELD "infob" TEXT ""
  FIELD "info" TEXT " Loading webpage ..."
  FIELD "infob" SHOW
  FIELD "info" SHOW
  PAUSE 2
endif
  BROWSER "a" SHOW
  BROWSER "a" URL Source$
  if full then FIELD "info" TEXT " Webpage loaded ..."
ENDIF

Inspect:
  '---- Continue or stop
IF full THEN
  DO
    prompt$= "Continue? (Y/N)"
    Answer$=TRIM$(LOWSTR$(Input$(0,0,sw,top,top$, prompt$)))
  UNTIL Answer$="y" OR Answer$="n"
ELSE
  Answer$="y"
ENDIF

IF Answer$="n" THEN GOSUB Finish
FIELD top$ DELETE
'---- download binary contents
IF full THEN
  
  FIELD "infob" TEXT ""
  FIELD "info" TEXT " Scanning webpage ..."
  FIELD "infob" SHOW
  FIELD "info" SHOW
  PAUSE 2
  FIELD "infob" HIDE
  FIELD "info" HIDE
ENDIF
IF Update THEN
  HTTP Source$ GETDIM Bin
  FILE Web$ WRITEDIM Bin
ENDIF
RETURN

DEF LatestFile$(undated$) ' find latest datafile
File$=""
DIR "." LIST FILES A$,n
FOR i=1 TO n
  IF INSTR(a$(i),undated$,1)>0 THEN File$=a$(i)
NEXT i
Date$=RIGHT$(File$,8)
RETURN File$
END DEF

DEF ISO_Date$
Date$=STR$(CURRENT_YEAR()*10000+100*CURRENT_MONTH()+CURRENT_DATE(),"########")
ISO_Date$=Date$
END DEF ' ISO_Date$
'
DEF PageContent$(file$) ' read html-content
FILE file$ SETPOS 0
content$=""
WHILE NOT FILE_END(file$)
  FILE file$ READLINE line$
  content$&=Line$
END WHILE
RETURN content$
END DEF
'
DEF Input$(x,y,w,h,Field$,Prompt$)
' Inline input by Dutchman
GOSUB Init 'local subroutine
DO
 IF FIELD_CURSOR_POS(Field$)<prompt THEN FIELD Field$ TEXT Prompt$
 SLOWDOWN
UNTIL FIELD_CHANGED(Field$)
Txt$=FIELD_TEXT$(Field$)
T$=RIGHT$(Txt$,LEN(Txt$)-prompt)
RETURN T$

Init: ' local subroutine
FIELD Field$ AT x,y SIZE w,h
FIELD Field$ BACK COLOR 0,0,1
FIELD Field$ FONT NAME "Menlo"
FIELD Field$ FONT COLOR 1,1,0
FIELD Field$ FONT SIZE h-6
FIELD Field$ SELECT
prompt=LEN(Prompt$)
RETURN ' from subroutine
END DEF
'
DEF Quicksort$(Array$(,),MaxRow,Rowsize,SortColumn)' for STRINGS
' by Dutchman
' Non-recursive version of the QuickSort algorithm
' This sortfunction operates on a 2-dimensional string-array
' Number of rows is <MaxRow> and number of columns is <RowSize>
' The variable <SortColumn> determines which column is sorted
ShowMaxStack=0 ' will display stack-usage if set to 1
MaxStackPtr=0
DIM SwapRow$(RowSize), Stack1$(30), Stack2$(30)
StackPtr=0 ! HeadPtr=1 ! TailPtr=MaxRow
Qlabel2:
IF HeadPtr>TailPtr THEN
  GOTO Qlabel4
ELSE
  Pivot$= CAPSTR$(Array$((HeadPtr+TailPtr)/2,SortColumn))
  qa=HeadPtr ! qb=TailPtr
  Qlabel1:
  IF CAPSTR$(Array$(qa,SortColumn))<Pivot$ THEN ' while2
    qa=qa+1
    GOTO Qlabel1
  END IF '1
Qlabel3:   
  IF CAPSTR$(Array$(qb, SortColumn))>Pivot$ THEN
    qb=qb-1
    GOTO Qlabel3
  END IF '2
  IF qa<qb THEN
  ' swap rows
    FOR qi=1 TO RowSize
      SwapRow$(qi)=Array$(qa,qi)'save row qa
      Array$(qa,qi)=Array$(qb,qi)'store row qb content in row qa
      Array$(qb,qi)=SwapRow$(qi)'restore content of row qa to row qb
    NEXT qi
    qa=qa+1
    qb=qb-1
    GOTO Qlabel1
   END IF '3
  IF qa=qb THEN
    qq = qb - 1
    qr = qa + 1
  ELSE
    qq = qb
    qr = qa
  END IF '4
  StackPtr = StackPtr + 1
  IF MaxStackPtr<StackPtr THEN
    MaxStackPtr=StackPtr        
  END IF '5      
  qp=HeadPtr
  qs=TailPtr
  IF (qq-qp)<(qs-qr) THEN
    Stack1$(StackPtr)=qr
    Stack2$(StackPtr)=qs
    HeadPtr=qp
    TailPtr=qq
  ELSE
    Stack1$(StackPtr) = qp
    Stack2$(StackPtr) = qq
    HeadPtr = qr
    TailPtr = qs
  END IF '6
  GOTO Qlabel2
END IF '7
Qlabel4:
IF StackPtr > 0 THEN
  HeadPtr = Stack1$(StackPtr)
  TailPtr = Stack2$(StackPtr)
  StackPtr = StackPtr - 1
  GOTO Qlabel2
END IF '8
IF ShowMaxStack THEN
  PRINT "Maximum stacksize=";MaxStackPtr
END IF '9
END DEF ' QuickSort$
Last edited by rbytes on Fri Nov 02, 2018 9:18 pm, edited 1 time in total.
Zzzzz

matt7
Posts: 105
Joined: Sun Jul 12, 2015 5:00 pm
My devices: iPhone 8, Windows
Location: Kentucky, USA

Re: iConvert V3.3

Post by matt7 » Fri Nov 02, 2018 3:48 pm

Haven't posted yet on this but great job on this app. Very handy.

Maybe you could have the program not run the update currencies script until the "Currency" category is selected. That way you don't have to wait for that data to be retrieved every time you want to convert something. I would guess that for most people most of the time, they will be using the app for something else (a non-currency conversion).

User avatar
Dutchman
Posts: 907
Joined: Mon May 06, 2013 9:21 am
My devices: iMac, iPad Air, iPhone
Location: Netherlands
Flag: Netherlands

Re: iConvert V3.3

Post by Dutchman » Fri Nov 02, 2018 4:01 pm

There is already a possibility to run "Update currencies" without interactivity. Change the value of the 'Test' constant to 1 and the program will use the existing HTML file or generate one from the internet. I used it during testing. ;)
I can change the program so that the "currencies.data" file is updated if the HTML file has a certain age.
However, I do not know how to test whether the currency website still has the correct format. That's why I added the interactivity. :)
We consider it a refreshing mental exercise to figure out ways to circumvent foolishness (Quote from Richard)

User avatar
rbytes
Posts: 1963
Joined: Sun May 31, 2015 12:11 am
My devices: iPhone X
iPad 4
MacBook
Dell Inspiron laptop
CHUWI Plus 10 convertible Windows/Android tablet
Location: Calgary, Canada
Flag: Canada
Contact:

Re: iConvert V3.3

Post by rbytes » Fri Nov 02, 2018 4:45 pm

Thanks, Matt. Yes, I find iConvert very handy. I have an icon on my desktop now to run it.
Any conversion categories you would like to see?
Zzzzz

matt7
Posts: 105
Joined: Sun Jul 12, 2015 5:00 pm
My devices: iPhone 8, Windows
Location: Kentucky, USA

Re: iConvert V3.3

Post by matt7 » Fri Nov 02, 2018 5:47 pm

I downloaded and used the first version and haven't redownloaded it yet, but I have been following all the discussion and additions. Went to download the latest and it cannot find iconvert3.png. I looked through all the different threads and found the animated GIF but don't see a PNG. Is there a place where you have collected all the latest files so I don't have to go through every thread and post and reconstruct the latest version? Or is there a dropbox link that I missed?

User avatar
rbytes
Posts: 1963
Joined: Sun May 31, 2015 12:11 am
My devices: iPhone X
iPad 4
MacBook
Dell Inspiron laptop
CHUWI Plus 10 convertible Windows/Android tablet
Location: Calgary, Canada
Flag: Canada
Contact:

Re: iConvert V3.3

Post by rbytes » Fri Nov 02, 2018 8:23 pm

Thanks for pointing this out. I will add the image files to this post and to any other posts that need them.

Update: Those files are now attached to this version post (iConvert 3.3) and also to iConvert 3.2
Zzzzz

User avatar
Dutchman
Posts: 907
Joined: Mon May 06, 2013 9:21 am
My devices: iMac, iPad Air, iPhone
Location: Netherlands
Flag: Netherlands

Re: iConvert V3.3

Post by Dutchman » Fri Nov 02, 2018 10:00 pm

I have changed the program "Update currencies" at https://kibernetik.pro/forum/viewtopic. ... 649#p13649 so that it can be used from the conversion program "iConvert" without interruption:
• Test mode is changed to View mode. If View is non-zero then program is interactive. Default: 'View = 0'
• If "currencies.data" is not present, then 'View' becomes inactive if "currenciies.html <date>" is present. The porogram will then extract data from that html-file and generate "currencies.data". This is the test mode for data extraction.
• If both files, "currencies.data" and "currenciies.html <date>", are not present then 'View' becomes active and the conversion-program identified by 'Convert$' will be started after finishing.

So the program "iConvert" can refresh the "Currencies" category as follows:
• Be sure that the constant "Convert$" in "Update currencies" (on red background) has the correct name of "iConvert"
• Delete the files "currencies.data" and "currenciies.html <date>"
• Run "Update currencies". That will generate "currencies.data" and return to "iConvert"

Richard, I suggest that when you present the code, you add a note that
"Update currencies" https://kibernetik.pro/forum/viewtopic.php?f=20&t=2272 must first be run before iConvert is suitable for use.
We consider it a refreshing mental exercise to figure out ways to circumvent foolishness (Quote from Richard)

User avatar
rbytes
Posts: 1963
Joined: Sun May 31, 2015 12:11 am
My devices: iPhone X
iPad 4
MacBook
Dell Inspiron laptop
CHUWI Plus 10 convertible Windows/Android tablet
Location: Calgary, Canada
Flag: Canada
Contact:

Re: iConvert V3.3

Post by rbytes » Fri Nov 02, 2018 10:16 pm

I have another idea besides the comments that I have placed on https://kibernetik.pro/forum/viewtopic. ... 766#p13639 We could create a controlling 'master' program that starts "iConvert" after it has tested whether the necessary other files are present.
If you try the iConvert Launch (code on this page), you will see that we both followed your suggestion. I changed Update Currencies to iConvert Launch, gave it a new look that harmonizes with the main program, and a method of making it silent or interactive. And of course it launches iConvert after saving currencies.data. I used graphics rather than text mode to keep a consistent look with the main program.

So it seems we were both pursuing the same goal - a launcher. It is impossible for each of us to know what the other is working on at any given time, and no doubt mutually frustrating when we duplicate each other's efforts.

But I think it would be worth integrating our Update Currencies/iConvert Launch code in a way that preserves the functional changes you made and the interface design changes I made.

Which of us should do that? ;) I am willing to apply the screen/interface look to Update Currencies V2 if that is OK with you.
Zzzzz

Post Reply