From 6c66ae9b24761ba6599545a87a7dc75c1b97d944 Mon Sep 17 00:00:00 2001 From: Nabeel Shahzad Date: Tue, 24 Sep 2024 13:42:30 -0500 Subject: [PATCH] Update to new return type for rules --- README.md | 40 +++++++++++++++++++------- src/aircraft/example.ts | 44 +++++++++++++++++++++++++++++ src/rules/beacon_lights.ts | 6 ++-- src/rules/excess_bank.ts | 27 +++++++++--------- src/rules/excess_gforce.ts | 4 +-- src/rules/excess_pitch.ts | 8 +++--- src/rules/excess_taxi_speed.ts | 6 ++-- src/rules/fuel_refilled.ts | 23 ++++++++------- src/rules/hard_landing.ts | 8 +++--- src/rules/lights_off_during_taxi.ts | 6 ++-- src/rules/lights_over_10k.ts | 8 ++++-- src/rules/lights_under_10k.ts | 8 ++++-- src/rules/simrate.ts | 2 +- src/rules/slew_activated.ts | 2 +- src/rules/speed_under_10k.ts | 18 +++++++++--- src/rules/stabilized_approach.ts | 14 +++++---- src/rules/stall_warning.ts | 2 +- src/rules/strobes_in_flights.ts | 12 +++++--- src/rules/strobes_on_during_taxi.ts | 6 ++-- src/types/rule.d.ts | 16 ++++++++--- 20 files changed, 178 insertions(+), 82 deletions(-) create mode 100644 src/aircraft/example.ts diff --git a/README.md b/README.md index 08c037b..2255559 100644 --- a/README.md +++ b/README.md @@ -336,23 +336,43 @@ A rule also has several components: ### Returning a `RuleValue` -The return value is an tuple, with one mandatory value, and 2 optional values: +The return value has multiple possible values, sending on +```typescript +export type RuleValue = undefined | boolean | [string?, number?] +``` + +If a rule is passing/hasn't been violated: + +```typescript +return +return false +``` + +If a rule has been violated: + +```typescript +return true ``` -RuleValue = [boolean, message, points] + +Or, if you want to return a custom message: + +```typescript +return ['message'] ``` +Or, if you want to return a message and points: + ```typescript -// The true/false MUST be there, it's if the rule was violated or not -return [true] +return ['message', points] +``` -// Return a message along with the state. If not set or null, it will -// use `this.meta.message` as the default -return [true, message] +If you want to return just the points, you can return: -// This returns that it was violated, uses the default message, but changes -// the points returned to -10 -return [true, null, -10] +```typescript +return ['', points] ``` +`points` and `message` are optional - if omitted, they're pulled from the `meta` block + ### Helper Methods diff --git a/src/aircraft/example.ts b/src/aircraft/example.ts new file mode 100644 index 0000000..28c27d2 --- /dev/null +++ b/src/aircraft/example.ts @@ -0,0 +1,44 @@ +import { AircraftConfigSimType, AircraftFeature, FeatureType } from '../defs' +import { + AircraftConfig, + FeatureAddresses, + FeatureState, + FlapNames, + Meta, +} from '../interface/aircraft' + +export default class Example extends AircraftConfig { + meta: Meta = { + id: 'example', + name: 'example', + sim: AircraftConfigSimType.MsFs, + enabled: true, + priority: 2, + } + + features: FeatureAddresses = { + [AircraftFeature.BeaconLights]: { + example_lvar: FeatureType.Int, + }, + } + + flapNames: FlapNames = { + 0: 'UP', + 1: 'CONF 1', + } + + /** + * + * @param {string} title The title of the aircraft, lowercased + * @param {string=} icao The ICAO of the aircraft. Might not be available + * @param {string=} config_path Path to the aircraft config. Might not be there + * @return {boolean} + */ + match(title: string, icao: string, config_path: string): boolean { + return ['example', 'aircraft'].every((w) => title.includes(w)) + } + + beaconLights(): FeatureState { + return null + } +} diff --git a/src/rules/beacon_lights.ts b/src/rules/beacon_lights.ts index 04eac04..b394105 100644 --- a/src/rules/beacon_lights.ts +++ b/src/rules/beacon_lights.ts @@ -21,7 +21,7 @@ export default class BeaconLights implements Rule { violated(pirep: Pirep, data: Telemetry, previousData?: Telemetry): RuleValue { if (!Acars.IsFeatureEnabled(AircraftFeature.BeaconLights)) { - return [false] + return false } return Acars.ViolatedAfterDelay( @@ -29,10 +29,10 @@ export default class BeaconLights implements Rule { this.meta.delay_time, (): RuleValue => { if (!pirep.isInActiveState) { - return [false] + return false } - return data.anyEnginesRunning && !data.beaconLights ? [true] : [false] + return data.anyEnginesRunning && !data.beaconLights }, ) } diff --git a/src/rules/excess_bank.ts b/src/rules/excess_bank.ts index 62e26af..0467c5b 100644 --- a/src/rules/excess_bank.ts +++ b/src/rules/excess_bank.ts @@ -1,7 +1,7 @@ /** * Excess bank angle */ -import { AircraftFeature, PirepState } from '../defs' +import { PirepState } from '../defs' import { Meta, Rule, RuleValue } from '../types/rule' import { Pirep, Telemetry } from '../types/types' @@ -27,20 +27,19 @@ export default class ExcessBank implements Rule { violated(pirep: Pirep, data: Telemetry, previousData?: Telemetry): RuleValue { if (data.onGround) { - return [false] + return } - return Acars.ViolatedAfterDelay(this.meta.id, this.meta.delay_time, () => { - // +Bank is right, -Bank is left - const value = - data.bank < -1 * this.meta.parameter! || - data.bank > this.meta.parameter! - - if (value) { - return [true] - } else { - return [false] - } - }) + return Acars.ViolatedAfterDelay( + this.meta.id, + this.meta.delay_time, + (): RuleValue => { + // +Bank is right, -Bank is left + return ( + data.bank < -1 * this.meta.parameter! || + data.bank > this.meta.parameter! + ) + }, + ) } } diff --git a/src/rules/excess_gforce.ts b/src/rules/excess_gforce.ts index c04e477..acba0b2 100644 --- a/src/rules/excess_gforce.ts +++ b/src/rules/excess_gforce.ts @@ -27,9 +27,9 @@ export default class ExcessGForce implements Rule { violated(pirep: Pirep, data: Telemetry, previousData?: Telemetry): RuleValue { if (data.onGround) { - return [false] + return } - return [data.gForce >= this.meta.parameter!] + return data.gForce >= this.meta.parameter! } } diff --git a/src/rules/excess_pitch.ts b/src/rules/excess_pitch.ts index 2dd0e52..80b9606 100644 --- a/src/rules/excess_pitch.ts +++ b/src/rules/excess_pitch.ts @@ -27,12 +27,12 @@ export default class ExcessPitch implements Rule { violated(pirep: Pirep, data: Telemetry, previousData?: Telemetry): RuleValue { if (data.onGround) { - return [false] + return } - return [ + return ( data.pitch < -1 * this.meta.parameter! || - data.pitch > this.meta.parameter!, - ] + data.pitch > this.meta.parameter! + ) } } diff --git a/src/rules/excess_taxi_speed.ts b/src/rules/excess_taxi_speed.ts index b261b22..2eb1f26 100644 --- a/src/rules/excess_taxi_speed.ts +++ b/src/rules/excess_taxi_speed.ts @@ -28,15 +28,15 @@ export default class ExcessTaxiSpeed implements Rule { this.meta.delay_time, (): RuleValue => { if (!data.onGround) { - return [false] + return } // If they're on a runway, ignore any taxi speed warnings, might be taking off if (data.approachingRunway != null || data.runway != null) { - return [false] + return } - return [data.groundSpeed.Knots > this.meta.parameter!] + return data.groundSpeed.Knots > this.meta.parameter! }, ) } diff --git a/src/rules/fuel_refilled.ts b/src/rules/fuel_refilled.ts index 711c3a9..bd3d4b2 100644 --- a/src/rules/fuel_refilled.ts +++ b/src/rules/fuel_refilled.ts @@ -32,20 +32,23 @@ export default class FuelRefilled implements Rule { violated(pirep: Pirep, data: Telemetry, previousData?: Telemetry): RuleValue { if (data.onGround || previousData == null) { - return [false] + return } if (data.fuelQuantity.Pounds > previousData.fuelQuantity.Pounds) { - return [false] + return } - return [ - Acars.NumberOverPercent( - data.fuelQuantity.Pounds, - previousData.fuelQuantity.Pounds, - 10, - ), - `Fuel Refilled: Current: ${data.fuelQuantity.Pounds}, previous=${previousData.fuelQuantity.Pounds}`, - ] + const violated = Acars.NumberOverPercent( + data.fuelQuantity.Pounds, + previousData.fuelQuantity.Pounds, + 10, + ) + + if (violated) { + return [ + `Fuel Refilled: Current: ${data.fuelQuantity.Pounds}, previous=${previousData.fuelQuantity.Pounds}`, + ] + } } } diff --git a/src/rules/hard_landing.ts b/src/rules/hard_landing.ts index 601a8e9..9005366 100644 --- a/src/rules/hard_landing.ts +++ b/src/rules/hard_landing.ts @@ -6,27 +6,27 @@ export default class HandLandings implements Rule { meta: Meta = { id: 'HARD_LANDING', name: 'Hard Landing', - enabled: true, // Default, will change depending on airline config + enabled: true, message: 'Hard Landing', states: [PirepState.Final, PirepState.Landed], repeatable: false, cooldown: 60, max_count: 3, points: -1, - parameter: 300, // default, gets overwritten from remote + parameter: 500, } violated(pirep: Pirep, data: Telemetry, previousData?: Telemetry): RuleValue { const absRate = Math.abs(pirep.landingRate.FeetPerMinute) const absParam = Math.abs(this.meta.parameter!) if (absRate < absParam) { - return [false] + return } console.log( `Hard landing violation, rate=${absRate}, threshold=${absParam}`, ) - return [true] + return true } } diff --git a/src/rules/lights_off_during_taxi.ts b/src/rules/lights_off_during_taxi.ts index 4013983..b6f5316 100644 --- a/src/rules/lights_off_during_taxi.ts +++ b/src/rules/lights_off_during_taxi.ts @@ -21,7 +21,7 @@ export default class LightsOffDuringTaxi implements Rule { violated(pirep: Pirep, data: Telemetry, previousData?: Telemetry): RuleValue { if (!Acars.IsFeatureEnabled(AircraftFeature.LandingLights)) { - return [false] + return } return Acars.ViolatedAfterDelay( @@ -30,10 +30,10 @@ export default class LightsOffDuringTaxi implements Rule { (): RuleValue => { // Ignore landing lights being turned on if (data.approachingRunway != null || data.runway != null) { - return [false] + return } - return [data.landingLights] + return data.landingLights }, ) } diff --git a/src/rules/lights_over_10k.ts b/src/rules/lights_over_10k.ts index d272541..e1eaf31 100644 --- a/src/rules/lights_over_10k.ts +++ b/src/rules/lights_over_10k.ts @@ -21,11 +21,11 @@ export default class LightsOver10K implements Rule { violated(pirep: Pirep, data: Telemetry, previousData?: Telemetry): RuleValue { if (!Acars.IsFeatureEnabled(AircraftFeature.LandingLights)) { - return [false] + return } if (data.onGround) { - return [false] + return } return Acars.ViolatedAfterDelay( @@ -37,7 +37,9 @@ export default class LightsOver10K implements Rule { data.landingLights && data.planeAltitude.Feet > this.meta.parameter! + 500 - return [violated, this.meta.message + this.meta.parameter!] + if (violated) { + return [this.meta.message + this.meta.parameter!] + } }, ) } diff --git a/src/rules/lights_under_10k.ts b/src/rules/lights_under_10k.ts index 6366d52..8eb881c 100644 --- a/src/rules/lights_under_10k.ts +++ b/src/rules/lights_under_10k.ts @@ -21,11 +21,11 @@ export default class LightsUnder10K implements Rule { violated(pirep: Pirep, data: Telemetry, previousData?: Telemetry): RuleValue { if (!Acars.IsFeatureEnabled(AircraftFeature.LandingLights)) { - return [false] + return } if (data.onGround) { - return [false] + return } return Acars.ViolatedAfterDelay( @@ -37,7 +37,9 @@ export default class LightsUnder10K implements Rule { !data.landingLights && data.planeAltitude.Feet < this.meta.parameter! - 500 - return [violated, this.meta.message + this.meta.parameter!] + if (violated) { + return [this.meta.message + this.meta.parameter!] + } }, ) } diff --git a/src/rules/simrate.ts b/src/rules/simrate.ts index dbb247b..fb69cea 100644 --- a/src/rules/simrate.ts +++ b/src/rules/simrate.ts @@ -21,6 +21,6 @@ export default class SimRate implements Rule { } violated(pirep: Pirep, data: Telemetry, previousData?: Telemetry): RuleValue { - return [data.simRate > this.meta.parameter!] + return data.simRate > this.meta.parameter! } } diff --git a/src/rules/slew_activated.ts b/src/rules/slew_activated.ts index cd50177..15dc2e6 100644 --- a/src/rules/slew_activated.ts +++ b/src/rules/slew_activated.ts @@ -20,6 +20,6 @@ export default class SlewActivated implements Rule { } violated(pirep: Pirep, data: Telemetry, previousData?: Telemetry): RuleValue { - return [data.slewActive] + return data.slewActive } } diff --git a/src/rules/speed_under_10k.ts b/src/rules/speed_under_10k.ts index 060a224..8d8907f 100644 --- a/src/rules/speed_under_10k.ts +++ b/src/rules/speed_under_10k.ts @@ -16,11 +16,19 @@ export default class SpeedUnder10K implements Rule { max_count: 3, points: -1, delay_time: 5000, + + speed: 260, + altitude: 10000, } violated(pirep: Pirep, data: Telemetry, previousData?: Telemetry): RuleValue { if (data.onGround) { - return [false] + return + } + + // This should come from the web-module, if it's been updated + if (this.meta.parameter > 0) { + this.meta.speed = this.meta.parameter } return Acars.ViolatedAfterDelay( @@ -29,10 +37,12 @@ export default class SpeedUnder10K implements Rule { (): RuleValue => { // Ignore landing lights being turned on const violated = - data.indicatedAirspeed.Knots > this.meta.parameter! && - data.planeAltitude.Feet < 10000 + data.indicatedAirspeed.Knots > this.meta.speed && + data.planeAltitude.Feet < this.meta.altitude - return [violated, this.meta.message + this.meta.parameter!] + if (violated) { + return [this.meta.message + this.meta.speed] + } }, ) } diff --git a/src/rules/stabilized_approach.ts b/src/rules/stabilized_approach.ts index 255c238..fe26940 100644 --- a/src/rules/stabilized_approach.ts +++ b/src/rules/stabilized_approach.ts @@ -22,19 +22,23 @@ export default class StabilizedApproach implements Rule { violated(pirep: Pirep, data: Telemetry, previousData?: Telemetry): RuleValue { if (data.onGround) { - return [false] + return } // Above the min altitude so ignore it - if (data.groundAltitude.Feet > this.meta.parameter!) return [false] + if (data.groundAltitude.Feet > this.meta.parameter!) { + return + } - if (data.gearUp) return [true] + if (data.gearUp) { + return true + } // No flaps landing doesn't seem right if (pirep.features == null) { - return [false] + return } - return [pirep.features.flapsCount > 0 && data.flaps === 0] + return pirep.features.flapsCount > 0 && data.flaps === 0 } } diff --git a/src/rules/stall_warning.ts b/src/rules/stall_warning.ts index 140ca06..0e016e9 100644 --- a/src/rules/stall_warning.ts +++ b/src/rules/stall_warning.ts @@ -26,6 +26,6 @@ export default class SimRate implements Rule { } violated(pirep: Pirep, data: Telemetry, previousData?: Telemetry): RuleValue { - return [!data.onGround && data.stallWarning] + return !data.onGround && data.stallWarning } } diff --git a/src/rules/strobes_in_flights.ts b/src/rules/strobes_in_flights.ts index 7d64eff..38688ff 100644 --- a/src/rules/strobes_in_flights.ts +++ b/src/rules/strobes_in_flights.ts @@ -26,11 +26,15 @@ export default class StrobesInFlight implements Rule { violated(pirep: Pirep, data: Telemetry, previousData?: Telemetry): RuleValue { if (!Acars.IsFeatureEnabled(AircraftFeature.StrobeLights)) { - return [false] + return } - return Acars.ViolatedAfterDelay(this.meta.id, this.meta.delay_time, () => { - return !data.strobeLights ? [true] : [false] - }) + return Acars.ViolatedAfterDelay( + this.meta.id, + this.meta.delay_time, + (): RuleValue => { + return !data.strobeLights + }, + ) } } diff --git a/src/rules/strobes_on_during_taxi.ts b/src/rules/strobes_on_during_taxi.ts index e00bfdc..66a8565 100644 --- a/src/rules/strobes_on_during_taxi.ts +++ b/src/rules/strobes_on_during_taxi.ts @@ -27,7 +27,7 @@ export default class LightsOffDuringTaxi implements Rule { violated(pirep: Pirep, data: Telemetry, previousData?: Telemetry): RuleValue { if (!Acars.IsFeatureEnabled(AircraftFeature.StrobeLights)) { - return [false] + return } return Acars.ViolatedAfterDelay( @@ -36,10 +36,10 @@ export default class LightsOffDuringTaxi implements Rule { (): RuleValue => { // Ignore landing lights being turned on if (data.approachingRunway != null || data.runway != null) { - return [false] + return } - return [data.strobeLights] + return data.strobeLights }, ) } diff --git a/src/types/rule.d.ts b/src/types/rule.d.ts index 8469bd2..c4cec9d 100644 --- a/src/types/rule.d.ts +++ b/src/types/rule.d.ts @@ -9,16 +9,24 @@ import type { Pirep, Telemetry } from '../types' * Return it as a tuple. * * If a rule is passing/hasn't been violated: - * return [false] - * + * return false + * // or: + * return [false] + *a * If a rule has been violated: + * return true + * // or, if you want to return a custom message: + * return ['message'] + * // or, if you want to return a message and points: + * return ['message', points] * - * return [true, message, points ] + * If you want to return just the points, you can return: + * return ['', points] * * points and message are optional - if omitted, they're pulled from * the 'meta' block */ -export type RuleValue = [boolean, string?, number?] +export type RuleValue = undefined | null | boolean | [string?, number?] /** *