Compare commits

...
10 Commits
Author SHA1 Message Date
zhiqiang feng a814a2190a use time keyword constant 2021-01-05 18:11:51 +08:00
zhiqiang feng 99440a393a fix composite 2021-01-05 18:04:17 +08:00
zhiqiang feng 625cc6b94e delay test 2021-01-05 13:28:01 +08:00
zhiqiang feng 1a8bacdc53 delay 2021-01-05 13:14:15 +08:00
zhiqiang feng 807487a64d clean 2021-01-05 12:45:24 +08:00
zhiqiang feng 18f26bfed8 clean 2021-01-05 12:45:09 +08:00
zhiqiang feng b3b10173c3 clean 2021-01-05 12:43:37 +08:00
zhiqiang feng 67a28c2280 arr and dep with composite regex 2021-01-05 12:43:04 +08:00
zhiqiang feng 263f38633f add fpl dla 2021-01-04 18:07:48 +08:00
zhiqiang feng 576216f712 add dep test 2021-01-04 16:02:13 +08:00
7 changed files with 334 additions and 90 deletions
+2 -2
View File
@@ -10,7 +10,7 @@ import (
func main() {
app := &cli.App{
Name: "boom",
Name: "boom",
Usage: "make an explosive entrance",
Action: func(c *cli.Context) error {
fmt.Println("boom! I say!")
@@ -22,4 +22,4 @@ func main() {
if err != nil {
log.Fatal(err)
}
}
}
+112
View File
@@ -0,0 +1,112 @@
package parser
import (
"errors"
"fmt"
"regexp"
)
const (
FlopRegex = `(?m)\((?P<type>[A-Z]{3}).*(.|\n|\r)*\)`
DestinationRegex = `(?P<dest>[A-Z]+)(?P<time>\d{0,4})`
DofValueRex = `(?m)DOF\/(?P<time>\d{6})`
TypeArrival = "ARR"
TypeDeparture = "DEP"
TypeFlightPlan = "FPL"
TypeDelay = "DLA"
DepRegex = `(?P<dep>[A-Z]+\d{0,4})`
ArrRegex = `(?P<arr>[A-Z]+\d{0,4})`
PlaneRegex = `(?P<plane>\w+\d+\/?\w\d+)`
AircraftRegex = `-?(?P<aircraft>[\w\/]+)`
DofRegex = `-?(?P<dof>DOF\/\d{6})?`
OtherRegex = `-?(?P<NAME>[A-Z0-9\/ \n\r]+)`
/**
* example:
* (ARR-CSN3126/A5040-ZSPD-ZBTJ1601)
* (DEP-CSN3125/A4553-ZGHA0554-ZBTJ-DOF/120820)
*/
CompositeDepArr = `(?m)\([A-Z]{3}-` + PlaneRegex + "-" + DepRegex + "-" + ArrRegex + DofRegex + `\)`
/**
* sample:
* (DLAABC123NZAA0145VTBSDOF/091120)
*/
CompositeDelay = `(?m)\(DLA-` + PlaneRegex + "-" + DepRegex + "-" + ArrRegex + DofRegex + `\)`
KeyDeparture = "dep"
KeyArrival = "arr"
KeyDof = "dof"
KeyPlane = "plane"
KeyAircraft = "aircraft"
KeyTime = "time"
)
var flopRegex = regexp.MustCompile(FlopRegex)
/**
* example:
* (FPL-AAR997-IS
* -B763/H-SDHIPRWZ/S
* -RKSI0120
* -N0473F320 NOPIK1B NOPIK G597 GONAV/N0473F320 G597 AGAVO/K0876S0980
* G597 DONVO A326 ANRAT ANRAT2A
* -ZBTJ0126 ZBAA
* -EET/ZSHA0025 ZYSH0039 ZBPE0059 REG/HL7507 SEL/KRHJ OPR/AAR
* DOF/090516 RMK/TCAS II EQUIPPED NAV/RNAV1 RNAV5 STS/CARGO)
* NNNN
*/
var CompositeFlightPlan = `(?m)\(FPL-` + PlaneRegex + `-IS( |\n)+` +
AircraftRegex + getOtherRegexWithName("p1") + "-" +
DepRegex + `[ \n]+-` +
getOtherRegexWithName("p2") + "-" +
ArrRegex + ` \w+[ \n]+-` +
getOtherRegexWithName("p3") + `\)`
func parseArrOrDep(telegram *Telegram, data string) {
fmt.Println(CompositeDepArr)
fields := getFields(CompositeDepArr, data)
if len(fields) < 1 {
telegram.ParseErrors = append(telegram.ParseErrors, errors.New("data less than 4 "))
telegram.Parsed = false
return
}
telegram.FlightNumber, telegram.RegisterNumber = parseFlight(fields[KeyPlane])
telegram.Departure, telegram.DepartureTime = parseAirportAndTime(fields[KeyDeparture])
telegram.Destination, telegram.DestinationTime = parseAirportAndTime(fields[KeyArrival])
dofValue := fields[KeyDof]
if len(dofValue) > 0 {
telegram.DateOfFlight = parseDof(dofValue)
}
telegram.Parsed = true
}
func parseFlightPlan(telegram *Telegram, data string) {
fmt.Println(CompositeFlightPlan)
fields := getFields(CompositeFlightPlan, data)
telegram.FlightNumber, _ = parseFlight(fields[KeyPlane])
telegram.Aircraft = fields[KeyAircraft]
telegram.Departure, telegram.DepartureTime = parseAirportAndTime(fields[KeyDeparture])
telegram.Destination, telegram.DestinationTime = parseAirportAndTime(fields[KeyArrival])
telegram.DateOfFlight = parseDof(fields["p3"])
}
func parseDelay(telegram *Telegram, data string) {
fields := getFields(CompositeDelay, data)
if len(fields) < 1 {
telegram.ParseErrors = append(telegram.ParseErrors, errors.New("data less than 4 "))
telegram.Parsed = false
return
}
telegram.FlightNumber, telegram.RegisterNumber = parseFlight(fields[KeyPlane])
telegram.Departure, telegram.DepartureTime = parseAirportAndTime(fields[KeyDeparture])
telegram.Destination, telegram.DestinationTime = parseAirportAndTime(fields[KeyArrival])
dofValue := fields[KeyDof]
if len(dofValue) > 0 {
telegram.DateOfFlight = parseDof(dofValue)
}
telegram.Parsed = true
}
+188
View File
@@ -0,0 +1,188 @@
package parser
import (
"github.com/stretchr/testify/assert"
"testing"
)
func TestAirportAndTimeRegex(t *testing.T) {
ast := assert.New(t)
text := "-ZBTJ0554"
fields := getFields(DepRegex, text)
ast.Equal(1, len(fields), "Should get 1 filed")
ast.Equal("ZBTJ0554", fields[KeyDeparture])
fields = getFields(DestinationRegex, text)
ast.Equal(2, len(fields))
ast.Equal("ZBTJ", fields["dest"])
ast.Equal("0554", fields["time"])
}
func TestPlaneRegex(t *testing.T) {
ast := assert.New(t)
text := "-JAE7433/A0132"
fields := getFields(PlaneRegex, text)
ast.Equal(1, len(fields), "Should get plane value")
ast.Equal("JAE7433/A0132", fields[KeyPlane])
}
func TestAircraftRegex(t *testing.T) {
ast := assert.New(t)
text := "-B763/H-SDHIPRWZ/S"
fields := getFields(AircraftRegex, text)
ast.Equal(1, len(fields))
ast.Equal("B763/H", fields[KeyAircraft])
}
func TestDofRegex(t *testing.T) {
ast := assert.New(t)
text := "DOF/120820"
fields := getFields(DofRegex, text)
ast.Equal(1, len(fields), "Should get dof value")
ast.Equal("DOF/120820", fields[KeyDof])
d := parseDof(text)
ast.Equal(2012, d.Year())
ast.Equal(8, int(d.Month()))
ast.Equal(20, d.Day())
}
func TestGetOtherRegex(t *testing.T) {
ast := assert.New(t)
regex := getOtherRegexWithName("p1")
ast.Equal(`-?(?P<p1>[A-Z0-9\/ \n\r]+)`, regex)
}
func TestOthers(t *testing.T) {
ast := assert.New(t)
text := `-N0473F320 NOPIK1B
NOPIK G597 GONAV/N0473F320 G597 AGAVO/K0876S0980 G597 DONVO A326
ANRAT ANRATA`
fields := getFields(OtherRegex, text)
ast.Equal(1, len(fields))
ast.Equal(text[1:], fields["NAME"])
text = "-N0473F320 NOPIK1B"
fields = getFields(OtherRegex, text)
ast.Equal(1, len(fields))
ast.Equal(text[1:], fields["NAME"])
}
func TestArrDep(t *testing.T) {
ast := assert.New(t)
s := `ZCZC TMQ2526 141605
FF ZBTJZPZX
141604 ZBACZQZX
(ARR-JAE7433/A0132-RKSI-ZBTJ1604)
NNNN`
tele, err := Parse(s)
ast.Nil(err, "Should be no error")
ast.Equal(tele.Complete, true, "Should be complete telegram")
ast.Equal(4, len(tele.Fields), "get 4 lines")
ast.Equal("ZCZC TMQ2526 141605", tele.Fields[0])
ast.Equal(2526, tele.Sequence, "TMQ must be 2526")
ast.Equal(false, tele.Type == "PLN", "Not a plan")
ast.Equal("ARR", tele.Type, "Flop type is ARR")
ast.Equal("JAE7433", tele.FlightNumber, "flight number is JAE7433")
ast.Equal("A0132", tele.RegisterNumber, "register number is A0132")
ast.Equal("RKSI", tele.Departure, "departure airport is RKSI")
ast.Equal("ZBTJ", tele.Destination, "destination airport is ZBTJ")
ast.Equal(16, tele.DestinationTime.Hour())
ast.Equal(4, tele.DestinationTime.Minute())
s = `ZCZC TMQ2526 141605
FF ZBTJZPZX
141604 ZBACZQZX
(DEP-JAE7433/A0132-RKSI1604-ZBTJ-DOF/120820)
NNNN`
tele, err = Parse(s)
ast.Nil(err, "Should be no error")
ast.Equal(tele.Complete, true, "Should be complete telegram")
ast.Equal(4, len(tele.Fields), "get 4 lines")
ast.Equal("ZCZC TMQ2526 141605", tele.Fields[0])
ast.Equal(2526, tele.Sequence, "TMQ must be 2526")
ast.Equal(false, tele.Type == "PLN", "Not a plan")
ast.Equal("DEP", tele.Type, "Flop type is DEP")
ast.Equal("JAE7433", tele.FlightNumber, "flight number is JAE7433")
ast.Equal("A0132", tele.RegisterNumber, "register number is A0132")
ast.Equal("RKSI", tele.Departure, "departure airport is RKSI")
ast.Equal("ZBTJ", tele.Destination, "destination airport is ZBTJ")
ast.Equal(16, tele.DepartureTime.Hour())
ast.Equal(4, tele.DepartureTime.Minute())
ast.Equal(2012, tele.DateOfFlight.Year())
ast.Equal(8, int(tele.DateOfFlight.Month()))
ast.Equal(20, tele.DateOfFlight.Day())
s = `ZCZC TMQ2526 141605
FF ZBTJZPZX
141604 ZBACZQZX
(ARR-JAE7433/A0132-RKSI)
NNNN`
if tele, _ = Parse(s); tele != nil {
ast.Equal(1, len(tele.ParseErrors))
}
}
func TestFpl(t *testing.T) {
ast := assert.New(t)
text := `ZCZC TMQ2628 151601
FF ZBTJZPZX
151600 RKSSAARO
(FPL-AAR997-IS
-B763/H-SDHIPRWZ/S
-RKSI0120
-N0473F320 NOPIK1B NOPIK G597 GONAV/N0473F320 G597 AGAVO/K0876S0980
G597 DONVO A326 ANRAT ANRAT2A
-ZBTJ0126 ZBAA
-EET/ZSHA0025 ZYSH0039 ZBPE0059 REG/HL7507 SEL/KRHJ OPR/AAR
DOF/090516 RMK/TCAS II EQUIPPED NAV/RNAV1 RNAV5 STS/CARGO)
NNNN
`
tele, err := Parse(text)
ast.Nil(err, "Should be no error")
ast.Equal(12, len(tele.Fields), "get 12 lines")
ast.Equal(2628, tele.Sequence, "TMQ must be 2628")
ast.Equal(false, tele.Type == "PLN", "Not a plan")
ast.Equal("FPL", tele.Type, "Flop type is FPL")
ast.Equal("AAR997", tele.FlightNumber, "flight number is AAR997")
ast.Equal("B763/H", tele.Aircraft, "aircraft is B763/H")
ast.Equal("RKSI", tele.Departure, "departure airport is RKSI")
ast.Equal(1, tele.DepartureTime.Hour())
ast.Equal(20, tele.DepartureTime.Minute())
ast.Equal("ZBTJ", tele.Destination)
ast.Equal(1, tele.DestinationTime.Hour())
ast.Equal(26, tele.DestinationTime.Minute())
ast.Equal(2009, tele.DateOfFlight.Year())
ast.Equal(5, int(tele.DateOfFlight.Month()))
ast.Equal(16, tele.DateOfFlight.Day())
}
func TestDelay(t *testing.T) {
ast := assert.New(t)
text := `ZCZC TMQ2626 142159
FF ZBTJZXZX
142158 ZBTJZPZX
(DLA-JAE7433-NZAA0145-VTBS-DOF/091120)
NNNN`
tele, err := Parse(text)
ast.Nil(err, "Should be no error")
ast.Equal(4, len(tele.Fields), "get 4 lines")
ast.Equal("ZCZC TMQ2626 142159", tele.Fields[0])
ast.Equal(2626, tele.Sequence, "TMQ must be 2626")
ast.Equal("DLA", tele.Type, "Flop type is DLA")
ast.Equal("JAE7433", tele.FlightNumber)
ast.Equal("NZAA", tele.Departure)
ast.Equal(1, tele.DepartureTime.Hour())
ast.Equal(45, tele.DepartureTime.Minute())
ast.Equal(2009, tele.DateOfFlight.Year())
ast.Equal(11, int(tele.DateOfFlight.Month()))
ast.Equal(20, tele.DateOfFlight.Day())
}
-35
View File
@@ -1,35 +0,0 @@
package parser
import (
"errors"
"time"
)
const (
FlopRegex = `(?m)^\((?P<flop>\w{3})-.*`
DestinationRegex = `(?P<dest>[A-Z]+)(?P<time>\d{0,4})?`
DOFRegex = `(?P<dof>\w+)/(?P<time>\d{6})`
TypeArrival = "ARR"
)
func parseArr(telegram *Telegram, data string) {
values := getFlopValues(data)
l := len(values)
if l < 4 {
telegram.ParseErrors = append(telegram.ParseErrors, errors.New("arrival data less than 4 "))
return
}
telegram.FlightNumber, telegram.RegisterNumber = parseFlight(values[1])
telegram.Departure = values[2]
telegram.Destination, telegram.DestinationTime = getAirportAndTime(values[3])
if l == 5 {
parseDof(telegram, values[4])
}
telegram.Parsed = true
}
func parseDof(telegram *Telegram, text string) {
if dof := getFields(DOFRegex, text); dof["dof"] == "DOF" {
telegram.DateOfFlight, _ = time.Parse("060102", dof["time"])
}
}
-42
View File
@@ -1,42 +0,0 @@
package parser
import (
"github.com/stretchr/testify/assert"
"testing"
)
func TestArr(t *testing.T) {
ast := assert.New(t)
s := `ZCZC TMQ2526 141605
FF ZBTJZPZX
141604 ZBACZQZX
(ARR-JAE7433/A0132-RKSI-ZBTJ1604-DOF/120820)
NNNN`
tele, err := Parse(s)
ast.Nil(err, "Should be no error")
ast.Equal(tele.Complete, true, "Should be complete telegram")
ast.Equal(4, len(tele.Fields), "get 4 lines")
ast.Equal("ZCZC TMQ2526 141605", tele.Fields[0])
ast.Equal(2526, tele.Sequence, "TMQ must be 2526")
ast.Equal(false, tele.Type == "PLN", "Not a plan")
ast.Equal("ARR", tele.Type, "Flop type is ARR")
ast.Equal("JAE7433", tele.FlightNumber, "flight number is JAE7433")
ast.Equal("A0132", tele.RegisterNumber, "register number is A0132")
ast.Equal("RKSI", tele.Departure, "departure airport is RKSI")
ast.Equal("ZBTJ", tele.Destination, "destination airport is ZBTJ")
ast.Equal(16, tele.DestinationTime.Hour())
ast.Equal(4, tele.DestinationTime.Minute())
ast.Equal(2012, tele.DateOfFlight.Year())
ast.Equal(8, int(tele.DateOfFlight.Month()))
ast.Equal(20, tele.DateOfFlight.Day())
s = `ZCZC TMQ2526 141605
FF ZBTJZPZX
141604 ZBACZQZX
(ARR-JAE7433/A0132-RKSI)
NNNN`
if tele, _ = Parse(s); tele != nil {
ast.Equal(1, len(tele.ParseErrors))
}
}
+22 -7
View File
@@ -16,6 +16,8 @@ type Telegram struct {
Type string
FlopValue []string
FlightNumber string
Plane string
Aircraft string
RegisterNumber string
Departure string
DepartureTime time.Time
@@ -42,12 +44,15 @@ func Parse(text string) (*Telegram, error) {
if isPln(*telegram) {
telegram.Type = TypePLN
} else if flopValues := getFields(FlopRegex, telegram.Text); len(flopValues) > 0 {
telegram.Type = flopValues["flop"]
r := regexp.MustCompile(FlopRegex)
data := r.FindString(telegram.Text)
telegram.Type = flopValues["type"]
data := flopRegex.FindString(telegram.Text)
switch telegram.Type {
case TypeArrival:
parseArr(telegram, data)
case TypeArrival, TypeDeparture:
parseArrOrDep(telegram, data)
case TypeFlightPlan:
parseFlightPlan(telegram, data)
case TypeDelay:
parseDelay(telegram, data)
}
}
return telegram, nil
@@ -80,7 +85,7 @@ func getFields(regEx string, field string) (fields map[string]string) {
return
}
func getFlopValues(s string) []string {
func getSplitValues(s string) []string {
// get rid of ()
s = strings.TrimSpace(s)
s = s[1 : len(s)-1]
@@ -94,8 +99,18 @@ func parseFlight(s string) (flightNumber string, registerNumber string) {
return s, ""
}
func getAirportAndTime(s string) (airport string, arrivalTime time.Time) {
func parseAirportAndTime(s string) (airport string, arrivalTime time.Time) {
fields := getFields(DestinationRegex, s)
arrivalTime, _ = time.Parse("1504", fields["time"])
return fields["dest"], arrivalTime
}
func parseDof(text string) time.Time {
value := getFields(DofValueRex, text)
dof, _ := time.Parse("060102", value[KeyTime])
return dof
}
func getOtherRegexWithName(name string) string {
return strings.ReplaceAll(OtherRegex, "NAME", name)
}
+10 -4
View File
@@ -64,21 +64,21 @@ func TestGetValues(t *testing.T) {
func TestParseDestAndTime(t *testing.T) {
ast := assert.New(t)
text := `ZBTJ1604`
dest, destTime := getAirportAndTime(text)
dest, destTime := parseAirportAndTime(text)
ast.Equal("ZBTJ", dest)
ast.Equal(16, destTime.Hour())
ast.Equal(4, destTime.Minute())
text = `ZBTJ`
dest, _ = getAirportAndTime(text)
dest, _ = parseAirportAndTime(text)
ast.Equal("ZBTJ", dest)
}
func TestGetFlopValues(t *testing.T) {
ast := assert.New(t)
text := `(ARR-JAE7433/A0132-RKSI-ZBTJ1604-ZBTJ)`
values := getFlopValues(text)
text := "(ARR-JAE7433/A0132-RKSI-ZBTJ1604-ZBTJ)"
values := getSplitValues(text)
ast.Equal(5, len(values))
ast.Equal("ARR", values[0])
ast.Equal("JAE7433/A0132", values[1])
@@ -86,6 +86,12 @@ func TestGetFlopValues(t *testing.T) {
ast.Equal("ZBTJ1604", values[3])
ast.Equal("ZBTJ", values[4])
values = getSplitValues("(DLA-JAE7433-NZAA0145-VTBS-DOF/091120)")
ast.Equal(5, len(values))
ast.Equal("JAE7433", values[1])
ast.Equal("NZAA0145", values[2])
ast.Equal("VTBS", values[3])
ast.Equal("DOF/091120", values[4])
}
func TestGetFlight(t *testing.T) {