More leeway on TF overfly (MHTG)

NG skip
This commit is contained in:
Kilian Kurt Hofmann 2025-08-17 00:01:22 +02:00
parent 900babf4cc
commit 266606d9ab
5 changed files with 73 additions and 59 deletions

View File

@ -17,6 +17,7 @@ function App() {
const [params, setParams] = useState<DeviceFlowParams | null>(null); const [params, setParams] = useState<DeviceFlowParams | null>(null);
const [selectedTransition, setSelectedTransition] = useState<Procedure>(); const [selectedTransition, setSelectedTransition] = useState<Procedure>();
const [selectedChart, setSelectedChart] = useState<Chart>(); const [selectedChart, setSelectedChart] = useState<Chart>();
const [skippedNG, setSkippedNG] = useState(false);
const { user, signIn, initialized } = useNavigraphAuth(); const { user, signIn, initialized } = useNavigraphAuth();
@ -42,16 +43,22 @@ function App() {
return ( return (
<> <>
{!user ? ( {!user && !skippedNG ? (
<div className="flex min-h-dvh w-full"> <div className="flex min-h-dvh w-full">
{initialized && !params && ( {initialized && !params && (
<div className="flex h-dvh w-dvw items-center justify-center"> <div className="flex h-dvh w-dvw flex-col items-center justify-center gap-2">
<button <button
className="cursor-pointer rounded border border-gray-300 bg-gray-300 px-2 py-1 font-semibold focus:outline-2 focus-visible:outline-2 disabled:bg-gray-100" className="cursor-pointer rounded border border-gray-300 bg-gray-300 px-2 py-1 font-semibold focus:outline-2 focus-visible:outline-2"
onClick={handleSignIn} onClick={handleSignIn}
> >
Sign in to NG Sign in to NG
</button> </button>
<button
className="cursor-pointer rounded border border-gray-600 px-2 py-1 font-semibold focus:outline-2 focus-visible:outline-2"
onClick={() => setSkippedNG(true)}
>
Skip NG
</button>
</div> </div>
)} )}
@ -79,6 +86,7 @@ function App() {
transitions={transitions} transitions={transitions}
transition={selectedTransition} transition={selectedTransition}
chart={selectedChart} chart={selectedChart}
skippedNG={skippedNG}
setTransition={setSelectedTransition} setTransition={setSelectedTransition}
setChart={setSelectedChart} setChart={setSelectedChart}
backAction={() => { backAction={() => {

View File

@ -12,6 +12,7 @@ interface SidebarProps {
transitions: Procedure[]; transitions: Procedure[];
transition: Procedure | undefined; transition: Procedure | undefined;
chart: Chart | undefined; chart: Chart | undefined;
skippedNG?: boolean;
setTransition: Dispatch<SetStateAction<SidebarProps['transition']>>; setTransition: Dispatch<SetStateAction<SidebarProps['transition']>>;
setChart: Dispatch<SetStateAction<SidebarProps['chart']>>; setChart: Dispatch<SetStateAction<SidebarProps['chart']>>;
backAction: () => void; backAction: () => void;
@ -24,6 +25,7 @@ export const Sidebar: FC<SidebarProps> = ({
transitions, transitions,
transition, transition,
chart, chart,
skippedNG,
setTransition, setTransition,
setChart, setChart,
backAction, backAction,
@ -36,6 +38,8 @@ export const Sidebar: FC<SidebarProps> = ({
}>({ star: [], sid: [], iap: [] }); }>({ star: [], sid: [], iap: [] });
useEffect(() => { useEffect(() => {
if (skippedNG) return;
setInFlight(true); setInFlight(true);
(async () => { (async () => {
const _chartIndex = await charts.getChartsIndex({ icao: airport.ICAO, version: 'STD' }); const _chartIndex = await charts.getChartsIndex({ icao: airport.ICAO, version: 'STD' });
@ -134,61 +138,63 @@ export const Sidebar: FC<SidebarProps> = ({
))} ))}
</div> </div>
<div className="flex flex-col gap-2"> {!skippedNG && (
<div className="sticky top-0 z-10 -mx-2 bg-gray-500 px-2 text-lg font-semibold text-white">Charts</div>
{inFlight && <Loader size={3} />}
<div className="flex flex-col gap-2"> <div className="flex flex-col gap-2">
<div className="sticky top-7 -mx-2 -mt-2 bg-gray-500 px-2 text-lg font-semibold text-white">Arrivals</div> <div className="sticky top-0 z-10 -mx-2 bg-gray-500 px-2 text-lg font-semibold text-white">Charts</div>
{chartIndex.star {inFlight && <Loader size={3} />}
.filter((_chart) => _chart.is_georeferenced)
.map((_chart) => (
<button
key={_chart.index_number}
className={`cursor-pointer rounded border border-gray-300 bg-gray-300 px-2 py-1 text-left font-semibold focus:outline-2 focus:outline-black focus-visible:outline-2 focus-visible:outline-black ${chart?.index_number === _chart.index_number ? 'outline-2' : ''}`}
onClick={() => findChart(_chart)}
>
<span className="font-bold">{_chart.index_number}</span>
<br />
{_chart.name}
</button>
))}
</div>
<div className="flex flex-col gap-2"> <div className="flex flex-col gap-2">
<div className="sticky top-7 -mx-2 bg-gray-500 px-2 text-lg font-semibold text-white">Departures</div> <div className="sticky top-7 -mx-2 -mt-2 bg-gray-500 px-2 text-lg font-semibold text-white">Arrivals</div>
{chartIndex.sid {chartIndex.star
.filter((_chart) => _chart.is_georeferenced) .filter((_chart) => _chart.is_georeferenced)
.map((_chart) => ( .map((_chart) => (
<button <button
key={_chart.index_number} key={_chart.index_number}
className={`cursor-pointer rounded border border-gray-300 bg-gray-300 px-2 py-1 text-left font-semibold focus:outline-2 focus:outline-black focus-visible:outline-2 focus-visible:outline-black ${chart?.index_number === _chart.index_number ? 'outline-2' : ''}`} className={`cursor-pointer rounded border border-gray-300 bg-gray-300 px-2 py-1 text-left font-semibold focus:outline-2 focus:outline-black focus-visible:outline-2 focus-visible:outline-black ${chart?.index_number === _chart.index_number ? 'outline-2' : ''}`}
onClick={() => findChart(_chart)} onClick={() => findChart(_chart)}
> >
<span className="font-bold">{_chart.index_number}</span> <span className="font-bold">{_chart.index_number}</span>
<br /> <br />
{_chart.name} {_chart.name}
</button> </button>
))} ))}
</div> </div>
<div className="flex flex-col gap-2"> <div className="flex flex-col gap-2">
<div className="sticky top-7 -mx-2 bg-gray-500 px-2 text-lg font-semibold text-white">Approaches</div> <div className="sticky top-7 -mx-2 bg-gray-500 px-2 text-lg font-semibold text-white">Departures</div>
{chartIndex.iap {chartIndex.sid
.filter((_chart) => _chart.is_georeferenced) .filter((_chart) => _chart.is_georeferenced)
.map((_chart) => ( .map((_chart) => (
<button <button
key={_chart.index_number} key={_chart.index_number}
className={`cursor-pointer rounded border border-gray-300 bg-gray-300 px-2 py-1 text-left font-semibold focus:outline-2 focus:outline-black focus-visible:outline-2 focus-visible:outline-black ${chart?.index_number === _chart.index_number ? 'outline-2' : ''}`} className={`cursor-pointer rounded border border-gray-300 bg-gray-300 px-2 py-1 text-left font-semibold focus:outline-2 focus:outline-black focus-visible:outline-2 focus-visible:outline-black ${chart?.index_number === _chart.index_number ? 'outline-2' : ''}`}
onClick={() => findChart(_chart)} onClick={() => findChart(_chart)}
> >
<span className="font-bold">{_chart.index_number}</span> <span className="font-bold">{_chart.index_number}</span>
<br /> <br />
{_chart.name} {_chart.name}
</button> </button>
))} ))}
</div>
<div className="flex flex-col gap-2">
<div className="sticky top-7 -mx-2 bg-gray-500 px-2 text-lg font-semibold text-white">Approaches</div>
{chartIndex.iap
.filter((_chart) => _chart.is_georeferenced)
.map((_chart) => (
<button
key={_chart.index_number}
className={`cursor-pointer rounded border border-gray-300 bg-gray-300 px-2 py-1 text-left font-semibold focus:outline-2 focus:outline-black focus-visible:outline-2 focus-visible:outline-black ${chart?.index_number === _chart.index_number ? 'outline-2' : ''}`}
onClick={() => findChart(_chart)}
>
<span className="font-bold">{_chart.index_number}</span>
<br />
{_chart.name}
</button>
))}
</div>
</div> </div>
</div> )}
</div> </div>
</div> </div>
); );

View File

@ -32,7 +32,7 @@ export const TerminatorsTF = (
// Compute overfly arc // Compute overfly arc
let arc1: LineSegment[] | null = null; let arc1: LineSegment[] | null = null;
let arc2: LineSegment[] = [[previousFix.longitude, previousFix.latitude]]; let arc2: LineSegment[] = [[previousFix.longitude, previousFix.latitude]];
if (previousFix.isFlyOver) { if (previousFix.isFlyOver && !lastCourse.equal(crsIntoEndpoint, 0.5)) {
arc1 = generateTangentArc(crsIntoEndpoint, lastCourse, previousFix, targetFix, leg.TurnDir); arc1 = generateTangentArc(crsIntoEndpoint, lastCourse, previousFix, targetFix, leg.TurnDir);
} else { } else {
arc1 = [[previousFix.longitude, previousFix.latitude]]; arc1 = [[previousFix.longitude, previousFix.latitude]];

View File

@ -59,8 +59,8 @@ Number.prototype.toTrue = function (fix) {
Number.prototype.toMetre = function () { Number.prototype.toMetre = function () {
return (this as number) * 1852.0; return (this as number) * 1852.0;
}; };
Number.prototype.equal = function (other: number) { Number.prototype.equal = function (other: number, accuracy = 0.1) {
return Math.abs((this as number) - other) <= 0.1; return Math.abs((this as number) - other) <= accuracy;
}; };
String.prototype.parseAltitude = function () { String.prototype.parseAltitude = function () {

View File

@ -26,9 +26,9 @@ export declare global {
*/ */
toMetre: () => number; toMetre: () => number;
/** /**
* @returns True if delta is less than 0.1 * @returns True if delta is less than accuracy (default 0.1)
*/ */
equal: (other: number) => boolean; equal: (other: number, accuracy?: number) => boolean;
} }
interface String { interface String {