Commit inicial

This commit is contained in:
2024-04-22 11:52:36 -06:00
parent 91a2ddba48
commit 133b34606e
11 changed files with 1648 additions and 0 deletions

2
.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
**/Objects
**/AutoBackups

272
DBRequestManager.bas Normal file
View File

@@ -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

36
GuessMyNumber.bas Normal file
View File

@@ -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

196
Mapa.bas Normal file
View File

@@ -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:<br>* r - La ruta<br>* a - El almacen<br>* c - id_cliente,lon,lat separadas por punto y coma.<br>* 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($"<a href="https://osm.quelltextlich.at/viewer-js.html?kml_url=https://pi.famguerra.com/kmz.php?c=${listCoords}">Mapa</a>"$)
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($"<a href="https://osm.quelltextlich.at/viewer-js.html?kml_url=https://pi.famguerra.com/kmz.php?c=${listCoords}">Mapa</a>"$)
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

18
ResetMyNumber.bas Normal file
View File

@@ -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

605
Ruteador-NonUI.b4j Normal file
View File

@@ -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

21
Ruteador-NonUI.b4j.meta Normal file
View File

@@ -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

179
Ruteador.bas Normal file
View File

@@ -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:<br>* r - La ruta<br>* a - El almacen<br>* c - id_cliente,lon,lat separadas por punto y coma.<br>* 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

65
WSGuessMyNumber.bas Normal file
View File

@@ -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("<b>Well done!!!</b>")
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

57
delDB.bas Normal file
View File

@@ -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:<br>* r - La ruta<br>* a - El almacen<br>* c - id_cliente,lon,lat separadas por punto y coma.<br>* m - La matriz a usar LOCAL u OSRM (Opcional, default local)") 'this file will be loaded from the www folder
End If
End Sub

197
rutaCompleta.bas Normal file
View File

@@ -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:<br>* r - La ruta<br>* a - El almacen<br>* c - id_cliente,lon,lat separadas por punto y coma.<br>* 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($"<a href="https://osm.quelltextlich.at/viewer-js.html?kml_url=https://pi.famguerra.com/kmz.php?c=${listCoords}">Mapa</a>"$)
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($"<a href="https://osm.quelltextlich.at/viewer-js.html?kml_url=https://pi.famguerra.com/kmz.php?c=${listCoords}">Mapa</a>"$)
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