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") Main.inicio = req.GetParameter("i") Main.final = req.GetParameter("f") 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 If Main.final <> "" Then coords = coords & ";" & Main.final 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 siguientes parametros:
* r - La ruta
* a - El almacen
* c - Lista de puntos (id_cliente,lon,lat) separadas por punto y coma, el primer punto de la lista, se considera el punto de INICIO de la ruta.
* m - La matriz a usar LOCAL u OSRM (Opcional, default local
* f - El destino final (id_cliente,lon,lat) de donde termina la ruta (Opcional)") '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 If checkIfTableExists(r&"_punteo") Then 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) tempMap.Put("mensaje", Main.msg) If tempMap.get("puntos") = 0 Then tempMap.Put("code", "KO") ' Log(tempMap) js.Initialize(tempMap) StopMessageLoop Main.error = "" Main.msg = "" 'Regresamos en un JSON la info del ruteo. resp.ContentType = "text/html" resp.Write(js.ToString) Else tempMap.Put("api", "") tempMap.Put("code", "KO") tempMap.Put("error", Main.error) tempMap.Put("ruta", ruta) tempMap.Put("almacen", almacen) tempMap.Put("duration", 0) tempMap.Put("distance", 0) tempMap.Put("puntos", 0) tempMap.Put("coords", "") tempMap.Put("mensaje", Main.msg) ' Log(tempMap) js.Initialize(tempMap) StopMessageLoop Main.error = "" Main.msg = "" resp.ContentType = "text/html" resp.Write(js.ToString) End If 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) tempMap.Put("mensaje", Main.msg) If tempMap.get("puntos") = 0 Then tempMap.Put("code", "KO") ' Log(tempMap) js.Initialize(tempMap) StopMessageLoop Main.error = "" Main.msg = "" 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