Esempio n. 1
0
    def test_default_year_constant(self):
        """Возраст в виде простого числа определяется корректно"""

        right = AgeRight("5 ")
        correct_range = ValueRange(5, 5)
        self.assertEqual(correct_range, right.age_range, f"Диапазон должен быть '{correct_range}'")
        self.assertEqual(AgeRight.MODE_YEAR, right.mode, "Режим должен быть 'year'")
Esempio n. 2
0
    def test_constant_age_with_sign_and_optional_mode(self):
        """Возраст в виде числа с опциональным режимом и направлением определяется корректно"""

        ages = [
            ["> 0 дней", (0, ")"), float("inf"), AgeRight.MODE_DAY],
            ["> 0 дней", (0, ")"), float("inf"), AgeRight.MODE_DAY],
            ["больше 5 дней", (5, ")"), float("inf"), AgeRight.MODE_DAY],
            ["более 5 дней", (5, ")"), float("inf"), AgeRight.MODE_DAY],
            ["от 1 дня", (1, "]"), float("inf"), AgeRight.MODE_DAY],
            ["≥ 1 дня", (1, "]"), float("inf"), AgeRight.MODE_DAY],
            ["с 1 дня", (1, "]"), float("inf"), AgeRight.MODE_DAY],
            [">= 1 дня", (1, "]"), float("inf"), AgeRight.MODE_DAY],
            ["≥ 1 дня", (1, "]"), float("inf"), AgeRight.MODE_DAY],
            ["до 7 дней", 0, (7, ")"), AgeRight.MODE_DAY],
            ["< 7 дней", 0, (7, ")"), AgeRight.MODE_DAY],
            ["старше 5 лет", (5, ")"), float("inf"), AgeRight.MODE_YEAR],
            ["младше 5 лет", 0, (5, ")"), AgeRight.MODE_YEAR],
            ["меньше 5 лет", 0, (5, ")"), AgeRight.MODE_YEAR],
            ["менее 5 лет", 0, (5, ")"), AgeRight.MODE_YEAR],
            ["до 20", 0, (20, ")"), AgeRight.MODE_YEAR],
            ["< 100", 0, (100, ")"), AgeRight.MODE_YEAR],
            ["&lt; 100", 0, (100, ")"), AgeRight.MODE_YEAR],
            ["≤ 100", 0, (100, "]"), AgeRight.MODE_YEAR],
            ["<= 100", 0, (100, "]"), AgeRight.MODE_YEAR],
            ["&le; 100", 0, (100, "]"), AgeRight.MODE_YEAR],
        ]

        for age in ages:
            correct_range = ValueRange(age[1], age[2])
            right = AgeRight(age[0])
            self.assertEqual(correct_range, right.age_range, f"Диапазон должен быть '{correct_range}', а не '{right.age_range}' для '{age[0]}'")
            self.assertEqual(age[3], right.mode, f"Режим должен быть '{age[3]}' для '{age[0]}'")
Esempio n. 3
0
    def test_value_from_to(self):
        """Значения от или до (больше, меньше, >=, <=)"""
        rs = [
            ["> 1.1", (1.1, ")"), float("inf"), ResultRight.MODE_NUMBER_RANGE],
            ["> 1,1", (1.1, ")"), float("inf"), ResultRight.MODE_NUMBER_RANGE],
            ["> 1", (1, ")"), float("inf"), ResultRight.MODE_NUMBER_RANGE],
            ["&gt; 1", (1, ")"), float("inf"), ResultRight.MODE_NUMBER_RANGE],
            ["больше 1", (1, ")"), float("inf"), ResultRight.MODE_NUMBER_RANGE],
            ["больше 10<sup>2</sup>", (100, ")"), float("inf"), ResultRight.MODE_NUMBER_RANGE],
            [">= 1.1", (1.1, "]"), float("inf"), ResultRight.MODE_NUMBER_RANGE],
            ["≥ 1.1", (1.1, "]"), float("inf"), ResultRight.MODE_NUMBER_RANGE],
            ["&ge; 1.1", (1.1, "]"), float("inf"), ResultRight.MODE_NUMBER_RANGE],
            ["от 1.1", (1.1, "]"), float("inf"), ResultRight.MODE_NUMBER_RANGE],
            ["< 10", float("-inf"), (10, ")"), ResultRight.MODE_NUMBER_RANGE],
            ["&lt; 10", float("-inf"), (10, ")"), ResultRight.MODE_NUMBER_RANGE],
            ["меньше 10", float("-inf"), (10, ")"), ResultRight.MODE_NUMBER_RANGE],
            ["менее 10", float("-inf"), (10, ")"), ResultRight.MODE_NUMBER_RANGE],
            ["до 10", float("-inf"), (10, ")"), ResultRight.MODE_NUMBER_RANGE],
            ["<= 10,1", float("-inf"), (10.1, "]"), ResultRight.MODE_NUMBER_RANGE],
            ["≤ 10", float("-inf"), (10, "]"), ResultRight.MODE_NUMBER_RANGE],
            ["&le; 10", float("-inf"), (10, "]"), ResultRight.MODE_NUMBER_RANGE],
            ["по 10", float("-inf"), (10, "]"), ResultRight.MODE_NUMBER_RANGE],
        ]

        for r in rs:
            right = ResultRight(r[0])
            valid = ValueRange(r[1], r[2])
            self.assertEqual(valid, right.range, f"Диапазон должен быть '{valid}', а не '{right.range}' для '{r[0]}'")
            self.assertEqual(r[3], right.mode, f"Режим должен быть '{r[3]}' для '{r[0]}'")
