From 4a7bcd7f80f3183963afe18f4738f655810ab111 Mon Sep 17 00:00:00 2001 From: Fred Boniface Date: Sun, 7 Apr 2024 20:59:41 +0100 Subject: [PATCH] Increase use of pointers to minimise memory usage --- cif/convert.go | 55 +++++++++++++++++++++++++++++++++++++++++++++ cif/convert_test.go | 31 +++++++++++++++++++++++++ cif/helpers.go | 12 +++++----- cif/helpers_test.go | 4 ++-- cif/process.go | 12 +++++----- 5 files changed, 101 insertions(+), 13 deletions(-) create mode 100644 cif/convert.go create mode 100644 cif/convert_test.go diff --git a/cif/convert.go b/cif/convert.go new file mode 100644 index 0000000..5097ddc --- /dev/null +++ b/cif/convert.go @@ -0,0 +1,55 @@ +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" +) + +func ConvertServiceType(input *upstreamApi.JsonScheduleV1, vstp bool) (*database.Service, error) { + output := database.Service{ + TransactionType: input.TransactionType, + StpIndicator: input.CifStpIndicator, + Vstp: vstp, // Simply uses the value passed into the function + 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"), + 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 { + log.Msg.Debug("CIFSpeed Input: '" + *CIFSpeed + "'") + if *CIFSpeed == "" || CIFSpeed == nil { + log.Msg.Debug("Speed data not provided") + return int32(0) + } + actualSpeed, exists := helpers.SpeedMap[*CIFSpeed] + if !exists { + actualSpeed = *CIFSpeed + } + log.Msg.Debug("Corrected Speed: " + actualSpeed) + + speed, err := strconv.ParseInt(actualSpeed, 10, 32) + if err != nil { + log.Msg.Warn("Unable to parse speed: " + *CIFSpeed + ", returning 0") + return int32(0) + } + return int32(speed) +} + +func parseStops(input *[]upstreamApi.CifScheduleLocation) []database.Stop { + output := make([]database.Stop, 0, len(*input)) + return output +} diff --git a/cif/convert_test.go b/cif/convert_test.go new file mode 100644 index 0000000..8233ebc --- /dev/null +++ b/cif/convert_test.go @@ -0,0 +1,31 @@ +package cif + +import "testing" + +func TestParseSpeed(t *testing.T) { + testCases := []struct { + input *string + expected int32 + }{ + {strPtr("075"), 75}, + {strPtr("125"), 125}, + {strPtr("40"), 40}, + {strPtr("040"), 40}, + {strPtr("134"), 60}, + {strPtr("179"), 80}, + {strPtr("186"), 186}, + {strPtr("417"), 186}, + } + + for _, tc := range testCases { + result := parseSpeed(tc.input) + + if result != tc.expected { + t.Errorf("For speed: %s, expected: %d, but got: %d", tc.input, tc.expected, result) + } + } +} + +func strPtr(s string) *string { + return &s +} diff --git a/cif/helpers.go b/cif/helpers.go index a81a50f..7f89ebf 100644 --- a/cif/helpers.go +++ b/cif/helpers.go @@ -70,11 +70,11 @@ func generateUpdateDays(days int) []time.Time { } // Parses CIF Schedule Start/End Dates (YYYY-MM-DD) into time.Time types (00:00:00 for start, 23:59:59 for end) -func ParseCifDate(input, startOrEnd string) time.Time { +func ParseCifDate(input *string, startOrEnd string) time.Time { layout := "2006-01-02" // Layout of input - t, err := time.ParseInLocation(layout, input, londonTimezone) + t, err := time.ParseInLocation(layout, *input, londonTimezone) if err != nil { - log.Msg.Error("Error parsing date string", zap.String("date string", input), zap.Error(err)) + log.Msg.Error("Error parsing date string", zap.String("date string", *input), zap.Error(err)) return time.Time{} } @@ -83,7 +83,7 @@ func ParseCifDate(input, startOrEnd string) time.Time { } else if startOrEnd == "end" { t = time.Date(t.Year(), t.Month(), t.Day(), 23, 59, 59, 0, londonTimezone) } else { - log.Msg.Error("Error parsing date string", zap.String("date string", input), zap.Error(err)) + log.Msg.Error("Error parsing date string", zap.String("date string", *input), zap.Error(err)) return time.Time{} } @@ -91,10 +91,10 @@ func ParseCifDate(input, startOrEnd string) time.Time { } // Parses CIF days_run field and converts to array of day strings -func parseDaysRun(daysBinary string) []string { +func parseDaysRun(daysBinary *string) []string { shortDays := []string{"m", "t", "w", "th", "f", "s", "su"} var result []string - for i, digit := range daysBinary { + for i, digit := range *daysBinary { if digit == '1' { result = append(result, shortDays[i]) } diff --git a/cif/helpers_test.go b/cif/helpers_test.go index e130b02..47ad779 100644 --- a/cif/helpers_test.go +++ b/cif/helpers_test.go @@ -102,7 +102,7 @@ func TestParseCifDate(t *testing.T) { layout := "2006-01-02 15:04:05" // Layout for printing times in error cases. for _, tc := range testCases { - result := ParseCifDate(tc.dateString, tc.startOrEnd) + result := ParseCifDate(&tc.dateString, tc.startOrEnd) if result != tc.expect { t.Errorf("For datestring %s, startOrEnd %s, expected %s, but got %s", tc.dateString, tc.startOrEnd, tc.expect.Format(layout), result.Format(layout)) } @@ -122,7 +122,7 @@ func TestParseDaysRun(t *testing.T) { } for _, tc := range testCases { - result := parseDaysRun(tc.input) + result := parseDaysRun(&tc.input) if !reflect.DeepEqual(result, tc.expect) { t.Errorf("For input %s, expected %v, but got %v", tc.input, tc.expect, result) } diff --git a/cif/process.go b/cif/process.go index 73d39d1..a46f1a0 100644 --- a/cif/process.go +++ b/cif/process.go @@ -47,7 +47,7 @@ func doDeletions(deletions []*upstreamApi.JsonScheduleV1) error { deleteQueries := make([]database.DeleteQuery, 0) for _, item := range deletions { query := database.DeleteQuery{ - ScheduleStartDate: ParseCifDate(item.ScheduleStartDate, "start"), + ScheduleStartDate: ParseCifDate(&item.ScheduleStartDate, "start"), StpIndicator: item.CifStpIndicator, TrainUid: item.CifTrainUid, } @@ -70,10 +70,12 @@ func doCreations(creations []*upstreamApi.JsonScheduleV1) error { createDocuments := make([]database.Service, 0) for _, item := range creations { - document := database.Service{} - // Do type conversion here - REMOVE THIS LOG LINE, IT WILL CAUSE 10000s of log entries - log.Msg.Debug("item", zap.Any("item", item)) - createDocuments = append(createDocuments, document) + document, err := ConvertServiceType(item, false) + if err != nil { + log.Msg.Error("Error converting JsonSchedule to Service type", zap.Error(err)) + } + + createDocuments = append(createDocuments, *document) } err := dbAccess.CreateCifEntries(createDocuments)