diff --git a/5 сии/лабораторные/lab2/.gitignore b/5 сии/лабораторные/lab2/.gitignore index e69de29..80463b7 100644 --- a/5 сии/лабораторные/lab2/.gitignore +++ b/5 сии/лабораторные/lab2/.gitignore @@ -0,0 +1,134 @@ +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Machine codes +*.out + +# debug info +dbg/ + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ +cover/ + +# Ruff +.ruff_cache + +## pyenv +# poetry.lock + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Translations +*.mo +*.pot + +# PyBuilder +.pybuilder/ +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# PEP 582 +__pypackages__/ + +# Celery stuff +celerybeat-schedule +celerybeat.pid + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ + +# pytype static type analyzer +.pytype/ + +# Cython debug symbols +cython_debug/ + +# IDEs +.idea/ +.vscode/ + +# Draw.io schemas +*.drawio + +# Misc +*.DS_Store diff --git a/5 сии/лабораторные/lab2/.markdownlint.yml b/5 сии/лабораторные/lab2/.markdownlint.yml index 019d7ed..5881c50 100644 --- a/5 сии/лабораторные/lab2/.markdownlint.yml +++ b/5 сии/лабораторные/lab2/.markdownlint.yml @@ -8,5 +8,6 @@ MD031: false MD032: false MD033: false MD040: false +MD046: false MD049: false MD051: false # Link fragments should be valid diff --git a/5 сии/лабораторные/lab2/README.md b/5 сии/лабораторные/lab2/README.md index 9807aef..db5b082 100644 --- a/5 сии/лабораторные/lab2/README.md +++ b/5 сии/лабораторные/lab2/README.md @@ -19,6 +19,7 @@ Мне 13 лет, мне нравятся: RPG, инди-игры + ### Нужно Спарсить строку, разбить на факты, построить запрос, используя эти предикаты (**формат входной строки фиксированный**, искать частичное соответствие подстроки не нужно) @@ -32,6 +33,54 @@ --- +## Как запустить? + +*Убедитесь, что у вас установлены [Python 3.12](https://www.python.org/downloads/release/python-3123/) и [Poetry](https://python-poetry.org/)* + +- Сначала: + +```sh +poetry install +``` + +- Линтер и форматтер: + +```sh +make +# или +poetry run ruff format . +poetry run ruff check . +``` + +- Запуск программы: + +```sh +make run +# или +poetry run main +``` + +### Возможные запросы + +Примеры запросов, которые вам доступны: + +- Какие страны входят в альянс Ось? +- Какие страны воюют друг с другом? +- Какие страны являются коммунистическими? +- Какие страны могут вступить в альянс с uk? +- Может ли usa создать новый альянс при текущем уровне мировой напряженности? +- Какой количество рекрутов в poland? +- Какие страны имеют выход к Чёрному морю? +- Армии каких стран имеют в своём составе пехотные дивизии? +- Какие страны находятся в оборонительной войне против germany? +- Какое население провинции ulaanbaatar в mongolia? +- Какие страны марионетки japan? +- Может ли ussr пересечь Босфор и Дарданеллы? +- Я играю за страну uk. Какое мое текущее отношение к france? +- Может ли hungary сфабриковать цель войны на yugoslavia? + +--- + ## Полезные ссылки | Ссылка | Описание | diff --git a/5 сии/лабораторные/lab2/poetry.lock b/5 сии/лабораторные/lab2/poetry.lock index f3a7689..6547d4e 100644 --- a/5 сии/лабораторные/lab2/poetry.lock +++ b/5 сии/лабораторные/lab2/poetry.lock @@ -1,5 +1,31 @@ # This file is automatically @generated by Poetry 1.8.3 and should not be changed by hand. +[[package]] +name = "ruff" +version = "0.1.15" +description = "An extremely fast Python linter and code formatter, written in Rust." +optional = false +python-versions = ">=3.7" +files = [ + {file = "ruff-0.1.15-py3-none-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:5fe8d54df166ecc24106db7dd6a68d44852d14eb0729ea4672bb4d96c320b7df"}, + {file = "ruff-0.1.15-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:6f0bfbb53c4b4de117ac4d6ddfd33aa5fc31beeaa21d23c45c6dd249faf9126f"}, + {file = "ruff-0.1.15-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e0d432aec35bfc0d800d4f70eba26e23a352386be3a6cf157083d18f6f5881c8"}, + {file = "ruff-0.1.15-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:9405fa9ac0e97f35aaddf185a1be194a589424b8713e3b97b762336ec79ff807"}, + {file = "ruff-0.1.15-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c66ec24fe36841636e814b8f90f572a8c0cb0e54d8b5c2d0e300d28a0d7bffec"}, + {file = "ruff-0.1.15-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:6f8ad828f01e8dd32cc58bc28375150171d198491fc901f6f98d2a39ba8e3ff5"}, + {file = "ruff-0.1.15-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:86811954eec63e9ea162af0ffa9f8d09088bab51b7438e8b6488b9401863c25e"}, + {file = "ruff-0.1.15-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fd4025ac5e87d9b80e1f300207eb2fd099ff8200fa2320d7dc066a3f4622dc6b"}, + {file = "ruff-0.1.15-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b17b93c02cdb6aeb696effecea1095ac93f3884a49a554a9afa76bb125c114c1"}, + {file = "ruff-0.1.15-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:ddb87643be40f034e97e97f5bc2ef7ce39de20e34608f3f829db727a93fb82c5"}, + {file = "ruff-0.1.15-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:abf4822129ed3a5ce54383d5f0e964e7fef74a41e48eb1dfad404151efc130a2"}, + {file = "ruff-0.1.15-py3-none-musllinux_1_2_i686.whl", hash = "sha256:6c629cf64bacfd136c07c78ac10a54578ec9d1bd2a9d395efbee0935868bf852"}, + {file = "ruff-0.1.15-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:1bab866aafb53da39c2cadfb8e1c4550ac5340bb40300083eb8967ba25481447"}, + {file = "ruff-0.1.15-py3-none-win32.whl", hash = "sha256:2417e1cb6e2068389b07e6fa74c306b2810fe3ee3476d5b8a96616633f40d14f"}, + {file = "ruff-0.1.15-py3-none-win_amd64.whl", hash = "sha256:3837ac73d869efc4182d9036b1405ef4c73d9b1f88da2413875e34e0d6919587"}, + {file = "ruff-0.1.15-py3-none-win_arm64.whl", hash = "sha256:9a933dfb1c14ec7a33cceb1e49ec4a16b51ce3c20fd42663198746efc0427360"}, + {file = "ruff-0.1.15.tar.gz", hash = "sha256:f6dfa8c1b21c913c326919056c390966648b680966febcb796cc9d1aaab8564e"}, +] + [[package]] name = "swiplserver" version = "1.0.2" @@ -14,4 +40,4 @@ files = [ [metadata] lock-version = "2.0" python-versions = "^3.12" -content-hash = "ebea2b4b9934dd39850ad9c2e0e9147431fd8587bc138ff2c44035ac75440e52" +content-hash = "e813a8061617c5c7825a6f86dd5a31a709675bed68251bd1fd010926f49ac0bb" diff --git a/5 сии/лабораторные/lab2/pyproject.toml b/5 сии/лабораторные/lab2/pyproject.toml index 43a6b83..2b68ddc 100644 --- a/5 сии/лабораторные/lab2/pyproject.toml +++ b/5 сии/лабораторные/lab2/pyproject.toml @@ -79,14 +79,13 @@ ignore = [ "E501", # allow lines longer than 80 symbols (up to 120) "T201", # `print` found "PD011", # Breaks .values + "RUF001", # Breaks cyrillic strings "RUF002", # Docstring contains ambiguous `В` (CYRILLIC CAPITAL LETTER VE). Did you mean `B` (LATIN CAPITAL LETTER B) "RUF003", # Comment contains ambiguous `с` (CYRILLIC SMALL LETTER ES). Did you mean `c` (LATIN SMALL LETTER C) "PTH123", # `open()` should be replaced by `Path.open()` # to simplify code for non-Python programmers "PTH118", # `os.path.join()` should be replaced by `Path` with `/` operator "UP032", # [*] Use f-string instead of `format` call - - ] unfixable = [ "ERA001", # prohibit to "auto-fix" (=remove) commented-out code diff --git a/5 сии/лабораторные/lab2/src/main.py b/5 сии/лабораторные/lab2/src/main.py new file mode 100644 index 0000000..2dc28ea --- /dev/null +++ b/5 сии/лабораторные/lab2/src/main.py @@ -0,0 +1,101 @@ +import logging +import re + +from src.methods import ( + can_fabricate_war_goal, + can_form_alliance, + can_go_throw_strait, + find_countries_at_war, + find_countries_by_ideology, + find_countries_in_alliance, + find_countries_near_sea, + find_defensive_countries, + get_countries_by_division, + get_population, + get_possible_allied_countries, + get_puppets, + get_recruits_number, + get_relationship, +) +from swiplserver import PrologMQI, create_posix_path + +KNOWLEDGE_BASE_PATH = "./src/prolog/knowledge_base.pl" + +incorrect_request = "Неправильный запрос" + +requests = [ + # Ось / Союзники / Коминтерн / Второй объединённый фронт / Великая восточноазиатская сфера сопроцветания + "Какие страны входят в альянс Ось?", + "Какие страны воюют друг с другом?", + # коммунистическими / демократическими / нейтральными / фашистскими + "Какие страны являются коммунистическими?", + "Какие страны могут вступить в альянс с uk?", + "Может ли usa создать новый альянс при текущем уровне мировой напряженности?", + "Какой количество рекрутов в poland?", + # Чёрному морю / Средиземному морю / Балтийскому морю / Адриатическому морю / Красному морю + # Атлантическому океану / Тихому океану / Индийскому океану + "Какие страны имеют выход к Чёрному морю?", + # пехотные / десантные / артиллерийские / танковые + "Армии каких стран имеют в своём составе пехотные дивизии?", + "Какие страны находятся в оборонительной войне против germany?", + "Какое население провинции ulaanbaatar в mongolia?", + "Какие страны марионетки japan?", + # Босфор и Дарданеллы / Панамский канал / Суэцкий канал / пролив Отранто + # Гибралтарский пролив / Кильский канал / Баб-эль-Мандебский пролив / Сингапурский пролив + "Может ли ussr пересечь Босфор и Дарданеллы?", + "Я играю за страну uk. Какое мое текущее отношение к france?", + "Может ли hungary сфабриковать цель войны на yugoslavia?", +] + +patterns = { + r"Какие страны входят в альянс (.+)\?": find_countries_in_alliance.FindCountriesInAlliance, + r"Какие страны воюют друг с другом\?": find_countries_at_war.FindCountriesAtWar, + r"Какие страны являются (.+)\?": find_countries_by_ideology.FindCountriesByIdeology, + r"Какие страны могут вступить в альянс с (.+)\?": get_possible_allied_countries.GetPossibleAlliedCountries, + r"Может ли (.+) создать новый альянс при текущем уровне мировой напряженности\?": can_form_alliance.CanFormAlliance, + r"Какой количество рекрутов в (.+)\?": get_recruits_number.GetRecruitsNumber, + r"Какие страны имеют выход к (.+)\?": find_countries_near_sea.FindCountriesNearSea, + r"Армии каких стран имеют в своём составе (.+) дивизии\?": get_countries_by_division.GetCountriesByDivision, + r"Какие страны находятся в оборонительной войне против (.+)\?": find_defensive_countries.FindDefensiveCountries, + r"Какое население провинции (.+) в (.+)\?": get_population.GetPopulation, + r"Какие страны марионетки (.+)\?": get_puppets.GetPuppets, + r"Может ли (.+) пересечь (.+)\?": can_go_throw_strait.CanGoThrowStrait, + r"Я играю за страну (.+). Какое мое текущее отношение к (.+)\?": get_relationship.GetRelationship, + r"Может ли (.+) сфабриковать цель войны на (.+)\?": can_fabricate_war_goal.CanFabricateWarGoal, +} + + +def start() -> None: + logging.getLogger().setLevel(logging.WARNING) + + with PrologMQI() as mqi: + with mqi.create_thread() as prolog: + path = create_posix_path(KNOWLEDGE_BASE_PATH) + logging.debug("DEBUG: knowledge base path %s", path) + + prolog.query(f'consult("{path}")') + logging.debug("DEBUG: knowledge base loaded") + + print("\nПримеры запросов, которые вам доступны:", "\n * " + ("\n * ".join(requests))) + print("\nДля завершения введите - exit.") + + while True: + query = input("> ") + if query.lower() == "exit": + break + + for pattern in patterns: + match = re.match(pattern, query, re.IGNORECASE) + if match is None: + continue + + logging.debug("DEBUG: '%s' matches to '%s'", query, match) + processor = patterns[pattern](*match.groups()) + processor.run(prolog) + break + else: + print(incorrect_request) + + +if __name__ == "__main__": + start() diff --git a/5 сии/лабораторные/lab2/src/methods/__init__.py b/5 сии/лабораторные/lab2/src/methods/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/5 сии/лабораторные/lab2/src/methods/can_fabricate_war_goal.py b/5 сии/лабораторные/lab2/src/methods/can_fabricate_war_goal.py new file mode 100644 index 0000000..7885beb --- /dev/null +++ b/5 сии/лабораторные/lab2/src/methods/can_fabricate_war_goal.py @@ -0,0 +1,29 @@ +from swiplserver import PrologThread + + +class CanFabricateWarGoal: + def __init__(self, country1: str, country2: str): + self.country1 = country1 + self.country2 = country2 + + def run(self, prolog: PrologThread): + if self.country1 == self.country2: + print( + f"Нет, {self.country1} не может сфабриковать цель войны на {self.country2}, так как это одна и та же страна." + ) + return + + res = prolog.query(self.query()) + if not res: + self.failure() + else: + self.success() + + def query(self): + return f"can_justify_war_goal({self.country1}, {self.country2})." + + def success(self): + print(f"Да, {self.country1} может сфабриковать цель войны на {self.country2}.") + + def failure(self): + print(f"Нет, {self.country1} не может сфабриковать цель войны на {self.country2}.") diff --git a/5 сии/лабораторные/lab2/src/methods/can_form_alliance.py b/5 сии/лабораторные/lab2/src/methods/can_form_alliance.py new file mode 100644 index 0000000..c61b770 --- /dev/null +++ b/5 сии/лабораторные/lab2/src/methods/can_form_alliance.py @@ -0,0 +1,22 @@ +from swiplserver import PrologThread + + +class CanFormAlliance: + def __init__(self, country: str): + self.country = country + + def run(self, prolog: PrologThread): + res = prolog.query(self.query()) + if not res: + self.failure() + else: + self.success() + + def query(self): + return f"can_form_alliance({self.country})." + + def success(self): + print(f"Да, {self.country} может создать новый альянс при текущем уровне мировой напряженности.") + + def failure(self): + print(f"Нет, {self.country} не может создать новый альянс при текущем уровне мировой напряженности.") diff --git a/5 сии/лабораторные/lab2/src/methods/can_go_throw_strait.py b/5 сии/лабораторные/lab2/src/methods/can_go_throw_strait.py new file mode 100644 index 0000000..ed76aa2 --- /dev/null +++ b/5 сии/лабораторные/lab2/src/methods/can_go_throw_strait.py @@ -0,0 +1,38 @@ +from swiplserver import PrologThread + + +class CanGoThrowStrait: + def __init__(self, country: str, strait: str): + self.country = country + self.strait = strait + + def run(self, prolog: PrologThread): + res = prolog.query(self.query()) + if not res: + self.failure() + else: + self.success() + + def query(self): + return f"can_cross_the_strait({self.country}, {self.get_strait()})." + + def success(self): + print(f"Да, {self.country} может пересечь {self.strait}.") + + def failure(self): + print(f"Нет, {self.country} не может пересечь {self.strait}.") + + def get_strait(self): + straits = { + "Босфор и Дарданеллы": "bosporus_and_dardanelles", + "Панамский канал": "panama_canal_strait", + "Суэцкий канал": "suez_canal", + "пролив Отранто": "otranto", + "Гибралтарский пролив": "gibraltar_strait", + "Кильский канал": "kiel_canal", + "Баб-эль-Мандебский пролив": "bab_el_mandeb", + "Сингапурский пролив": "singapur_strait", + } + if self.strait not in straits: + return "not_found" + return straits[self.strait] diff --git a/5 сии/лабораторные/lab2/src/methods/find_countries_at_war.py b/5 сии/лабораторные/lab2/src/methods/find_countries_at_war.py new file mode 100644 index 0000000..6fe92a7 --- /dev/null +++ b/5 сии/лабораторные/lab2/src/methods/find_countries_at_war.py @@ -0,0 +1,21 @@ +from swiplserver import PrologThread + + +class FindCountriesAtWar: + def run(self, prolog: PrologThread): + res = prolog.query(self.query()) + if not res or len(res) == 0: + self.failure(res) + else: + self.success(res) + + def query(self): + return "at_offencive_war(Country1, Country2)" + + def success(self, res): + print(f"Найдено {len(res)} стран, которые воюют друг с другом:") + for index, line in enumerate(res, 1): + print(f"{index}. {line['Country1']} воюет с {line['Country2']}") + + def failure(self, res): + print("Нет стран, которые воюют друг с другом.") diff --git a/5 сии/лабораторные/lab2/src/methods/find_countries_by_ideology.py b/5 сии/лабораторные/lab2/src/methods/find_countries_by_ideology.py new file mode 100644 index 0000000..ea5aa5e --- /dev/null +++ b/5 сии/лабораторные/lab2/src/methods/find_countries_by_ideology.py @@ -0,0 +1,35 @@ +from swiplserver import PrologThread + + +class FindCountriesByIdeology: + def __init__(self, ideology: str): + self.ideology = ideology + + def run(self, prolog: PrologThread): + res = prolog.query(self.query()) + if not res or len(res) == 0: + self.failure(res) + else: + self.success(res) + + def query(self): + return f"ideology(Country, {self.get_ideology()})." + + def success(self, res): + print(f"Найдено {len(res)} стран с идеологией {self.ideology}:") + for index, line in enumerate(res, 1): + print(f"{index}. {line['Country']}") + + def failure(self, res): + print(f"Нет стран с идеологией {self.ideology}.") + + def get_ideology(self): + ideologies = { + "коммунистическими": "communist", + "демократическими": "democratic", + "нейтральными": "neutral", + "фашистскими": "fascist", + } + if self.ideology not in ideologies: + return "not_found" + return ideologies[self.ideology] diff --git a/5 сии/лабораторные/lab2/src/methods/find_countries_in_alliance.py b/5 сии/лабораторные/lab2/src/methods/find_countries_in_alliance.py new file mode 100644 index 0000000..66da2f4 --- /dev/null +++ b/5 сии/лабораторные/lab2/src/methods/find_countries_in_alliance.py @@ -0,0 +1,36 @@ +from swiplserver import PrologThread + + +class FindCountriesInAlliance: + def __init__(self, alliance: str): + self.alliance = alliance + + def run(self, prolog: PrologThread): + res = prolog.query(self.query()) + if not res or len(res) == 0: + self.failure(res) + else: + self.success(res) + + def query(self): + return f"alliance(Country, {self.get_alliance_tag()})" + + def success(self, res): + print(f"Найдено {len(res)} стран, которые входят в альянс {self.alliance}:") + for index, line in enumerate(res, 1): + print(f"{index}. ", line["Country"]) + + def failure(self, res): + print(f"Нет стран, которые входят в альянс {self.alliance}.") + + def get_alliance_tag(self): + alliances = { + "Ось": "axis", + "Союзники": "allies", + "Коминтерн": "comintern", + "Второй объединённый фронт": "united_chinese_front", + "Великая восточноазиатская сфера сопроцветания": "great_east_asia_coprosperity_sphere", + } + if self.alliance not in alliances: + return "not_found" + return alliances[self.alliance] diff --git a/5 сии/лабораторные/lab2/src/methods/find_countries_near_sea.py b/5 сии/лабораторные/lab2/src/methods/find_countries_near_sea.py new file mode 100644 index 0000000..304ec67 --- /dev/null +++ b/5 сии/лабораторные/lab2/src/methods/find_countries_near_sea.py @@ -0,0 +1,40 @@ +from swiplserver import PrologThread + + +class FindCountriesNearSea: + def __init__(self, sea: str): + self.sea = sea + + def run(self, prolog: PrologThread): + res = prolog.query(self.query()) + if not res or len(res) == 0: + self.failure(res) + else: + self.success(res) + + def query(self): + return f"has_access_to_sea(Province, {self.get_seas()}), province_of(Country, Province)." + + def success(self, res): + unique_res = list({object_["Country"]: object_ for object_ in res}.values()) + print(f"Найдено {len(unique_res)} стран с выходом к {self.sea}:") + for index, line in enumerate(unique_res, 1): + print(f"{index}. {line['Country']}") + + def failure(self, res): + print(f"Нет стран с выходом к {self.sea}.") + + def get_seas(self): + seas = { + "Чёрному морю": "black_sea", + "Средиземному морю": "mediterranean_sea", + "Балтийскому морю": "baltic_sea", + "Адриатическому морю": "adriatic_sea", + "Красному морю": "red_sea", + "Атлантическому океану": "atlantic_ocean", + "Тихому океану": "pacific_ocean", + "Индийскому океану": "indian_ocean", + } + if self.sea not in seas: + return "not_found" + return seas[self.sea] diff --git a/5 сии/лабораторные/lab2/src/methods/find_defensive_countries.py b/5 сии/лабораторные/lab2/src/methods/find_defensive_countries.py new file mode 100644 index 0000000..08f1960 --- /dev/null +++ b/5 сии/лабораторные/lab2/src/methods/find_defensive_countries.py @@ -0,0 +1,24 @@ +from swiplserver import PrologThread + + +class FindDefensiveCountries: + def __init__(self, country: str): + self.country = country + + def run(self, prolog: PrologThread): + res = prolog.query(self.query()) + if not res or len(res) == 0: + self.failure() + else: + self.success(res) + + def query(self): + return f"at_defensive_war(Country, {self.country})." + + def success(self, res): + print(f"На {self.country} нападают страны:") + for index, line in enumerate(res, 1): + print(f"{index}. {line['Country']}") + + def failure(self): + print(f"{self.country} не находится в оборонительной войне.") diff --git a/5 сии/лабораторные/lab2/src/methods/get_countries_by_division.py b/5 сии/лабораторные/lab2/src/methods/get_countries_by_division.py new file mode 100644 index 0000000..545e204 --- /dev/null +++ b/5 сии/лабораторные/lab2/src/methods/get_countries_by_division.py @@ -0,0 +1,36 @@ +from swiplserver import PrologThread + + +class GetCountriesByDivision: + def __init__(self, division: str): + self.division = division + + def run(self, prolog: PrologThread): + res = prolog.query(self.query()) + if not res or len(res) == 0: + self.failure() + else: + self.success(res) + + def query(self): + return f"has_division(Army, {self.division_name()}), army(Army, Country)." + + def success(self, res): + print(f"Страны, у которых в войсках есть {self.division} дивизии:") + unique_res = list({object_["Country"]: object_ for object_ in res}.values()) + for index, line in enumerate(unique_res, 1): + print(f"{index}. {line['Country']}") + + def failure(self): + print(f"Нет стран с дивизией {self.division}.") + + def division_name(self): + divisions = { + "пехотные": "infantry_division", + "десантные": "naval_division", + "артиллерийские": "artillery_division", + "танковые": "armored_division", + } + if self.division not in divisions: + return "not_found" + return divisions[self.division] diff --git a/5 сии/лабораторные/lab2/src/methods/get_population.py b/5 сии/лабораторные/lab2/src/methods/get_population.py new file mode 100644 index 0000000..926d967 --- /dev/null +++ b/5 сии/лабораторные/lab2/src/methods/get_population.py @@ -0,0 +1,24 @@ +from swiplserver import PrologThread + + +class GetPopulation: + def __init__(self, province: str, country: str): + self.province = province + self.country = country + + def run(self, prolog: PrologThread): + res = prolog.query(self.query()) + if not res: + self.failure(res) + else: + self.success(res) + + def query(self): + return f"population({self.province}, Population), province_of({self.country}, {self.province})." + + def success(self, res): + population = res[0]["Population"] + print(f"Население провинции {self.province} в стране {self.country}: {population}") + + def failure(self, res): + print(f"Не удалось найти информацию о населении провинции {self.province} в стране {self.country}.") diff --git a/5 сии/лабораторные/lab2/src/methods/get_possible_allied_countries.py b/5 сии/лабораторные/lab2/src/methods/get_possible_allied_countries.py new file mode 100644 index 0000000..f40577e --- /dev/null +++ b/5 сии/лабораторные/lab2/src/methods/get_possible_allied_countries.py @@ -0,0 +1,24 @@ +from swiplserver import PrologThread + + +class GetPossibleAlliedCountries: + def __init__(self, country: str): + self.country = country + + def run(self, prolog: PrologThread): + res = prolog.query(self.query()) + if not res or len(res) == 0: + self.failure() + else: + self.success(res) + + def query(self): + return f"can_invite_to_alliance({self.country}, _, Country)." + + def success(self, res): + print(f"Страны, которые могут вступить в альянс с {self.country}:") + for index, line in enumerate(res, 1): + print(f"{index}. {line['Country']}") + + def failure(self): + print(f"Нет стран, которые могут вступить в альянс с {self.country}.") diff --git a/5 сии/лабораторные/lab2/src/methods/get_puppets.py b/5 сии/лабораторные/lab2/src/methods/get_puppets.py new file mode 100644 index 0000000..d983c16 --- /dev/null +++ b/5 сии/лабораторные/lab2/src/methods/get_puppets.py @@ -0,0 +1,24 @@ +from swiplserver import PrologThread + + +class GetPuppets: + def __init__(self, country: str): + self.country = country + + def run(self, prolog: PrologThread): + res = prolog.query(self.query()) + if not res or len(res) == 0: + self.failure() + else: + self.success(res) + + def query(self): + return f"puppet({self.country}, PuppetCountry)." + + def success(self, res): + print(f"Марионетки {self.country}:") + for index, line in enumerate(res, 1): + print(f"{index}. {line['PuppetCountry']}") + + def failure(self): + print(f"У {self.country} нет марионеток.") diff --git a/5 сии/лабораторные/lab2/src/methods/get_recruits_number.py b/5 сии/лабораторные/lab2/src/methods/get_recruits_number.py new file mode 100644 index 0000000..844419b --- /dev/null +++ b/5 сии/лабораторные/lab2/src/methods/get_recruits_number.py @@ -0,0 +1,23 @@ +from swiplserver import PrologThread + + +class GetRecruitsNumber: + def __init__(self, country: str): + self.country = country + + def run(self, prolog: PrologThread): + res = prolog.query(self.query()) + if not res: + self.failure(res) + else: + self.success(res) + + def query(self): + return f"recruits({self.country}, Recruits)." + + def success(self, res): + recruits = res[0]["Recruits"] + print(f"Количество рекрутов в {self.country}: {recruits}") + + def failure(self, res): + print(f"Не удалось найти информацию о рекрутах в {self.country}.") diff --git a/5 сии/лабораторные/lab2/src/methods/get_relationship.py b/5 сии/лабораторные/lab2/src/methods/get_relationship.py new file mode 100644 index 0000000..475bdac --- /dev/null +++ b/5 сии/лабораторные/lab2/src/methods/get_relationship.py @@ -0,0 +1,30 @@ +from swiplserver import PrologThread + + +class GetRelationship: + def __init__(self, country1: str, country2: str): + self.country1 = country1 + self.country2 = country2 + + def run(self, prolog: PrologThread): + if self.country1 == self.country2: + print( + f"Не удалось найти информацию об отношении {self.country1} к {self.country2}, так как это одна и та же страна." + ) + return + + res = prolog.query(self.query()) + if not res: + self.failure() + else: + self.success(res) + + def query(self): + return f"current_relationship({self.country1}, {self.country2}, Relationship)." + + def success(self, res): + relationship = res[0]["Relationship"] + print(f"Отношение {self.country1} к {self.country2} составляет {relationship}.") + + def failure(self): + print(f"Не удалось найти информацию об отношении {self.country1} к {self.country2}.")