Esempio n. 4
0
    def test_default_year_ages(self):
        """Возраст в виде простого диапазона определяется корректно"""

        strs = ["1-10", "1 - 10", " 1 - 10 "]

        correct_range = ValueRange(1, 10)

        for s in strs:
            right = AgeRight(s)
            self.assertEqual(correct_range, right.age_range, f"Диапазон должен быть '{correct_range}'")
            self.assertEqual(AgeRight.MODE_YEAR, right.mode, "Режим должен быть 'year'")
Esempio n. 5
0
    def test_all_ages(self):
        """Все возраста определяются корректно"""

        strs = ["все", "Все", " все ", ""]

        correct_range = ValueRange(0, float('inf'))

        for s in strs:
            right = AgeRight(s)
            self.assertEqual(correct_range, right.age_range, f"Диапазон должен быть '{correct_range}'")
            self.assertEqual(AgeRight.MODE_YEAR, right.mode, "Режим должен быть 'year'")
Esempio n. 6
0
    def __init__(self, orig_str: str):
        self.const_orig = orig_str.strip()

        orig_str = self.const_orig.lower()
        self.range = ValueRange(0, 0)

        if not orig_str:
            self.mode = ResultRight.MODE_ANY
            return

        orig_str = replace_pow(re.sub(' +', ' ', orig_str))

        const_range = ResultRight.check_is_constant_with_sign(orig_str)

        if const_range:
            self.mode = const_range[0]
            self.range = ValueRange(const_range[1], const_range[2])
            return

        simple_range = ResultRight.check_is_range(orig_str)

        if simple_range:
            self.mode = simple_range[0]
            self.range = ValueRange(simple_range[1], simple_range[2])
            return

        self.mode = ResultRight.MODE_CONSTANT
        self.const = orig_str
Esempio n. 7
0
    def test_constant_age_with_mode(self):
        """Возраст в виде константного числа с режимом определяется корректно"""

        ages = [
            ["0 дней", 0, AgeRight.MODE_DAY],
            ["6 месяцев", 6, AgeRight.MODE_MONTH],
            ["5 л.", 5, AgeRight.MODE_YEAR],
            [" 100  лет", 100, AgeRight.MODE_YEAR],
        ]

        for age in ages:
            correct_range = ValueRange(age[1], age[1])
            right = AgeRight(age[0])
            self.assertEqual(correct_range, right.age_range, f"Диапазон должен быть '{correct_range}' для '{age[0]}'")
            self.assertEqual(age[2], right.mode, f"Режим должен быть 'year' для '{age[0]}'")
Esempio n. 8
0
    def get_active_ref(self, raw_ref=True, single=False):
        if raw_ref:
            if single:
                show_only_needed_ref = SettingManager.get("show_only_needed_ref", default='True', default_type='b')
                if not show_only_needed_ref or not self.raw_ref:
                    return None

                show_full_needed_ref = SettingManager.get("show_full_needed_ref", default='False', default_type='b')
                if show_full_needed_ref:
                    return {self.key: self.raw_ref}

                return {'Все': self.raw_ref}
            return self.raw_ref
        if isinstance(self.ref, ResultRight):
            return self.ref
        return ValueRange((0, ")"), (0, ")"))
Esempio n. 9
0
    def test_range(self):
        """Диапазон число - число"""
        rs = [
            ["10-100", 10, 100],
            ["0.55 – 0.633", 0.55, 0.633],
            ["2.0-21.0", 2.0, 21.0],
            ["10 -100", 10, 100],
            ["-10 - 100", -10, 100],
            ["-100 - -10", -100, -10],
            ["10 – 20", 10, 20],
            ["0,23 - 2,0", 0.23, 2.0],
            ["от 1 до 2", 1, (2, ")")],
        ]

        for r in rs:
            right = ResultRight(r[0])
            valid = ValueRange(r[1], r[2])
            self.assertEqual(valid, right.range, f"Диапазон должен быть '{valid}', а не '{right.range}' для '{r[0]}'")
