f20080305d
Определение специфических рекомендаций (матрица профилей §8):
1. Ж/д слой (закрыт мёртвый railway ×2.5 у РАС):
- /api/v1/water/{case_id} отдаёт railway=rail как LineString
(без service/industrial/military веток), кэш общий v2;
- railway_warning «перекрыть/проверить немедленно» по профилям;
- SearchMap: Polyline слой ж/д (тёмно-красный), счётчики 💧/🚂.
2. cant_swim → профиль не_умеет_плавать (water ×3.0, без изменения
радиуса, critical_warning «обследовать водоёмы НЕМЕДЛЕННО»):
- раньше чекбокс влиял только на текст, в скоринге был пробел;
- derive в analyze._derive_profiles — работает и для closed_cases.
3. unmodeled_profiles: ДЦП/слабое зрение/слух — честная пометка
«вне поведенческой модели» с пояснением (vector_tasks B12:
профили без аналога не выдавать за учтённые); блок на фронте
в карточке здоровья.
Площадь воды: сферический эксцесс, проверен на квадрате 53° (744017 м²
vs 743272 точного). Тесты: 202 passed (новый test_cant_swim_profile).
105 lines
3.0 KiB
Python
105 lines
3.0 KiB
Python
"""
|
|
pygments.scanner
|
|
~~~~~~~~~~~~~~~~
|
|
|
|
This library implements a regex based scanner. Some languages
|
|
like Pascal are easy to parse but have some keywords that
|
|
depend on the context. Because of this it's impossible to lex
|
|
that just by using a regular expression lexer like the
|
|
`RegexLexer`.
|
|
|
|
Have a look at the `DelphiLexer` to get an idea of how to use
|
|
this scanner.
|
|
|
|
:copyright: Copyright 2006-present by the Pygments team, see AUTHORS.
|
|
:license: BSD, see LICENSE for details.
|
|
"""
|
|
import re
|
|
|
|
|
|
class EndOfText(RuntimeError):
|
|
"""
|
|
Raise if end of text is reached and the user
|
|
tried to call a match function.
|
|
"""
|
|
|
|
|
|
class Scanner:
|
|
"""
|
|
Simple scanner
|
|
|
|
All method patterns are regular expression strings (not
|
|
compiled expressions!)
|
|
"""
|
|
|
|
def __init__(self, text, flags=0):
|
|
"""
|
|
:param text: The text which should be scanned
|
|
:param flags: default regular expression flags
|
|
"""
|
|
self.data = text
|
|
self.data_length = len(text)
|
|
self.start_pos = 0
|
|
self.pos = 0
|
|
self.flags = flags
|
|
self.last = None
|
|
self.match = None
|
|
self._re_cache = {}
|
|
|
|
def eos(self):
|
|
"""`True` if the scanner reached the end of text."""
|
|
return self.pos >= self.data_length
|
|
eos = property(eos, eos.__doc__)
|
|
|
|
def check(self, pattern):
|
|
"""
|
|
Apply `pattern` on the current position and return
|
|
the match object. (Doesn't touch pos). Use this for
|
|
lookahead.
|
|
"""
|
|
if self.eos:
|
|
raise EndOfText()
|
|
if pattern not in self._re_cache:
|
|
self._re_cache[pattern] = re.compile(pattern, self.flags)
|
|
return self._re_cache[pattern].match(self.data, self.pos)
|
|
|
|
def test(self, pattern):
|
|
"""Apply a pattern on the current position and check
|
|
if it patches. Doesn't touch pos.
|
|
"""
|
|
return self.check(pattern) is not None
|
|
|
|
def scan(self, pattern):
|
|
"""
|
|
Scan the text for the given pattern and update pos/match
|
|
and related fields. The return value is a boolean that
|
|
indicates if the pattern matched. The matched value is
|
|
stored on the instance as ``match``, the last value is
|
|
stored as ``last``. ``start_pos`` is the position of the
|
|
pointer before the pattern was matched, ``pos`` is the
|
|
end position.
|
|
"""
|
|
if self.eos:
|
|
raise EndOfText()
|
|
if pattern not in self._re_cache:
|
|
self._re_cache[pattern] = re.compile(pattern, self.flags)
|
|
self.last = self.match
|
|
m = self._re_cache[pattern].match(self.data, self.pos)
|
|
if m is None:
|
|
return False
|
|
self.start_pos = m.start()
|
|
self.pos = m.end()
|
|
self.match = m.group()
|
|
return True
|
|
|
|
def get_char(self):
|
|
"""Scan exactly one char."""
|
|
self.scan('.')
|
|
|
|
def __repr__(self):
|
|
return '<%s %d/%d>' % (
|
|
self.__class__.__name__,
|
|
self.pos,
|
|
self.data_length
|
|
)
|