Logic updates

This commit is contained in:
2026-02-16 23:34:41 +10:00
parent 28613170a1
commit 5e4b8b2214
3 changed files with 45 additions and 24 deletions

View File

@@ -1,7 +1,6 @@
module Controller
open System
open System.Net.Http
open System.Text.RegularExpressions
open NextFlight.Types
open FSharp.Collections
open HtmlAgilityPack
@@ -36,7 +35,7 @@ let private formatDateReadable (date: DateTime) (timezone: string) =
// Helper to extract city from "City / Airport" format
let private extractCity (location: string) =
match location.Split('/') with
| parts when parts.Length > 0 -> parts.[0].Trim()
| parts when parts.Length > 0 -> parts[0].Trim()
| _ -> location
let private calculateArrivalDate (departureDate: DateTime) (departureTime: string) (arrivalTime: string) =
@@ -46,10 +45,10 @@ let private calculateArrivalDate (departureDate: DateTime) (departureTime: strin
let arrParts = arrivalTime.Split(':')
if depParts.Length = 2 && arrParts.Length = 2 then
let depHour = Int32.Parse(depParts.[0])
let depMinute = Int32.Parse(depParts.[1])
let arrHour = Int32.Parse(arrParts.[0])
let arrMinute = Int32.Parse(arrParts.[1])
let depHour = Int32.Parse(depParts[0])
let depMinute = Int32.Parse(depParts[1])
let arrHour = Int32.Parse(arrParts[0])
let arrMinute = Int32.Parse(arrParts[1])
let depTimeOfDay = TimeSpan(depHour, depMinute, 0)
let arrTimeOfDay = TimeSpan(arrHour, arrMinute, 0)
@@ -67,8 +66,23 @@ let private calculateArrivalDate (departureDate: DateTime) (departureTime: strin
// If any error in parsing, assume same day
departureDate
let getLogoUrl rawFlight = $"https://content.airhex.com/content/logos/airlines_{rawFlight.AirlineCode}_60_60_t.png"
let removeDuplicateWords (string: string) =
string.Split(' ')
|> Array.fold (fun acc word ->
match acc with
| [] -> [word]
| head :: _ when head = word -> acc
| _ -> word :: acc
) []
|> List.rev
|> String.concat " "
// Map RawFlight to Flight
let private mapToFlight (raw: RawFlight) (timezone: string) : Flight =
let arrivalDate = calculateArrivalDate raw.Date raw.DepartureTime raw.ArrivalTime
{
departureAirportCode = raw.FromCode
@@ -80,8 +94,10 @@ let private mapToFlight (raw: RawFlight) (timezone: string) : Flight =
arrivalDateReadable = formatDateReadable arrivalDate timezone
arrivalTime = raw.ArrivalTime
flightNumber = raw.FlightNumber
airlineCode = raw.AirlineCode
airlineName = raw.Airline
aircraftType = raw.Aircraft
aircraftType = removeDuplicateWords raw.Aircraft
logoUrl = getLogoUrl raw
}
let private parseTableRow (row: HtmlNode) : RawFlight option =
@@ -91,53 +107,54 @@ let private parseTableRow (row: HtmlNode) : RawFlight option =
if cells = null || cells.Count < 13 then None
else
// Extract date
let dateNode = cells.[0].SelectSingleNode(".//span[@class='inner-date']")
let dateNode = cells[0].SelectSingleNode(".//span[@class='inner-date']")
if dateNode = null then None
else
let dateStr = dateNode.InnerText.Trim()
let date = DateTime.Parse(dateStr)
// Flight number
let flightNumber = getInnerText (Some cells.[1])
let flightNumber = getInnerText (Some cells[1])
// Registration
let registration = getInnerText (Some cells.[2])
let registration = getInnerText (Some cells[2])
// From airport
let fromNode = cells.[3].SelectSingleNode(".//span[@class='tooltip']")
let fromNode = cells[3].SelectSingleNode(".//span[@class='tooltip']")
let fromCode = getInnerText (Some fromNode)
let fromFull = getAttributeValue (Some fromNode) "data-tooltip-value"
// To airport
let toNode = cells.[4].SelectSingleNode(".//span[@class='tooltip']")
let toNode = cells[4].SelectSingleNode(".//span[@class='tooltip']")
let toCode = getInnerText (Some toNode)
let toFull = getAttributeValue (Some toNode) "data-tooltip-value"
// Distance (remove commas)
let distanceStr = getInnerText (Some cells.[5])
let distanceStr = getInnerText (Some cells[5])
let distance =
if String.IsNullOrWhiteSpace(distanceStr) then 0
else Int32.Parse(distanceStr.Replace(",", ""))
// Times
let depTime = getInnerText (Some cells.[6])
let arrTime = getInnerText (Some cells.[7])
let depTime = getInnerText (Some cells[6])
let arrTime = getInnerText (Some cells[7])
// Airline
let airlineNode = cells.[8].SelectSingleNode(".//span[@class='tooltip']")
let airlineNode = cells[8].SelectSingleNode(".//span[@class='tooltip']")
let airline = getAttributeValue (Some airlineNode) "data-tooltip-value"
let airlineCode = getInnerText (Some cells[8])
// Aircraft
let aircraftNode = cells.[9].SelectSingleNode(".//span[@class='tooltip']")
let aircraftNode = cells[9].SelectSingleNode(".//span[@class='tooltip']")
let aircraft = getAttributeValue (Some aircraftNode) "data-tooltip-value"
// Seat - look for pattern like "19A" in the seat cell
let seatText = cells.[10].InnerText
let seatText = cells[10].InnerText
let seatMatch = System.Text.RegularExpressions.Regex.Match(seatText, @"\d+[A-Z]")
let seat = if seatMatch.Success then seatMatch.Value else ""
// Class and Reason from icons column
let iconsCell = cells.[12]
let iconsCell = cells[12]
// Class
let classNode = iconsCell.SelectSingleNode(".//span[contains(@class, 'class-')]")
@@ -174,6 +191,7 @@ let private parseTableRow (row: HtmlNode) : RawFlight option =
DepartureTime = depTime
ArrivalTime = arrTime
Airline = airline
AirlineCode = airlineCode
Aircraft = aircraft
Seat = seat
Class = flightClass
@@ -225,8 +243,8 @@ let GetNextFlights (username: string) (timezoneCountry: string) (timezoneCity: s
try
let timeParts = flight.DepartureTime.Split(':')
if timeParts.Length = 2 then
let hour = Int32.Parse(timeParts.[0])
let minute = Int32.Parse(timeParts.[1])
let hour = Int32.Parse(timeParts[0])
let minute = Int32.Parse(timeParts[1])
// Create departure DateTime in YOUR timezone
let departureDateTime = DateTime(flight.Date.Year, flight.Date.Month, flight.Date.Day, hour, minute, 0)
departureDateTime > now
@@ -240,8 +258,8 @@ let GetNextFlights (username: string) (timezoneCountry: string) (timezoneCity: s
try
let timeParts = flight.DepartureTime.Split(':')
if timeParts.Length = 2 then
let hour = Int32.Parse(timeParts.[0])
let minute = Int32.Parse(timeParts.[1])
let hour = Int32.Parse(timeParts[0])
let minute = Int32.Parse(timeParts[1])
DateTime(flight.Date.Year, flight.Date.Month, flight.Date.Day, hour, minute, 0)
else
flight.Date

View File

@@ -40,7 +40,7 @@ module Program =
use_static (Path.Combine(AppContext.BaseDirectory, "wwwroot"))
use_developer_exceptions
service_config ServiceConfig
url "http://0.0.0.0:5001"
url "http://0.0.0.0:5000"
}
run app

View File

@@ -13,6 +13,7 @@ type RawFlight = {
DepartureTime: string
ArrivalTime: string
Airline: string
AirlineCode: string
Aircraft: string
Seat: string
Class: string
@@ -29,6 +30,8 @@ type Flight = {
arrivalDateReadable: string
arrivalTime: string
flightNumber: string
airlineCode: string
airlineName: string
aircraftType: string
logoUrl: string
}