Esempio n. 10
0
    def test_full_defined_range(self):
        """Проверка полностью определённого диапазона с опциональными частями"""

        ages = [
            ["10 - 20", 10, 20, AgeRight.MODE_YEAR],
            ["1 г - 2 г", 1, 2, AgeRight.MODE_YEAR],
            ["10 лет – 20 лет", 10, 20, AgeRight.MODE_YEAR],
            ["2г. – 3г.", 2, 3, AgeRight.MODE_YEAR],
            ["от 3 до 5 дней", 3, (5, ")"), AgeRight.MODE_DAY],
            ["от 3 дней до 5", 3, (5, ")"), AgeRight.MODE_DAY],
            ["от 3 месяцев до 5 месяцев", 3, (5, ")"), AgeRight.MODE_MONTH],
            ["с 3 по 5", 3, 5, AgeRight.MODE_YEAR],
        ]

        for age in ages:
            correct_range = ValueRange(age[1], age[2])
            right = AgeRight(age[0])
            self.assertEqual(correct_range, right.age_range, f"Диапазон должен быть '{correct_range}', а не '{right.age_range}' для '{age[0]}'")
            self.assertEqual(age[3], right.mode, f"Режим должен быть '{age[3]}' для '{age[0]}'")
Esempio n. 11
0
class AgeRight:
    MODE_DAY = "day"
    MODE_MONTH = "month"
    MODE_YEAR = "year"
    MODE_UNKNOWN = "unknow"

    DAY_ORIGS = (
        "дней",
        "день",
        "дня",
        "дн",
        "дн.",
        "д",
        "д.",
    )

    MONTH_ORIGS = (
        "месяц",
        "месяцев",
        "месяца",
        "мес",
        "мес.",
        "м",
        "м.",
    )

    YEAR_ORIGS = (
        "год",
        "года",
        "лет",
        "г",
        "г.",
        "л",
        "л.",
    )

    MODES_FROM_ORIGS = (
        (DAY_ORIGS, MODE_DAY),
        (MONTH_ORIGS, MODE_MONTH),
        (YEAR_ORIGS, MODE_YEAR),
    )

    def __init__(self, orig_str: str):
        orig_str = orig_str.strip().lower()
        if AgeRight.check_is_all(orig_str):
            self.age_range = ValueRange(0, float('inf'))
            self.mode = AgeRight.MODE_YEAR
            return

        if "един" in orig_str:
            orig_str = "0-2"
        if "отсутств" in orig_str:
            orig_str = "0-0"

        constant_simple_year = AgeRight.check_is_constant_simple_year(orig_str)
        if constant_simple_year:
            self.age_range = ValueRange(constant_simple_year, constant_simple_year)
            self.mode = AgeRight.MODE_YEAR
            return

        simple_year_age = AgeRight.check_is_simple_year_range(orig_str)
        if simple_year_age:
            self.age_range = ValueRange(int(simple_year_age.group(1)), int(simple_year_age.group(2)))
            self.mode = AgeRight.MODE_YEAR
            return

        orig_str = re.sub(' +', ' ', orig_str)

        constant_age_with_mode = AgeRight.check_is_constant_age_with_mode(orig_str)
        if constant_age_with_mode:
            self.age_range = ValueRange(constant_age_with_mode[0], constant_age_with_mode[0])
            self.mode = constant_age_with_mode[1]
            return

        constant_age_with_sign = AgeRight.check_is_constant_age_with_sign_and_optional_mode(orig_str)
        if constant_age_with_sign:
            self.age_range = ValueRange(constant_age_with_sign[1], constant_age_with_sign[2])
            self.mode = constant_age_with_sign[0]
            return

        full_range = AgeRight.check_is_full_range(orig_str)
        if full_range:
            self.age_range = ValueRange(full_range[1], full_range[2])
            self.mode = full_range[0]
            return

        self.age_range = ValueRange(Value(0, POINT_STRICT), Value(0, POINT_STRICT))
        self.mode = AgeRight.MODE_UNKNOWN

    def test(self, age: List[int]) -> bool:
        if self.mode == AgeRight.MODE_UNKNOWN:
            return False

        if self.mode == AgeRight.MODE_DAY:
            if age[1] > 0 or age[2] > 0:
                return False
            age_var = age[0]
        elif self.mode == AgeRight.MODE_MONTH:
            if age[2] > 0:
                return False
            age_var = age[1]
        else:
            age_var = age[2]

        return self.age_range.in_range(age_var) == RANGE_IN

    @staticmethod
    def check_is_all(orig_str: str) -> bool:
        return orig_str in ["все", ""]

    @staticmethod
    def check_is_simple_year_range(orig_str: str):
        orig_str = orig_str.replace(" ", "")
        return re.match(r"^(\d+)-(\d+)$", orig_str)

    @staticmethod
    def check_is_constant_simple_year(orig_str: str) -> Union[bool, int]:
        orig_str = orig_str.replace(" ", "")
        if not orig_str.isdigit():
            return False
        return int(orig_str)

    @staticmethod
    def check_is_constant_age_with_mode(orig_str: str) -> Union[bool, Tuple[int, str]]:
        matched = re.match(r"^(\d+) ([\w.]+)$", orig_str)
        if not matched:
            return False
        value = int(matched.group(1))
        mode_orig = matched.group(2).lower()

        mode = AgeRight.get_mode_by_string(mode_orig)
        if mode != AgeRight.MODE_UNKNOWN:
            return value, mode

        return False

    @staticmethod
    def check_is_constant_age_with_sign_and_optional_mode(orig_str: str) -> Union[bool, Tuple[str, Value, Value]]:
        matched = re.match(r"^([\w<>≤≥&;=]+) (\d+)( )?(\w+)?$", orig_str)

        if matched:
            g = list(matched.groups())
            if g[3]:
                mode = AgeRight.get_mode_by_string(g[3])
                if mode == AgeRight.MODE_UNKNOWN:
                    return False
            else:
                mode = AgeRight.MODE_YEAR

            sign_orig = g[0]
            sign = get_sign_by_string(sign_orig)
            if not sign:
                return False

            value = int(g[1])

            if sign == SIGN_GT:
                return mode, Value(value=value, mode=POINT_STRICT), Value(value=float('inf'))

            if sign == SIGN_GTE:
                return mode, Value(value=value), Value(value=float('inf'))

            if sign == SIGN_LT:
                return mode, Value(value=0), Value(value=value, mode=POINT_STRICT)

            if sign == SIGN_LTE:
                return mode, Value(value=0), Value(value=value)

        return False

    @staticmethod
    def check_is_full_range(orig_str: str) -> Union[bool, Tuple[str, Union[int, Value], Union[int, Value]]]:
        matched = re.match(RANGE_REGEXP, orig_str)

        if matched:
            g = list(map(lambda x: x if not x else x.strip(), matched.groups()))
            if g[3] or g[7]:
                mode = AgeRight.get_mode_by_string(g[3] or g[7])
                if mode == AgeRight.MODE_UNKNOWN:
                    return False
            else:
                mode = AgeRight.MODE_YEAR

            if g[4] == 'до':
                return mode, int(g[1]), Value(int(g[5]), mode=POINT_STRICT)

            return mode, int(g[1]), int(g[5])

        return False

    @staticmethod
    def get_mode_by_string(s: str) -> Union[bool, str]:
        for mode_origs, mode in AgeRight.MODES_FROM_ORIGS:
            if s in mode_origs:
                return mode
        return AgeRight.MODE_UNKNOWN
