updates on the api endpoints on the customer page and more
This commit is contained in:
71
internal/legs/legs.go
Normal file
71
internal/legs/legs.go
Normal file
@@ -0,0 +1,71 @@
|
||||
// Package legs answers one question, in one place: does a parcel go straight to
|
||||
// its receiver, or does it go via a base first?
|
||||
//
|
||||
// It exists because two packages need that answer and neither can import the
|
||||
// other. controllers decides it at pickup-complete (which state the consignment
|
||||
// lands in, and which base the rider is sent to); internal/routing needs it when
|
||||
// it sequences a rider's stops, because a hub-routed parcel's next stop is the
|
||||
// BASE, not the address on the booking. controllers already imports
|
||||
// internal/routing, so routing cannot import back — and a second copy of the
|
||||
// rule in routing is exactly the kind of duplication this codebase has been
|
||||
// bitten by before (the rival status table in dispatchShared, the batch windows
|
||||
// that drifted between two pages).
|
||||
//
|
||||
// So the rule lives here and both call it. Neither owns it.
|
||||
package legs
|
||||
|
||||
import "math"
|
||||
|
||||
// HaversineKM is the straight-line distance between two points, in kilometres.
|
||||
// One definition for the whole codebase — controllers.haversineKM delegates to
|
||||
// it rather than keeping a second copy.
|
||||
func HaversineKM(lat1, lon1, lat2, lon2 float64) float64 {
|
||||
const earthRadiusKM = 6371.0
|
||||
toRad := func(deg float64) float64 { return deg * math.Pi / 180 }
|
||||
dLat := toRad(lat2 - lat1)
|
||||
dLon := toRad(lon2 - lon1)
|
||||
a := math.Sin(dLat/2)*math.Sin(dLat/2) +
|
||||
math.Cos(toRad(lat1))*math.Cos(toRad(lat2))*math.Sin(dLon/2)*math.Sin(dLon/2)
|
||||
return earthRadiusKM * 2 * math.Atan2(math.Sqrt(a), math.Sqrt(1-a))
|
||||
}
|
||||
|
||||
// MaxHyperlocalKM bounds the straight-line pickup→delivery distance under which
|
||||
// a booking with a missing or unusable pincode is still treated as hyperlocal.
|
||||
// It is ONLY consulted when the pincode rule cannot decide: console-created
|
||||
// kitchen→customer bookings frequently carry accurate coordinates and no
|
||||
// delivery pincode, and must not be routed through a base because of it.
|
||||
const MaxHyperlocalKM = 30.0
|
||||
|
||||
// SamePostalArea reports whether two pincodes fall in the same 3-digit postal
|
||||
// area. Pincodes shorter than 3 characters are treated as unknown rather than
|
||||
// matching, so bad data falls back to the safe hub route instead of quietly
|
||||
// claiming two parcels belong together.
|
||||
func SamePostalArea(pickupPincode, deliveryPincode string) bool {
|
||||
if len(pickupPincode) < 3 || len(deliveryPincode) < 3 {
|
||||
return false
|
||||
}
|
||||
return pickupPincode[:3] == deliveryPincode[:3]
|
||||
}
|
||||
|
||||
// IsHyperlocal decides whether a parcel can skip the base and be carried
|
||||
// straight to the receiver by the collecting rider.
|
||||
//
|
||||
// The pincode-prefix rule decides outright when both pincodes are present — a
|
||||
// matching prefix is hyperlocal, a differing one is genuinely inter-area, and
|
||||
// distance does not get a vote. Pollachi is 40km from Coimbatore, closer than
|
||||
// plenty of runs treated as local, and it is still a different postal area.
|
||||
//
|
||||
// Only when a pincode is missing or too short does the straight-line distance
|
||||
// decide instead. With neither pincodes nor coordinates the answer is false,
|
||||
// which routes via a base — the safe direction to be wrong in, because a parcel
|
||||
// that reaches a base can still be forwarded, while one handed to a rider who
|
||||
// cannot reach the receiver is stuck.
|
||||
func IsHyperlocal(pickupPincode, deliveryPincode string, pLat, pLng, dLat, dLng float64) bool {
|
||||
if len(pickupPincode) >= 3 && len(deliveryPincode) >= 3 {
|
||||
return SamePostalArea(pickupPincode, deliveryPincode)
|
||||
}
|
||||
if pLat != 0 && pLng != 0 && dLat != 0 && dLng != 0 {
|
||||
return HaversineKM(pLat, pLng, dLat, dLng) <= MaxHyperlocalKM
|
||||
}
|
||||
return false
|
||||
}
|
||||
Reference in New Issue
Block a user