Superbird11/ranges

Feature request: add a .getEntry() method for a value in a certain range?

Closed this issue · 2 comments

fge commented

I am contributing in a project written in Python aiming at improving its automatic algorithm, and for this I want to be able to use the engine definitions of the game. Here is an example:

                torque_curve[]: (300, 0)
                torque_curve[]: (440, 0.5)
                torque_curve[]: (800, 0.7121)
                torque_curve[]: (900, 0.8545)
                torque_curve[]: (980, 1)
                torque_curve[]: (1400, 1)
                torque_curve[]: (1500, 0.936)
                torque_curve[]: (1600, 0.88)
                torque_curve[]: (1700, 0.828)
                torque_curve[]: (1800, 0.77)
                torque_curve[]: (1900, 0.72)
                torque_curve[]: (2000, 0.592)
                torque_curve[]: (2300, 0)

The engine definition also contains a torque variable which mentions the maximum torque. In the values in parens above, it may be obvious but here it is anyway:

  • the first is the RPM value;
  • the second is the multiplier to apply to the torque at that value.

If I add, say, the first two entries as such:

torque_curve[Range(300)] = 0
torque_curve[Range(440)} = 0.5

then the RangeDict will contain (pseudo-code):

[300, 440) -> 0,
[440, +inf] -> 0.5

Good, this is what I want. However, now I need to calculate the torque at 370 rpm, and of course I am taking this example because it's dead in the middle. I therefore need to calculate the slope and calculate the value. Ideally, what I would like to be able to do is this:

wanted_rpm = 370

#
# Get the lower rpm and torque spec 
#
torque_spec = torque_curve.getEntry(wanted_rpm) # returns, for instance, a tuple containing [Range("[300,440)"), 0]
rpm_range = torque_spec[0]
lower_rpm = rpm_range.start # 300
lower_multiplier = torque_spec[1] # 0

#
# Now get the uppper rpm and torque spec 
#
higher_rpm = rpm_range.end # 440
higher_multiplier = torque_curve.get(higher_rpm) # 0.5

#
# Now calculate the slope, then the multiplier, then the torque
#
slope = (higher_multiplier - lower_multiplier) / (higher_rpm - lower_rpm)
multiplier = lower_multiplier + slope * (wanted_rpm - lower_rpm) # 0.25
torque = max_torque * multiplier 

The code above of course does not account for special cases but I can deal with that.

Is it possible to add such a method?

This functionality should already exist, actually, though not quite as concisely as you're asking for (but almost). There are two ways to achieve what you're asking for currently:

The slow way:

rpm_range = torque_curve.getrange(wanted_rpm)  # Range[300, 440)
lower_rpm = rpm_range.start  # 300
lower_multiplier = torque_curve[rpm_range]  # 0

The quick way:

_, _, lower_rpm, lower_multiplier = torque_curve.getitem(wanted_rpm)

Does this really require a whole new method just to return the last half of .getitem()?

fge commented

Oh, so there is (nearly) such a method, OK...

It isn't mentioned in the documentation however :)