"""Scaling util functions.""" from __future__ import annotations def scale_ranged_value_to_int_range( source_low_high_range: tuple[float, float], target_low_high_range: tuple[float, float], value: float, ) -> int: """Given a range of low and high values convert a single value to another range. Given a source low value of 1 and a high value of 255 and a target range from 1 to 100 this function will return: (1,255), (1,100), 255: 100 (1,255), (1,100), 127: 49 (1,255), (1,100), 10: 3 """ source_offset = source_low_high_range[0] - 1 target_offset = target_low_high_range[0] - 1 return int( (value - source_offset) * states_in_range(target_low_high_range) // states_in_range(source_low_high_range) + target_offset ) def scale_to_ranged_value( source_low_high_range: tuple[float, float], target_low_high_range: tuple[float, float], value: float, ) -> float: """Given a range of low and high values convert a single value to another range. Do not include 0 in a range if 0 means off, e.g. for brightness or fan speed. Given a source low value of 1 and a high value of 255 and a target range from 1 to 100 this function will return: (1,255), 255: 100 (1,255), 127: ~49.8039 (1,255), 10: ~3.9216 """ source_offset = source_low_high_range[0] - 1 target_offset = target_low_high_range[0] - 1 return (value - source_offset) * ( states_in_range(target_low_high_range) ) / states_in_range(source_low_high_range) + target_offset def states_in_range(low_high_range: tuple[float, float]) -> float: """Given a range of low and high values return how many states exist.""" return low_high_range[1] - low_high_range[0] + 1 def int_states_in_range(low_high_range: tuple[float, float]) -> int: """Given a range of low and high values return how many integer states exist.""" return int(states_in_range(low_high_range))