Esempio n. 12
0
    def __init__(self, orig_str: str):
        orig_str = orig_str.strip().lower()
        if AgeRight.check_is_all(orig_str):
            self.age_range = ValueRange(0, float('inf'))
            self.mode = AgeRight.MODE_YEAR
            return

        if "един" in orig_str:
            orig_str = "0-2"
        if "отсутств" in orig_str:
            orig_str = "0-0"

        constant_simple_year = AgeRight.check_is_constant_simple_year(orig_str)
        if constant_simple_year:
            self.age_range = ValueRange(constant_simple_year, constant_simple_year)
            self.mode = AgeRight.MODE_YEAR
            return

        simple_year_age = AgeRight.check_is_simple_year_range(orig_str)
        if simple_year_age:
            self.age_range = ValueRange(int(simple_year_age.group(1)), int(simple_year_age.group(2)))
            self.mode = AgeRight.MODE_YEAR
            return

        orig_str = re.sub(' +', ' ', orig_str)

        constant_age_with_mode = AgeRight.check_is_constant_age_with_mode(orig_str)
        if constant_age_with_mode:
            self.age_range = ValueRange(constant_age_with_mode[0], constant_age_with_mode[0])
            self.mode = constant_age_with_mode[1]
            return

        constant_age_with_sign = AgeRight.check_is_constant_age_with_sign_and_optional_mode(orig_str)
        if constant_age_with_sign:
            self.age_range = ValueRange(constant_age_with_sign[1], constant_age_with_sign[2])
            self.mode = constant_age_with_sign[0]
            return

        full_range = AgeRight.check_is_full_range(orig_str)
        if full_range:
            self.age_range = ValueRange(full_range[1], full_range[2])
            self.mode = full_range[0]
            return

        self.age_range = ValueRange(Value(0, POINT_STRICT), Value(0, POINT_STRICT))
        self.mode = AgeRight.MODE_UNKNOWN
