<commit_before># -*- coding: utf-8 -*-
"""
    gauge
    ~~~~~

    Deterministic linear gauge library.

    :copyright: (c) 2013-2014 by <NAME>
    :license: BSD, see LICENSE for more details.
"""
from collections import namedtuple
import time
import warnings

from sortedcontainers import SortedList, SortedListWithKey


__all__ = ['Gauge', 'Momentum']
__version__ = '0.0.10'


add = 1
remove = 0
inf = float('inf')


def now_or(at):
    return time.time() if at is None else float(at)


class Gauge(object):
    """Represents a gauge. A gauge has a value at any moment. It can be
    modified by an user's adjustment or an effective momentum.
    """

    #: The value set by an user.
    value = 0

    #: The time when the value was set.
    set_at = None

    #: A sorted list of momenta. The items are :class:`Momentum` objects.
    momenta = None

    def __init__(self, value, max, min=0, at=None):
        self._max = max
        self._min = min
        self.value = value
        self.set_at = now_or(at)
        self.momenta = SortedListWithKey(key=lambda m: m[-1])  # sort by until
        self._plan = SortedList()

    @property
    def determination(self):
        """Returns the cached determination. If there's no the cache, it
        determines and caches that.

        A determination is a sorted list of 2-dimensional points which take
        times as x-values, gauge values as y-values.
        """
        try:
            return self._determination
        except AttributeError:
            self._determination = self.determine()
            return self._determination

    @determination.deleter
    def determination(self):
        """Clears the cached determination. If you touches the determination
        at the next first time, that will be redetermined.
        """
        try:
            del self._determination
        except AttributeError:
            pass

    @property
    def max(self):
        return self._max

    @max.setter
    def max(self, max):
        self.set_max(max)

    @property
    def min(self):
        return self._min

    @min.setter
    def min(self, min):
        self.set_min(min)

    def _set_limits(self, min=None, max=None, limit=True, at=None):
        if limit:
            at = now_or(at)
            value = self.get(at=at)
        if min is not None:
            self._min = min
        if max is not None:
            self._max = max
        if limit:
            if max is not None and value > max:
                limited = max
            elif min is not None and value < min:
                limited = min
            else:
                limited = None
            if limited is not None:
                self.forget_past(limited, at=at)
                return
        del self.determination

    def set_max(self, max, limit=True, at=None):
        """Changes the maximum.

        :param max: the value to set as the maximum.
        :param limit: limits the current value to be below the new maximum.
                      (default: ``True``)
        :param at: the time to change. (default: now)
        """
        self._set_limits(max=max, limit=limit, at=at)

    def set_min(self, min, limit=True, at=None):
        """Changes the minimum.

        :param min: the value to set as the minimum.
        :param limit: limits the current value to be above the new minimum.
                      (default: ``True``)
        :param at: the time to change. (default: now)
        """
        self._set_limits(min=min, limit=limit, at=at)

    def _current_value_and_velocity(self, at=None):
        at = now_or(at)
        x = self.determination.bisect_left((at,))
        if x == 0:
            return (self.determination[0][1], 0.)
        try:
            next_time, next_value = self.determination[x]
        except IndexError:
            return (self.determination[-1][1], 0.)
        prev_time, prev_value = self.determination[x - 1]
        t = float(at - prev_time) / (next_time - prev_time)
        delta = next_value - prev_value
        value = prev_value + t * delta
        velocity = delta / (next_time - prev_time)
        return (value, velocity)

    def get(self, at=None):
        """Predicts the current value.

        :param at: the time to observe. (default: now)
        """
        return self._current_value_and_velocity(at)[0]

    def velocity(self, at=None):
        """Predicts the current velocity.

        :param at: the time to observe. (default: now)
        """
        return self._current_value_and_velocity(at)[1]

    def incr(self, delta, limit=True, at=None):
        """Increases the value by the given delta immediately. The
        determination would be changed.

        :param delta: the value to increase.<commit_msg>optimize Gauge._current_value_and_velocity() for 1-node determination<commit_after># -*- coding: utf-8 -*-
"""
    gauge
    ~~~~~

    Deterministic linear gauge library.

    :copyright: (c) 2013-2014 by <NAME>
    :license: BSD, see LICENSE for more details.
