✨ Add configuration for Code Review Automation and enhance .gitignore. Introduce .coderabbit.yml for automated reviews with profiles for correctness, maintainability, security, and performance. Update paths to include relevant directories and exclude generated files. Modify .gitignore to include coverage reports and generated files. Refactor Docker Compose to use updated paths for database initialization scripts. Update Go module dependencies and enhance Makefile with new code generation tasks. Transition domain models to a new DTO structure for better separation of concerns.
This commit is contained in:
@@ -0,0 +1,221 @@
|
||||
package parser
|
||||
|
||||
import (
|
||||
"caatsm/internal/domain"
|
||||
"errors"
|
||||
"strings"
|
||||
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
func ExtractWaypoint(message string) *domain.WayPoint {
|
||||
matches := WaypointExpression.FindStringSubmatch(message)
|
||||
if matches == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
data := make(map[string]string)
|
||||
for i, name := range WaypointExpression.SubexpNames() {
|
||||
if i != 0 && name != "" {
|
||||
data[name] = matches[i]
|
||||
}
|
||||
}
|
||||
result := &domain.WayPoint{
|
||||
ArrivalTime: data[ArrivalTime],
|
||||
Airport: data[AirportCode],
|
||||
DepartureTime: data[DepartureTime],
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
func FindDef(code string) *LineParser {
|
||||
// fmt.Printf("Finding definition for %s\n", code)
|
||||
// fmt.Println("ParserDef: ", parserDef)
|
||||
for _, def := range *parserDef {
|
||||
for _, airline := range def.Airlines {
|
||||
if airline == code {
|
||||
return &def
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func standardizeSpaces(s string) string {
|
||||
return strings.Join(strings.Fields(s), " ")
|
||||
}
|
||||
|
||||
func ParseWithDef(line string, parserDef *LineParser) *domain.ScheduleLine {
|
||||
log := zap.S()
|
||||
cleanLine := standardizeSpaces(strings.TrimSpace(line))
|
||||
words := strings.Split(cleanLine, " ")
|
||||
var flightSchedule = &domain.ScheduleLine{
|
||||
Reference: line,
|
||||
}
|
||||
if strings.Contains(line, CANCELLED) {
|
||||
flightSchedule.Comments = "Cancelled"
|
||||
return flightSchedule
|
||||
}
|
||||
// var result map[string]string
|
||||
if parserDef == nil {
|
||||
log.Warnf("No definition found: %s", line)
|
||||
flightSchedule.Comments = "No definition found [" + line + "] "
|
||||
return flightSchedule
|
||||
}
|
||||
if len(words) < parserDef.MinLen {
|
||||
log.Warnf("Line too short: %s", line)
|
||||
flightSchedule.Comments = "Line too short [" + line + "] "
|
||||
return flightSchedule
|
||||
}
|
||||
|
||||
for i, field := range parserDef.Fields {
|
||||
// log.Debugf("Parsing field %v -> %s", i, field)
|
||||
data := extract(words[i], parserMap[field])
|
||||
if data != nil {
|
||||
switch field {
|
||||
case Index:
|
||||
flightSchedule.Index = data[Index]
|
||||
case Date:
|
||||
flightSchedule.Date = data[Date]
|
||||
case Task:
|
||||
flightSchedule.Task = data[Task]
|
||||
case FlightNumber:
|
||||
flightSchedule.FlightNumber = getFlightNumbers(data[FlightNumber])
|
||||
case Register:
|
||||
flightSchedule.AircraftReg = data[Register]
|
||||
}
|
||||
}
|
||||
}
|
||||
if len(words) > parserDef.WaypointStart {
|
||||
flightSchedule.Waypoints, _ = parseWaypoints(words[parserDef.WaypointStart:])
|
||||
} else {
|
||||
log.Warn("No waypoints found")
|
||||
flightSchedule.Comments = "No waypoints found"
|
||||
}
|
||||
|
||||
return flightSchedule
|
||||
}
|
||||
|
||||
// ParseLine processes a single line of schedule data and returns a ScheduleLine object.
|
||||
func ParseLine(line string) (*domain.ScheduleLine, error) {
|
||||
log := zap.S()
|
||||
cleanLine := strings.TrimSpace(line)
|
||||
words := strings.Split(cleanLine, " ")
|
||||
flightSchedule := &domain.ScheduleLine{Reference: line}
|
||||
|
||||
if indexData := extract(words[0], IndexExpression); indexData != nil {
|
||||
flightSchedule.Index = indexData[Index]
|
||||
words = words[1:]
|
||||
}
|
||||
|
||||
parseStrategy := []string{Task, Date, FlightNumber, Register}
|
||||
_, maxParsed, err := parseFields(words, parseStrategy, flightSchedule)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Check if there are any waypoints after the parsed fields
|
||||
if maxParsed+1 < len(words) {
|
||||
waypoints, err := parseWaypoints(words[maxParsed+1:])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
flightSchedule.Waypoints = waypoints
|
||||
} else {
|
||||
log.Warn("No waypoints found")
|
||||
flightSchedule.Comments = "No waypoints found"
|
||||
}
|
||||
|
||||
return flightSchedule, nil
|
||||
}
|
||||
|
||||
// parseFields processes the fields based on the given strategy and updates the flight schedule.
|
||||
func parseFields(words []string, parseStrategy []string, flightSchedule *domain.ScheduleLine) (map[string]bool, int, error) {
|
||||
parsed := make(map[string]bool)
|
||||
var maxParsed int
|
||||
|
||||
for i, word := range words {
|
||||
for _, name := range parseStrategy {
|
||||
if parsed[name] {
|
||||
continue
|
||||
}
|
||||
if data := extract(word, parserMap[name]); data != nil {
|
||||
updateFlightSchedule(flightSchedule, name, data)
|
||||
parsed[name] = true
|
||||
maxParsed = i
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
return parsed, maxParsed, nil
|
||||
}
|
||||
|
||||
// updateFlightSchedule updates the flight schedule based on the parsed data.
|
||||
func updateFlightSchedule(flightSchedule *domain.ScheduleLine, name string, data map[string]string) {
|
||||
switch name {
|
||||
case Task:
|
||||
flightSchedule.Task = data[Task]
|
||||
case Date:
|
||||
flightSchedule.Date = data[Date]
|
||||
case FlightNumber:
|
||||
flightSchedule.FlightNumber = getFlightNumbers(data[FlightNumber])
|
||||
case Register:
|
||||
flightSchedule.AircraftReg = data[Register]
|
||||
}
|
||||
}
|
||||
|
||||
// parseWaypoints processes a slice of waypoint strings and returns a slice of WayPoint objects.
|
||||
func parseWaypoints(target []string) ([]domain.WayPoint, error) {
|
||||
log := zap.S()
|
||||
points := getValidPoints(target)
|
||||
if len(points) == 0 {
|
||||
log.Warn("No waypoints found")
|
||||
return nil, errors.New("no waypoints")
|
||||
}
|
||||
var waypoints []domain.WayPoint
|
||||
for i, point := range points {
|
||||
if digits := extract(point, AllDigitsExpression); i > 0 && digits != nil && len(waypoints) > 0 {
|
||||
waypoints[len(waypoints)-1].DepartureTime = digits[DepartureTime]
|
||||
} else if waypoint := ExtractWaypoint(point); waypoint != nil {
|
||||
waypoints = append(waypoints, *waypoint)
|
||||
}
|
||||
}
|
||||
if len(waypoints) == 0 {
|
||||
log.Warn("No waypoints found")
|
||||
return nil, errors.New("no waypoints")
|
||||
}
|
||||
return waypoints, nil
|
||||
}
|
||||
|
||||
func getValidPoints(data []string) []string {
|
||||
var points []string
|
||||
for i, point := range data {
|
||||
if extract(point, WaypointExpression) != nil {
|
||||
return data[i:]
|
||||
}
|
||||
}
|
||||
return points
|
||||
}
|
||||
|
||||
/**
|
||||
* CZ6794/79
|
||||
* CZ3301/2
|
||||
* CA1371/1372/1527
|
||||
*/
|
||||
func getFlightNumbers(data string) []string {
|
||||
if strings.Contains(data, "/") {
|
||||
data := strings.Split(data, "/")
|
||||
baseNumber := data[0]
|
||||
baseLength := len(baseNumber)
|
||||
flightNumbers := append([]string{}, baseNumber)
|
||||
for _, number := range data[1:] {
|
||||
length := len(number)
|
||||
flightNumber := baseNumber[:baseLength-length] + number
|
||||
flightNumbers = append(flightNumbers, flightNumber)
|
||||
}
|
||||
return flightNumbers
|
||||
} else {
|
||||
return []string{data}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user