[#21] locode: Introduce locode overriding
Signed-off-by: Airat Arifullin <a.arifullin@yadro.com>
This commit is contained in:
parent
16ff77e35c
commit
f2113a9c02
4 changed files with 71 additions and 4 deletions
1
Makefile
1
Makefile
|
@ -51,6 +51,7 @@ locode_db: in/unlocode-CodeList.csv in/unlocode-SubdivisionCodes.csv in/continen
|
|||
--continents in/continents.geojson \
|
||||
--countries in/countries.dat \
|
||||
--in in/unlocode-CodeList.csv \
|
||||
--overrides in/unlocode-CodeList_overrides.csv \
|
||||
--subdiv in/unlocode-SubdivisionCodes.csv \
|
||||
--out locode_db
|
||||
chmod 644 locode_db
|
||||
|
|
|
@ -16,6 +16,7 @@ type namesDB struct {
|
|||
|
||||
const (
|
||||
locodeGenerateInputFlag = "in"
|
||||
locodeGenerateOverridesFlag = "overrides"
|
||||
locodeGenerateSubDivFlag = "subdiv"
|
||||
locodeGenerateAirportsFlag = "airports"
|
||||
locodeGenerateCountriesFlag = "countries"
|
||||
|
@ -25,6 +26,7 @@ const (
|
|||
|
||||
var (
|
||||
locodeGenerateInPaths []string
|
||||
locodeGenerateOverridesPath string
|
||||
locodeGenerateSubDivPath string
|
||||
locodeGenerateAirportsPath string
|
||||
locodeGenerateCountriesPath string
|
||||
|
@ -35,11 +37,11 @@ var (
|
|||
Use: "generate",
|
||||
Short: "Generate UN/LOCODE database for FrostFS",
|
||||
Run: func(cmd *cobra.Command, _ []string) {
|
||||
|
||||
locodeDB := csvlocode.New(
|
||||
csvlocode.Prm{
|
||||
Path: locodeGenerateInPaths[0],
|
||||
SubDivPath: locodeGenerateSubDivPath,
|
||||
Path: locodeGenerateInPaths[0],
|
||||
SubDivPath: locodeGenerateSubDivPath,
|
||||
OverridesPath: locodeGenerateOverridesPath,
|
||||
},
|
||||
csvlocode.WithExtraPaths(locodeGenerateInPaths[1:]...),
|
||||
)
|
||||
|
@ -79,6 +81,8 @@ func initUtilLocodeGenerateCmd() {
|
|||
flags.StringSliceVar(&locodeGenerateInPaths, locodeGenerateInputFlag, nil, "List of paths to UN/LOCODE tables (csv)")
|
||||
_ = locodeGenerateCmd.MarkFlagRequired(locodeGenerateInputFlag)
|
||||
|
||||
flags.StringVar(&locodeGenerateOverridesPath, locodeGenerateOverridesFlag, "", "Path to UN/LOCODE override tables (csv)")
|
||||
|
||||
flags.StringVar(&locodeGenerateSubDivPath, locodeGenerateSubDivFlag, "", "Path to UN/LOCODE subdivision database (csv)")
|
||||
_ = locodeGenerateCmd.MarkFlagRequired(locodeGenerateSubDivFlag)
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@ package csvlocode
|
|||
import (
|
||||
"encoding/csv"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"strings"
|
||||
|
@ -40,6 +41,10 @@ func (t *Table) IterateAll(f func(locode.Record) error) error {
|
|||
Remarks: words[11],
|
||||
}
|
||||
|
||||
if err := t.Override(&record); err != nil {
|
||||
return fmt.Errorf("override: %w", err)
|
||||
}
|
||||
|
||||
return f(record)
|
||||
})
|
||||
}
|
||||
|
@ -84,6 +89,14 @@ func (t *Table) SubDivName(countryCode *locodedb.CountryCode, code string) (stri
|
|||
return rec.name, nil
|
||||
}
|
||||
|
||||
func (t *Table) Override(record *locode.Record) error {
|
||||
override, found := t.overrides[record.LOCODE]
|
||||
if found {
|
||||
*record = override
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *Table) initSubDiv() (err error) {
|
||||
t.subDivOnce.Do(func() {
|
||||
t.mSubDiv = make(map[subDivKey]subDivRecord)
|
||||
|
@ -103,6 +116,40 @@ func (t *Table) initSubDiv() (err error) {
|
|||
return
|
||||
}
|
||||
|
||||
func (t *Table) initOverrides(overridesPath string) error {
|
||||
const wordsPerRecord = 12
|
||||
|
||||
t.overrides = make(map[locode.LOCODE]locode.Record)
|
||||
|
||||
if overridesPath == "" {
|
||||
return nil
|
||||
}
|
||||
|
||||
return t.scanWords([]string{overridesPath}, wordsPerRecord, func(words []string) error {
|
||||
lc, err := locode.FromString(strings.Join(words[1:3], " "))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
record := locode.Record{
|
||||
Ch: words[0],
|
||||
LOCODE: *lc,
|
||||
Name: words[3],
|
||||
NameWoDiacritics: words[4],
|
||||
SubDiv: words[5],
|
||||
Function: words[6],
|
||||
Status: words[7],
|
||||
Date: words[8],
|
||||
IATA: words[9],
|
||||
Coordinates: words[10],
|
||||
Remarks: words[11],
|
||||
}
|
||||
|
||||
t.overrides[record.LOCODE] = record
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
var errScanInt = errors.New("interrupt scan")
|
||||
|
||||
func (t *Table) scanWords(paths []string, fpr int, wordsHandler func([]string) error) error {
|
||||
|
|
|
@ -4,6 +4,8 @@ import (
|
|||
"fmt"
|
||||
"io/fs"
|
||||
"sync"
|
||||
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-locode-db/pkg/locode"
|
||||
)
|
||||
|
||||
// Prm groups the required parameters of the Table's constructor.
|
||||
|
@ -21,6 +23,11 @@ type Prm struct {
|
|||
//
|
||||
// Must not be empty.
|
||||
SubDivPath string
|
||||
|
||||
// Path to a csv table with UN/LOCODE overrides.
|
||||
//
|
||||
// Optional.
|
||||
OverridesPath string
|
||||
}
|
||||
|
||||
// Table is a descriptor of the UN/LOCODE table in csv format.
|
||||
|
@ -39,6 +46,8 @@ type Table struct {
|
|||
subDivOnce sync.Once
|
||||
|
||||
mSubDiv map[subDivKey]subDivRecord
|
||||
|
||||
overrides map[locode.LOCODE]locode.Record
|
||||
}
|
||||
|
||||
const invalidPrmValFmt = "invalid parameter %s (%T):%v"
|
||||
|
@ -67,9 +76,15 @@ func New(prm Prm, opts ...Option) *Table {
|
|||
opts[i](o)
|
||||
}
|
||||
|
||||
return &Table{
|
||||
t := &Table{
|
||||
paths: append(o.extraPaths, prm.Path),
|
||||
mode: o.mode,
|
||||
subDivPath: prm.SubDivPath,
|
||||
}
|
||||
|
||||
if err := t.initOverrides(prm.OverridesPath); err != nil {
|
||||
panic(fmt.Errorf("init overrides: %w", err))
|
||||
}
|
||||
|
||||
return t
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue