#DEFINE TEST_CLASS .T.
#IF TEST_CLASS
CLEAR
LOCAL Traject AS RoutePlanner
LOCAL TrajectStep AS RP_Step
LOCAL Distance AS Integer
LOCAL Duration AS Integer
m.Traject = CREATEOBJECT("RoutePlanner")
* IF m.Traject.GetRoute("Jardim Botânico, Coimbra", "Jardin des Plantes, Paris")
IF m.Traject.GetRoute("Grasmarktstraat 100, Brussel", "De Keizerlei 12, Antwerpen")
m.Distance = 0
m.Duration = 0
FOR EACH TrajectStep IN m.Traject.Steps
m.Distance = m.Distance + m.TrajectStep.Distance
m.Duration = m.Duration + m.TrajectStep.Duration
? m.TrajectStep.DurationText, "/", m.TrajectStep.DistanceText, "/", m.TrajectStep.Instructions
ENDFOR
? "Total distance (meters):", m.Distance
? "Total duration (seconds):", m.Duration
ENDIF
#ENDIF
DEFINE CLASS RoutePlanner AS Custom
Language = "en-US"
FromAddress = ""
ToAddress = ""
TravelMode = "DRIVING"
Steps = .NULL.
Service = .NULL.
FUNCTION Init
This.Service = CREATEOBJECT("MSXML2.ServerXMLHTTP.6.0")
RETURN !ISNULL(This.Service)
ENDFUNC
FUNCTION Destroy
This.Clear()
This.Service = .NULL.
ENDFUNC
FUNCTION GetRoute (FromAddress AS String, ToAddress AS String) AS Boolean
LOCAL URL AS String
LOCAL Response AS MSXML2.DOMDocument60
LOCAL Nodes AS MSXML2.IXMLDOMNodeList, Children AS MSXML2.IXMLDOMNodeList
LOCAL Node AS MSXML2.IXMLDOMNode
LOCAL SingleStep AS RP_Step
LOCAL DecimalPoint AS Character
This.FromAddress = m.FromAddress
This.ToAddress = m.ToAddress
This.Clear()
m.URL = "[URL unfurl="true"]https://maps.google.com/maps/api/directions/xml?origin="[/URL] + This.EncodeURL(m.FromAddress) + ;
"&" + "destination=" + This.EncodeURL(m.ToAddress) + ;
"&" + "mode=" + This.TravelMode + ;
"&" + "language=" + This.Language + "&" + "sensor=false"
WITH This.Service AS MSXML2.ServerXMLHTTP60
.open("GET", m.URL, .F.)
.send()
m.Response = .responseXML
ENDWITH
m.Nodes = m.Response.selectNodes("/DirectionsResponse/status")
IF ISNULL(m.Nodes) OR m.Nodes.length = 0 OR m.Nodes.item(0).text != "OK"
RETURN .F.
ENDIF
This.Steps = CREATEOBJECT("Collection")
m.DecimalPoint = SET("Point")
SET POINT TO "."
m.Nodes = m.Response.selectNodes("/DirectionsResponse/route/leg/step")
FOR EACH m.Node IN m.Nodes
m.NewStep = CREATEOBJECT("RP_Step")
WITH m.NewStep AS RP_Step
.TravelMode = m.Node.selectNodes("travel_mode").item(0).text
WITH .StartLocation AS RP_Location
.Latitude = VAL(m.Node.selectNodes("start_location/lat").item(0).text)
.Longitude = VAL(m.Node.selectNodes("start_location/lng").item(0).text)
ENDWITH
WITH .EndLocation AS RP_Location
.Latitude = VAL(m.Node.selectNodes("end_location/lat").item(0).text)
.Longitude = VAL(m.Node.selectNodes("end_location/lng").item(0).text)
ENDWITH
.Instructions = This.RemoveMarkup(m.Node.selectNodes("html_instructions").item(0).text)
.Duration = VAL(m.Node.selectNodes("duration/value").item(0).text)
.DurationText = m.Node.selectNodes("duration/text").item(0).text
.Distance = VAL(m.Node.selectNodes("distance/value").item(0).text)
.DistanceText = m.Node.selectNodes("distance/text").item(0).text
m.Children = m.Node.selectNodes("manouever")
IF !ISNULL(m.Children) AND m.Children.length > 0
.Manouever = m.Children.item(0).text
ENDIF
ENDWITH
This.Steps.Add(m.NewStep)
ENDFOR
SET POINT TO m.DecimalPoint
RETURN .T.
ENDFUNC
PROCEDURE Clear
IF !ISNULL(This.Steps)
This.Steps.Remove(-1)
ENDIF
This.Steps = .NULL.
ENDPROC
FUNCTION EncodeURL (Source AS String) AS String
LOCAL CharIndex AS Integer
LOCAL SingleChar AS Character
LOCAL Encoded AS String
LOCAL UTF8 AS String
m.UTF8 = STRCONV(STRCONV(m.Source,1),9)
m.Encoded = ""
FOR m.CharIndex = 1 TO LEN(m.UTF8)
m.SingleChar = SUBSTR(m.UTF8, m.CharIndex, 1)
IF m.SingleChar $ "&=%:/+ " OR ASC(m.SingleChar) > 127 OR ASC(m.SingleChar) < 32
m.SingleChar = "%" + RIGHT(TRANSFORM(ASC(m.SingleChar),"@0"), 2)
ENDIF
m.Encoded = m.Encoded + m.SingleChar
ENDFOR
RETURN m.Encoded
ENDFUNC
FUNCTION RemoveMarkup (Source AS String) AS String
LOCAL TaggedElement AS String
LOCAL Cleared AS String
m.Cleared = m.Source
m.TaggedElement = STREXTRACT(m.Cleared, "<", ">", 1, 4)
DO WHILE !EMPTY(m.TaggedElement)
m.Cleared = STRTRAN(m.Cleared, m.TaggedElement, "")
m.TaggedElement = STREXTRACT(m.Cleared, "<", ">", 1, 4)
ENDDO
RETURN m.Cleared
ENDFUNC
ENDDEFINE
DEFINE CLASS RP_Step AS Custom
TravelMode = ""
StartLocation = .NULL.
EndLocation = .NULL.
Instructions = ""
Duration = 0
DurationText = ""
Distance = 0
DistanceText = ""
Manouever = ""
FUNCTION Init
This.StartLocation = CREATEOBJECT("RP_Location")
This.EndLocation = CREATEOBJECT("RP_Location")
ENDFUNC
FUNCTION Destroy
This.StartLocation = .NULL.
This.EndLocation = .NULL.
ENDFUNC
ENDDEFINE
DEFINE CLASS RP_Location AS Custom
Latitude = 0
Longitude = 0
ENDDEFINE