diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..af94e9d --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +**/Objects +**/AutoBackups \ No newline at end of file diff --git a/DBRequestManager.bas b/DBRequestManager.bas new file mode 100644 index 0000000..3885b7f --- /dev/null +++ b/DBRequestManager.bas @@ -0,0 +1,272 @@ +B4A=true +Group=Default Group +ModulesStructureVersion=1 +Type=Class +Version=6.8 +@EndOfDesignText@ +'Class module +' Requiere RandomAccessFile, CompressStrings, ByteConverter y OkhttpUtils2 +Sub Class_Globals + Private mTarget As Object + Type DBResult (Tag As Object, Columns As Map, Rows As List) + Type DBCommand (Name As String, Parameters() As Object) + Private link As String + Private bc As ByteConverter + Private T_NULL = 0, T_STRING = 1, T_SHORT = 2, T_INT = 3, T_LONG = 4, T_FLOAT = 5 _ + ,T_DOUBLE = 6, T_BOOLEAN = 7, T_BLOB = 8 As Byte + Private VERSION As Float = 0.9 + Private tempArray(1) As Object + Dim jobTagAnterior As String = "" 'Mod por CHV - 211109 +End Sub + +'Target - The module that handles JobDone (usually Me). +'ConnectorLink - URL of the Java server. +Public Sub Initialize (Target As Object, ConnectorLink As String) + mTarget = Target + link = ConnectorLink +End Sub + +'Sends a query request. +'Command - Query name and parameters. +'Limit - Maximum rows to return or 0 for no limit. +'Tag - An object that will be returned in the result. +'Timeout - The http request timeout in ms, or 0 if default (30 secs) +Public Sub ExecuteQuery(Command As DBCommand, Limit As Int, Tag As Object, Timeout As Int) 'Mod por CHV, agregué el parametro Timeout - 211229 + Dim j As HttpJob + Dim ms As OutputStream + Dim out2 As OutputStream = StartJob(j,ms, Tag) + WriteObject(Command.Name, out2) + WriteInt(Limit, out2) + WriteList(Command.Parameters, out2) + out2.Close + j.PostBytes(link & "?method=query", ms.ToBytesArray) + If Timeout <> 0 Then j.GetRequest.Timeout = Timeout +End Sub + +'Executes a batch of (non-select) commands. +'ListOfCommands - List of the commands that will be executes. +'Tag - An object that will be returned in the result. +Public Sub ExecuteBatch(ListOfCommands As List, Tag As Object) + Dim j As HttpJob + Dim ms As OutputStream + Dim out2 As OutputStream = StartJob(j,ms, Tag) + WriteInt(ListOfCommands.Size, out2) + For Each Command As DBCommand In ListOfCommands + WriteObject(Command.Name, out2) + WriteList(Command.Parameters, out2) + Next + out2.Close + j.PostBytes(link & "?method=batch", ms.ToBytesArray) +End Sub + +'Similar to ExecuteBatch. Sends a single command. +Public Sub ExecuteCommand(Command As DBCommand, Tag As Object) + ExecuteBatch(Array As DBCommand(Command), Tag) +End Sub + +Private Sub StartJob(j As HttpJob, MemoryStream As OutputStream, Tag As Object) As OutputStream + j.Initialize("DBRequest", mTarget) + j.Tag = Tag + MemoryStream.InitializeToBytesArray(0) + Dim compress As CompressedStreams + Dim out As OutputStream = compress.WrapOutputStream(MemoryStream, "gzip") + WriteObject(VERSION, out) + Return out +End Sub + +Private Sub WriteList(Parameters As List, out As OutputStream) + Dim data() As Byte + If Parameters = Null Or Parameters.IsInitialized = False Then + Dim Parameters As List + Parameters.Initialize + End If + data = bc.IntsToBytes(Array As Int(Parameters.Size)) + out.WriteBytes(data, 0, data.Length) + For Each o As Object In Parameters + WriteObject(o, out) + Next +End Sub + +Private Sub WriteObject(o As Object, out As OutputStream) + Dim data() As Byte + tempArray(0) = o + If tempArray(0) = Null Then + out.WriteBytes(Array As Byte(T_NULL), 0, 1) + Else If tempArray(0) Is Short Then + out.WriteBytes(Array As Byte(T_SHORT), 0, 1) + data = bc.ShortsToBytes(Array As Short(o)) + Else If tempArray(0) Is Int Then + out.WriteBytes(Array As Byte(T_INT), 0, 1) + data = bc.IntsToBytes(Array As Int(o)) + Else If tempArray(0) Is Float Then + out.WriteBytes(Array As Byte(T_FLOAT), 0, 1) + data = bc.FloatsToBytes(Array As Float(o)) + Else If tempArray(0) Is Double Then + out.WriteBytes(Array As Byte(T_DOUBLE), 0, 1) + data = bc.DoublesToBytes(Array As Double(o)) + Else If tempArray(0) Is Long Then + out.WriteBytes(Array As Byte(T_LONG), 0, 1) + data = bc.LongsToBytes(Array As Long(o)) + Else If tempArray(0) Is Boolean Then + out.WriteBytes(Array As Byte(T_BOOLEAN), 0, 1) + Dim b As Boolean = 0 + Dim data(1) As Byte + If b Then data(0) = 1 Else data(0) = 0 + Else If GetType(tempArray(0)) = "[B" Then + data = o + out.WriteBytes(Array As Byte(T_BLOB), 0, 1) + WriteInt(data.Length, out) + Else 'If o Is String Then (treat all other values as string) + out.WriteBytes(Array As Byte(T_STRING), 0, 1) + data = bc.StringToBytes(o, "UTF8") + WriteInt(data.Length, out) + End If + If data.Length > 0 Then out.WriteBytes(data, 0, data.Length) +End Sub + +Private Sub ReadObject(In As InputStream) As Object + Dim data(1) As Byte + In.ReadBytes(data, 0, 1) + Select data(0) + Case T_NULL + Return Null + Case T_SHORT + Dim data(2) As Byte + Return bc.ShortsFromBytes(ReadBytesFully(In, data, data.Length))(0) + Case T_INT + Dim data(4) As Byte + Return bc.IntsFromBytes(ReadBytesFully(In, data, data.Length))(0) + Case T_LONG + Dim data(8) As Byte + Return bc.LongsFromBytes(ReadBytesFully(In, data, data.Length))(0) + Case T_FLOAT + Dim data(4) As Byte + Return bc.FloatsFromBytes(ReadBytesFully(In, data, data.Length))(0) + Case T_DOUBLE + Dim data(8) As Byte + Return bc.DoublesFromBytes(ReadBytesFully(In, data, data.Length))(0) + Case T_BOOLEAN + Dim b As Byte = ReadByte(In) + Return b = 1 + Case T_BLOB + Dim len As Int = ReadInt(In) + Dim data(len) As Byte + Return ReadBytesFully(In, data, data.Length) + Case Else + Dim len As Int = ReadInt(In) + Dim data(len) As Byte + ReadBytesFully(In, data, data.Length) + Return BytesToString(data, 0, data.Length, "UTF8") + End Select +End Sub + +Private Sub ReadBytesFully(In As InputStream, Data() As Byte, Len As Int) As Byte() + Dim count = 0, read As Int + Do While count < Len And read > -1 + read = In.ReadBytes(Data, count, Len - count) + count = count + read + Loop + Return Data +End Sub + +Private Sub WriteInt(i As Int, out As OutputStream) + Dim data() As Byte + data = bc.IntsToBytes(Array As Int(i)) + out.WriteBytes(data, 0, data.Length) +End Sub + +Private Sub ReadInt(In As InputStream) As Int + Dim data(4) As Byte + Return bc.IntsFromBytes(ReadBytesFully(In, data, data.Length))(0) +End Sub + +Private Sub ReadByte(In As InputStream) As Byte + Dim data(1) As Byte + In.ReadBytes(data, 0, 1) + Return data(0) +End Sub + +'Handles the Job result and returns a DBResult. +Public Sub HandleJob(Job As HttpJob) As DBResult + Dim start As Long = DateTime.Now 'ignore + Dim In As InputStream = Job.GetInputStream + Dim cs As CompressedStreams + In = cs.WrapInputStream(In, "gzip") + Dim serverVersion As Float = ReadObject(In) 'ignore + Dim method As String = ReadObject(In) + Dim table As DBResult + table.Initialize + table.Columns.Initialize + table.rows.Initialize + table.Tag = Job.Tag + If jobTagAnterior <> Job.Tag Then Log("HandleJob: '"&Job.Tag&"'") 'Mod por CHV - 211109 + jobTagAnterior = Job.Tag 'Mod por CHV - 211109 + If method = "query" Then + Dim numberOfColumns As Int = ReadInt(In) + For i = 0 To numberOfColumns - 1 + table.Columns.Put(ReadObject(In), i) + Next + Do While ReadByte(In) = 1 + Dim rowObjects(numberOfColumns) As Object + table.rows.Add(rowObjects) + For col = 0 To numberOfColumns - 1 + Dim o As Object = ReadObject(In) + rowObjects(col) = o + Next + Loop + Else If method = "batch" Then + table.Columns.Put("AffectedRows", 0) + Dim rows As Int = ReadInt(In) + For i = 0 To rows - 1 + table.rows.Add(Array As Object(ReadInt(In))) + Next + End If + In.Close +' Log("HandleJob: " & (DateTime.Now - start))'Comentado por CHV - 211112 + Return table +End Sub +'Reads a file and returns the file as a bytes array. +Public Sub FileToBytes(Dir As String, FileName As String) As Byte() + Dim out As OutputStream + out.InitializeToBytesArray(0) + Dim In As InputStream = File.OpenInput(Dir, FileName) + File.Copy2(In, out) + out.Close + Return out.ToBytesArray +End Sub +'Converts an image to a bytes array (for BLOB fields). +'Public Sub ImageToBytes(Image As Bitmap) As Byte() +' Dim out As OutputStream +' out.InitializeToBytesArray(0) +' Image.WriteToStream(out, 100, "JPEG") +' out.Close +' Return out.ToBytesArray +'End Sub +''Converts a bytes array to an image (for BLOB fields). +'Public Sub BytesToImage(bytes() As Byte) As Bitmap +' Dim In As InputStream +' In.InitializeFromBytesArray(bytes, 0, bytes.Length) +' Dim bmp As Bitmap +' bmp.Initialize2(In) +' Return bmp +'End Sub +'Prints the table to the logs. +Public Sub PrintTable(Table As DBResult) + Log("Tag: " & Table.Tag & ", Columns: " & Table.Columns.Size & ", Rows: " & Table.Rows.Size) + Dim sb As StringBuilder + sb.Initialize + For Each col In Table.Columns.Keys + sb.Append(col).Append(TAB) + Next + Log(sb.ToString) + For Each row() As Object In Table.Rows + Dim sb As StringBuilder + sb.Initialize + For Each record As Object In row + sb.Append(record).Append(TAB) + Next +' ToastMessageShow(sb.ToString, True) + Next +End Sub + + \ No newline at end of file diff --git a/GuessMyNumber.bas b/GuessMyNumber.bas new file mode 100644 index 0000000..27df738 --- /dev/null +++ b/GuessMyNumber.bas @@ -0,0 +1,36 @@ +B4J=true +Group=Default Group +ModulesStructureVersion=1 +Type=Class +Version=2.18 +@EndOfDesignText@ +'Class module +Sub Class_Globals +End Sub + +Public Sub Initialize + +End Sub + +Sub Handle(req As ServletRequest, resp As ServletResponse) + Try + If req.GetSession.HasAttribute("myNumber") = False Then + req.GetSession.SetAttribute("myNumber", Rnd(0, 101)) + End If + Dim myNumber As Int = req.GetSession.GetAttribute("myNumber") + Dim n As String = req.GetParameter("number") + If IsNumber(n) = False Then + resp.Write("Please enter a valid number.") + Else + If n > myNumber Then + resp.Write("My number is smaller.") + Else If n < myNumber Then + resp.Write("My number is larger.") + Else + resp.Write("Well done!!!") + End If + End If + Catch + resp.SendError(500, "error....") + End Try +End Sub \ No newline at end of file diff --git a/Mapa.bas b/Mapa.bas new file mode 100644 index 0000000..e54a899 --- /dev/null +++ b/Mapa.bas @@ -0,0 +1,196 @@ +B4J=true +Group=Default Group +ModulesStructureVersion=1 +Type=Class +Version=10 +@EndOfDesignText@ +'Class module +Sub Class_Globals + Private mreq As ServletRequest 'ignore + Private mresp As ServletResponse 'ignore +' Dim cmd As DBCommand + Dim getHash As CalculateHash + Dim js As JSONGenerator +End Sub + +Public Sub Initialize + +End Sub + +'Resumable Subs (wait for / sleep) in server handlers +'Resumable subs can only work when there is a message queue. +'By default, server handlers end when the Handle sub is completed. They do not create a message loop. +'If you want to wait for an event then you need to call StartMessageLoop and later StopMessageLoop. +'https://www.b4x.com/android/forum/threads/resumable-subs-wait-for-sleep-in-server-handlers.81833/ +Sub Handle(req As ServletRequest, resp As ServletResponse) + Log("##################################################") + Log("############# Mapa/Handle ################") + Log("##################################################") +' Log("q='"&req.GetParameter("q")&"'") +' Log($"REQ: ${req.FullRequestURI}"$) + Private elHash As String = getHash.CalculateTheHash(req.FullRequestURI) +' Log(elHash) + Private ruta As String = req.GetParameter("r") + Private almacen As String = req.GetParameter("a") + Private coords As String = req.GetParameter("c") + Private matriz As String = req.GetParameter("m") + If matriz <> "" And matriz <> "OSRM" Then matriz = "" +' Log($"r: ${ruta}, a: ${almacen}, Coords: ${coords}"$) + Private urlParams As Map + If ruta <> "" And almacen <> "" And coords <> "" Then + ruta = "R" & ruta + urlParams.Initialize + urlParams.Put("almacen", almacen) + urlParams.Put("coords", coords) + urlParams.Put("hash", elHash) + urlParams.Put("ruta", ruta) + Main.db.InitializeSQLite(File.DirApp, "kmt.db", True) + +' Si no existe la tabla del ruteo, la creamos. + If Not(checkIfTableExists($"${ruta}A${almacen}_${elHash}_punteo"$)) Then + Log($"Creamos tablas ruta ${ruta}, almacen ${almacen}"$) + Main.creaTablas(urlParams) + generaMatrizRuteoTiempos($"${ruta}A${almacen}_${elHash}"$, resp, ruta, almacen, matriz) + StartMessageLoop + Else 'Si ya existe, solo calculamos los tiempos y distancias. + tiempos($"${ruta}A${almacen}_${elHash}"$, resp, ruta, almacen, matriz) + StartMessageLoop + End If + Else + resp.ContentType = "text/html" + resp.Write("Hay un error en la solicitud, son necesarios los parametros:
* r - La ruta
* a - El almacen
* c - id_cliente,lon,lat separadas por punto y coma.
* m - La matriz a usar LOCAL u OSRM (Opcional, default local)") 'this file will be loaded from the www folder + End If +End Sub + +Sub generaMatrizRuteoTiempos(r As String, resp As ServletResponse, ruta As String, almacen As String, matriz As String) As ResumableSub + Log("############################################################################") + Log("############# Mapa/generaMatrizRuteoTiempos ########################") + Log("############################################################################") + 'Generamos la matriz + If matriz = "OSRM" Then + Wait for(Main.generaMatrizOSRM(r)) Complete (Result As Int) + Else + Main.generaMatrizLocal(r) + End If + 'Generamos el ruteo + Main.ruteo($"${r}"$, matriz) +' Wait for(Main.tiempos($"${r}"$)) Complete (Result As Int) +' Private ts As Map = Main.ts.Get($"${r}"$) +' Log(ts) + Private p As ResultSet = Main.db.ExecQuery($"select * from ${r}_punteo"$) + Private listCoords As String = "" + 'Ponemos el id de la tienda y las coordenadas en una lista para regresarla en un JSON. + Do While p.NextRow + If listCoords = "" Then + listCoords = $"${p.GetString("lon")},${p.GetString("lat")}"$ + Else + listCoords = $"${listCoords}:${p.GetString("lon")},${p.GetString("lat")}"$ + End If + Loop + Main.db.Close + StopMessageLoop + resp.ContentType = "text/html" + + resp.Write($"Mapa"$) + Return 1 +End Sub + +Sub tiempos(r As String, resp As ServletResponse, ruta As String, almacen As String, matriz As String) As ResumableSub + Log("############################################################") + Log("############# Mapa/tiempos ########################") + Log("###########################################################") + Private p As ResultSet = Main.db.ExecQuery($"select * from ${r}_punteo"$) + Private listCoords As String = "" + Do While p.NextRow + If listCoords = "" Then + listCoords = $"${p.GetString("lon")},${p.GetString("lat")}"$ + Else + listCoords = $"${listCoords}:${p.GetString("lon")},${p.GetString("lat")}"$ + End If + Loop + Main.db.Close + + Log("Iniciamos ruteoCompleto") + ruteoCompleto(r) + + StopMessageLoop + resp.ContentType = "text/html" + resp.Write($"Mapa"$) + Return 1 +End Sub + + +'Regresa la ruta esquina a esquina. +Sub ruteoCompleto(ruta As String) As ResumableSub 'ignore + Log("#################################################################") + Log("############# Mapa/ruteoCompleto ########################") + Log("#################################################################") +' Log("Tiempos: " & ruta) + Private c As ResultSet = Main.db.ExecQuery($"select * from ${ruta}_punteo"$) + Private estasCoords As String = "" + Private ts As Map + ts.Initialize + Do While c.NextRow + If estasCoords = "" Then + estasCoords = $"${c.GetString("lon")},${c.GetString("lat")}"$ + Else + estasCoords = $"${estasCoords};${c.GetString("lon")},${c.GetString("lat")}"$ + End If + Loop + Dim j As HttpJob + j.Initialize("", Me) + j.Download($"http://router.project-osrm.org/route/v1/driving/${estasCoords}?steps=true"$) + Wait For (j) JobDone(j As HttpJob) + If j.Success Then +' Log(j.GetString) + Private j0 As String = j.GetString + End If + j.Release +' StopMessageLoop + Private js1 As JSONParser + js1.Initialize(j0) +' Log(js1) +' For Each colroot As Map In js +' Log(colroot) +' Next +' Log("*****************************************") +' Log(js.NextObject) + Private m As Map = js1.NextObject +' Private estatus As String = m.Get("code") + Private rutas As Map = m.Get("routes").as(List).Get(0) +' Private waypoints As List = m.Get("waypoints") +' Log("Response: " & estatus) +' Log("Duration: " & rutas.Get("duration")) +' Log("Distance: " & rutas.Get("distance")) +' Log("Legs: " & rutas.Get("legs").As(List).Size) +' Log("Waypoints: " & waypoints.Size) + Private steps As List + steps.Initialize + steps = rutas.Get("legs").as(List).get("steps") + Log("STEPS SIZE: " & steps.Size) + ts.Put(ruta, CreateMap("code":"Ok", "duration":rutas.Get("duration"), "distance":rutas.Get("distance"), "puntos":rutas.Get("legs").As(List).Size)) +' Log(">>>>>>>>>>>>>>>>>>>>>>>>>>>" & ts) + Return 1 +End Sub + +'Convierte una lista en un arreglo (array as object). +Public Sub ListToArray(inList As List) As Object() + Dim OutArray(inList.Size) As Object + For i = 0 To inList.Size - 1 + OutArray(i) = inList.Get(i) + Next + Return OutArray +End Sub + +Sub checkIfTableExists(table As String) As Boolean +' B4XPages.MainPage.db.InitializeSQLite(File.DirApp, "kmt.db", True) + Private r As ResultSet = Main.db.ExecQuery($"Select name FROM sqlite_master WHERE Type='table' AND name='${table}'"$) + If r.NextRow Then +' B4XPages.MainPage.db.close +' Log($"NAME: ${r.GetString("name")}"$) + Return True + Else +' B4XPages.MainPage.db.close + Return False + End If +End Sub \ No newline at end of file diff --git a/ResetMyNumber.bas b/ResetMyNumber.bas new file mode 100644 index 0000000..f3c1f1a --- /dev/null +++ b/ResetMyNumber.bas @@ -0,0 +1,18 @@ +B4J=true +Group=Default Group +ModulesStructureVersion=1 +Type=Class +Version=2.18 +@EndOfDesignText@ +'Class module +Sub Class_Globals + +End Sub + +Public Sub Initialize + +End Sub + +Sub Handle(req As ServletRequest, resp As ServletResponse) + req.GetSession.RemoveAttribute("myNumber") +End Sub \ No newline at end of file diff --git a/Ruteador-NonUI.b4j b/Ruteador-NonUI.b4j new file mode 100644 index 0000000..c2ada0d --- /dev/null +++ b/Ruteador-NonUI.b4j @@ -0,0 +1,605 @@ +AppType=StandardJava +Build1=Default,b4j.example +Group=Default Group +Library1=compressstrings +Library10=byteconverter +Library2=jcore +Library3=jfx +Library4=jokhttputils2 +Library5=jrandomaccessfile +Library6=jserver +Library7=json +Library8=jsql +Library9=nhcalculatehash +Module1=DBRequestManager +Module2=delDB +Module3=Mapa +Module4=rutaCompleta +Module5=Ruteador +NumberOfFiles=0 +NumberOfLibraries=10 +NumberOfModules=5 +Version=10 +@EndOfDesignText@ +#Region Project Attributes + #CommandLineArgs: + #MergeLibraries: True + #AdditionalJar: sqlite-jdbc-3.7.2.jar + '########################################################################################################### + '###################### PULL ############################################################# + 'Ctrl + click ide://run?file=%WINDIR%\System32\cmd.exe&Args=/c&Args=git&Args=pull + '########################################################################################################### + '###################### PUSH ############################################################# + 'Ctrl + click ide://run?file=%WINDIR%\System32\WindowsPowerShell\v1.0\powershell.exe&Args=github&Args=..\..\ + '########################################################################################################### + '###################### PUSH TORTOISE GIT ######################################################### + 'Ctrl + click ide://run?file=%WINDIR%\System32\WindowsPowerShell\v1.0\powershell.exe&Args=TortoiseGitProc&Args=/command:commit&Args=/path:"./../"&Args=/closeonend:2 + '########################################################################################################### +#End Region + +Sub Process_Globals + Private srvr As Server + Dim db As SQL +' Dim fx As JFX + Dim punteoLista As List + Dim algoritmo As Int = 1 +' Dim api As Int = 0 +' Dim matriz As String = "" +' Dim urlParams As Map + Dim ts As Map +' Dim coords As List +' Dim estePunto() As String +End Sub + +Sub AppStart (Args() As String) + srvr.Initialize("srvr") + srvr.Port = 9002 + If(Args.Length > 0) Then + Log($"Args=${Args(0)}"$) + For i=0 To Args.Length -1 + If(Args(i).StartsWith("portX=") Or Args(i).StartsWith("PortX=")) Then +' DBRPort = Args(i).SubString(5) +' Log($"Puerto de DBRequest = ${Args(i).SubString(5)}"$) + Else if (Args(i).StartsWith("ip=") Or Args(i).StartsWith("IP=")) Then +' DBRIp = Args(i).SubString(3) +' Log($"IP de DBRequest = ${Args(i).SubString(3)}"$) + Else if (Args(i).ToUpperCase.StartsWith("PORT=") Or Args(i).ToUpperCase.StartsWith("P=")) Then + srvr.Port = Args(i).SubString(Args(i).IndexOf("=")+1) + Log($"Puerto del servidor = ${Args(i).SubString(Args(i).IndexOf("="))}"$) + End If + Next + End If + + + +' Log($"ARGS=${DBRIp}:${DBRPort}"$) + Log("Server Port=" & srvr.Port) + ts.Initialize + srvr.StaticFilesFolder = File.Combine(File.DirApp, "www") + srvr.LogsFileFolder = File.Combine(File.DirApp, "logs") + srvr.LogsRetainDays = 15 + srvr.AddHandler("/ruteador", "Ruteador", False) + srvr.AddHandler("/mapa", "Mapa", False) + srvr.AddHandler("/rutacompleta", "rutaCompleta", False) + srvr.AddHandler("/borrar", "delDB", False) + srvr.Start + StartMessageLoop + 'open browser and navigate to: http://127.0.0.1:51042/ + + + +End Sub + +#Region Shared Files +'#CustomBuildAction: folders ready, %WINDIR%\System32\Robocopy.exe,"..\..\Shared Files" "..\Files" +'Ctrl + click to sync files: ide://run?file=%WINDIR%\System32\Robocopy.exe&args=..\..\Shared+Files&args=..\Files&FilesSync=True +#End Region + +'Ctrl + click to export as zip: ide://run?File=%B4X%\Zipper.jar&Args=Project.zip + +Public Sub Initialize +' B4XPages.GetManager.LogEvents = True +End Sub + +'This event will be called once, before the page becomes visible. +Private Sub B4XPage_CreatedX +' urlParams.Initialize +' ts.Initialize +' Log(File.DirApp) +' db.InitializeSQLite(File.DirApp, "kmt.db", True) +' +'' almacen.Initialize2("19.44598465518769", "-99.1818326916271") 'Mexico-España - Lago Iseo 128 +' db.ExecNonQuery("CREATE TABLE IF NOT EXISTS R1_puntos (id TEXT, nombre TEXT, lat TEXT, lon TEXT)") +' db.ExecNonQuery("CREATE TABLE IF NOT EXISTS R1_punteo (pos TEXT, id TEXT, nombre TEXT, lat TEXT, lon TEXT)") +' db.ExecNonQuery("CREATE TABLE IF NOT EXISTS R1_matriz (idT TEXT, t1 TEXT, t2 TEXT, t3 TEXT, t4 TEXT, t5 TEXT, t6 TEXT, t7 TEXT, t8 TEXT, t9 TEXT, t10 TEXT)") +' db.ExecNonQuery("CREATE TABLE IF NOT EXISTS R1_matrizOSRM (idT TEXT, t1 TEXT, t2 TEXT, t3 TEXT, t4 TEXT, t5 TEXT, t6 TEXT, t7 TEXT, t8 TEXT, t9 TEXT, t10 TEXT)") +' +' 'Generamos la lista de puntos y la guardamos en la tabla "R1_puntos" +' coords.Initialize +' coords.AddAll(Array As String ("Mexico-España,19.44598465518769,-99.1818326916271", "Xochimilco 47,19.448171727202524,-99.1779942882756", "Little Caesars,19.449867997938245,-99.1833874413472", "El Globo,19.451633331080625,-99.18485729424397", "Bodega Aurrera,19.445747004224824,-99.18301691592744", "Wetter 76,19.446150110778017,-99.1936412539473", "Papeleria Progreso,19.443934235653053,-99.18575629823629", "La Esperanza,19.442779235275808,-99.19255124428338", "Modelo,19.440456467281724,-99.18896176081896", "Gringo,19.441000733767016,-99.1817225994711", "Pemex,19.439420250127483,-99.17486856671235")) +'' db.ExecNonQuery("delete from R1_puntos") +'' For a = 0 To coords.Size - 1 +'' estePunto = Regex.Split(",", coords.Get(a)) +'' db.ExecNonQuery($"insert into R1_puntos (id, nombre, lat, lon) values ('A${a}', '${estePunto(0)}', '${estePunto(1)}', '${estePunto(2)}')"$) +'' Next +' 'Creamos la tabla de la matriz con las columnas necesarias. +' Try +' db.ExecNonQuery($"drop table R1_matriz"$) +' db.ExecNonQuery($"drop table R1_matrizOSRM"$) +' db.ExecNonQuery("vacuum") +' Catch +' Log(LastException) +' End Try +' Private colsMatriz As String = "idT TEXT" +' Private pp As ResultSet = db.ExecQuery("select * from R1_puntos") +' Do While pp.NextRow +' colsMatriz = $"${colsMatriz},'${pp.GetString("id")}' REAL"$ +' Loop +' Log(colsMatriz) +' db.ExecNonQuery($"create table if not exists R1_matriz (${colsMatriz})"$) +' db.ExecNonQuery($"create table if not exists R1_matrizOSRM (${colsMatriz})"$) +' 'Generamos la matriz +' b_generaMatriz_Click +End Sub + +Sub creaTablas(params As Map) + 'Creamos las tablas de la ruta con las columnas necesarias. + Log("##########################################################") + Log("############# Main/creaTablas ####################") + Log("##########################################################") + Log(params) + Private almacen As String = params.Get("almacen") + Private estasCoords As String = params.Get("coords") + Private hash As String = params.Get("hash") + Private ruta As String = $"${params.Get("ruta")}A${almacen}_${hash}"$ + Try +' Log($"drop table if exists ${ruta}_matriz"$) + db.ExecNonQuery($"drop table if exists ${ruta}_matriz"$) +' Log($"drop table if exists ${ruta}_matrizOSRM"$) + db.ExecNonQuery($"drop table if exists ${ruta}_matrizOSRM"$) +' Log($"drop table if exists ${ruta}_puntos"$) + db.ExecNonQuery($"drop table if exists ${ruta}_puntos"$) + Catch + Log(LastException) + End Try + db.ExecNonQuery($"create table if not exists ${ruta}_puntos (id TEXT, nombre TEXT, lat TEXT, lon TEXT)"$) +' Log($"create table if not exists ${ruta}_puntos (id TEXT, nombre TEXT, lat TEXT, lon TEXT)"$) + db.ExecNonQuery($"create table if not exists ${ruta}_punteo (pos TEXT, id TEXT, nombre TEXT, lat TEXT, lon TEXT)"$) +' Log($"create table if not exists ${ruta}_punteo (pos TEXT, id TEXT, nombre TEXT, lat TEXT, lon TEXT)"$) + + Private f() As String = Regex.Split(";", estasCoords) + For i = 0 To f.Length - 1 +' Log(f(i)) + Private pars() As String = Regex.Split(",", f(i)) + If pars.Length < 3 Then Log("####################" & CRLF & "Se necesita el id del cliente, la longitud y la latitud" & CRLF & "##############################") +' Log($"(${i}, ${pars(0)}, 'a', ${pars(2)}, ${pars(1)})"$) + db.ExecNonQuery($"insert into ${ruta}_puntos (id, nombre, lat, lon) values ('CC${pars(0)}','a', ${pars(2)}, ${pars(1)})"$) + Next + + Private colsMatriz As String = "idT TEXT" + Private pp As ResultSet = db.ExecQuery($"select * from ${ruta}_puntos"$) + Do While pp.NextRow + colsMatriz = $"${colsMatriz},'${pp.GetString("id")}' REAL"$ + Loop +' Log(colsMatriz) + db.ExecNonQuery($"create table if not exists ${ruta}_matriz (${colsMatriz})"$) + db.ExecNonQuery($"create table if not exists ${ruta}_matrizOSRM (${colsMatriz})"$) +End Sub + +Private Sub b_generaMatriz_Click +' If api = 0 Then +' generaMatrizLocal("R1") +' Else +' generaMatrizOSRM("R1") +' End If +End Sub + +Sub generaMatrizLocal(ruta As String) 'ignore + Log("#################################################################") + Log("############# Main/generaMatrizLocal ####################") + Log("#################################################################") +' Log($"delete from ${ruta}_punteo"$) + Log("Generamos matriz LOCAL") + db.ExecNonQuery($"delete from ${ruta}_punteo"$) +' Log($"delete from ${ruta}_matriz"$) + db.ExecNonQuery($"delete from ${ruta}_matriz"$) +' matriz = "" + punteoLista.Initialize +' Private otroPunto() As String + Private lasCols, losVals As String + Private c As ResultSet = db.ExecQuery($"select * from ${ruta}_puntos"$) +' Dim h As String = c.GetString("id") + db.ExecNonQuery($"insert into ${ruta}_punteo (pos, id, nombre, lat, lon) values ('0', '${c.GetString("id")}', 'Almacen', ${c.Getdouble("lat")}, ${c.Getdouble("lon")})"$) +' Log($"insert into ${ruta}_punteo (pos, id, nombre, lat, lon) values ('0', '${c.GetString("id")}', 'Almacen', ${c.Getdouble("lat")}, ${c.Getdouble("lon")})"$) + punteoLista.Add(c.GetString("id")) 'Lista para ruteoNearestInsertion, ponemos el primer punto (almacen). + Do While c.NextRow + lasCols = "idT" +' Log($"${c.GetString("id")}, ${c.GetString("nombre")}, ${c.GetString("lat")}, ${c.GetString("lon")}"$) + Private d As ResultSet = db.ExecQuery($"select * from ${ruta}_puntos"$) + losVals = $"'${c.GetString("id")}'"$ + Do While d.NextRow + Private laDist As Double = calculateDistance1(c.GetDouble("lat"), c.GetDouble("lon"), d.GetDouble("lat"), d.GetDouble("lon")) + lasCols = $"${lasCols}, '${d.GetString("id")}'"$ + losVals = $"${losVals}, '${laDist}'"$ +' Log($"(${c.GetString("id")},${d.GetString("id")}) - Dist entre ${c.GetString("nombre")} y ${d.GetString("nombre")} = ${laDist}"$) + Loop +' Log($"${lasCols}${CRLF}${losVals}"$) + db.ExecNonQuery($"insert into ${ruta}_matriz (${lasCols}) values (${losVals})"$) + Loop + Log("Matriz LOCAL generada") +' generaMatrizOSRM +End Sub + +Sub generaMatrizOSRM(ruta As String) As ResumableSub 'ignore + Log("Generamos matriz OSRM") + Log("################################################################") + Log("############# Main/generaMatrizOSRM ####################") + Log("################################################################") + db.ExecNonQuery($"delete from ${ruta}_punteo"$) + db.ExecNonQuery($"delete from ${ruta}_matrizOSRM"$) +' matriz = "OSRM" + punteoLista.Initialize + Private c As ResultSet = db.ExecQuery($"select * from ${ruta}_puntos"$) + db.ExecNonQuery($"insert into ${ruta}_punteo (pos, id, nombre, lat, lon) values ('0', '${c.GetString("id")}', 'Almacen', ${c.Getdouble("lat")}, ${c.Getdouble("lon")})"$) + punteoLista.Add(c.GetString("id")) 'Lista para ruteoNearestInsertion, ponemos el primer punto (almacen). + Private lasCoords = "", lasCols = "idT", losIds = c.GetString("id") As String 'ignore + Private listLasCols As List + listLasCols.Initialize + Do While c.NextRow + listLasCols.Add(c.GetString("Id")) + If lasCoords = "" Then + lasCoords = $"${c.GetString("lon")},${c.GetString("lat")}"$ + lasCols = $"${lasCols},'${c.GetString("Id")}'"$ + Else + lasCoords = $"${lasCoords};${c.GetString("lon")},${c.GetString("lat")}"$ + lasCols = $"${lasCols},'${c.GetString("Id")}'"$ + End If + Loop + Log(">>>>>>>>>>>> " & lasCols & CRLF & lasCoords) + Dim j As HttpJob + j.Initialize("", Me) + j.Download($"http://router.project-osrm.org/table/v1/driving/${lasCoords}"$) + Wait For (j) JobDone(j As HttpJob) + If j.Success Then +' Log(j.GetString) + Private j0 As String = j.GetString + End If + j.Release +' StopMessageLoop + Private durs As String = j0.SubString2(j0.IndexOf($""durations""$)+12, j0.IndexOf($""sources""$)).Replace("[","") + Private dur1() As String = Regex.Split("]", durs) + Log(durs) + For i = 0 To dur1.Length - 1 + Private estosVals As String = dur1(i) + If estosVals.StartsWith(",") Then estosVals = $"${estosVals.SubString(1)}"$ + If estosVals.Length > 0 Then + estosVals = $"'${listLasCols.get(i)}',${estosVals}"$ + Log(estosVals) +' Log($"insert into ${ruta}_matrizOSRM (${lasCols}) values (${estosVals})"$) + db.ExecNonQuery($"insert into ${ruta}_matrizOSRM (${lasCols}) values (${estosVals})"$) + End If + Next +' fx.ShowExternalDocument($"http://router.project-osrm.org/table/v1/driving/${lasCoords}"$) + Log("Matriz OSRM generada") +End Sub + +Sub b_ruteo_Click +' ruteo("R1") +End Sub + +'Genera el ruteo de la ruta especificada. +Sub ruteo(ruta As String, matriz As String) 'ignore + Log("#####################################################") + Log("############# Main/ruteo ####################") + Log("#####################################################") + db.ExecNonQuery($"delete from ${ruta}_punteo"$) + punteoLista.Initialize + Private c As ResultSet = db.ExecQuery($"select * from ${ruta}_puntos"$) +' Dim h As String = c.GetString("id") + db.ExecNonQuery($"insert into ${ruta}_punteo (pos, id, nombre, lat, lon) values ('0', '${c.GetString("id")}', 'Almacen', ${c.Getdouble("lat")}, ${c.Getdouble("lon")})"$) + punteoLista.Add(c.GetString("id")) 'Lista para ruteoNearestInsertion, ponemos el primer punto (almacen). + Private cualAlgoritmo As String = "" 'ignore + Log($"Usamos matriz |${matriz}|"$) + If algoritmo = 1 Then + ruteoNearestInsertion(ruta, matriz) + cualAlgoritmo = " (NI)" + Else If algoritmo = 0 Then + Log(3) + ruteoNearestNeighbor(ruta, matriz) + cualAlgoritmo = " (NN)" + Else + ruteoNearestInsertion2 + cualAlgoritmo = " (NI2)" + End If +End Sub + +Private Sub b_verRuta_Click +' verRuta("R1") +End Sub + +Sub verRuta(ruta As String) 'ignore + Log("#######################################################") + Log("############# Main/verRuta ####################") + Log("#######################################################") + Private r As ResultSet = db.ExecQuery($"select * from ${ruta}_punteo"$) + Private coords2 As String = "" + Do While r.NextRow + If coords2 = "" Then + coords2 = $"${r.GetString("lon")},${r.GetString("lat")}"$ + Else + coords2 = $"${coords2}:${r.GetString("lon")},${r.GetString("lat")}"$ + End If + Loop + + Log($"http://keymon.lat:9001/kmz.php?a=1&c=${coords2}"$) + +' fx.ShowExternalDocument($"https://osm.quelltextlich.at/viewer-js.html?kml_url=https://pi.famguerra.com/kmz.php?c=${coords2}"$) +' r = db.ExecQuery("select * from ${ruta}_punteo") +' Private coords2 As String = "" +' Do While r.NextRow +' If coords2 = "" Then +' coords2 = $"${r.GetString("lon")},${r.GetString("lat")}"$ +' Else +' coords2 = $"${coords2};${r.GetString("lon")},${r.GetString("lat")}"$ +' End If +' Loop +' fx.ShowExternalDocument($"http://router.project-osrm.org/route/v1/driving/${coords2}?overview=false"$) +End Sub + +Private Sub b_tiempos_Click +' tiempos("R1") +End Sub + +'Regresa El tiempo y distancia de la ruta especificada. +Sub tiempos(ruta As String) As ResumableSub 'ignore + Log("#######################################################") + Log("############# Main/tiempos ####################") + Log("#######################################################") +' Log("Tiempos: " & ruta) + Private c As ResultSet = db.ExecQuery($"select * from ${ruta}_punteo"$) + Private estasCoords As String = "" + Do While c.NextRow + If estasCoords = "" Then + estasCoords = $"${c.GetString("lon")},${c.GetString("lat")}"$ + Else + estasCoords = $"${estasCoords};${c.GetString("lon")},${c.GetString("lat")}"$ + End If + Loop +' fx.ShowExternalDocument($"http://router.project-osrm.org/route/v1/driving/${estasCoords}"$) + Private d() As String + d = Regex.Split(";", estasCoords) +' Log("$$$$$$ " & d.Length) + Log($"http://router.project-osrm.org/route/v1/driving/${estasCoords}"$) + Dim j As HttpJob + j.Initialize("", Me) + j.Download($"http://router.project-osrm.org/route/v1/driving/${estasCoords}"$) + Wait For (j) JobDone(j As HttpJob) + If j.Success Then + Log("RESPONSE:") + Log(j.GetString) + Private j0 As String = j.GetString + End If + j.Release +' StopMessageLoop + Private js As JSONParser + js.Initialize(j0) +' Log(j0) +' Log("*****************************************") +' Log(js) +'' For Each colroot As Map In js +'' Log(colroot) +'' Next +' Log("*****************************************") + Private m As Map = js.NextObject + Log(m) + Private estatus As String = m.Get("code") + Private rutas As Map = m.Get("routes").as(List).Get(0) + Private waypoints As List = m.Get("waypoints") +' Log("Response: " & estatus) +' Log("Duration: " & rutas.Get("duration")) +' Log("Distance: " & rutas.Get("distance")) +' Log("Legs: " & rutas.Get("legs").As(List).Size) +' Log("Waypoints: " & waypoints.Size) + ts.Put(ruta, CreateMap("code":"Ok", "duration":rutas.Get("duration"), "distance":rutas.Get("distance"), "puntos":rutas.Get("legs").As(List).Size)) +' Log(">>>>>>>>>>>>>>>>>>>>>>>>>>>" & ts) + Return 1 +End Sub + +'Nearest Neighbor +'The nearest neighbor heuristic Is another greedy algorithm, Or what some may call naive. +'It starts at one city And connects with the closest unvisited city. It repeats until every city has been visited. +'It Then returns To the starting city. +Sub ruteoNearestNeighbor(ruta As String, matriz As String) 'ignore + Log("Usamos Nearest Neighbor") + Log("####################################################################") + Log("############# Main/ruteoNearestNeighbor ####################") + Log("####################################################################") + Dim g As ResultSet + Private x As ResultSet = db.ExecQuery($"select id from ${ruta}_puntos"$) + Do While x.NextRow 'Ejecutamos el siguiente codigo la cantidad de veces que hay puntos. + Private punto As ResultSet = db.ExecQuery($"select id, count(id) as regs from ${ruta}_punteo order by pos DESC limit 1"$) + Do While punto.NextRow +' Log($"Select idt, '${punto.GetString("id")}', nombre, lat, lon from R1_matriz join R1_puntos on idT = id where idT Not in (Select id from r1_punteo) order by '${punto.GetString("id")}' Asc limit 1"$) + g = db.ExecQuery($"Select idt, '${punto.GetString("id")}', nombre, lat, lon from ${ruta}_matriz${matriz} join ${ruta}_puntos on idT = id where idT Not in (Select id from ${ruta}_punteo) order by '${punto.GetString("id")}' Asc limit 1"$) + Do While g.NextRow + db.ExecNonQuery($"insert into ${ruta}_punteo (pos, id, nombre, lat, lon) values (${punto.GetString("regs")}, '${g.GetString("idT")}', '${g.GetString("nombre")}', '${g.GetString("lat")}', '${g.GetString("lon")}')"$) + Loop + Loop + Loop +End Sub + +'Nearest Insertion +'The insertion algorithms add new points between existing points on a tour As it grows. +'One implementation of Nearest Insertion begins with two cities. +'It then repeatedly finds the city not already in the tour that Is closest to any city in the tour, +'and places it between whichever two cities would cause the resulting tour to be the shortest possible. +'It stops when no more insertions remain. +Sub ruteoNearestInsertion(ruta As String, matriz As String) 'ignore + Log($"Usamos Nearest Insertion - Matriz ${matriz}"$) + Log("#####################################################################") + Log("############# Main/ruteoNearestInsertion ####################") + Log("#####################################################################") + Private a As ResultSet = db.ExecQuery($"Select idt, ${punteoLista.Get(0)} as laCol, nombre, lat, lon from ${ruta}_matriz${matriz} join ${ruta}_puntos on idT = id where idT <> '${punteoLista.Get(0)}' order by ${punteoLista.Get(0)} asc limit 1"$) +' Log($"Select idt, ${punteoLista.Get(0)} as laCol, nombre, lat, lon from ${ruta}_matriz${matriz} join ${ruta}_puntos on idT = id where idT <> '${punteoLista.Get(0)}' order by ${punteoLista.Get(0)} asc limit 1"$) +' Log(punteoLista) +' Log(a.GetString("idt")) + If punteoLista.IndexOf(a.GetString("idt")) = -1 Then +' Log($"Agregamos ${a.GetString("idt")}"$) + punteoLista.Add(a.GetString("idt")) 'Agregamos el punto mas cercano al almacen. + End If + Private d As ResultSet = db.ExecQuery($"select count(id) as regs from ${ruta}_puntos"$) 'Obtenemos el total de puntos. +' Log(lis2string(punteoLista)) + Private b, c, e As ResultSet 'ignore +' Log(d.GetInt("regs")) + For k = 0 To d.GetInt("regs") - 1 'Bucle por el total de puntos en la ruta. + Private minimo As Double = 100000000 'Inicializamos con un numero alto para que asigne el primer "minimo" que encuentre. + Private elMasCercano = "", elAnterior = "", estePar = "" As String 'ignore +' Log(punteoLista.Size &"|"&d.GetInt("regs")) + Private cuantosPuntos As Int = d.GetInt("regs") +' cuantosPuntos = 21 +' Log(punteoLista) + If punteoLista.Size < cuantosPuntos Then 'Si hay puntos fuera de la ruta ... + For j = 0 To punteoLista.Size - 2 +' Log(">>>>>>>>>>>>>>>>>>>>>> ${j} | ${j-2}") + 'Buscamos el punto mas cercano (de los que no estan en la lista) a los dos puntos que estamos usando en esta vuelta del bucle. + Private b1 As ResultSet = db.ExecQuery($"Select idT, ${punteoLista.Get(j)} as elMinimo from ${ruta}_matriz${matriz} where idT Not in (${lis2string(punteoLista)}) order by ${punteoLista.Get(j)} Asc limit 1"$) +' Log($"Select idT, ${punteoLista.Get(j)} as elMinimo from ${ruta}_matriz${matriz} where idT Not in (${lis2string(punteoLista)}) order by ${punteoLista.Get(j)} Asc limit 1"$) +' Log(b1.GetString("elMinimo")) + c = db.ExecQuery($"Select idT, "${punteoLista.Get(j+1)}" as elMinimo from ${ruta}_matriz${matriz} where idT Not in (${lis2string(punteoLista)}) order by "${punteoLista.Get(j+1)}" Asc limit 1"$) +' Log($"Select idT, "${punteoLista.Get(j)}" as elMinimo from ${ruta}_matriz${matriz} where idT Not in (${lis2string(punteoLista)}) order by "${punteoLista.Get(j)}" Asc limit 1"$) +' Log($"Select idT, "${punteoLista.Get(j+1)}" as elMinimo from ${ruta}_matriz${matriz} where idT Not in (${lis2string(punteoLista)}) order by "${punteoLista.Get(j+1)}" Asc limit 1"$) +' Log(b1.NextRow) + Do While b1.NextRow + 'Si b1 regresa registro +' Log("yyy") + If b1.GetDouble("elMinimo") < minimo Or c.GetDouble("elMinimo") < minimo Then + minimo = b1.GetDouble("elMinimo") + If c.GetDouble("elMinimo") < minimo Then minimo = c.GetDouble("elMinimo") + elMasCercano = b1.GetString("idT") + elAnterior = punteoLista.Get(j) + estePar = $"${punteoLista.Get(j)}|${punteoLista.Get(j+1)}"$ + End If + Loop + Next + End If + If elMasCercano <> "" Then +' Log($"${elMasCercano}, ${estePar}"$) + punteoLista.InsertAt(punteoLista.IndexOf(elAnterior)+1, elMasCercano) + End If + Next +' Log(punteoLista) + db.ExecNonQuery($"delete from ${ruta}_punteo"$) + For h = 0 To punteoLista.Size - 1 + e = db.ExecQuery($"select * from ${ruta}_puntos where id = '${punteoLista.Get(h)}'"$) + Do While e.NextRow + db.ExecNonQuery($"insert into ${ruta}_punteo (pos, id, nombre, lat, lon) values (${h}, '${e.GetString("id")}', '${e.GetString("nombre")}', '${e.GetString("lat")}', '${e.GetString("lon")}')"$) +' Log($"insert into ${ruta}_punteo (pos, id, nombre, lat, lon) values (${h}, '${e.GetString("id")}', '${e.GetString("nombre")}', '${e.GetString("lat")}', '${e.GetString("lon")}')"$) + Loop + Next + Log("Terminamos Nearest Insertion") +End Sub + +'Nearest Insertion +'The insertion algorithms add new points between existing points on a tour As it grows. +'One implementation of Nearest Insertion begins with two cities. +'It then repeatedly finds the city not already in the tour that Is closest to any city in the tour, +'and places it between whichever two cities would cause the resulting tour to be the shortest possible. +'It stops when no more insertions remain. +Sub ruteoNearestInsertion2 'ignore +' Log("Usamos Nearest Insertion 2") +'' Log($"Select idt, "${punteoLista.Get(0)}" as laCol, nombre, lat, lon from R1_matriz join R1_puntos on idT = id where idT <> ${punteoLista.Get(0)} order by "${punteoLista.Get(0)}" desc limit 1"$) +' Private a As ResultSet = db.ExecQuery($"Select idt, "${punteoLista.Get(0)}" as laCol, nombre, lat, lon from R1_matriz${matriz} join R1_puntos on idT = id where idT <> ${punteoLista.Get(0)} order by "${punteoLista.Get(0)}" asc limit 1"$) +' If punteoLista.IndexOf(a.GetString("idt")) = -1 Then punteoLista.Add(a.GetString("idt")) 'Agregamos el punto mas cercano al almacen. +' Private d As ResultSet = db.ExecQuery("select count(id) as regs from R1_puntos") 'Obtenemos el total de puntos. +'' Log(lis2string(punteoLista)) +' Private b, c, e As ResultSet +'' Log(d.GetInt("regs")) +' For k = 0 To d.GetInt("regs") - 1 'Bucle por el total de puntos en la ruta. +' Private minimo As Double = 100000000 'Inicializamos con un numero alto para que asigne el primer "minimo" que encuentre. +' Private elMasCercano = "", elAnterior = "", estePar = "" As String +' Log(punteoLista.Size &"|"&d.GetInt("regs")) +' Private cuantosPuntos As Int = d.GetInt("regs") +'' cuantosPuntos = 21 +' If punteoLista.Size < cuantosPuntos Then 'Si hay puntos fuera de la ruta ... +' For j = 0 To punteoLista.Size - 2 +' 'Buscamos el punto mas cercano (de los que no estan en la lista) a los dos puntos que estamos usando en esta vuelta del bucle. +' b = db.ExecQuery($"Select idT, "${punteoLista.Get(j)}" as elMinimo from R1_matriz${matriz} where idT Not in (${lis2string(punteoLista)}) order by "${punteoLista.Get(j)}" Asc limit 1"$) +' c = db.ExecQuery($"Select idT, "${punteoLista.Get(j+1)}" as elMinimo from R1_matriz${matriz} where idT Not in (${lis2string(punteoLista)}) order by "${punteoLista.Get(j+1)}" Asc limit 1"$) +' If b.NextRow Then 'Si b regresa registro +' If b.GetDouble("elMinimo") < minimo Or c.GetDouble("elMinimo") < minimo Then +' minimo = b.GetDouble("elMinimo") +' If c.GetDouble("elMinimo") < minimo Then minimo = c.GetDouble("elMinimo") +' elMasCercano = b.GetString("idT") +' elAnterior = punteoLista.Get(j) +' estePar = $"${punteoLista.Get(j)}|${punteoLista.Get(j+1)}"$ +' End If +' End If +' Next +' End If +' If elMasCercano <> "" Then +'' Log($"${elMasCercano}, ${estePar}"$) +' punteoLista.InsertAt(punteoLista.IndexOf(elAnterior)+1, elMasCercano) +' End If +' Next +' Log(punteoLista) +' db.ExecNonQuery("delete from R1_punteo") +' For h = 0 To punteoLista.Size - 1 +' e = db.ExecQuery($"select * from R1_puntos where id = '${punteoLista.Get(h)}'"$) +' Do While e.NextRow +' db.ExecNonQuery($"insert into R1_punteo (pos, id, nombre, lat, lon) values (${h}, '${e.GetString("id")}', '${e.GetString("nombre")}', '${e.GetString("lat")}', '${e.GetString("lon")}')"$) +' Loop +' Next +End Sub + +'Calculate distance - Haversine +'Using average radius of earth 6378.137 km. +Sub calculateDistance1(Latitude1 As Double, Longitude1 As Double, Latitude2 As Double, Longitude2 As Double) As Double 'ignore + Return NumberFormat2(2 * 6378137 * ASin (Sqrt (SinD ((Latitude2 - Latitude1) * 0.5) * SinD ((Latitude2 - Latitude1) * 0.5) + CosD (Latitude1) * CosD (Latitude2) * SinD ((Longitude2 - Longitude1) * 0.5) * SinD ((Longitude2 - Longitude1) * 0.5))), 1, 2, 2, False) +End Sub + +Sub calculateDistance2(Latitude1 As Double, Longitude1 As Double, Latitude2 As Double, Longitude2 As Double) As Double 'ignore + Dim EarthRadius, Angle, distance As Double + EarthRadius = 6378.137 ' WGS -84 kilometers? + Angle = ACos(SinD(Latitude1) * SinD(Latitude2) + CosD(Latitude1) * CosD(Latitude2) * CosD(Longitude2 - Longitude1)) + distance = EarthRadius * Angle + Return distance * 1000 +End Sub + +Public Sub calculateDistance3(lat1 As Double, lon1 As Double, lat2 As Double, lon2 As Double) As Double 'ignore + Try + Dim Miles As Double + Dim Yards As Double + Dim X As Double + Dim Coeff As Double= 1760.0 + X = Sin(lat1 * 0.01745) * Sin(lat2 * 0.01745) + Cos(lat1 * 0.01745)* Cos(lat2 * 0.01745) * Cos(( lon2 - lon1 ) * 0.01745) + Miles = 1.15 * 3963 * ( ATan(-X / Sqrt(-X * X+ 1.0000000000001)) + 2* ATan(1) ) +' Miles = Round2(Miles, 2) + Yards = Miles * Coeff + Return Round(Yards) + Catch + Log("CalcDistance " & LastException) + Return -1 + End Try +End Sub + +Sub lis2string(l As List) As String 'ignore + Private s As String = "" + For i = 0 To l.Size - 1 + If s = "" Then + s = $"'${l.get(i)}'"$ + Else + s = $"${s}, '${l.get(i)}'"$ + End If + Next + Return s +End Sub + +Private Sub cb_algorithm_SelectedIndexChanged(Index As Int, Value As Object) +'' Log(Index) +' algoritmo = Index +End Sub + +Private Sub cb_api_SelectedIndexChanged(Index As Int, Value As Object) +' api = Index +' If Index = 0 Then matriz = "" Else matriz = "OSRM" +End Sub \ No newline at end of file diff --git a/Ruteador-NonUI.b4j.meta b/Ruteador-NonUI.b4j.meta new file mode 100644 index 0000000..4449f42 --- /dev/null +++ b/Ruteador-NonUI.b4j.meta @@ -0,0 +1,21 @@ +ModuleBookmarks0= +ModuleBookmarks1= +ModuleBookmarks2= +ModuleBookmarks3= +ModuleBookmarks4= +ModuleBookmarks5= +ModuleBreakpoints0= +ModuleBreakpoints1= +ModuleBreakpoints2= +ModuleBreakpoints3= +ModuleBreakpoints4= +ModuleBreakpoints5= +ModuleClosedNodes0= +ModuleClosedNodes1= +ModuleClosedNodes2= +ModuleClosedNodes3= +ModuleClosedNodes4= +ModuleClosedNodes5= +NavigationStack=delDB,Class_Globals,7,0,Main,b_tiempos_Click,302,0,Main,ruteoNearestInsertion,387,0,Main,AppStart,22,0,Ruteador,generaMatrizRuteoTiempos,86,4,Mapa,ruteoCompleto,152,6,rutaCompleta,ruteoCompleto,153,0,Ruteador,tiempos,125,6,delDB,Handle,31,6,Main,tiempos,331,6,Main,Process_Globals,18,0 +SelectedBuild=0 +VisibleModules=5,3,4,1,2 diff --git a/Ruteador.bas b/Ruteador.bas new file mode 100644 index 0000000..9c5f2bc --- /dev/null +++ b/Ruteador.bas @@ -0,0 +1,179 @@ +B4J=true +Group=Default Group +ModulesStructureVersion=1 +Type=Class +Version=10 +@EndOfDesignText@ +'Class module +Sub Class_Globals + Private mreq As ServletRequest 'ignore + Private mresp As ServletResponse 'ignore +' Dim cmd As DBCommand + Dim theQuery As String + Dim m, m2 As Map + Dim getHash As CalculateHash + Dim js As JSONGenerator +End Sub + +Public Sub Initialize + +End Sub + +'Resumable Subs (wait for / sleep) in server handlers +'Resumable subs can only work when there is a message queue. +'By default, server handlers end when the Handle sub is completed. They do not create a message loop. +'If you want to wait for an event then you need to call StartMessageLoop and later StopMessageLoop. +'https://www.b4x.com/android/forum/threads/resumable-subs-wait-for-sleep-in-server-handlers.81833/ +Sub Handle(req As ServletRequest, resp As ServletResponse) + Log("##############################################################") + Log("############# Ruteador/Handle ########################") + Log("##############################################################") +' Log("q='"&req.GetParameter("q")&"'") + Log($"REQ: ${req.FullRequestURI}"$) + Private elHash As String = getHash.CalculateTheHash(req.FullRequestURI) +' Log(elHash) + Private ruta As String = req.GetParameter("r") + Private almacen As String = req.GetParameter("a") + Private coords As String = req.GetParameter("c") + Private matriz As String = req.GetParameter("m") + If matriz <> "" And matriz <> "OSRM" Then matriz = "" + Log($"r: ${ruta}, a: ${almacen}, Coords: ${coords}"$) + Private urlParams As Map + If ruta <> "" And almacen <> "" And coords <> "" Then + ruta = "R" & ruta + urlParams.Initialize + urlParams.Put("almacen", almacen) + urlParams.Put("coords", coords) + urlParams.Put("hash", elHash) + urlParams.Put("ruta", ruta) + Main.db.InitializeSQLite(File.DirApp, "kmt.db", True) + Log($"${ruta}A${almacen}_${elHash}_punteo"$) +' Log(checkIfTableExists($"${ruta}A${almacen}_${elHash}_punteo"$)) + +' Si no existe la tabla del ruteo, la creamos. + If Not(checkIfTableExists($"${ruta}A${almacen}_${elHash}_punteo"$)) Then +' Log($"Creamos tablas ruta ${ruta}, almacen ${almacen}"$) + Main.creaTablas(urlParams) + generaMatrizRuteoTiempos($"${ruta}A${almacen}_${elHash}"$, resp, ruta, almacen, matriz) + StartMessageLoop + Else 'Si ya existe, solo calculamos los tiempos y distancias. +' Log("Ya existe la tabla") + tiempos($"${ruta}A${almacen}_${elHash}"$, resp, ruta, almacen, matriz) + StartMessageLoop +' Main.verRuta(ruta) + End If + Else + resp.ContentType = "text/html" + resp.Write("Hay un error en la solicitud, son necesarios los parametros:
* r - La ruta
* a - El almacen
* c - id_cliente,lon,lat separadas por punto y coma.
* m - La matriz a usar LOCAL u OSRM (Opcional, default local)") 'this file will be loaded from the www folder + End If +End Sub + +Sub generaMatrizRuteoTiempos(r As String, resp As ServletResponse, ruta As String, almacen As String, matriz As String) As ResumableSub + Log("############################################################################") + Log("############# Ruteador/generaMatrizRuteoTiempos ####################") + Log("############################################################################") + 'Generamos la matriz + If matriz = "OSRM" Then + Wait for(Main.generaMatrizOSRM(r)) Complete (Result As Int) + Else + Main.generaMatrizLocal(r) + End If + 'Generamos el ruteo + Main.ruteo($"${r}"$, matriz) + Wait for(Main.tiempos($"${r}"$)) Complete (Result As Int) + Private ts As Map = Main.ts.Get($"${r}"$) + Log(ts) + Private tempMap As Map + tempMap.Initialize + Private p As ResultSet = Main.db.ExecQuery($"select * from ${r}_punteo"$) + Private listCoords As List + listCoords.Initialize + 'Ponemos el id de la tienda y las coordenadas en una lista para regresarla en un JSON. + Do While p.NextRow + listCoords.Add(CreateMap("pos":p.GetString("pos"), "id":p.GetString("id"), "lat":p.GetString("lat"), "lon":p.GetString("lon"))) + Loop + Main.db.Close + tempMap.Put("api", matriz) + If matriz = "" Then tempMap.Put("api", "Local") + 'Ponemos la ruta, almacen, tiempos, distancias y la lista de las coordenadas en un mapa para regresarla en un JSON. + tempMap.Put("code", "Ok") + tempMap.Put("ruta", ruta) + tempMap.Put("almacen", almacen) + tempMap.Put("duration", ts.Get("duration")) + tempMap.Put("distance", ts.Get("distance")) + tempMap.Put("puntos", ts.Get("puntos")) + tempMap.Put("coords", listCoords) +' Log(tempMap) + js.Initialize(tempMap) + StopMessageLoop + 'Regresamos en un JSON la info del ruteo. + resp.ContentType = "text/html" + resp.Write(js.ToString) + Return 1 +End Sub + +Sub tiempos(r As String, resp As ServletResponse, ruta As String, almacen As String, matriz As String) As ResumableSub + Log("############################################################") + Log("############# Ruteador/tiempos ####################") + Log("############################################################") + Wait for(Main.tiempos($"${r}"$)) Complete (Result As Int) + Private ts As Map = Main.ts.Get($"${r}"$) + Log(ts) + Private tempMap As Map + tempMap.Initialize + Private p As ResultSet = Main.db.ExecQuery($"select * from ${r}_punteo"$) + Private listCoords As List + listCoords.Initialize + Private coords2 As String = "" + Do While p.NextRow + listCoords.Add(CreateMap("pos":p.GetString("pos"), "id":p.GetString("id"), "lat":p.GetString("lat"), "lon":p.GetString("lon"))) + If coords2 = "" Then + coords2 = $"${p.GetString("lon")},${p.GetString("lat")}"$ + Else + coords2 = $"${coords2}:${p.GetString("lon")},${p.GetString("lat")}"$ + End If + Loop + Main.db.Close + tempMap.Put("api", matriz) + If matriz = "" Then tempMap.Put("api", "Local") + tempMap.Put("code", "Ok") + tempMap.Put("ruta", ruta) + tempMap.Put("almacen", almacen) + tempMap.Put("duration", ts.Get("duration")) + tempMap.Put("distance", ts.Get("distance")) + tempMap.Put("puntos", ts.Get("puntos")) + tempMap.Put("coords", listCoords) +' Log(tempMap) + js.Initialize(tempMap) + StopMessageLoop + resp.ContentType = "text/html" + resp.Write(js.ToString) + Log("###################################################################" & CRLF) + Log($"http://keymon.lat:9001/kmz.php?a=1&c=${coords2}"$) + Log("###################################################################" & CRLF) + Log("Liga para ver la ruta en mapa:" & CRLF) + Log($"https://osm.quelltextlich.at/viewer-js.html?kml_url=http://keymon.lat:9001/kmz.php?c=${coords2}"$) + Return 1 +End Sub + +'Convierte una lista en un arreglo (array as object). +Public Sub ListToArray(inList As List) As Object() + Dim OutArray(inList.Size) As Object + For i = 0 To inList.Size - 1 + OutArray(i) = inList.Get(i) + Next + Return OutArray +End Sub + +Sub checkIfTableExists(table As String) As Boolean +' B4XPages.MainPage.db.InitializeSQLite(File.DirApp, "kmt.db", True) + Private r As ResultSet = Main.db.ExecQuery($"Select name FROM sqlite_master WHERE Type='table' AND name='${table}'"$) + If r.NextRow Then +' B4XPages.MainPage.db.close +' Log($"NAME: ${r.GetString("name")}"$) + Return True + Else +' B4XPages.MainPage.db.close + Return False + End If +End Sub \ No newline at end of file diff --git a/WSGuessMyNumber.bas b/WSGuessMyNumber.bas new file mode 100644 index 0000000..25c70c4 --- /dev/null +++ b/WSGuessMyNumber.bas @@ -0,0 +1,65 @@ +B4J=true +Group=Default Group +ModulesStructureVersion=1 +Type=Class +Version=2.18 +@EndOfDesignText@ +'Class module +Sub Class_Globals + Private ws As WebSocket + Private myNumber As Int + Private timer1 As Timer + 'these variables will be set automatically. + Private TxtNumber As JQueryElement 'matches an element with id = "txtnumber" + Private Result As JQueryElement + Private ServerTime As JQueryElement +End Sub + +Public Sub Initialize + myNumber = Rnd(1, 101) +End Sub + +Private Sub WebSocket_Connected (WebSocket1 As WebSocket) + ws = WebSocket1 + timer1.Initialize("timer1", 1000) + timer1.Enabled = True +End Sub + +Private Sub WebSocket_Disconnected + timer1.Enabled = False +End Sub + +Sub btnGuess_Click (Params As Map) + Log(ws.Secure) + Dim s As Long = DateTime.Now + Dim number As String = TxtNumber.GetVal.Value + If IsNumber(number) Then + Dim n As Int = number + If n > myNumber Then + Result.SetHtml("My number is smaller.") + Else If n < myNumber Then + Result.SetHtml("My number is larger.") + Else + Result.SetHtml("Well done!!!") + End If + Else + Result.SetHtml("Please enter a valid number.") + End If + TxtNumber.RunMethod("select", Null) + Log(ws.UpgradeRequest.RemoteAddress & ": " & (DateTime.Now - s)) +End Sub + +Sub Timer1_Tick + ServerTime.SetHtml("Server time: " & DateTime.Time(DateTime.Now)) + ws.Flush 'required here as this is a server event +End Sub + +Sub txtNumber_KeyUp(Params As Map) + If 13 = Params.Get("which") Then + btnGuess_Click (Null) + End If +End Sub + +Sub btnReset_Click (Params As Map) + myNumber = Rnd(1, 101) +End Sub diff --git a/delDB.bas b/delDB.bas new file mode 100644 index 0000000..1773db6 --- /dev/null +++ b/delDB.bas @@ -0,0 +1,57 @@ +B4J=true +Group=Default Group +ModulesStructureVersion=1 +Type=Class +Version=10 +@EndOfDesignText@ +Sub Class_Globals + Private mreq As ServletRequest 'ignore + Private mresp As ServletResponse 'ignore +' Dim cmd As DBCommand + Dim theQuery As String + Dim m, m2 As Map + Dim getHash As CalculateHash + Dim js As JSONGenerator +End Sub + +'Initializes the object. You can add parameters to this method if needed. +Public Sub Initialize + +End Sub + +'Resumable Subs (wait for / sleep) in server handlers +'Resumable subs can only work when there is a message queue. +'By default, server handlers end when the Handle sub is completed. They do not create a message loop. +'If you want to wait for an event then you need to call StartMessageLoop and later StopMessageLoop. +'https://www.b4x.com/android/forum/threads/resumable-subs-wait-for-sleep-in-server-handlers.81833/ +Sub Handle(req As ServletRequest, resp As ServletResponse) +' Log("q='"&req.GetParameter("q")&"'") + Log($"REQ: ${req.FullRequestURI}"$) + Private b As String = req.GetParameter("b") + If b = 1 Then + Try + Log("Borramos base") + Main.db.InitializeSQLite(File.DirApp, "kmt.db", True) + + Main.db.ExecNonQuery("PRAGMA writable_schema = 1") + Main.db.ExecNonQuery("delete from sqlite_master where Type in ('table', 'index', 'trigger')") + Main.db.ExecNonQuery("PRAGMA writable_schema = 0") + +' Private t As ResultSet = Main.db.ExecQuery($"Select name FROM sqlite_master WHERE Type='table'"$) +' Do While t.NextRow +' Log(t.GetString("name")) +' Main.db.ExecNonQuery($"drop table ${t.GetString("name")}"$) +' Loop + Main.db.ExecNonQuery("vacuum") + + Catch + Log(LastException) + End Try + Else + resp.ContentType = "text/html" + resp.Write("Hay un error en la solicitud, son necesarios los parametros:
* r - La ruta
* a - El almacen
* c - id_cliente,lon,lat separadas por punto y coma.
* m - La matriz a usar LOCAL u OSRM (Opcional, default local)") 'this file will be loaded from the www folder + End If +End Sub + + + diff --git a/rutaCompleta.bas b/rutaCompleta.bas new file mode 100644 index 0000000..8def770 --- /dev/null +++ b/rutaCompleta.bas @@ -0,0 +1,197 @@ +B4J=true +Group=Default Group +ModulesStructureVersion=1 +Type=Class +Version=10 +@EndOfDesignText@ +'Class module +Sub Class_Globals + Private mreq As ServletRequest 'ignore + Private mresp As ServletResponse 'ignore +' Dim cmd As DBCommand + Dim getHash As CalculateHash + Dim js As JSONGenerator +End Sub + +Public Sub Initialize + +End Sub + +'Resumable Subs (wait for / sleep) in server handlers +'Resumable subs can only work when there is a message queue. +'By default, server handlers end when the Handle sub is completed. They do not create a message loop. +'If you want to wait for an event then you need to call StartMessageLoop and later StopMessageLoop. +'https://www.b4x.com/android/forum/threads/resumable-subs-wait-for-sleep-in-server-handlers.81833/ +Sub Handle(req As ServletRequest, resp As ServletResponse) + Log("##########################################################") + Log("############# rutaCompleta/Handle ################") + Log("##########################################################") +' Log("q='"&req.GetParameter("q")&"'") +' Log($"REQ: ${req.FullRequestURI}"$) + Private elHash As String = getHash.CalculateTheHash(req.FullRequestURI) +' Log(elHash) + Private ruta As String = req.GetParameter("r") + Private almacen As String = req.GetParameter("a") + Private coords As String = req.GetParameter("c") + Private matriz As String = req.GetParameter("m") + If matriz <> "" And matriz <> "OSRM" Then matriz = "" +' Log($"r: ${ruta}, a: ${almacen}, Coords: ${coords}"$) + Private urlParams As Map + If ruta <> "" And almacen <> "" And coords <> "" Then + ruta = "R" & ruta + urlParams.Initialize + urlParams.Put("almacen", almacen) + urlParams.Put("coords", coords) + urlParams.Put("hash", elHash) + urlParams.Put("ruta", ruta) + Main.db.InitializeSQLite(File.DirApp, "kmt.db", True) + +' Si no existe la tabla del ruteo, la creamos. + If Not(checkIfTableExists($"${ruta}A${almacen}_${elHash}_punteo"$)) Then + Log($"Creamos tablas ruta ${ruta}, almacen ${almacen}"$) + Main.creaTablas(urlParams) + generaMatrizRuteoTiempos($"${ruta}A${almacen}_${elHash}"$, resp, ruta, almacen, matriz) + StartMessageLoop + Else 'Si ya existe, solo calculamos los tiempos y distancias. +' tiempos($"${ruta}A${almacen}_${elHash}"$, resp, ruta, almacen, matriz) + ruteoCompleto($"${ruta}A${almacen}_${elHash}"$) + StartMessageLoop + End If + Else + resp.ContentType = "text/html" + resp.Write("Hay un error en la solicitud, son necesarios los parametros:
* r - La ruta
* a - El almacen
* c - id_cliente,lon,lat separadas por punto y coma.
* m - La matriz a usar LOCAL u OSRM (Opcional, default local)") 'this file will be loaded from the www folder + End If +End Sub + +Sub generaMatrizRuteoTiempos(r As String, resp As ServletResponse, ruta As String, almacen As String, matriz As String) As ResumableSub + Log("############################################################################") + Log("############# rutaCompleta/generaMatrizRuteoTiempos ################") + Log("############################################################################") + 'Generamos la matriz + If matriz = "OSRM" Then + Wait for(Main.generaMatrizOSRM(r)) Complete (Result As Int) + Else + Main.generaMatrizLocal(r) + End If + 'Generamos el ruteo + Main.ruteo($"${r}"$, matriz) +' Wait for(Main.tiempos($"${r}"$)) Complete (Result As Int) +' Private ts As Map = Main.ts.Get($"${r}"$) +' Log(ts) + Private p As ResultSet = Main.db.ExecQuery($"select * from ${r}_punteo"$) + Private listCoords As String = "" + 'Ponemos el id de la tienda y las coordenadas en una lista para regresarla en un JSON. + Do While p.NextRow + If listCoords = "" Then + listCoords = $"${p.GetString("lon")},${p.GetString("lat")}"$ + Else + listCoords = $"${listCoords}:${p.GetString("lon")},${p.GetString("lat")}"$ + End If + Loop + Main.db.Close + StopMessageLoop + resp.ContentType = "text/html" + + resp.Write($"Mapa"$) + Return 1 +End Sub + +Sub tiempos(r As String, resp As ServletResponse, ruta As String, almacen As String, matriz As String) As ResumableSub + Log("###########################################################") + Log("############# rutaCompleta/tiempos ################") + Log("###########################################################") + Private p As ResultSet = Main.db.ExecQuery($"select * from ${r}_punteo"$) + Private listCoords As String = "" + Do While p.NextRow + If listCoords = "" Then + listCoords = $"${p.GetString("lon")},${p.GetString("lat")}"$ + Else + listCoords = $"${listCoords}:${p.GetString("lon")},${p.GetString("lat")}"$ + End If + Loop + Main.db.Close + +' Log("Iniciamos ruteoCompleto") +' ruteoCompleto(r) + + StopMessageLoop + resp.ContentType = "text/html" + resp.Write($"Mapa"$) + Return 1 +End Sub + + +'Regresa la ruta esquina a esquina. +Sub ruteoCompleto(ruta As String) As ResumableSub 'ignore + Log("#################################################################") + Log("############# rutaCompleta/ruteoCompleto ################") + Log("#################################################################") +' Log("Tiempos: " & ruta) + Private c As ResultSet = Main.db.ExecQuery($"select * from ${ruta}_punteo"$) + Private estasCoords As String = "" + Private ts As Map + ts.Initialize + Do While c.NextRow + If estasCoords = "" Then + estasCoords = $"${c.GetString("lon")},${c.GetString("lat")}"$ + Else + estasCoords = $"${estasCoords};${c.GetString("lon")},${c.GetString("lat")}"$ + End If + Loop + Dim j As HttpJob + j.Initialize("", Me) + j.Download($"http://router.project-osrm.org/route/v1/driving/${estasCoords}?steps=true"$) + Wait For (j) JobDone(j As HttpJob) + If j.Success Then +' Log(j.GetString) + Private j0 As String = j.GetString + End If + j.Release +' StopMessageLoop + Private js1 As JSONParser + js1.Initialize(j0) +' Log(js1) +' For Each colroot As Map In js +' Log(colroot) +' Next +' Log("*****************************************") +' Log(js.NextObject) + Private m As Map = js1.NextObject +' Private estatus As String = m.Get("code") + Private rutas As Map = m.Get("routes").as(List).Get(0) +' Private waypoints As List = m.Get("waypoints") +' Log("Response: " & estatus) +' Log("Duration: " & rutas.Get("duration")) +' Log("Distance: " & rutas.Get("distance")) +' Log("Legs: " & rutas.Get("legs").As(List).Size) +' Log("Waypoints: " & waypoints.Size) + Private steps As List + steps.Initialize + steps = rutas.Get("legs").as(List).get(0).As(Map).Get("steps") + Log("STEPS SIZE: " & steps.Size) + ts.Put(ruta, CreateMap("code":"Ok", "duration":rutas.Get("duration"), "distance":rutas.Get("distance"), "puntos":rutas.Get("legs").As(List).Size)) +' Log(">>>>>>>>>>>>>>>>>>>>>>>>>>>" & ts) + Return 1 +End Sub + +'Convierte una lista en un arreglo (array as object). +Public Sub ListToArray(inList As List) As Object() + Dim OutArray(inList.Size) As Object + For i = 0 To inList.Size - 1 + OutArray(i) = inList.Get(i) + Next + Return OutArray +End Sub + +Sub checkIfTableExists(table As String) As Boolean +' B4XPages.MainPage.db.InitializeSQLite(File.DirApp, "kmt.db", True) + Private r As ResultSet = Main.db.ExecQuery($"Select name FROM sqlite_master WHERE Type='table' AND name='${table}'"$) + If r.NextRow Then +' B4XPages.MainPage.db.close +' Log($"NAME: ${r.GetString("name")}"$) + Return True + Else +' B4XPages.MainPage.db.close + Return False + End If +End Sub \ No newline at end of file