001package jmri.jmrix.bachrus.speedmatcher.speedStepScale; 002 003import javax.swing.JLabel; 004 005import jmri.jmrix.bachrus.Speed; 006import jmri.jmrix.bachrus.speedmatcher.SpeedMatcher; 007 008/** 009 * Abstract class defining the basic operations of a Speed Step Scale speed 010 * matcher (sets up the complex speed table such that the speed step equals the 011 * locomotive speed when using "128" speed step mode). All speed step scale 012 * speed matcher implementations must extend this class. 013 * 014 * @author Todd Wegter Copyright (C) 2024 015 */ 016public abstract class SpeedStepScaleSpeedMatcher extends SpeedMatcher { 017 018 //<editor-fold defaultstate="collapsed" desc="Instance Variables"> 019 protected final SpeedTableStepSpeed targetMaxSpeedStep; 020 protected final float targetMaxSpeedKPH; 021 protected final Speed.Unit speedUnit; 022 protected final JLabel actualMaxSpeedField; 023 024 protected float measuredMaxSpeedKPH = 0; 025 protected float speedMatchMaxSpeedKPH = 0; 026 //</editor-fold> 027 028 /** 029 * Constructs the abstract SpeedStepScaleSpeedMatcher at the core of any 030 * Speed Step Scale Speed Matcher 031 * 032 * @param config SpeedStepScaleSpeedMatcherConfig 033 */ 034 public SpeedStepScaleSpeedMatcher(SpeedStepScaleSpeedMatcherConfig config) { 035 super(config); 036 037 this.actualMaxSpeedField = config.actualMaxSpeedField; 038 this.speedUnit = config.speedUnit; 039 040 this.targetMaxSpeedStep = config.targetMaxSpeedStep; 041 this.targetMaxSpeedKPH = config.speedUnit == Speed.Unit.MPH ? Speed.mphToKph(this.targetMaxSpeedStep.getSpeed()) : this.targetMaxSpeedStep.getSpeed(); 042 } 043 044 //<editor-fold defaultstate="collapsed" desc="Protected APIs"> 045 /** 046 * Validates the speed matcher's configuration 047 * 048 * @return true if the configuration is valid, false otherwise 049 */ 050 @Override 051 protected boolean validate() { 052 if (dccLocoAddress.getNumber() <= 0) { 053 statusLabel.setText(Bundle.getMessage("StatInvalidDCCAddress")); 054 return false; 055 } 056 057 if (targetMaxSpeedStep == null) { 058 statusLabel.setText(Bundle.getMessage("StatInvalidMaxSpeed")); 059 return false; 060 } 061 062 return true; 063 } 064 065 /** 066 * Gets the speed in KPH for a given speed step for a speed step scale speed 067 * matcher 068 * 069 * @param speedStep the int speed step to get the speed for 070 * @return speed for the given speedStep in KPH 071 */ 072 protected float getSpeedStepScaleSpeedInKPH(int speedStep) { 073 //speed = step in 128 speed step mode 074 float speedStepSpeed = getSpeedForSpeedTableStep(speedStep); 075 076 //convert MPH to KPH since Bachrus does everything in KPH 077 if (speedUnit == Speed.Unit.MPH) { 078 speedStepSpeed = Speed.mphToKph(speedStepSpeed); 079 } 080 081 //speed must be bounded by the target max speed 082 speedStepSpeed = Math.min(speedStepSpeed, speedMatchMaxSpeedKPH); 083 084 return speedStepSpeed; 085 } 086 087 /** 088 * Gets the speed step value for a linear speed table 089 * @param speedStep the inst speed step to get the value for 090 * @return value for the speed step 091 */ 092 protected int getSpeedStepLinearValue(int speedStep) { 093 return (int) (speedStep / 28f * 255f); 094 } 095 096 /** 097 * Gets the 128 speed step mode speed for a speed table step 098 * 099 * @param speedStep the int speed table step to get the 128 speed step mode 100 * speed for 101 * @return the 128 speed step mode speed for the given speedStep 102 */ 103 public static float getSpeedForSpeedTableStep(int speedStep) { 104 //speed step 1 (28) = speed step 1 (128), 28 (28) = 126 (128), 105 //so 27 speed steps (28) = 125 speed steps (128), 106 //so each step (28) = 4.6296 steps (128) 107 return (speedStep * 4.6296f) - 3.6296f; 108 } 109 110 /** 111 * Gets the next lowest speed table step for the given speed 112 * 113 * @param speed float speed in the user facing unit 114 * @return the next lowest int speed table step for the given speed 115 */ 116 public static int getNextLowestSpeedTableStepForSpeed(float speed) { 117 return (int) Math.floor((speed + 3.6296f) / 4.6296f); 118 } 119 //</editor-fold> 120}