Esempio n. 13
0
class ResultRight:
    MODE_NUMBER_RANGE = 'number_range'
    MODE_CONSTANT = 'constant'
    MODE_ANY = 'any'

    RESULT_MODE_NORMAL = 'normal'
    RESULT_MODE_MAYBE = 'maybe'
    RESULT_MODE_NOT_NORMAL = 'not_normal'

    def __init__(self, orig_str: str):
        self.const_orig = orig_str.strip()

        orig_str = self.const_orig.lower()
        self.range = ValueRange(0, 0)

        if not orig_str:
            self.mode = ResultRight.MODE_ANY
            return

        orig_str = replace_pow(re.sub(' +', ' ', orig_str))

        const_range = ResultRight.check_is_constant_with_sign(orig_str)

        if const_range:
            self.mode = const_range[0]
            self.range = ValueRange(const_range[1], const_range[2])
            return

        simple_range = ResultRight.check_is_range(orig_str)

        if simple_range:
            self.mode = simple_range[0]
            self.range = ValueRange(simple_range[1], simple_range[2])
            return

        self.mode = ResultRight.MODE_CONSTANT
        self.const = orig_str

    def test(self, value: str) -> Tuple[str, str]:
        if self.mode == ResultRight.MODE_ANY:
            return ResultRight.RESULT_MODE_NORMAL, RANGE_IN

        value = replace_pow(value.strip().lower().replace("''", "\""))

        if "един" in value:
            value = "1"

        if "отсутств" in value or "нет" in value:
            value = "0"

        if self.mode == ResultRight.MODE_CONSTANT:
            return (ResultRight.RESULT_MODE_NORMAL,
                    RANGE_IN) if value == self.const else (
                        ResultRight.RESULT_MODE_MAYBE, RANGE_NEQ)

        if "сплошь" in value.lower(
        ) or "++" in value or "+ +" in value or "++++" in value or "+" == value.strip(
        ) or "оксал ед" in value:
            value = "inf"

        numbers = re.findall(r"-?\d*[.,]\d+|-?\d+|inf", value)

        if numbers:
            for n in numbers:
                n = float(n.replace(',', '.'))
                rv = self.range.in_range(n)
                if rv != RANGE_IN:
                    return ResultRight.RESULT_MODE_NOT_NORMAL, rv
        elif value:
            return ResultRight.RESULT_MODE_MAYBE, RANGE_NEQ

        return ResultRight.RESULT_MODE_NORMAL, RANGE_IN

    @staticmethod
    def check_is_range(
        s: str
    ) -> Union[bool, Tuple[str, Union[float, Value], Union[float, Value]]]:
        matched = re.match(RANGE_REGEXP, s)

        if matched:
            g = list(map(lambda x: x
                         if not x else x.strip(), matched.groups()))

            mode = ResultRight.MODE_NUMBER_RANGE

            if g[4] == 'до':
                return mode, Value(g[1]), Value(float(g[5]), mode=POINT_STRICT)

            return mode, Value(g[1]), Value(g[5])
        return False

    @staticmethod
    def check_is_constant_with_sign(
            orig_str: str) -> Union[bool, Tuple[str, Value, Value]]:
        matched = re.match(r"^([\w<>≤≥&;=]+) ?(-?\d+[.,]\d+|-?\d+)$", orig_str)

        if matched:
            g = list(matched.groups())

            mode = ResultRight.MODE_NUMBER_RANGE

            sign_orig = g[0]
            sign = get_sign_by_string(sign_orig)
            if not sign:
                return False

            value = g[1]

            if sign == SIGN_GT:
                return mode, Value(
                    value=value, mode=POINT_STRICT), Value(value=float('inf'))

            if sign == SIGN_GTE:
                return mode, Value(value=value), Value(value=float('inf'))

            if sign == SIGN_LT:
                return mode, Value(value=float('-inf')), Value(
                    value=value, mode=POINT_STRICT)

            if sign == SIGN_LTE:
                return mode, Value(value=float('-inf')), Value(value=value)

        return False