Version:0.9 StartHTML:0000000105 EndHTML:0000072283 StartFragment:0000001053 EndFragment:0000072267 mXScriptasHTML
{ for the BlaisePascal Magazine #103 - opensource solution}
Unit Geocoding_mX47610_VII_WinAPIDownload41_Tripplaner;

//{$mode objfpc}{$H+}

interface

const
  AURLS='https://clients5.google.com/translate_a/t?client=dict-chrome-ex&sl=%s&tl=%s&q=%s';
  AURL='https://translate.googleapis.com/translate_a/single';
  UrlWeatherReport30= 'https://wttr.in/%s';     
  UAGENT ='Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/111.0';
  
const WeatherreportVT=
  '       .-.      Heavy rain, mist '
  +'     (   ).    +14(13) °C '
  +'    (___(__)   ? 9 km/h  '     
  +'    ‚‘‚‘‚‘‚‘    4 km  '         
  +'    ‚’‚’‚’‚’    0.3 mm  ' ;        

implementation
//{$R *.lfm}

type tlatlong = record
       lat, long: double;
       descript: string;
     end;  
                                                                       
function TAddressGeoCodeOSM(faddress: string): tlatlong;
var url, res, display: string;
  jo: TJSONObject; urlid: TIduri; winapi: TWinApiDownload;
 begin
  urlid:= TIdURI.create('');
  url:= urlid.URLEncode('https://nominatim.openstreetmap.org/search?format=json&q='+
                                                                fAddress);
  writeln(url)
  winapi:= TWinApiDownload.create;
  winapi.useragent:= 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1'; 
  winapi.url:= url;
  writeln('check url: '+itoa(winapi.CheckURL(url)));      
  winapi.download1(res);
  if (res <> '') and (res <> '[]') then begin
   //windown.OnWorkStart
   StrReplace(res, '[{', '{');
   jo:= TJSONObject.create4(res);
   try
     if jo.getString('place_id') <> ' ' then               
       display:= jo.getstring('display_name');
     result.descript:= Format('Coords: lat %2.5f  lng %2.5f %s importance: %2.4f',
                             [jo.getdouble('lat'),jo.getdouble('lon'),display,
                                                  jo.getdouble('importance')]); 
     result.lat:= jo.getdouble('lat'); 
     result.long:= jo.getdouble('lon');                                     
   except
     writeln('E: '+ExceptiontoString(exceptiontype, exceptionparam));                 
   finally                                  
     jo.Free;    
     urlid.free;
     winapi.free;
   end; 
  end else showmessagebig('geo location not found! ');
end;  

function TAddressGeoCoding4(faddr, fcountry: string): string;
var Url,API_KEY, source: string;
  jo, locate: TJSONObject;
  urlid: TIdURI; 
  fLat,fLong: double;  
begin
  urlid:= TIdURI.create('');
  API_KEY:='785b4141b...................'; //get your own one please
  if fcountry <> '' then
    Url:= urlid.URLEncode('https://api.geocod.io/v1.7/geocode?q='+
                          fAddr+'&country='+fcountry+'&api_key='+API_KEY) else
    Url:= urlid.URLEncode('https://api.geocod.io/v1.7/geocode?q='+
                          fAddr+'&api_key='+API_KEY);                                      
  jo:= TJSONObject.Create4(wdc_WinInet_HttpGet2(Url,Nil));
  try
    jo.getString('input')
    locate:= jo.getJSONArray('results').getJSONObject(0).getJSONObject('location');
    source:= jo.getJSONArray('results').getJSONObject(0).getString('source');
    //geometry.getJSONObject('coordinates');
    flat:= locate.getDouble('lat') 
    fLong:= locate.getDouble('lng');
    result:=Format('Coordinates: lat %2.3f lng %2.3f :%s',[flat,flong,source]);
  except
    Xraise(Exception.Create(jo.getString('json error')));
  finally                                      
    jo.Free;       
    urlid.free;
  end;  
end;  

function Text_to_traslate_API2(AURL, aclient,langorig,langtarget,atext: string):string;
var httpq: THttpConnectionWinInet;
    rets: TStringStream;  
    heads: TStrings; iht:IHttpConnection2; 
    jo: TJSON; jarr:TJsonArray2; jobj: TJsonObject2;
    tmpstr: string; 
begin
  httpq:= THttpConnectionWinInet.Create(true); 
  rets:= TStringStream.create('');
  heads:= TStringlist.create;     
   try
     {heads.add('client='+aclient);
     heads.add('sl=auto');
     heads.add('tl='+ langTarget); }
     heads.add('User-Agent='+UAGENT);
     iht:= httpq.setHeaders(heads);
     //iht:= httpq.setParameters(heads);
     httpq.Get(Format(AURLS,[langorig,langtarget,atext]),rets);
     writeln('server: '+Httpq.GetResponseHeader('server'));
     //writeln(Httpq.GetResponseHeader('pragma'));  
     //tmpstr:= StringReplace(rets.datastring, '[','{[',[rfReplaceAll, rfIgnoreCase]);  
      jo:= TJSON.Create(); 
      jo.parse(rets.datastring)   
      jarr:= jo.JsonArray;
      //writeln(jarr.items[0].stringify);
      if httpq.getresponsecode=200 Then result:=jarr[0].stringify
       else result:='Failed:'+
             itoa(Httpq.getresponsecode)+Httpq.GetResponseHeader('message');    
   except 
      writeln('EWI_HTTP: '+ExceptiontoString(exceptiontype,exceptionparam));
   finally
     //httpq.free;
     httpq:= Nil;
     heads.Free;
     rets.Free;
     jo.free;
   end;                  
end; 

var WebBrowser1: TWebBrowser;

procedure loadWebform;
var Form1:  TForm;
begin
 Form1:= TForm.create(self);
 with form1 do begin
  SetBounds(76,46,1100, 700)
  Caption:= 'maXbox4 WinControlWebBrowserFeed_WeatherReport'
  Color:= clBtnFace
  Font.Charset:= DEFAULT_CHARSET
  Font.Color:= clWindowText
  Font.Name:= 'MS Sans Serif'
  Font.Style:= []
  OldCreateOrder := False
  //OnShow := @TForm1FormShow;
  PixelsPerInch:= 96
  WebBrowser1:= TWebBrowser.create(form1);
  with webbrowser1 do begin
    TWinControl(WebBrowser1).Name:= 'MyWebBrowser1';
    //TWinControl(WebBrowser1).loadfromstream('MyWebBrowser1');
    TWinControl(WebBrowser1).Parent:= form1;
    TWinControl(WebBrowser1).setbounds(20,24,962,441)
    TWinControl(WebBrowser1).color:= clblack;
    TWinControl(WebBrowser1).Align:= alClient;
    Silent:= True;
    //EmbeddedWB1.HostCSS:= FmtCSS;
    //WebBrowser1.OleObject.Document.bgColor := '#000000';
    //(WebBrowser1.Document as TWinControl).Color := clblack;
     Color:=  clblack; //'#000000';
    TabOrder:= 0
    end;
   end;
 form1.show;
end; 

var latlong: tLatlong; atext: string;

begin  //@main
  writeln('CPUSpeed '+cpuspeed);
 //the hash to trash smash
  maXcalcf('2^160'); maXcalcf('16^40');
  //latlong:=  TAddressGeoCodeOSM('Krumauerstrasse, Klagenfurt, Austria'); 
  latlong:=  TAddressGeoCodeOSM('Gereonswall 66, Cologne, Germany');
  writeln('res back_: '+latlong.descript);
  writeln('get geocord: '+flots(latlong.lat)+'   '+flots(latlong.long));  
  OpenWeb('https://www.latlong.net/c/?lat='+flots(latlong.lat)+'&long='+flots(latlong.long));
  
  loadWebform;     
   //WebBrowser1.Navigate('file://c:/maxbox/lazarus/rssweather.htm');
  WebBrowser1.Navigate('https://wttr.in/Cologne');
  
  atext:= urlencode('A research paper at cologne suggests improving GPT-4 performance by 30% by having it consider why it was wrong.');
  
  writeln(utf8ToAnsi(Text_to_traslate_API2(AURL,'dict-chrome-ex','auto','it',atext)));

 end.
End.

ref:
 {hnd:=InternetOpen('Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; InfoPath.1)',
            INTERNET_OPEN_TYPE_PRECONFIG, '','',1);  }
    //https://stackoverflow.com/questions/17121143/how-to-stop-script-errors-in-twebbrowser-in-delphi
    
 //ANSI A for the terminal;
   memo2.font.size:= 12;  
   memo2.font.name:= 'Lucida console';  
   pngStream:= TMemoryStream.Create;
   //vURL:= 'https://wttr.in/Cologne?A';
      vURL:= 'https://wttr.in/Bern?A';
    try
      HTTPget(vURL, pngStream)
    except
      showmessage('E.message')
    end 
    writeln(UTF8toAnsi(streamtoString3(pngStream))); 
   pngStream.Free;
   
   ComTerminal:= TCustomComTerminal.create(self);
   EditComTerminal(comterminal); 
   
  
 TWinApiDownload = class(TObject)
  private
    fEventWorkStart : TEventWorkStart;
    fEventWork : TEventWork;
    fEventWorkEnd : TEventWorkEnd;
    fEventError : TEventError;
    fURL : string;
    fUserAgent : string;
    fStop : Boolean;
    fActive : Boolean;
    fCachingEnabled : Boolean;
    fProgressUpdateInterval : Cardinal;
    function GetIsActive : Boolean;
  public
    constructor Create;
    destructor Destroy; override;
    function CheckURL(aURL: string) : Integer;
    function Download(Stream : TStream) : Integer; overload;
    function Download(var res : string) : Integer; overload;
    function ErrorCodeToMessageString(aErrorCode : Integer) : string;
    procedure Stop;
    procedure Clear;
    property UserAgent : string read fUserAgent write fUserAgent;
    property URL : string read fURL write fURL;
    property DownloadActive : Boolean read GetIsActive;
    property CachingEnabled : Boolean read fCachingEnabled write fCachingEnabled;
    property UpdateInterval:Cardinal read fProgressUpdateInterval write fProgressUpdateInterval;
    property OnWorkStart : TEventWorkStart read fEventWorkStart write fEventWorkStart;
    property OnWork : TEventWork read fEventWork write fEventWork;
    property OnWorkEnd : TEventWorkEnd read fEventWorkEnd write fEventWorkEnd;
    property OnError : TEventError read fEventError write fEventError;
  end;
  
  TEventWorkStart;
  TEventWork = procedure(Sender: TObject; iBytesTransfered: Int64) of object;
  TEventWorkEnd = procedure(Sender: TObject; iBytesTransfered: Int64;
                             ErrorCode: Integer) of object;
  TEventError = procedure(Sender : TObject; iErrorCode : Integer;
                         sURL : string) of object;
  
  
constructor TWinApiDownload.Create;
begin
  inherited;
  fUserAgent:= 'Mozilla/5.001(windows; U; NT4.0; en-US; rv:1.0) Gecko/25250101';
  fProgressUpdateInterval:= 100;
  fCachingEnabled:= True;
  fStop:= False;
  fActive:= False;
end;


-----_____
                   _____------           __      ----_
            ___----             ___------              \
               ----________        ----                 \
                           -----__    |             _____)
                                __-                /     \
                    _______-----    ___--          \    /)\
              ------_______      ---____            \__/  /
                           -----__    \ --    _          /\
                                  --__--__     \_____/   \_/\
                                          ----|   /          |
                                              |  |___________|
                                              |  | ((_(_)| )_)
                                              |  \_((_(_)|/(_)
                                              \             (
                                               \_____________)


https://dateandtime.info/citycoordinates.php?id=2661552
https://api.geocod.io/v1.7/geocode?q=cologne&api_key=785b4141b66646f4f421e5216e611b4e611f215
https://www.geocod.io/docs/?python#geocoding
https://github.com/Geocodio/openapi-spec/blob/master/geocodio-api.yml
tests online:
https://www.geoapify.com/geocoding-api

Geocodio provides bulk geocoding and reverse lookup services through a REST API. The API is able to process a single address, as well as handle bulk requests of up to 10,000 addresses. Geocoded results are returned with an accuracy score indicating the confidence Geocodio has in the accuracy of the result. Geocodio is also able to parse addresses into individual components.

Geographic coordinates of Delphi, Greece
Latitude: 38°28'45" N
Longitude: 22°29'36" E
Elevation above sea level: 560 m =  ft

Geographic coordinates of Bern, Switzerland
Latitude: 46°56'53" N
Longitude: 7°26'50" E
Elevation above sea level: 549 m = 1801 ft

geo(address = c("Tokyo, Japan", "Lima, Peru", "Nairobi, Kenya"),
 method = 'osm')
#> Passing 3 addresses to the Nominatim single address geocoder
#> Query completed in: 3 seconds
#> # A tibble: 3 × 3
#>   address           lat  long
#>   <chr>           <dbl> <dbl>
#> 1 Tokyo, Japan    35.7  140. 
#> 2 Lima, Peru     -12.1  -77.0
#> 3 Nairobi, Kenya  -1.28  36.8