aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLeah (ctucx) <leah@ctu.cx>2021-03-08 12:52:04 +0100
committerLeah (ctucx) <leah@ctu.cx>2021-03-08 12:52:04 +0100
commit0b3a3db4f9992966706a36ea3025b5159dd2b3ea (patch)
tree2ae1e55609e4832b808ec429168f96ac0e5398ec
parent72bca49014503a60e3e1ab7994d38eb9870a9ced (diff)
downloadoeffi-web-0b3a3db4f9992966706a36ea3025b5159dd2b3ea.tar.gz
oeffi-web-0b3a3db4f9992966706a36ea3025b5159dd2b3ea.tar.bz2
oeffi-web-0b3a3db4f9992966706a36ea3025b5159dd2b3ea.zip
use submodule for hafas-client
-rw-r--r--.gitmodules3
-rw-r--r--src/backend/hafas.nim7
-rw-r--r--src/backend/hafas/api/journeys.nim80
-rw-r--r--src/backend/hafas/api/refresh_journey.nim23
-rw-r--r--src/backend/hafas/api/suggestions.nim29
-rw-r--r--src/backend/hafas/errors.nim199
-rw-r--r--src/backend/hafas/parse/accessibility.nim6
-rw-r--r--src/backend/hafas/parse/date.nim31
-rw-r--r--src/backend/hafas/parse/journey.nim38
-rw-r--r--src/backend/hafas/parse/journeys_response.nim27
-rw-r--r--src/backend/hafas/parse/leg.nim67
-rw-r--r--src/backend/hafas/parse/line.nim71
-rw-r--r--src/backend/hafas/parse/msg.nim12
-rw-r--r--src/backend/hafas/parse/operator.nim9
-rw-r--r--src/backend/hafas/parse/point.nim78
-rw-r--r--src/backend/hafas/parse/polyline.nim73
-rw-r--r--src/backend/hafas/parse/products.nim37
-rw-r--r--src/backend/hafas/parse/remark.nim32
-rw-r--r--src/backend/hafas/parse/stopover.nim33
-rw-r--r--src/backend/hafas/todo10
-rw-r--r--src/backend/hafas/types.nim53
-rw-r--r--src/backend/hafas/util.nim57
-rw-r--r--src/endpoints/api/journeys.nim2
-rw-r--r--src/endpoints/api/moreJourneys.nim4
-rw-r--r--src/endpoints/api/refreshJourney.nim4
-rw-r--r--src/endpoints/api/suggestions.nim2
-rw-r--r--src/endpoints/journeyHandler.nim2
-rw-r--r--src/endpoints/journeysHandler.nim2
-rw-r--r--src/endpoints/searchHandler.nim2
-rw-r--r--src/endpoints/suggestionsHandler.nim2
m---------src/hafas0
-rw-r--r--src/oeffi.nim2
-rw-r--r--src/utils.nim2
33 files changed, 15 insertions, 984 deletions
diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 0000000..dca2950
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,3 @@
+[submodule "src/hafas"]
+ path = src/hafas
+ url = https://cgit.ctu.cx/hafas.nim
diff --git a/src/backend/hafas.nim b/src/backend/hafas.nim
deleted file mode 100644
index e73862f..0000000
--- a/src/backend/hafas.nim
+++ /dev/null
@@ -1,7 +0,0 @@
-import hafas/api/journeys
-import hafas/api/suggestions
-import hafas/api/refresh_journey
-
-export journeys
-export suggestions
-export refresh_journey
diff --git a/src/backend/hafas/api/journeys.nim b/src/backend/hafas/api/journeys.nim
deleted file mode 100644
index 8f97990..0000000
--- a/src/backend/hafas/api/journeys.nim
+++ /dev/null
@@ -1,80 +0,0 @@
-import ../parse/products
-import ../parse/point
-import ../parse/accessibility
-import ../parse/journeys_response
-import ../types
-import ../util
-import json
-import times
-import asyncdispatch
-import options
-
-proc journeys*(params: JourneysParams): Future[JourneysResponse] {.async.} =
- var `when` = now().toTime()
- var isDeparture = true
- if params.departure.isSome:
- `when` = params.departure.get.fromUnix
- elif params.arrival.isSome:
- `when` = params.arrival.get.fromUnix
- isDeparture = false
-
- let req = %* {
- "cfg": {
- "polyEnc": "GPA"
- },
- "meth": "TripSearch",
- "req": {
- "ctxScr": nil,
- "getPasslist": params.stopovers.get(false),
- "maxChg": params.transfers.get(-1),
- "minChgTime": params.transferTime.get(0),
- "numF": params.results.get(5),
- "depLocL": [ params.fromPoint.formatPoint() ],
- "viaLocL": [],
- "arrLocL": [ params.toPoint.formatPoint() ],
- "jnyFltrL": [
- {
- "type": "PROD",
- "mode": "INC",
- "value": $formatProducts(params.products.get(parseProducts(1023))),
- },
- {
- "type": "META",
- "mode": "INC",
- "meta": formatAccessibility(params.accessibility.get(Accessibility.none)),
- }
- ],
- "gisFltrL": [],
- "getTariff": params.tickets.get(true),
- "ushrp": params.startWithWalking.get(true),
- "getPT": true,
- "getIV": false,
- "getPolyline": params.polylines.get(false),
- "outFrwd": isDeparture,
- "outDate": `when`.format("yyyyMMdd"),
- "outTime": `when`.format("HHmmss"),
- "trfReq": {
- "jnyCl": 2,
- "tvlrProf": [
- {
- "type": "E",
- "redtnCard": nil
- }
- ],
- "cType": "PK"
- }
- }
- }
-
- if params.laterRef.isSome:
- req["req"]["ctxScr"] = %* params.laterRef.get
- elif params.earlierRef.isSome:
- req["req"]["ctxScr"] = %* params.earlierRef.get
-
- if params.viaPoint.isSome:
- let viaPoint = params.viaPoint.get
- req["req"]["viaLocL"] = %* [{ "loc": viaPoint.formatPoint() }]
-
- let data = await request(req)
-
- return parseJourneysResponse(data)
diff --git a/src/backend/hafas/api/refresh_journey.nim b/src/backend/hafas/api/refresh_journey.nim
deleted file mode 100644
index 9eb1a55..0000000
--- a/src/backend/hafas/api/refresh_journey.nim
+++ /dev/null
@@ -1,23 +0,0 @@
-import ../types
-import ../parse/journeys_response
-import ../util
-import json
-import asyncdispatch
-import options
-
-proc refreshJourney*(params: RefreshJourneyParams): Future[Journey] {.async.} =
- let req = %* {
- "cfg": {
- },
- "meth": "Reconstruction",
- "req": {
- "ctxRecon": params.refreshToken,
- "getIST": true,
- "getPasslist": params.stopovers.get(false),
- "getPolyline": params.polylines.get(false),
- "getTariff": params.tickets.get(false),
- }
- }
-
- let data = await request(req)
- return parseJourneysResponse(data, true).journeys[0]
diff --git a/src/backend/hafas/api/suggestions.nim b/src/backend/hafas/api/suggestions.nim
deleted file mode 100644
index 18a2ed6..0000000
--- a/src/backend/hafas/api/suggestions.nim
+++ /dev/null
@@ -1,29 +0,0 @@
-import ../../../types
-import ../parse/point
-import ../util
-import json
-import asyncdispatch
-import sequtils
-import options
-
-proc suggestions*(params: SuggestionsParams): Future[seq[Point]] {.async.} =
- let req = %* {
- "cfg": {
- "polyEnc": "GPA"
- },
- "meth": "LocMatch",
- "req": {
- "input": {
- "loc": {
- "type": "ALL",
- "name": params.query & "?"
- },
- "maxLoc": params.results.get(10),
- "field": "S"
- }
- }
- }
- let data = await request(req)
- let locs = data["res"]["match"]["locL"].getElems()
-
- return locs.map(parsePoint)
diff --git a/src/backend/hafas/errors.nim b/src/backend/hafas/errors.nim
deleted file mode 100644
index 0ab1270..0000000
--- a/src/backend/hafas/errors.nim
+++ /dev/null
@@ -1,199 +0,0 @@
-import asynchttpserver
-import ../../types
-
-proc parseError*(errstr: string): hafasException =
- case errstr:
- of "H_UNKNOWN":
- return hafasException(
- code: SERVER_ERROR,
- message: "unknown internal error",
- statusCode: Http500,
- )
- of "AUTH":
- return hafasException(
- code: ACCESS_DENIED,
- message: "invalid or missing authentication data",
- statusCode: Http401,
- )
- of "R0001":
- return hafasException(
- code: INVALID_REQUEST,
- message: "unknown method",
- statusCode: Http400,
- )
- of "R0002":
- return hafasException(
- code: INVALID_REQUEST,
- message: "invalid or missing request parameters",
- statusCode: Http400,
- )
- of "R0007":
- return hafasException(
- code: SERVER_ERROR,
- message: "internal communication error",
- statusCode: Http500,
- )
- of "R5000":
- return hafasException(
- code: ACCESS_DENIED,
- message: "access denied",
- statusCode: Http401,
- )
- of "S1":
- return hafasException(
- code: SERVER_ERROR,
- message: "journeys search: a connection to the backend server couldn\'t be established",
- statusCode: Http503,
- )
- of "LOCATION":
- return hafasException(
- code: INVALID_REQUEST,
- message: "location/stop not found",
- statusCode: Http400,
- )
- of "H390":
- return hafasException(
- code: INVALID_REQUEST,
- message: "journeys search: departure/arrival station replaced",
- statusCode: Http400,
- )
- of "H410":
- return hafasException(
- code: SERVER_ERROR,
- message: "journeys search: incomplete response due to timetable change"
- )
- of "H455":
- return hafasException(
- code: INVALID_REQUEST,
- message: "journeys search: prolonged stop",
- statusCode: Http400,
- )
- of "H460":
- return hafasException(
- code: INVALID_REQUEST,
- message: "journeys search: stop(s) passed multiple times",
- statusCode: Http400,
- )
- of "H500":
- return hafasException(
- code: INVALID_REQUEST,
- message: "journeys search: too many trains, connection is not complete",
- statusCode: Http400,
- )
- of "H890":
- return hafasException(
- code: NOT_FOUND,
- message: "journeys search unsuccessful",
- statusCode: Http404,
- )
- of "H891":
- return hafasException(
- code: NOT_FOUND,
- message: "journeys search: no route found, try with an intermediate stations",
- statusCode: Http404,
- )
- of "H892":
- return hafasException(
- code: INVALID_REQUEST,
- message: "journeys search: query too complex, try less intermediate stations",
- statusCode: Http400,
- )
- of "H895":
- return hafasException(
- code: INVALID_REQUEST,
- message: "journeys search: departure & arrival are too near",
- statusCode: Http400,
- )
- of "H899":
- return hafasException(
- code: SERVER_ERROR,
- message: "journeys search unsuccessful or incomplete due to timetable change"
- )
- of "H900":
- return hafasException(
- code: SERVER_ERROR,
- message: "journeys search unsuccessful or incomplete due to timetable change"
- )
- of "H9220":
- return hafasException(
- code: NOT_FOUND,
- message: "journeys search: no stations found close to the address",
- statusCode: Http400,
- )
- of "H9230":
- return hafasException(
- code: SERVER_ERROR,
- message: "journeys search: an internal error occured",
- statusCode: Http500,
- )
- of "H9240":
- return hafasException(
- code: NOT_FOUND,
- message: "journeys search unsuccessful",
- statusCode: Http404,
- )
- of "H9250":
- return hafasException(
- code: SERVER_ERROR,
- message: "journeys search: leg query interrupted",
- statusCode: Http500,
- )
- of "H9260":
- return hafasException(
- code: INVALID_REQUEST,
- message: "journeys search: unknown departure station",
- statusCode: Http400,
- )
- of "H9280":
- return hafasException(
- code: INVALID_REQUEST,
- message: "journeys search: unknown intermediate station",
- statusCode: Http400,
- )
- of "H9300":
- return hafasException(
- code: INVALID_REQUEST,
- message: "journeys search: unknown arrival station",
- statusCode: Http400,
- )
- of "H9320":
- return hafasException(
- code: INVALID_REQUEST,
- message: "journeys search: the input is incorrect or incomplete",
- statusCode: Http400,
- )
- of "H9360":
- return hafasException(
- code: INVALID_REQUEST,
- message: "journeys search: error in a data field",
- statusCode: Http400,
- )
- of "H9380":
- return hafasException(
- code: INVALID_REQUEST,
- message: "journeys search: departure/arrival/intermediate station defined more than once",
- statusCode: Http400,
- )
- of "SQ001":
- return hafasException(
- code: SERVER_ERROR,
- message: "no departures/arrivals data available",
- statusCode: Http503,
- )
- of "SQ005":
- return hafasException(
- code: NOT_FOUND,
- message: "no trips found",
- statusCode: Http404,
- )
- of "TI001":
- return hafasException(
- code: SERVER_ERROR,
- message: "no trip info available",
- statusCode: Http503,
- )
- return hafasException(
- code: SERVER_ERROR,
- message: "unknown HAFAS exception " & errstr,
- statusCode: Http500,
- )
diff --git a/src/backend/hafas/parse/accessibility.nim b/src/backend/hafas/parse/accessibility.nim
deleted file mode 100644
index b0093b1..0000000
--- a/src/backend/hafas/parse/accessibility.nim
+++ /dev/null
@@ -1,6 +0,0 @@
-import ../types
-
-proc formatAccessibility*(a: Accessibility): string =
- if a == none: result = "notBarrierfree"
- elif a == partial: result = "limitedBarrierfree"
- elif a == complete: result = "completeBarrierfree"
diff --git a/src/backend/hafas/parse/date.nim b/src/backend/hafas/parse/date.nim
deleted file mode 100644
index de04406..0000000
--- a/src/backend/hafas/parse/date.nim
+++ /dev/null
@@ -1,31 +0,0 @@
-import ../types
-import options
-import strutils
-import times
-
-proc parseDate*(common: CommonData, time: Option[string], tzoffset: Option[int]): Option[int64] =
- if time.isNone:
- return none(int64)
-
- let tzoffset = tzoffset.get(60) # FIXME: sometimes no time zone is given. how to deal with that?
- let date = common.dateStr
- var time = time.get
- var dayoffset = 0
-
- if time.len == 8:
- dayoffset = parseInt(time[0..1])
- time = time[2..7]
-
- var tzoffhours = align($(int(tzoffset / 60)), 2, '0')
- var tzoffmins = align($(tzoffset mod 60), 2, '0')
- var tzoff = tzoffhours & ":" & tzoffmins
- if tzoffset >= 0:
- tzoff = "+" & tzoff
-
- let datestr = date & time & tzoff
- let dateformat = "yyyyMMddHHmmsszzz"
- var dt = datestr.parse(dateformat)
-
- dt = dt + initTimeInterval(days = dayoffset)
- return some(dt.toTime().toUnix())
-
diff --git a/src/backend/hafas/parse/journey.nim b/src/backend/hafas/parse/journey.nim
deleted file mode 100644
index b6ebafc..0000000
--- a/src/backend/hafas/parse/journey.nim
+++ /dev/null
@@ -1,38 +0,0 @@
-import ../types
-import json
-import leg
-import options
-
-proc mkParseJourney*(common: CommonData): proc =
- proc parseJourney(j: JsonNode): Journey =
- var common = common
- common.dateStr = j{"date"}.getStr()
-
- if j{"trfRes"}{"statusCode"}.getStr == "OK":
- result.price = some(Price(
- amount: j["trfRes"]["fareSetL"][0]["fareL"][0]["prc"].getInt / 100,
- currency: some("Euro"),
- ))
-
- result.refreshToken = j{"ctxRecon"}.getStr()
- result.legs = j{"secL"}.getElems().map(mkParseLeg(common))
- result.lastUpdated = common.timeStamp
-
- # combine walking legs
- var i = -1
- var firstWalking = -1
- while true:
- inc(i)
- if i >= len(result.legs): break
- if result.legs[i].isWalking:
- if firstWalking == -1:
- firstWalking = i
- else:
- result.legs[firstWalking].arrival = result.legs[i].arrival
- result.legs[firstWalking].distance.get += result.legs[i].distance.get
- result.legs.delete(i)
- dec(i)
- else:
- firstWalking = -1
-
- return parseJourney
diff --git a/src/backend/hafas/parse/journeys_response.nim b/src/backend/hafas/parse/journeys_response.nim
deleted file mode 100644
index 5eb84e5..0000000
--- a/src/backend/hafas/parse/journeys_response.nim
+++ /dev/null
@@ -1,27 +0,0 @@
-import ../types
-import ./remark
-import ./point
-import ./operator
-import ./journey
-import ./line
-import ./polyline
-import json
-import sequtils
-import strutils
-
-proc parseJourneysResponse*(data: JsonNode, isRefresh: bool = false): JourneysResponse =
- let points = map(data["res"]["common"]["locL"].getElems(), parsePoint)
- let operators = map(data["res"]["common"]["opL"].getElems(), parseOperator)
- let remarks = map(data["res"]["common"]["remL"].getElems(), parseRemark)
- let lines = data["res"]["common"]["prodL"]
- let polylines = map(data["res"]["common"]["polyL"].getElems(), mkParsePolyline(points))
- let timestamp = parseInt(data["res"]["planrtTS"].getStr())
- let common = CommonData(points: points, operators: operators, remarks: remarks, lines: lines, polylines: polylines, timestamp: timestamp)
-
- result.journeys = data["res"]["outConL"].getElems().map(mkParseJourney(common))
- if not isRefresh:
- if data["res"].hasKey("outCtxScrB"):
- result.earlierRef = data["res"]["outCtxScrB"].getStr()
-
- if data["res"].hasKey("outCtxScrF"):
- result.laterRef = data["res"]["outCtxScrF"].getStr()
diff --git a/src/backend/hafas/parse/leg.nim b/src/backend/hafas/parse/leg.nim
deleted file mode 100644
index 2a966eb..0000000
--- a/src/backend/hafas/parse/leg.nim
+++ /dev/null
@@ -1,67 +0,0 @@
-import ../types
-import ./stopover
-import ./msg
-import ./date
-import ./line
-import json
-import options
-
-proc parseLegPart(common: CommonData, lp: JsonNode): LegPart =
- let h = lp.to(HafasStopParams)
- let plannedDepartureTime = parseDate(common, h.dTimeS, h.dTZOffset)
- let plannedArrivalTime = parseDate(common, h.aTimeS, h.aTZOffset)
-
- if h.dPlatfS.isSome: result.plannedPlatform = h.dPlatfS
- elif h.aPlatfS.isSome: result.plannedPlatform = h.aPlatfS
- if h.dPlatfR.isSome: result.prognosedPlatform = h.dPlatfR
- elif h.aPlatfR.isSome: result.prognosedPlatform = h.aPlatfR
- if h.dTimeR.isSome: result.prognosedTime = parseDate(common, h.dTimeR, h.dTZOffset)
- elif h.aTimeR.isSome: result.prognosedTime = parseDate(common, h.aTimeR, h.aTZOffset)
-
- if plannedDepartureTime.isSome: result.plannedTime = plannedDepartureTime.get
- elif plannedArrivalTime.isSome: result.plannedTime = plannedArrivalTime.get
- else: raise newException(CatchableError, "missing departure and arrival time for leg")
-
- result.point = common.points[h.locX.get]
-
-proc mkParseLeg*(common: CommonData): proc =
- proc parseLeg(l: JsonNode): Leg =
-
- if l{"jny"}{"polyG"}{"polyXL"}.getElems().len() > 0:
- result.polyline = some(Polyline(
- type: "FeatureCollection",
- ))
- for n in l{"jny"}{"polyG"}{"polyXL"}.getElems():
- result.polyline.get.features &= common.polylines[n.getInt()].features
-
- let typeStr = l{"type"}.getStr()
- if typeStr == "JNY":
- result.direction = some(l{"jny"}{"dirTxt"}.getStr())
- result.tripId = some(l{"jny"}{"jid"}.getStr())
- result.line = common.parseLine(l["jny"]["prodX"].getInt())
-
- let stopovers = l{"jny"}{"stopL"}.getElems()
- if stopovers.len > 0:
- result.stopovers = some(stopovers.map(mkParseStopover(common)))
-
- let remarks = l{"jny"}{"msgL"}.getElems()
- if remarks.len > 0:
- result.remarks = some(remarks.map(mkParseMsg(common)))
-
- elif typeStr == "WALK":
- result.isWalking = true
- result.distance = some(l{"gis"}{"dist"}.getInt())
-
- elif typeStr == "TRSF" or typeStr == "DEVI":
- result.isTransfer = true
-
- else:
- raise newException(CatchableError, "Unimplemented hafas leg type: " & typeStr)
-
- result.departure = common.parseLegPart(l{"dep"})
- result.arrival = common.parseLegPart(l{"arr"})
-
- result.cancelled = l{"dep"}{"dCncl"}.getBool(false) or l{"arr"}{"aCncl"}.getBool(false)
-
- return parseLeg
-
diff --git a/src/backend/hafas/parse/line.nim b/src/backend/hafas/parse/line.nim
deleted file mode 100644
index c37d390..0000000
--- a/src/backend/hafas/parse/line.nim
+++ /dev/null
@@ -1,71 +0,0 @@
-import ../types
-import ../util
-import ./products
-import json
-import options
-import tables
-import httpClient
-import asyncdispatch
-
-
-var trainTypes = initTable[string, string]()
-var trainTypesShort = initTable[string, string]()
-
-proc fetchTrainTypes() {.async.} =
- var client = newAsyncHttpClient()
- let resp = await client.getContent("https://lib.finalrewind.org/dbdb/ice_type.json")
- let data = parseJson(resp)
- for key, info in pairs(data):
- if info{"type"}.getStr != "" and info{"type"}.getStr != "EC" and info{"type"}.getStr != "IC":
- trainTypes[key] = info{"type"}.getStr
- if info{"short"}.getStr != "":
- trainTypesShort[key] = info{"short"}.getStr
-
-asyncCheck fetchTrainTypes()
-
-
-proc parseLine*(common: CommonData, i: int): Option[Line] =
- let l = common.lines[i]
-
- # unparsable
- if l{"cls"}.getInt == 0:
- return options.none(Line)
-
- let line = l.to(HafasProd)
- var res = Line()
-
- res.name = line.name
- res.product = parseProduct(line.cls)
- res.tripNum = line.prodCtx.num
-
- if not isNone(line.prodCtx.catOut):
- res.productName = get(line.prodCtx.catOut)
- else:
- res.productName = "?"
-
- res.fullProductName = line.prodCtx.catOutL
- res.id = slug(line.prodCtx.lineId.get(line.name))
-
- if line.opX.isSome:
- res.operator = some(common.operators[line.opX.get])
-
- # DB
-
- if res.productName == "IC" or res.productName == "ICE" or res.productName == "EC" or res.productName == "ECE":
- if trainTypes.contains(res.tripNum) and trainTypes[res.tripNum] != res.productName:
- res.trainType = some(trainTypes[res.tripNum])
- if trainTypesShort.contains(res.tripNum):
- res.trainTypeShort = some(trainTypesShort[res.tripNum])
-
- if line.nameS.isSome and (res.product == bus or res.product == tram or res.product == ferry):
- res.name = line.nameS.get
-
- if line.addName.isSome:
- # swap name and addName
- res.additionalName = some(res.name)
- res.name = line.addName.get
-
- # End DB
-
- res.mode = MODES[int(res.product)]
- return some(res)
diff --git a/src/backend/hafas/parse/msg.nim b/src/backend/hafas/parse/msg.nim
deleted file mode 100644
index 3e04a38..0000000
--- a/src/backend/hafas/parse/msg.nim
+++ /dev/null
@@ -1,12 +0,0 @@
-import ../types
-import json
-
-proc mkParseMsg*(common: CommonData): proc =
- proc parseMsg(m: JsonNode): Remark =
- let typeStr = m{"type"}.getStr()
- if typeStr != "REM":
- raise newException(CatchableError, "Unimplemented hafas msg type: " & typeStr)
- return common.remarks[m{"remX"}.getInt()]
-
- return parseMsg
-
diff --git a/src/backend/hafas/parse/operator.nim b/src/backend/hafas/parse/operator.nim
deleted file mode 100644
index b7b7712..0000000
--- a/src/backend/hafas/parse/operator.nim
+++ /dev/null
@@ -1,9 +0,0 @@
-import ../../../types
-import ../util
-import json
-
-proc parseOperator*(op: JsonNode): Operator =
- return (%* {
- "name": op{"name"},
- "id": %* slug(op{"name"}.getStr()),
- }).to(Operator)
diff --git a/src/backend/hafas/parse/point.nim b/src/backend/hafas/parse/point.nim
deleted file mode 100644
index 38451e4..0000000
--- a/src/backend/hafas/parse/point.nim
+++ /dev/null
@@ -1,78 +0,0 @@
-import ../types
-import ./products
-import json
-import options
-import tables
-
-proc parsePoint*(loc: JsonNode): Point =
- let typeStr = loc{"type"}.getStr()
- if typeStr == "S":
- result.stop = some(Stop(
- id: loc{"extId"}.getStr(),
- name: loc{"name"}.getStr(),
- location: Location(
- latitude: loc{"crd"}{"y"}.getInt() / 1000000,
- longitude: loc{"crd"}{"x"}.getInt() / 1000000,
- ),
- products: parseProducts(loc{"pCls"}.getInt()),
- ))
- elif typeStr == "P":
- result.location = some(Location(
- id: some(loc{"extId"}.getStr()),
- name: some(loc{"name"}.getStr()),
- latitude: loc{"crd"}{"y"}.getInt() / 1000000,
- longitude: loc{"crd"}{"x"}.getInt() / 1000000,
- ))
- elif typeStr == "A":
- result.location = some(Location(
- address: some(loc{"name"}.getStr()),
- latitude: loc{"crd"}{"y"}.getInt() / 1000000,
- longitude: loc{"crd"}{"x"}.getInt() / 1000000,
- ))
- else:
- raise newException(CatchableError, "Unimplemented hafas loc type: " & typeStr)
-
-proc formatLocationIdentifier(d: Table[string, string]): string =
- for key, val in d:
- result &= key
- result &= "="
- result &= val
- result &= "@"
-
-proc formatCoord(c: float): string =
- return $int(c * 1000000)
-
-proc formatPoint*(point: Point): JsonNode =
- if point.stop.isSome:
- let stop = point.stop.get
- return %* {
- "type": "S",
- "lid": formatLocationIdentifier({
- "A": "1",
- "L": $stop.id,
- }.toTable),
- }
- elif point.location.isSome:
- let loc = point.location.get
- if loc.address.isSome:
- return %* {
- "type": "A",
- "lid": formatLocationIdentifier({
- "A": "2",
- "O": loc.address.get,
- "X": formatCoord(loc.longitude),
- "Y": formatCoord(loc.latitude),
- }.toTable),
- }
- elif loc.name.isSome and loc.id.isSome:
- return %* {
- "type": "P",
- "lid": formatLocationIdentifier({
- "A": "4",
- "O": loc.address.get,
- "L": loc.id.get,
- "X": formatCoord(loc.longitude),
- "Y": formatCoord(loc.latitude),
- }.toTable),
- }
- raise newException(CatchableError, "Cannot format HAFAS location")
diff --git a/src/backend/hafas/parse/polyline.nim b/src/backend/hafas/parse/polyline.nim
deleted file mode 100644
index 1da6aa3..0000000
--- a/src/backend/hafas/parse/polyline.nim
+++ /dev/null
@@ -1,73 +0,0 @@
-import ../types
-import json
-import options
-import math
-
-proc gpsDistance(fromLat: float, fromLon: float, toLat: float, toLon: float): float =
- proc toRad(x: float): float = x * PI / 180
- let dLat = toRad(toLat - fromLat)
- let dLon = toRad(toLon - fromLon)
- let fromLat = toRad(fromLat)
- let toLat = toRad(toLat)
- let a = pow(sin(dLat / 2), 2) + (pow(sin(dLon / 2), 2) * cos(fromLat) * cos(toLat))
- let c = 2 * arctan2(sqrt(a), sqrt(1 - a))
- return 6371 * c
-
-proc parseIntegers(str: string): seq[int] =
- var byte = 0
- var current = 0
- var bits = 0
- for c in str:
- byte = int(c) - 63
- current = current or (( byte and 31 ) shl bits)
- bits += 5
-
- if byte < 32:
- if (current and 1) == 1:
- current = -current
- current = current shr 1
-
- result.add(current)
-
- current = 0
- bits = 0
-
-proc mkParsePolyline*(points: seq[Point]): proc =
- proc parsePolyline(l: JsonNode): Polyline =
- let line = l.to(HafasPolyLine)
-
- result.type = "FeatureCollection"
-
- var lat = 0
- var lon = 0
-
- let ints = parseIntegers(line.crdEncYX)
- var i = 0
- while i < len(ints):
- lat += ints[i]
- lon += ints[i+1]
- result.features.add(Feature(
- type: "Feature",
- geometry: FeatureGeometry(
- type: "Point",
- coordinates: @[lon / 100000, lat / 100000],
- ),
- ))
- i += 2
-
- if line.ppLocRefL.isSome:
- for p in line.ppLocRefL.get:
- result.features[p.ppIdx].properties = points[p.locX].stop
-
- # sort out coordinates closer than 5m to their neighbours
- var j = 1
- while true:
- if j >= len(result.features): break
- let last = result.features[j-1].geometry.coordinates
- let current = result.features[j].geometry.coordinates
- if gpsDistance(last[1], last[0], current[1], current[0]) <= 0.005:
- result.features.delete(j)
- continue
- j += 1
-
- return parsePolyline
diff --git a/src/backend/hafas/parse/products.nim b/src/backend/hafas/parse/products.nim
deleted file mode 100644
index ba2d084..0000000
--- a/src/backend/hafas/parse/products.nim
+++ /dev/null
@@ -1,37 +0,0 @@
-import ../../../types
-import bitops
-
-proc parseProduct*(cls: int): Product =
- var tmp = cls
- var res = 0
- while tmp > 1:
- tmp = tmp shr 1
- res += 1
-
- return Product(res)
-
-proc parseProducts*(pCls: int): Products =
- return Products(
- nationalExp: pCls.testBit(0),
- national: pCls.testBit(1),
- regionalExp: pCls.testBit(2),
- regional: pCls.testBit(3),
- suburban: pCls.testBit(4),
- bus: pCls.testBit(5),
- ferry: pCls.testBit(6),
- subway: pCls.testBit(7),
- tram: pCls.testBit(8),
- taxi: pCls.testBit(9),
- )
-
-proc formatProducts*(p: Products): int =
- if p.nationalExp: result.setBit(0)
- if p.national: result.setBit(1)
- if p.regionalExp: result.setBit(2)
- if p.regional: result.setBit(3)
- if p.suburban: result.setBit(4)
- if p.bus: result.setBit(5)
- if p.ferry: result.setBit(6)
- if p.subway: result.setBit(7)
- if p.tram: result.setBit(8)
- if p.taxi: result.setBit(9)
diff --git a/src/backend/hafas/parse/remark.nim b/src/backend/hafas/parse/remark.nim
deleted file mode 100644
index 63ffc8b..0000000
--- a/src/backend/hafas/parse/remark.nim
+++ /dev/null
@@ -1,32 +0,0 @@
-import ../../../types
-import json
-
-proc parseRemark*(rem: JsonNode): Remark =
- let typeStr = rem{"type"}.getStr()
- if typeStr == "M" or typeStr == "P":
- return (%* {
- "type": %* "status",
- "summary": rem{"txtS"},
- "code": rem{"code"},
- "text": rem{"txtN"},
- }).to(Remark)
- elif typeStr == "L":
- return (%* {
- "type": %* "status",
- "code": %* "alternative-trip",
- "text": rem{"txtN"},
- "tripId": rem{"jid"},
- }).to(Remark)
- elif typeStr == "A" or typeStr == "I" or typeStr == "H":
- return (%* {
- "type": %* "hint",
- "code": rem{"code"},
- "text": rem{"txtN"},
- }).to(Remark)
- else:
- # TODO: parse more accurately
- return (%* {
- "type": %* "status",
- "code": rem{"code"},
- "text": rem{"txtN"},
- }).to(Remark)
diff --git a/src/backend/hafas/parse/stopover.nim b/src/backend/hafas/parse/stopover.nim
deleted file mode 100644
index 67bb74a..0000000
--- a/src/backend/hafas/parse/stopover.nim
+++ /dev/null
@@ -1,33 +0,0 @@
-import ../types
-import ./date
-import options
-import json
-
-proc parseStopoverPart(common: CommonData, mode: string, h: HafasStopParams): StopoverPart =
-
- if (mode != "arrival"):
- result.plannedPlatform = h.dPlatfS
- result.prognosedPlatform = h.dPlatfR
- result.plannedTime = parseDate(common, h.dTimeS, h.dTZOffset)
- result.prognosedTime = parseDate(common, h.dTimeR, h.dTZOffset)
- else:
- result.plannedPlatform = h.aPlatfS
- result.prognosedPlatform = h.aPlatfR
- result.plannedTime = parseDate(common, h.aTimeS, h.aTZOffset)
- result.prognosedTime = parseDate(common, h.aTimeR, h.aTZOffset)
-
-proc mkParseStopover*(common: CommonData): proc =
- proc parseStopover(s: JsonNode): Stopover =
- let typeStr = s{"type"}.getStr()
- if typeStr != "N":
- echo pretty(s)
- raise newException(CatchableError, "Unimplemented hafas stopover type: " & typeStr)
-
- let h = s.to(HafasStopParams)
- result.stop = common.points[s{"locX"}.getInt()].stop.get
- result.cancelled = h.aCncl.get(false) or h.dCncl.get(false)
- result.arrival = common.parseStopoverPart("arrival", h)
- result.departure = common.parseStopoverPart("departure", h)
-
- return parseStopover
-
diff --git a/src/backend/hafas/todo b/src/backend/hafas/todo
deleted file mode 100644
index 96dfd9f..0000000
--- a/src/backend/hafas/todo
+++ /dev/null
@@ -1,10 +0,0 @@
-- implement leg parsing with nim types
-- check and pass back hafas errors
-- isAdd (is additional stop)
-- hafas information manager (him) remarks
-- cycle information
-- price information
-- reachable
-- profiles
-- mark current alternatives
-- stations
diff --git a/src/backend/hafas/types.nim b/src/backend/hafas/types.nim
deleted file mode 100644
index d36baa4..0000000
--- a/src/backend/hafas/types.nim
+++ /dev/null
@@ -1,53 +0,0 @@
-import ../../types
-import options
-export types
-import json
-
-type
- CommonData* = object
- lines*: JsonNode
- remarks*: seq[Remark]
- operators*: seq[Operator]
- points*: seq[Point]
- polylines*: seq[Polyline]
- dateStr*: string
- timestamp*: int64
-
- HafasStopParams* = object
- aTimeS*: Option[string]
- aPlatfS*: Option[string]
- aTZOffset*: Option[int]
- aCncl*: Option[bool]
- aTimeR*: Option[string]
- aPlatfR*: Option[string]
- dTimeS*: Option[string]
- dPlatfS*: Option[string]
- dTZOffset*: Option[int]
- dCncl*: Option[bool]
- dTimeR*: Option[string]
- dPlatfR*: Option[string]
- locX*: Option[int]
-
- HafasProdCtx* = object
- name*: string
- num*: string
- catOut*: Option[string]
- catOutL*: string
- lineId*: Option[string]
-
- HafasProd* = object
- name*: string
- cls*: int
- icoX*: int
- nameS*: Option[string]
- addName*: Option[string]
- opX*: Option[int]
- prodCtx*: HafasProdCtx
-
- HafasLocRef* = object
- ppIdx*: int
- locX*: int
-
- HafasPolyline* = object
- crdEncYX*: string
- ppLocRefL*: Option[seq[HafasLocRef]]
diff --git a/src/backend/hafas/util.nim b/src/backend/hafas/util.nim
deleted file mode 100644
index 44dba35..0000000
--- a/src/backend/hafas/util.nim
+++ /dev/null
@@ -1,57 +0,0 @@
-import httpclient
-import asyncdispatch
-import md5
-import json
-import strutils
-import errors
-
-proc slug*(s: string): string =
- for c in s:
- if c.isAlphaNumeric():
- result &= c.toLowerAscii()
- else:
- result &= '-'
-
-proc request*(req: JsonNode): Future[JsonNode] {.async.} =
- let client = newAsyncHttpClient()
-
- let body = %*{
- "lang": "de",
- "svcReqL": [req]
- }
-
- # TODO: move to profile
- body["svcReqL"][0]["cfg"]["rtMode"] = %* "HYBRID"
- body["client"] = %* {
- "id": "DB",
- "v": "16040000",
- "type": "IPH",
- "name": "DB Navigator"
- }
- body["ext"] = %* "DB.R19.04.a"
- body["ver"] = %* "1.16"
- body["auth"] = %* {
- "type": "AID",
- "aid": "n91dB8Z77MLdoR0K"
- }
- let salt = "bdI8UVj40K5fvxwf"
- let bodytext = $body
- let checksum = $toMD5(bodytext & salt)
- let url = "https://reiseauskunft.bahn.de/bin/mgate.exe?checksum=" & checksum
-
- client.headers = newHttpHeaders({
- "Content-Type": "application/json",
- "Accept": "application/json",
- "user-agent": "my-awesome-e5f276d8fe6cprogram",
- })
-
- #echo pretty body
- let req = await client.request(url, httpMethod = HttpPost, body = $body)
- let resp = await req.body
- let data = parseJson(resp)
-
- let error = data{"svcResL"}{0}{"err"}.getStr()
- if error != "OK":
- raise parseError(error)
-
- return data{"svcResL"}{0}
diff --git a/src/endpoints/api/journeys.nim b/src/endpoints/api/journeys.nim
index d9f9631..33b7e7c 100644
--- a/src/endpoints/api/journeys.nim
+++ b/src/endpoints/api/journeys.nim
@@ -1,5 +1,5 @@
import json, tables, options, asyncdispatch
-import ../../types, ../../backend/hafas, ../../cache
+import ../../types, ../../hafas/hafas, ../../cache
when not defined(release):
import hotcodereloading
diff --git a/src/endpoints/api/moreJourneys.nim b/src/endpoints/api/moreJourneys.nim
index aff9bf1..eb9b89a 100644
--- a/src/endpoints/api/moreJourneys.nim
+++ b/src/endpoints/api/moreJourneys.nim
@@ -1,5 +1,5 @@
import json, tables, options, asyncdispatch, strutils
-import ../../types, ../../cache_types, ../../backend/hafas, ../../cache
+import ../../types, ../../cache_types, ../../hafas/hafas, ../../cache
proc moreJourneysEndpoint*(requestData: JsonNode): Future[JsonNode] {.async.} =
var reqId = requestData{"reqId"}.getStr()
@@ -39,4 +39,4 @@ proc moreJourneysEndpoint*(requestData: JsonNode): Future[JsonNode] {.async.} =
return response
else:
- raise newException(errorException, "MISSING_VALUES") \ No newline at end of file
+ raise newException(errorException, "MISSING_VALUES")
diff --git a/src/endpoints/api/refreshJourney.nim b/src/endpoints/api/refreshJourney.nim
index b53d0ed..154c9f1 100644
--- a/src/endpoints/api/refreshJourney.nim
+++ b/src/endpoints/api/refreshJourney.nim
@@ -1,5 +1,5 @@
import json, tables, options, asyncdispatch, strutils
-import ../../types, ../../cache_types, ../../backend/hafas, ../../cache
+import ../../types, ../../cache_types, ../../hafas/hafas, ../../cache
proc refreshJourneyEndpoint*(requestData: JsonNode): Future[JsonNode] {.async.} =
let reqId = requestData{"reqId"}.getStr()
@@ -34,4 +34,4 @@ proc refreshJourneyEndpoint*(requestData: JsonNode): Future[JsonNode] {.async.}
delete(response["journeys"][journeyId]["legs"][legKey], "cycle")
delete(response["journeys"][journeyId]["legs"][legKey], "tripId")
- return response \ No newline at end of file
+ return response
diff --git a/src/endpoints/api/suggestions.nim b/src/endpoints/api/suggestions.nim
index 0543f71..6509a27 100644
--- a/src/endpoints/api/suggestions.nim
+++ b/src/endpoints/api/suggestions.nim
@@ -1,5 +1,5 @@
import json, options, asyncdispatch
-import ../../types, ../../backend/hafas
+import ../../types, ../../hafas/hafas
proc suggestionsEndpoint* (data: JsonNode): Future[JsonNode] {.async.} =
return %* (await suggestions(data.to(SuggestionsParams)))
diff --git a/src/endpoints/journeyHandler.nim b/src/endpoints/journeyHandler.nim
index 89d9fa9..219967e 100644
--- a/src/endpoints/journeyHandler.nim
+++ b/src/endpoints/journeyHandler.nim
@@ -1,6 +1,6 @@
import json, options, strutils, tables
import ../asyncWebServer
-import ../utils, ../translations, ../types, ../cache_types, ../cache, ../backend/hafas
+import ../utils, ../translations, ../types, ../cache_types, ../cache, ../hafas/hafas
import ../formaters/renderJourney
proc journeyHandler* (request: Request, server: ServerRef) {.async.} =
diff --git a/src/endpoints/journeysHandler.nim b/src/endpoints/journeysHandler.nim
index d6743a5..0bd01e4 100644
--- a/src/endpoints/journeysHandler.nim
+++ b/src/endpoints/journeysHandler.nim
@@ -1,6 +1,6 @@
import json, asyncdispatch, options, strutils
import ../asyncWebServer
-import ../utils, ../translations, ../types, ../cache_types, ../cache, ../backend/hafas
+import ../utils, ../translations, ../types, ../cache_types, ../cache, ../hafas/hafas
import ../formaters/renderJourneys
proc journeysHandler* (request: Request, server: ServerRef) {.async.} =
diff --git a/src/endpoints/searchHandler.nim b/src/endpoints/searchHandler.nim
index 24689bb..1d4ee6f 100644
--- a/src/endpoints/searchHandler.nim
+++ b/src/endpoints/searchHandler.nim
@@ -1,6 +1,6 @@
import json, times, options, strutils
import ../asyncWebServer
-import ../utils, ../translations, ../types, ../cache_types, ../cache, ../backend/hafas
+import ../utils, ../translations, ../types, ../cache_types, ../cache, ../hafas/hafas
import ../formaters/formaters, ../formaters/renderJourneys
proc searchHandler* (request: Request, server: ServerRef) {.async.} =
diff --git a/src/endpoints/suggestionsHandler.nim b/src/endpoints/suggestionsHandler.nim
index bbbb533..f78872c 100644
--- a/src/endpoints/suggestionsHandler.nim
+++ b/src/endpoints/suggestionsHandler.nim
@@ -1,6 +1,6 @@
import json, options, strutils
import ../asyncWebServer
-import ../types, ../backend/hafas
+import ../types, ../hafas/hafas
import ../formaters/formaters
proc suggestionsHandler* (request: Request, server: ServerRef) {.async.} =
diff --git a/src/hafas b/src/hafas
new file mode 160000
+Subproject e815bbfd2ef4f49c4e3a757739a60d802bcc53f
diff --git a/src/oeffi.nim b/src/oeffi.nim
index d98d1a1..dc8ac3a 100644
--- a/src/oeffi.nim
+++ b/src/oeffi.nim
@@ -13,7 +13,7 @@ import endpoints/api/journeys
import endpoints/api/moreJourneys
import endpoints/api/refreshJourney
-import types, backend/hafas, formaters/formaters
+import types, hafas/hafas, formaters/formaters
proc removePidFile() =
if getEnv("PID_FILE") != "":
diff --git a/src/utils.nim b/src/utils.nim
index f6e85d1..2b5dcee 100644
--- a/src/utils.nim
+++ b/src/utils.nim
@@ -1,5 +1,5 @@
import json, asyncdispatch, asynchttpserver, options, strutils, httpcore
-import types, translations, backend/hafas
+import types, translations, hafas/hafas
import moustachu, moustachu_context
proc getPoint* (name: string): Future[Point] {.async} =