refactor: Rename AFTN struct field from "Text" to "Body"

This commit is contained in:
windyboy
2024-07-20 18:26:17 +08:00
parent d4eabd42e4
commit 4bb79e92dd
3 changed files with 217 additions and 0 deletions
+28
View File
@@ -0,0 +1,28 @@
package domain
/*
ZCZC TMQ1324 150631
FF ZBTJZPZX
150630 ZBACZQZX
*/
/*
Start Indicator: ZCZC
Message ID: TMQ1324
Date-Time: 150631
Priority Indicator: FF
Primary Address: ZBTJZPZX
Secondary Addresses: 150630 ZBACZQZX
Originator and Originator Date-Time: Not present in this example but handled if present.
*/
// ParsedMessage holds the parsed data from an aviation message
type ParsedMessage struct {
StartIndicator string // Start of the message indicator
MessageID string // Unique identifier for the message
DateTime string // Date and time the message was created
PriorityIndicator string // Priority level of the message
PrimaryAddress string // Primary recipient address
SecondaryAddresses []string // Additional recipient addresses
Originator string // Sender of the message
OriginatorDateTime string // Date and time when the originator sent the message
BodyAndFooter string
}
+77
View File
@@ -0,0 +1,77 @@
package parsers
import (
"caatsm/internal/domain"
"strings"
)
// ParseHeader parses the header of the message and returns a ParsedMessage struct
func ParseHeader(fullMessage string) domain.ParsedMessage {
var (
startIndicator string
messageID string
dateTime string
priorityIndicator string
primaryAddress string
secondaryAddresses []string
originator string
originatorDateTime string
bodyAndFooter strings.Builder
headerEnded bool
)
fullMessage = strings.TrimSpace(fullMessage)
lines := strings.Split(fullMessage, "\n")
for lineCounter, line := range lines {
switch lineCounter {
case 0:
if strings.HasPrefix(line, "ZCZC") {
parts := strings.Fields(line)
if len(parts) >= 3 {
startIndicator = parts[0]
messageID = parts[1]
dateTime = parts[2]
}
}
case 1:
parts := strings.Fields(line)
if len(parts) >= 2 {
priorityIndicator = parts[0]
primaryAddress = parts[1]
}
default:
if !headerEnded {
if strings.TrimSpace(line) == "." {
continue
} else if strings.HasPrefix(line, ".") {
originatorInfo := strings.Fields(line[1:])
if len(originatorInfo) >= 2 {
originator = originatorInfo[0]
originatorDateTime = originatorInfo[1]
}
headerEnded = true
} else if strings.HasPrefix(line, "BEGIN PART") || strings.HasPrefix(line, "(") {
headerEnded = true
bodyAndFooter.WriteString(line + "\n")
} else {
secondaryAddresses = append(secondaryAddresses, line)
}
} else {
bodyAndFooter.WriteString(line + "\n")
}
}
}
return domain.ParsedMessage{
StartIndicator: startIndicator,
MessageID: messageID,
DateTime: dateTime,
PriorityIndicator: priorityIndicator,
PrimaryAddress: primaryAddress,
SecondaryAddresses: secondaryAddresses,
Originator: originator,
OriginatorDateTime: originatorDateTime,
BodyAndFooter: bodyAndFooter.String(),
}
}
+112
View File
@@ -0,0 +1,112 @@
package parsers
import (
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
)
var _ = Describe("Aviation Parser", func() {
Describe("ParseHeader", func() {
It("should parse the header correctly", func() {
message := `
ZCZC TAF6789 160530
QU TSNZPCA
.
QU PEKUDCA TSNUOCA TSNZPCA TSNUFCA
.TAF WSSS 160500Z 1606/1712 20010KT 9999 SCT018
BECMG 1608/1610 24012KT 9999 SCT018
TEMPO 1610/1612 4000 SHRA BKN012
BECMG 1612/1614 18008KT 9999 SCT020
BEGIN PART 02
(FORECAST AMENDMENT
VALID 1606/1700
THUNDERSTORMS EXPECTED
ALTERNATE ROUTES ADVISED)
NNNN`
parsedHeader := ParseHeader(message)
Expect(parsedHeader.StartIndicator).To(Equal("ZCZC"))
Expect(parsedHeader.MessageID).To(Equal("TAF6789"))
Expect(parsedHeader.DateTime).To(Equal("160530"))
Expect(parsedHeader.PriorityIndicator).To(Equal("QU"))
Expect(parsedHeader.PrimaryAddress).To(Equal("TSNZPCA"))
Expect(parsedHeader.SecondaryAddresses).To(Equal([]string{"QU PEKUDCA TSNUOCA TSNZPCA TSNUFCA"}))
})
It("should parse the header correctly with originator information", func() {
message := `
ZCZC NOTAM1122 171000
QU TSNZPCA
.
QU PEKUDCA TSNUOCA TSNZPCA TSNUFCA
.SELOZKE 170999
BEGIN PART 01
RUNWAY MAINTENANCE NOTICE.
- MAINTENANCE MANAGER: JOHN DOE
RUNWAY 09/27 WILL BE CLOSED FOR MAINTENANCE FROM 0800Z TO 1600Z.
- AIRPORT OPERATIONS: SIGN . . . . . . . . . .
WE ACKNOWLEDGE THE RUNWAY CLOSURE.
- CONTROL TOWER:
SIGN . . . . . . . . . .
BEGIN PART 02
(ALERT MESSAGE - WEATHER WARNING
VALID 1500Z - 1800Z
SEVERE THUNDERSTORM FORECASTED
ALL DEPARTURES/ARRIVALS EXPECTED TO BE DELAYED)
NNNN`
parsedHeader := ParseHeader(message)
Expect(parsedHeader.StartIndicator).To(Equal("ZCZC"))
Expect(parsedHeader.MessageID).To(Equal("NOTAM1122"))
Expect(parsedHeader.DateTime).To(Equal("171000"))
Expect(parsedHeader.PriorityIndicator).To(Equal("QU"))
Expect(parsedHeader.PrimaryAddress).To(Equal("TSNZPCA"))
Expect(parsedHeader.SecondaryAddresses).To(Equal([]string{"QU PEKUDCA TSNUOCA TSNZPCA TSNUFCA"}))
Expect(parsedHeader.Originator).To(Equal("SELOZKE"))
Expect(parsedHeader.OriginatorDateTime).To(Equal("170999"))
})
})
Context("with NOTAM message", func() {
It("should parse the header correctly", func() {
message := `
ZCZC NOTAM1234 230715
GG EDDNZEZN
.
GG EDDNYNYX
.BERLINTWR 230714
Q) EDMM/QOATT/IV/BO/A/000/999/4814N01120E005
A) EDDM
B) 2307150600 C) 2307151800
E) AERODROME CONTROL TOWER HOURS OF SERVICE
0600-1800 DUE TO MAINTENANCE
NNNN`
parsedMessage := ParseHeader(message)
Expect(parsedMessage.StartIndicator).To(Equal("ZCZC"))
Expect(parsedMessage.MessageID).To(Equal("NOTAM1234"))
Expect(parsedMessage.DateTime).To(Equal("230715"))
Expect(parsedMessage.PriorityIndicator).To(Equal("GG"))
Expect(parsedMessage.PrimaryAddress).To(Equal("EDDNZEZN"))
Expect(parsedMessage.SecondaryAddresses).To(Equal([]string{"GG EDDNYNYX"}))
Expect(parsedMessage.Originator).To(Equal("BERLINTWR"))
Expect(parsedMessage.OriginatorDateTime).To(Equal("230714"))
Expect(parsedMessage.BodyAndFooter).To(ContainSubstring("Q) EDMM/QOATT/IV/BO/A/000/999/4814N01120E005\nA) EDDM\nB) 2307150600 C) 2307151800\nE) AERODROME CONTROL TOWER HOURS OF SERVICE\n 0600-1800 DUE TO MAINTENANCE\nNNNN"))
})
})
})