mirror of
https://github.com/NinjaCheetah/RIT-Dining.git
synced 2025-12-02 01:21:35 -05:00
Dining locations that also exist on FD MealPlanner now have a "View Menu" button under the favorite/OnDemand/map buttons that take you to a new view that pulls the location's menu from FD MealPlanner. You can view all of the menu items that have actually been added to that site, and tap them for more details (which will be expanded on later). Searching the item list is supported, with more filtering options coming in the next update. Meal periods can be browsed using the clock button in the top right for locations that are open more than once per day. Other changes: - App renamed from "RIT Dining" to "TigerDine" to not get me in trouble for an App Store release - Slightly changed the way that dining locations' short descriptions and current open times are displayed in the detail view - Fixed the box truck icon used in the food truck view being squished
98 lines
4.3 KiB
Swift
98 lines
4.3 KiB
Swift
//
|
||
// FoodTruckParsers.swift
|
||
// RIT Dining
|
||
//
|
||
// Created by Campbell on 11/3/25.
|
||
//
|
||
|
||
import Foundation
|
||
import SwiftSoup
|
||
|
||
// This code is actually miserable and might break sometimes. Sorry. Parse the HTML of the RIT food trucks web page and build
|
||
// a list of food trucks that are going to be there the next time they're there. This is not a good way to get this data but it's
|
||
// unfortunately the best way that I think I could make it happen. Sorry again for both my later self and anyone else who tries to
|
||
// work on this code.
|
||
func parseWeekendFoodTrucks(htmlString: String) -> [FoodTruckEvent] {
|
||
do {
|
||
let doc = try SwiftSoup.parse(htmlString)
|
||
var events: [FoodTruckEvent] = []
|
||
let now = Date()
|
||
let calendar = Calendar.current
|
||
|
||
let paragraphs = try doc.select("p:has(strong)")
|
||
|
||
for p in paragraphs {
|
||
let text = try p.text()
|
||
let parts = text.components(separatedBy: .whitespaces).joined(separator: " ")
|
||
|
||
let dateRegex = /(?:(Monday|Tuesday|Wednesday|Thursday|Friday|Saturday|Sunday),\s+[A-Za-z]+\s+\d+)/
|
||
let date = parts.firstMatch(of: dateRegex).map { String($0.0) } ?? ""
|
||
if date.isEmpty { continue }
|
||
|
||
let timeRegex = /(\d{1,2}(:\d{2})?\s*[-–]\s*\d{1,2}(:\d{2})?\s*p\.m\.)/
|
||
let time = parts.firstMatch(of: timeRegex).map { String($0.0) } ?? ""
|
||
|
||
let locationRegex = /A-Z Lot/
|
||
let location = parts.firstMatch(of: locationRegex).map { String($0.0) } ?? ""
|
||
|
||
let year = Calendar.current.component(.year, from: Date())
|
||
let fullDateString = "\(date) \(year)"
|
||
let formatter = DateFormatter()
|
||
formatter.dateFormat = "EEEE, MMMM d yyyy"
|
||
formatter.locale = Locale(identifier: "en_US_POSIX")
|
||
let dateParsed = formatter.date(from: fullDateString) ?? now
|
||
|
||
let timeStrings = time.split(separator: "-", maxSplits: 1)
|
||
print("raw open range: \(timeStrings)")
|
||
var openTime = Date()
|
||
var closeTime = Date()
|
||
if let openString = timeStrings.first?.trimmingCharacters(in: .whitespaces) {
|
||
// If the time is NOT in the morning, add 12 hours.
|
||
let openHour = if openString.contains("a.m") {
|
||
Int(openString.filter("0123456789".contains))!
|
||
} else {
|
||
Int(openString)! + 12
|
||
}
|
||
let openTimeComponents = DateComponents(hour: openHour, minute: 0, second: 0)
|
||
openTime = calendar.date(
|
||
bySettingHour: openTimeComponents.hour!,
|
||
minute: openTimeComponents.minute!,
|
||
second: openTimeComponents.second!,
|
||
of: now)!
|
||
}
|
||
if let closeString = timeStrings.last?.filter(":0123456789".contains) {
|
||
// I've chosen to assume that no visiting chef will ever close in the morning. This could bad choice but I have
|
||
// yet to see any evidence of a visiting chef leaving before noon so far.
|
||
let closeStringComponents = closeString.split(separator: ":", maxSplits: 1)
|
||
let closeTimeComponents = DateComponents(
|
||
hour: Int(closeStringComponents[0])! + 12,
|
||
minute: closeStringComponents.count > 1 ? Int(closeStringComponents[1]) : 0,
|
||
second: 0)
|
||
closeTime = calendar.date(
|
||
bySettingHour: closeTimeComponents.hour!,
|
||
minute: closeTimeComponents.minute!,
|
||
second: closeTimeComponents.second!,
|
||
of: now)!
|
||
}
|
||
|
||
if let ul = try p.nextElementSibling(), ul.tagName() == "ul" {
|
||
let trucks = try ul.select("li").array().map { try $0.text() }
|
||
|
||
events.append(FoodTruckEvent(
|
||
date: dateParsed,
|
||
openTime: openTime,
|
||
closeTime: closeTime,
|
||
location: location,
|
||
trucks: trucks
|
||
))
|
||
print(events)
|
||
}
|
||
}
|
||
|
||
return events
|
||
} catch {
|
||
print(error)
|
||
return []
|
||
}
|
||
}
|