UNPKG

@fboes/aerofly-patterns

Version:

Landegerät - Create random custom missions for Aerofly FS 4.

255 lines (254 loc) 11.3 kB
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) { if (kind === "m") throw new TypeError("Private method is not writable"); if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter"); if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it"); return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value; }; var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) { if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); }; var _AeroflyMissionAutofill_mission; import { AeroflyMissionTargetPlane } from "@fboes/aerofly-custom-missions"; export class AeroflyMissionAutofill { constructor(mission) { _AeroflyMissionAutofill_mission.set(this, void 0); __classPrivateFieldSet(this, _AeroflyMissionAutofill_mission, mission, "f"); } get title() { if (__classPrivateFieldGet(this, _AeroflyMissionAutofill_mission, "f").origin.icao == __classPrivateFieldGet(this, _AeroflyMissionAutofill_mission, "f").destination.icao) { return `Local flight at ${__classPrivateFieldGet(this, _AeroflyMissionAutofill_mission, "f").origin.icao}`; } return `From ${__classPrivateFieldGet(this, _AeroflyMissionAutofill_mission, "f").origin.icao} to ${__classPrivateFieldGet(this, _AeroflyMissionAutofill_mission, "f").destination.icao}`; } get description() { const weatherAdjectives = this.weatherAdjectives; const weatherAdjectivesString = weatherAdjectives.length > 0 ? ` ${weatherAdjectives.join(", ")}` : ""; return `Your ${this.aircraftName} is ${this.flightSetting} on this${weatherAdjectivesString} ${this.timeOfDay} with ${this.wind}.`; } get tags() { const tags = []; if (__classPrivateFieldGet(this, _AeroflyMissionAutofill_mission, "f").conditions.wind.speed >= 22) { tags.push("windy"); } if (__classPrivateFieldGet(this, _AeroflyMissionAutofill_mission, "f").conditions.visibility_sm <= 3) { tags.push("low_visibility"); } if (this.timeOfDay === "night") { tags.push("night"); } if (__classPrivateFieldGet(this, _AeroflyMissionAutofill_mission, "f").flightSetting === "cold_and_dark") { tags.push("cold_and_dark"); } else if (__classPrivateFieldGet(this, _AeroflyMissionAutofill_mission, "f").flightSetting === "before_start") { tags.push("before_start"); } return tags; } get weatherAdjectives() { /** * @type {string[]} */ const adjectives = []; const conditions = __classPrivateFieldGet(this, _AeroflyMissionAutofill_mission, "f").conditions; if (conditions.wind.speed >= 48) { adjectives.push("stormy"); } else if (conditions.wind.speed >= 34) { adjectives.push("very windy"); } else if (conditions.wind.gusts >= 10) { // Gusty being more interesting as windy adjectives.push("gusty"); } else if (conditions.wind.speed >= 22) { adjectives.push("windy"); } if (conditions.visibility_sm <= 1) { adjectives.push("foggy"); } else if (conditions.visibility_sm <= 3) { adjectives.push("misty"); } else { switch (conditions.clouds[0]?.cover_code) { case "OVC": adjectives.push("overcast"); break; case "BKN": adjectives.push("cloudy"); break; case "CLR": adjectives.push("clear"); break; } } return adjectives; } /** * @param {number} knots in knots * @returns {number} duration in seconds, considering aircraft flight setting */ calculateDuration(knots) { let duration = (__classPrivateFieldGet(this, _AeroflyMissionAutofill_mission, "f").distance ?? 0) / (knots * (1852 / 3600)); switch (__classPrivateFieldGet(this, _AeroflyMissionAutofill_mission, "f").flightSetting) { case "cold_and_dark": duration += 240; break; case "before_start": duration += 120; break; case "taxi": duration += 60; break; } return duration; } /** * Setting a target plane in around 1 meter distance in front of the aircraft. */ removeGuides() { const directionRad = (__classPrivateFieldGet(this, _AeroflyMissionAutofill_mission, "f").origin.dir * Math.PI) / 180; const offset = 0.00001; __classPrivateFieldGet(this, _AeroflyMissionAutofill_mission, "f").finish = new AeroflyMissionTargetPlane(__classPrivateFieldGet(this, _AeroflyMissionAutofill_mission, "f").origin.longitude + Math.sin(directionRad) * offset, __classPrivateFieldGet(this, _AeroflyMissionAutofill_mission, "f").origin.latitude + Math.cos(directionRad) * offset, __classPrivateFieldGet(this, _AeroflyMissionAutofill_mission, "f").origin.dir); } /** * Will also add the bearing between the given checkpoints. * @returns {number} in meters */ get distance() { /** * @type {AeroflyMissionCheckpoint?} */ let lastCp = null; let distance = 0; for (const cp of __classPrivateFieldGet(this, _AeroflyMissionAutofill_mission, "f").checkpoints) { if (lastCp !== null) { const vector = AeroflyMissionAutofill.getDistanceBetweenCheckpoints(lastCp, cp); distance += vector.distance; cp.direction = vector.bearing; } lastCp = cp; } return distance; } get nauticalTimeHours() { return (__classPrivateFieldGet(this, _AeroflyMissionAutofill_mission, "f").conditions.time.getUTCHours() + this.nauticalTimezoneOffset + 24) % 24; } get nauticalTimezoneOffset() { return Math.round((__classPrivateFieldGet(this, _AeroflyMissionAutofill_mission, "f").origin.longitude ?? 0) / 15); } get timeOfDay() { const nauticalTimeHours = this.nauticalTimeHours; if (nauticalTimeHours < 5 || nauticalTimeHours >= 19) { return "night"; } if (nauticalTimeHours < 8) { return "early morning"; } if (nauticalTimeHours < 11) { return "morning"; } if (nauticalTimeHours < 13) { return "noon"; } if (nauticalTimeHours < 15) { return "afternoon"; } if (nauticalTimeHours < 19) { return "late afternoon"; } return "day"; } get aircraftName() { switch (__classPrivateFieldGet(this, _AeroflyMissionAutofill_mission, "f").aircraft.name) { case "f15e": case "f18": case "mb339": case "p38": case "uh60": return __classPrivateFieldGet(this, _AeroflyMissionAutofill_mission, "f").aircraft.name.toUpperCase().replace(/^(\D+)(\d+)/, "$1-$2"); case "camel": case "concorde": case "jungmeister": case "pitts": case "swift": return __classPrivateFieldGet(this, _AeroflyMissionAutofill_mission, "f").aircraft.name[0].toUpperCase() + String(__classPrivateFieldGet(this, _AeroflyMissionAutofill_mission, "f").aircraft.name).slice(1); default: return __classPrivateFieldGet(this, _AeroflyMissionAutofill_mission, "f").aircraft.name.toUpperCase().replace(/_/, "-"); } } get flightSetting() { switch (__classPrivateFieldGet(this, _AeroflyMissionAutofill_mission, "f").flightSetting) { case "cold_and_dark": return "cold and dark"; case "before_start": return "just before engine start"; case "taxi": return "ready to taxi"; case "takeoff": return "ready for take-off"; case "cruise": return "cruising"; case "approach": return "in approach configuration"; case "landing": return "in landing configuration"; case "pushback": return "ready for push-back"; case "aerotow": return "towed by a tow-plane"; case "winch_launch": return "ready for winch-launch"; default: return "ready to go"; } } get wind() { let wind = ``; const conditions = __classPrivateFieldGet(this, _AeroflyMissionAutofill_mission, "f").conditions; if (conditions.wind.speed < 1) { wind = `no wind`; } else if (conditions.wind.speed <= 5) { wind = `almost no wind`; } else { wind = `wind from ${String(conditions.wind.direction).padStart(3, "0")}° at ${conditions.wind.speed} kts`; } if (__classPrivateFieldGet(this, _AeroflyMissionAutofill_mission, "f").conditions.thermalStrength > 0.8) { wind += ` and lots of thermal activity`; } else if (__classPrivateFieldGet(this, _AeroflyMissionAutofill_mission, "f").conditions.thermalStrength > 0.4) { wind += ` and moderate thermal activity`; } return wind; } /** * * @param {AeroflyMissionCheckpoint} lastCp * @param {AeroflyMissionCheckpoint} cp * @returns {{distance:number,bearing:number}} distance in meters */ static getDistanceBetweenCheckpoints(lastCp, cp) { const lat1 = (lastCp.latitude / 180) * Math.PI; const lon1 = (lastCp.longitude / 180) * Math.PI; const lat2 = (cp.latitude / 180) * Math.PI; const lon2 = (cp.longitude / 180) * Math.PI; const dLon = lon2 - lon1; const dLat = lat2 - lat1; const y = Math.sin(dLon) * Math.cos(lat2); const x = Math.cos(lat1) * Math.sin(lat2) - Math.sin(lat1) * Math.cos(lat2) * Math.cos(dLon); const bearing = ((Math.atan2(y, x) * 180) / Math.PI + 360) % 360; const a = Math.sin(dLat / 2) * Math.sin(dLat / 2) + Math.sin(dLon / 2) * Math.sin(dLon / 2) * Math.cos(lat1) * Math.cos(lat2); const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)); const distance = 6_371_000 * c; return { distance, bearing, }; } } _AeroflyMissionAutofill_mission = new WeakMap();