"""
from collections import namedtuple
import time
import warnings

from sortedcontainers import SortedList, SortedListWithKey


__all__ = ['Gauge', 'Momentum']
__version__ = '0.0.11'


add = 1
remove = 0
inf = float('inf')


def now_or(at):
    return time.time() if at is None else float(at)


class Gauge(object):
    """Represents a gauge. A gauge has a value at any moment. It can be
    modified by an user's adjustment or an effective momentum.
    """

    #: The value set by an user.
    value = 0

    #: The time when the value was set.
    set_at = None

    #: A sorted list of momenta. The items are :class:`Momentum` objects.
    momenta = None

    def __init__(self, value, max, min=0, at=None):
        self._max = max
        self._min = min
        self.value = value
        self.set_at = now_or(at)
        self.momenta = SortedListWithKey(key=lambda m: m[-1])  # sort by until
        self._plan = SortedList()

    @property
    def determination(self):
        """Returns the cached determination. If there's no the cache, it
        determines and caches that.

        A determination is a sorted list of 2-dimensional points which take
        times as x-values, gauge values as y-values.
        """
        try:
            return self._determination
        except AttributeError:
            self._determination = self.determine()
            return self._determination

    @determination.deleter
    def determination(self):
        """Clears the cached determination. If you touches the determination
        at the next first time, that will be redetermined.
        """
        try:
            del self._determination
        except AttributeError:
            pass

    @property
    def max(self):
        return self._max

    @max.setter
    def max(self, max):
        self.set_max(max)

    @property
    def min(self):
        return self._min

    @min.setter
    def min(self, min):
        self.set_min(min)

    def _set_limits(self, min=None, max=None, limit=True, at=None):
        if limit:
            at = now_or(at)
            value = self.get(at=at)
        if min is not None:
            self._min = min
        if max is not None:
            self._max = max
        if limit:
            if max is not None and value > max:
                limited = max
            elif min is not None and value < min:
                limited = min
            else:
                limited = None
            if limited is not None:
                self.forget_past(limited, at=at)
                return
        del self.determination

    def set_max(self, max, limit=True, at=None):
        """Changes the maximum.

        :param max: the value to set as the maximum.
        :param limit: limits the current value to be below the new maximum.
                      (default: ``True``)
        :param at: the time to change. (default: now)
        """
        self._set_limits(max=max, limit=limit, at=at)

    def set_min(self, min, limit=True, at=None):
        """Changes the minimum.

        :param min: the value to set as the minimum.
        :param limit: limits the current value to be above the new minimum.
                      (default: ``True``)
        :param at: the time to change. (default: now)
        """
        self._set_limits(min=min, limit=limit, at=at)

    def _current_value_and_velocity(self, at=None):
        at = now_or(at)
        determination = self.determination
        if len(determination) == 1:
            # skip bisect_left() because it is expensive
            x = 0
        else:
            x = determination.bisect_left((at,))
        if x == 0:
            return (determination[0][1], 0.)
        try:
            next_time, next_value = determination[x]
        except IndexError:
            return (determination[-1][1], 0.)
        prev_time, prev_value = determination[x - 1]
        t = float(at - prev_time) / (next_time - prev_time)
        delta = next_value - prev_value
        value = prev_value + t * delta
        velocity = delta / (next_time - prev_time)
        return (value, velocity)

    def get(self, at=None):
        """Predicts the current value.

        :param at: the time to observe. (default: now)
        """
        return self._current_value_and_velocity(at)[0]

    def velocity(self, at=None):
        """Predicts the current velocity.

        :param at: the time to observe. (default: now)
        """
        return self._current_value_and_velocity(at)[1]

    def incr(self, delta, limit=True, at=None):
        """Increases the value by the given delta immediately. The
        determination would be changed.

        :param delta: the value to increase.
{'fraction_non_alphanumeric': 0.09585092144548543, 'fraction_numerical': 0.006280242973334706, 'mean_word_length': 1.984331797235023, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1473205', 'n_tokens_mistral': 2896, 'n_tokens_neox': 2717, 'n_words': 957}