# AUTOGENERATED! DO NOT EDIT! File to edit: ../nbs/08_perc.ipynb.

# %% auto 0
__all__ = ['percent', 'ipercent', 'integer_percent', 'ipercents', 'integer_percents', 'apercents', 'accumulate_percents',
           'rpercents', 'perbounds', 'range_percents', 'idxstep']

# %% ../nbs/08_perc.ipynb 6
from functools import wraps
from itertools import takewhile, accumulate

# %% ../nbs/08_perc.ipynb 8
#| export


# %% ../nbs/08_perc.ipynb 11
#| export

# %% ../nbs/08_perc.ipynb 13
#| export


# %% ../nbs/08_perc.ipynb 15
#| export


# %% ../nbs/08_perc.ipynb 17
#| export


# %% ../nbs/08_perc.ipynb 19
from quac import int2

# %% ../nbs/08_perc.ipynb 21
from .cons import WRAPS_ASSIGN_ANNDOCS

# %% ../nbs/08_perc.ipynb 23
def percent(p: float, digits: int = 3) -> float:
    '''Converts a percentage `p` to a decimal, rounding to `digits` decimal places.
    
    Parameters
    ----------
    p : float
        The percentage to convert.
        
    digits : int, default 3
        The number of decimal places to round to.
        
    Returns
    -------
    float
        The converted decimal percentage.
    '''
    return round(p if (p := abs(p)) < 1 else p / 100, digits)

# %% ../nbs/08_perc.ipynb 25
def ipercent(total: int = 1, p: float = 1., digits: int = 3) -> int:
    '''Calculates the integer part of `p` percent of `total`, 
    rounded to `digits` decimal places.
    
    Parameters
    ----------
    total : int, default: 1
        The total amount to calculate the percentage of.
        
    p : float, default: 1.0
        The percentage to calculate.

    digits : int, default: 3
        The number of decimal places to round to.
        
    Returns
    -------
    int
        The integer part of the calculated percentage.
        
    See Also
    --------
    integer_percent : Alias for ipercent
    '''
    return int(total * percent(p, digits))

@wraps(ipercent, assigned=WRAPS_ASSIGN_ANNDOCS)
def integer_percent(*args, **kwargs):
    '''Alias for ipercent'''
    return ipercent(*args, **kwargs)

# %% ../nbs/08_perc.ipynb 27
def ipercents(
    total: int, *percents: float, digits: int = 3, 
    useall: bool = True, overflow: bool = False,
) -> tuple[int, ...]:
    '''Divides total into the corresponding integer values given the
    percents in `*percents` and ensures that all values are used
    
    Parameters
    ----------
    total : int
        The total amount to divide according to `percents`.
        
    *percents : float
        Percentages to divide `total` into.
        
    digits : int, default: 3
        The number of decimal places to round percentages to.
        
    useall : bool, default: True
        Whether to ensure that the sum of values is equal to `total`.

    overflow : bool, default: False
        Whether to allow overflowing the total amount. If `False`, the last value will be
        less than or equal to the total amount.
    
    Returns
    -------
    tuple[int, ...]
        The integer values corresponding to the percentages in `percents`.
        
    See Also
    --------
    integer_percents : Alias for ipercents
    '''
    pints = [ipercent(total, pct, digits) for pct in percents]    
    if not overflow and sum(pints) > total: pints.pop()
    if useall and sum(pints) < total: pints.append(total - sum(pints))
    return pints

@wraps(ipercents, assigned=WRAPS_ASSIGN_ANNDOCS)
def integer_percents(*args, **kwargs):
    '''Alias for ipercents'''
    return ipercents(*args, **kwargs)

# %% ../nbs/08_perc.ipynb 29
def apercents(
    total: int, *percents: float, digits: int = 3,
    useall: bool = True, overflow: bool = False,
) -> tuple[int, ...]:
    '''Accumulate the integer values of the corresponding percentages for `total`.
    
    Parameters
    ----------
    total : int
        The total amount to divide according to `percents`.
        
    *percents : float
        Percentages to divide `total` into.
        
    digits : int, default: 3
        The number of decimal places to round percentages to.
        
    useall : bool, default: True
        Whether to ensure that the sum of values is equal to `total`.

    overflow : bool, default: False
        Whether to allow overflowing the total amount. If `False`, the last value will be
        less than or equal to the total amount.
    
    Returns
    -------
    tuple[tuple[int, int], ...]
        Tuples of start and end indices for each percentage of `total`.
        
    See Also
    --------
    accumulate_percents : Alias for apercents
    '''
    pints = ipercents(total, *percents, digits=digits, useall=useall, overflow=overflow)
    asums = takewhile(lambda s: s <= total, accumulate(pints))
    return list(asums)

@wraps(apercents, assigned=WRAPS_ASSIGN_ANNDOCS)
def accumulate_percents(*args, **kwargs):
    '''Alias for apercents'''
    return apercents(*args, **kwargs)

# %% ../nbs/08_perc.ipynb 31
def rpercents(
    total: int, *percents: float, digits: int = 3,
    useall: bool = True, overflow: bool = False,
) -> tuple[int2, ...]:
    '''Generates tuples representing ranges based on percentages of `total`.
    
    Parameters
    ----------
    total : int
        The total amount to divide according to `percents`.
        
    *percents : float
        Percentages to divide `total` into.
        
    digits : int, default: 3
        The number of decimal places to round percentages to.
        
    Returns
    -------
    tuple[tuple[int, int], ...]
        Tuples of start and end indices for each percentage of `total`.
        
    See Also
    --------
    perbounds : Alias for rpercents
    range_percents : Alias for rpercents
    '''
    pints = ipercents(total, *percents, digits=digits, useall=useall, overflow=overflow)
    asums = apercents(total, *percents, digits=digits, useall=useall, overflow=overflow)
    return list((idx-off, idx) for off, idx in zip(pints, asums))

@wraps(rpercents, assigned=WRAPS_ASSIGN_ANNDOCS)
def perbounds(*args, **kwargs):
    '''Alias for rpercents'''
    return rpercents(*args, **kwargs)

@wraps(rpercents, assigned=WRAPS_ASSIGN_ANNDOCS)
def range_percents(*args, **kwargs):
    '''Alias for rpercents'''
    return rpercents(*args, **kwargs)

@wraps(rpercents, assigned=WRAPS_ASSIGN_ANNDOCS)
def idxstep(*args, **kwargs):
    '''Alias for rpercents'''
    return rpercents(*args, **kwargs)

# %% ../nbs/08_perc.ipynb 33
#| export
