This repository has been archived on 2025-07-20. You can view files and clone it, but you cannot make any changes to it's state, such as pushing and creating new issues, pull requests or comments.
hacknotts23/feedprocessor/schedule/structures.go
AKP 70d0fdc809
Alter 8 files
Update `config.go`
Add `feed.go`
Add `messageTypes.go`
Add `process.go`
Update `main.go`
Update `structures.go`
Update `go.mod`
Update `go.sum`
2023-02-12 05:57:10 +00:00

213 lines
5.4 KiB
Go

package schedule
import (
"bufio"
"context"
"encoding/json"
"fmt"
"github.com/pkg/errors"
"github.com/redis/go-redis/v9"
"github.com/rs/zerolog/log"
"io"
"os"
)
func LoadFile(client *redis.Client, filename string) error {
f, err := os.Open(filename)
if err != nil {
return err
}
defer f.Close()
scheduleIDCount := make(map[string]int)
n := 0
_, _ = fmt.Fprintf(os.Stderr, "%d\r", 0)
rd := bufio.NewReader(f)
for {
line, err := rd.ReadBytes('\n')
if err != nil {
if errors.Is(err, io.EOF) {
break
}
return err
}
record := new(Record)
if err := json.Unmarshal(line, record); err != nil {
log.Debug().Msg(err.Error())
log.Debug().Bytes("record", line).Send()
return err
}
if record.TIPLOC != nil {
r := client.HMSet(context.Background(), fmt.Sprintf("tiploc:%s", record.TIPLOC.Code), record.TIPLOC.ToMap())
if err := r.Err(); err != nil {
return err
}
}
if record.Schedule != nil {
n := scheduleIDCount[record.Schedule.CIFTrainUid]
scheduleIDCount[record.Schedule.CIFTrainUid] = n + 1
sched := fmt.Sprintf("schedule:%s:%d", record.Schedule.CIFTrainUid, n)
r := client.HMSet(context.Background(), sched, record.Schedule.ToMap())
if err := r.Err(); err != nil {
return err
}
rr := client.Set(context.Background(), sched+":locations", len(record.Schedule.ScheduleSegment.ScheduleLocation), 0)
if err := rr.Err(); err != nil {
return err
}
for i, loc := range record.Schedule.ScheduleSegment.ScheduleLocation {
r = client.HMSet(context.Background(), fmt.Sprintf("%s:locations:%d", sched, i), loc.ToMap())
if err := r.Err(); err != nil {
return err
}
}
}
n += 1
if n%1000 == 0 {
_, _ = fmt.Fprintf(os.Stderr, "%d\r", n)
}
}
_, _ = fmt.Fprintf(os.Stderr, "%d records processed\n", n)
for key, val := range scheduleIDCount {
client.Set(context.Background(), "schedule:"+key, val, 0)
}
_, _ = fmt.Fprintln(os.Stderr, "Inserted schedule counts")
return nil
}
type Record struct {
//TimetableDecl any `json:"JsonTimetableV1"`
TIPLOC *TIPLOC `json:"TiplocV1"`
// TODO: Associations?
Schedule *Schedule `json:"JsonScheduleV1"`
}
type TIPLOC struct {
Code string `json:"tiploc_code"`
Stanox string `json:"stanox"`
Description string `json:"tps_description"`
HumanDescription string `json:"description"`
}
func (t *TIPLOC) ToMap() map[string]interface{} {
mp := map[string]interface{}{
"description": t.Description,
}
if t.HumanDescription != "" {
mp["humanDescription"] = t.HumanDescription
}
return mp
}
type Schedule struct {
CIFStpIndicator string `json:"CIF_stp_indicator"`
CIFTrainUid string `json:"CIF_train_uid"`
ScheduleDaysRuns string `json:"schedule_days_runs"`
ScheduleEndDate string `json:"schedule_end_date"`
ScheduleSegment *ScheduleSegment `json:"schedule_segment"`
ScheduleStartDate string `json:"schedule_start_date"`
TrainStatus string `json:"train_status"`
}
func (s *Schedule) ToMap() map[string]interface{} {
return map[string]interface{}{
"signallingID": s.ScheduleSegment.SignallingId,
"stpIndicator": s.CIFStpIndicator,
"trainUID": s.CIFTrainUid,
"scheduleDaysRuns": s.ScheduleDaysRuns,
"trainStatus": s.TrainStatus,
}
}
type ScheduleSegment struct {
SignallingId string `json:"signalling_id"`
CIFTrainCategory string `json:"CIF_train_category"`
CIFHeadcode string `json:"CIF_headcode"`
CIFSpeed string `json:"CIF_speed"`
CIFTrainClass string `json:"CIF_train_class"`
ScheduleLocation []*ScheduleLocation `json:"schedule_location"`
}
type ScheduleLocation struct {
LocationType string `json:"location_type"`
RecordIdentity string `json:"record_identity"`
TiplocCode string `json:"tiploc_code"`
TiplocInstance *string `json:"tiploc_instance"`
Departure *string `json:"departure,omitempty"`
PublicDeparture *string `json:"public_departure,omitempty"`
Platform *string `json:"platform"`
EngineeringAllowance *string `json:"engineering_allowance,omitempty"`
PathingAllowance *string `json:"pathing_allowance"`
PerformanceAllowance *string `json:"performance_allowance"`
Arrival *string `json:"arrival,omitempty"`
Pass *string `json:"pass,omitempty"`
PublicArrival *string `json:"public_arrival,omitempty"`
}
func (s *ScheduleLocation) ToMap() map[string]interface{} {
m := map[string]interface{}{
"locationType": s.LocationType,
"recordIdentity": s.RecordIdentity,
"tiplocCode": s.TiplocCode,
}
if s.TiplocInstance != nil {
m["tiplocInstance"] = *s.TiplocInstance
}
if s.Departure != nil {
m["departure"] = *s.Departure
}
if s.PublicDeparture != nil {
m["publicDeparture"] = *s.PublicDeparture
}
if s.Platform != nil {
m["platform"] = *s.Platform
}
if s.EngineeringAllowance != nil {
m["engineeringAllowance"] = *s.EngineeringAllowance
}
if s.PathingAllowance != nil {
m["pathingAllowance"] = *s.PathingAllowance
}
if s.PerformanceAllowance != nil {
m["performanceAllowance"] = *s.PerformanceAllowance
}
if s.Arrival != nil {
m["arrival"] = *s.Arrival
}
if s.Pass != nil {
m["pass"] = *s.Pass
}
if s.PublicArrival != nil {
m["publicArrival"] = *s.PublicArrival
}
return m
}