timetable-mgr/cif/convert.go

129 lines
3.6 KiB
Go

package cif
import (
"strconv"
"git.fjla.uk/owlboard/go-types/pkg/database"
"git.fjla.uk/owlboard/go-types/pkg/upstreamApi"
"git.fjla.uk/owlboard/timetable-mgr/helpers"
"git.fjla.uk/owlboard/timetable-mgr/log"
"go.uber.org/zap"
)
func ConvertServiceType(input *upstreamApi.JsonScheduleV1, vstp bool) (*database.Service, error) {
output := database.Service{
TransactionType: input.TransactionType,
StpIndicator: input.CifStpIndicator,
Operator: input.AtocCode,
TrainUid: input.CifTrainUid,
Headcode: input.ScheduleSegment.SignallingId,
PowerType: input.ScheduleSegment.CifPowerType,
PlanSpeed: parseSpeed(&input.ScheduleSegment.CifSpeed),
ScheduleStartDate: ParseCifDate(&input.ScheduleStartDate, "start"),
ScheduleEndDate: ParseCifDate(&input.ScheduleEndDate, "end"),
ServiceDetail: generateServiceDetail(&input.ScheduleSegment.CifTrainClass, &input.ScheduleSegment.SignallingId, &input.ScheduleSegment.CifCateringCode, &input.ScheduleSegment.CifSleepers, vstp),
DaysRun: parseDaysRun(&input.ScheduleDaysRun),
Stops: parseStops(&input.ScheduleSegment.ScheduleLocation),
}
return &output, nil
}
// Converts CifSpeed input string to an int32, automatically corrects VSTP speeds which are not actual speed values
func parseSpeed(CIFSpeed *string) int32 {
if CIFSpeed == nil {
return 0
}
if *CIFSpeed == "" {
return int32(0)
}
actualSpeed, exists := helpers.SpeedMap[*CIFSpeed]
if !exists {
actualSpeed = *CIFSpeed
}
speed, err := strconv.ParseInt(actualSpeed, 10, 32)
if err != nil {
log.Warn("Unable to parse speed", zap.String("input-value", *CIFSpeed))
return int32(0)
}
return int32(speed)
}
// Not tested
func parseStops(input *[]upstreamApi.CifScheduleLocation) []database.Stop {
output := make([]database.Stop, 0, len(*input))
for _, item := range *input {
stop := database.Stop{
PublicDeparture: item.PublicDeparture,
PublicArrival: item.PublicArrival,
WttDeparture: item.Departure,
WttArrival: item.Arrival,
Pass: item.Pass,
Platform: item.Platform,
ArrLine: item.Path,
DepLine: item.Line,
Tiploc: item.TiplocCode,
IsPublic: isPublic(&item),
}
output = append(output, stop)
}
return output
}
// Ascertains whether a given location is a public stop or not
func isPublic(input *upstreamApi.CifScheduleLocation) bool {
if input.PublicArrival == "" && input.PublicDeparture == "" {
return false
}
return true
}
// Generates a ServiceDetail struct based on the input
func generateServiceDetail(
cifTrainClass, signallingId,
cateringCode, sleepers *string,
vstp bool,
) database.ServiceDetail {
return database.ServiceDetail{
FirstClass: hasFirstClass(cifTrainClass, signallingId),
Catering: hasCatering(cateringCode),
Sleeper: hasSleeper(sleepers),
Vstp: vstp,
}
}
// Ascertains whether the service offers first class
func hasFirstClass(input, signallingId *string) bool {
if input == nil || signallingId == nil {
return false
}
// Handle non passenger headcodes and ensure first class is not shown as available
firstChar := (*signallingId)[0]
if firstChar == '3' || firstChar == '4' || firstChar == '5' || firstChar == '6' || firstChar == '7' || firstChar == '8' || firstChar == '0' {
return false
}
return *input != "S"
}
// Ascertains whether the service offers catering
func hasCatering(input *string) bool {
if input == nil {
return false
}
return *input != ""
}
// Ascertains whether the service offers sleeping berths
func hasSleeper(input *string) bool {
if input == nil {
return false
}
return *input != ""
}