From 5f09410869b36cb26a7f9e3c329212501f837f49 Mon Sep 17 00:00:00 2001 From: Dmitry Date: Tue, 7 Apr 2026 21:00:58 +0300 Subject: [PATCH] =?UTF-8?q?=D0=98=D0=BD=D0=B8=D1=86=D0=B8=D0=B0=D0=BB?= =?UTF-8?q?=D0=B8=D0=B7=D0=B0=D1=86=D0=B8=D1=8F=20=D1=80=D0=B5=D0=BF=D0=BE?= =?UTF-8?q?=D0=B7=D0=B8=D1=82=D0=BE=D1=80=D0=B8=D1=8F=20=D0=B4=D0=BB=D1=8F?= =?UTF-8?q?=20=D0=98=D0=A0=D0=A4=D0=9C=5F=D0=9C=D0=98=D0=A4=D0=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 5 + .python-version | 1 + LR1/specialities.html | 2204 +++++++++++++++++++++++++++++++++++++++++ LR1/specialities.xsl | 299 ++++++ LR1/transform.py | 14 + LR2/irfm_lr2.ipynb | 681 +++++++++++++ LR3/cli_client.py | 168 ++++ LR3/irfm_lr3.py | 300 ++++++ LR3/task3.pdf | Bin 0 -> 70900 bytes pyproject.toml | 17 + 10 files changed, 3689 insertions(+) create mode 100644 .gitignore create mode 100644 .python-version create mode 100644 LR1/specialities.html create mode 100644 LR1/specialities.xsl create mode 100644 LR1/transform.py create mode 100644 LR2/irfm_lr2.ipynb create mode 100644 LR3/cli_client.py create mode 100644 LR3/irfm_lr3.py create mode 100644 LR3/task3.pdf create mode 100644 pyproject.toml diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..075a631 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +# Local datasets and databases +/data/montcoalert/ +*.db +*.sqlite +*.sqlite3 diff --git a/.python-version b/.python-version new file mode 100644 index 0000000..e4fba21 --- /dev/null +++ b/.python-version @@ -0,0 +1 @@ +3.12 diff --git a/LR1/specialities.html b/LR1/specialities.html new file mode 100644 index 0000000..2ee5de0 --- /dev/null +++ b/LR1/specialities.html @@ -0,0 +1,2204 @@ + + + + Анализ данных файла specialities.xml + + + +

Анализ данных файла specialities.xml (specialities.xml)

+
+
Анализ поля id
+
Тип данных: integer
+
Число пустых: 0
+
Нужен: NOT NULL
+
+
+
Анализ поля name
+
Тип данных: Текст
+
Самый длинный элемент: + Твердотельная электроника, радиоэлектронные компоненты, микро- и наноэлектроника на квантовых эффектах , длина: 102
+
Число пустых: 0
+
Нужен: NOT NULL
+
+
+
Анализ поля code
+
Тип данных: Текст
+
Самый длинный элемент: + 14.05.03 , длина: 8
+
Число пустых: 0
+
Нужен: NOT NULL
+
+
+
Анализ поля level
+
Тип данных: Текст
+
Самый длинный элемент: + Магистратура , длина: 12
+
Число пустых: 0
+
Нужен: NOT NULL
+
Нужен: CHECK (level IN( + 'Специалитет' , 'Магистратура' , 'Бакалавриат' , 'Аспирантура' + ))
+
+
+
Анализ поля level-id
+
Тип данных: integer
+
Число пустых: 0
+
Нужен: NOT NULL
+
Нужен: CHECK (level_id IN( + '1' , '2' , '0' , '3' + ))
+
+
+
Анализ поля generation
+
Тип данных: Текст
+
Самый длинный элемент: + ФГОС3+ , длина: 6
+
Число пустых: 0
+
Нужен: NOT NULL
+
Нужен: CHECK (generation IN( + 'ФГОС3+' , 'ГОС2' + ))
+
+
+
Анализ поля generation-id
+
Тип данных: integer
+
Число пустых: 0
+
Нужен: NOT NULL
+
Нужен: CHECK (generation_id IN( + '1' , '0' + ))
+
+
+
Анализ поля type
+
Тип данных: Текст
+
Самый длинный элемент: + специальность , длина: 13
+
Число пустых: 0
+
Нужен: NOT NULL
+
Нужен: CHECK (type IN( + 'специальность' , 'направление' + ))
+
+
+
Анализ поля type-id
+
Тип данных: integer
+
Число пустых: 0
+
Нужен: NOT NULL
+
Нужен: CHECK (type_id IN( + '1' , '0' + ))
+
+

SQL-файл

+
DROP TABLE IF EXISTS specialities; +DROP SEQUENCE IF EXISTS specialities_id_seq; + +CREATE SEQUENCE specialities_id_seq + START WITH 1 + INCREMENT BY 1; + +CREATE TABLE specialities ( + id INTEGER NOT NULL, + + name VARCHAR(102) NOT NULL, + + code VARCHAR(8) NOT NULL, + + level VARCHAR(12) NOT NULL CHECK (level IN ('Специалитет', 'Магистратура', 'Бакалавриат', 'Аспирантура')), + + level_id INTEGER NOT NULL CHECK (level_id IN (1, 2, 0, 3)), + + generation VARCHAR(6) NOT NULL CHECK (generation IN ('ФГОС3+', 'ГОС2')), + + generation_id INTEGER NOT NULL CHECK (generation_id IN (1, 0)), + + type VARCHAR(13) NOT NULL CHECK (type IN ('специальность', 'направление')), + + type_id INTEGER NOT NULL CHECK (type_id IN (1, 0)), + CONSTRAINT pk_specialities PRIMARY KEY (id) +);
+

SQL: INSERT-запросы, сформированные из XML

+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Технологии разделения изотопов и ядерное топливо', + '14.05.03', + 'Специалитет', + 1, + 'ФГОС3+', + 1, + 'специальность', + 1 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Ядерные физика и технологии', + '14.04.02', + 'Магистратура', + 2, + 'ФГОС3+', + 1, + 'направление', + 0 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Юриспруденция', + '030501', + 'Специалитет', + 1, + 'ГОС2', + 0, + 'специальность', + 1 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Прикладная математика', + '230401', + 'Специалитет', + 1, + 'ГОС2', + 0, + 'специальность', + 1 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Информационная безопасность', + '090900', + 'Бакалавриат', + 0, + 'ФГОС3+', + 1, + 'направление', + 0 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Конструкторско-технологическое обеспечение машиностроительных производств', + '151900', + 'Магистратура', + 2, + 'ФГОС3+', + 1, + 'направление', + 0 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Физика кинетических явлений', + '140303', + 'Специалитет', + 1, + 'ГОС2', + 0, + 'специальность', + 1 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Прикладная информатика', + '09.03.03', + 'Бакалавриат', + 0, + 'ФГОС3+', + 1, + 'направление', + 0 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Прикладная математика и информатика', + '01.03.02', + 'Бакалавриат', + 0, + 'ФГОС3+', + 1, + 'направление', + 0 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Бизнес-информатика', + '38.04.05', + 'Магистратура', + 2, + 'ФГОС3+', + 1, + 'направление', + 0 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Информационные системы и технологии', + '09.04.02', + 'Магистратура', + 2, + 'ФГОС3+', + 1, + 'направление', + 0 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Применение и эксплуатация автоматизированных систем специального назначения', + '09.05.01', + 'Специалитет', + 1, + 'ФГОС3+', + 1, + 'специальность', + 1 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Безопасность и нераспространение ядерных материалов', + '140309', + 'Специалитет', + 1, + 'ГОС2', + 0, + 'специальность', + 1 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Техническая физика', + '140400', + 'Магистратура', + 2, + 'ГОС2', + 0, + 'направление', + 0 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Ядерные физика и технологии', + '140800', + 'Бакалавриат', + 0, + 'ФГОС3+', + 1, + 'направление', + 0 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Прикладная математика и информатика', + '010501', + 'Специалитет', + 1, + 'ГОС2', + 0, + 'специальность', + 1 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Атомные станции: проектирование, эксплуатация и инжиниринг', + '14.05.02', + 'Специалитет', + 1, + 'ФГОС3+', + 1, + 'специальность', + 1 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Юриспруденция', + '40.03.01', + 'Бакалавриат', + 0, + 'ФГОС3+', + 1, + 'направление', + 0 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Экономика', + '38.03.01', + 'Бакалавриат', + 0, + 'ФГОС3+', + 1, + 'направление', + 0 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Прикладная информатика (по областям)', + '080801', + 'Специалитет', + 1, + 'ГОС2', + 0, + 'специальность', + 1 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Материаловедение и технологии материалов', + '22.03.01', + 'Бакалавриат', + 0, + 'ФГОС3+', + 1, + 'направление', + 0 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Юриспруденция', + '40.04.01', + 'Магистратура', + 2, + 'ФГОС3+', + 1, + 'направление', + 0 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Информационно-аналитические системы безопасности', + '10.05.04', + 'Специалитет', + 1, + 'ФГОС3+', + 1, + 'специальность', + 1 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Материаловедение и технологии материалов', + '150100', + 'Магистратура', + 2, + 'ФГОС3+', + 1, + 'направление', + 0 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Электроника и автоматика физических установок', + '14.05.04', + 'Специалитет', + 1, + 'ФГОС3+', + 1, + 'специальность', + 1 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Международные отношения', + '41.03.05', + 'Бакалавриат', + 0, + 'ФГОС3+', + 1, + 'направление', + 0 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Технологии разделения изотопов и ядерное топливо', + '141405', + 'Специалитет', + 1, + 'ФГОС3+', + 1, + 'специальность', + 1 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Безопасность информационных технологий в правоохранительной сфере', + '10.05.05', + 'Специалитет', + 1, + 'ФГОС3+', + 1, + 'специальность', + 1 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Экономика', + '080100', + 'Бакалавриат', + 0, + 'ФГОС3+', + 1, + 'направление', + 0 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Прикладная информатика', + '230700', + 'Бакалавриат', + 0, + 'ФГОС3+', + 1, + 'направление', + 0 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Ядерные физика и технологии', + '14.03.02', + 'Бакалавриат', + 0, + 'ФГОС3+', + 1, + 'направление', + 0 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Информатика и вычислительная техника', + '09.04.01', + 'Магистратура', + 2, + 'ФГОС3+', + 1, + 'направление', + 0 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Бизнес-информатика', + '38.03.05', + 'Бакалавриат', + 0, + 'ФГОС3+', + 1, + 'направление', + 0 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Системный анализ и управление', + '27.03.03', + 'Бакалавриат', + 0, + 'ФГОС3+', + 1, + 'направление', + 0 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Информационная безопасность', + '090900', + 'Магистратура', + 2, + 'ФГОС3+', + 1, + 'направление', + 0 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Ядерная энергетика и теплофизика', + '14.04.01', + 'Магистратура', + 2, + 'ФГОС3+', + 1, + 'направление', + 0 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Информатика и вычислительная техника', + '230100', + 'Бакалавриат', + 0, + 'ФГОС3+', + 1, + 'направление', + 0 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Вычислительные машины, комплексы, системы и сети', + '230101', + 'Специалитет', + 1, + 'ГОС2', + 0, + 'специальность', + 1 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Прикладная математика и информатика', + '010400', + 'Бакалавриат', + 0, + 'ФГОС3+', + 1, + 'направление', + 0 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Прикладная математика', + '01.03.04', + 'Бакалавриат', + 0, + 'ФГОС3+', + 1, + 'направление', + 0 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Комплексная защита объектов информатизации', + '090104', + 'Специалитет', + 1, + 'ГОС2', + 0, + 'специальность', + 1 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Прикладная математика и информатика', + '010400', + 'Магистратура', + 2, + 'ФГОС3+', + 1, + 'направление', + 0 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Правовое обеспечение национальной безопасности', + '40.05.01', + 'Специалитет', + 1, + 'ФГОС3+', + 1, + 'специальность', + 1 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Физика', + '03.03.02', + 'Бакалавриат', + 0, + 'ФГОС3+', + 1, + 'направление', + 0 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Информационная безопасность', + '10.03.01', + 'Бакалавриат', + 0, + 'ФГОС3+', + 1, + 'направление', + 0 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Физика металлов', + '150702', + 'Специалитет', + 1, + 'ГОС2', + 0, + 'специальность', + 1 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Физика пучков заряженных частиц и ускорительная техника', + '140304', + 'Специалитет', + 1, + 'ГОС2', + 0, + 'специальность', + 1 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Медицинская физика', + '010707', + 'Специалитет', + 1, + 'ГОС2', + 0, + 'специальность', + 1 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Прикладная математика и информатика', + '01.04.02', + 'Магистратура', + 2, + 'ФГОС3+', + 1, + 'направление', + 0 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Информационная безопасность', + '10.04.01', + 'Магистратура', + 2, + 'ФГОС3+', + 1, + 'направление', + 0 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Комплексное обеспечение информационной безопасности автоматизированных систем', + '090105', + 'Специалитет', + 1, + 'ГОС2', + 0, + 'специальность', + 1 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Прикладные математика и физика', + '03.04.01', + 'Магистратура', + 2, + 'ФГОС3+', + 1, + 'направление', + 0 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Материаловедение и технологии материалов', + '22.04.01', + 'Магистратура', + 2, + 'ФГОС3+', + 1, + 'направление', + 0 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Прикладная информатика', + '09.04.03', + 'Магистратура', + 2, + 'ФГОС3+', + 1, + 'направление', + 0 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Международные отношения', + '030701', + 'Специалитет', + 1, + 'ГОС2', + 0, + 'специальность', + 1 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Ядерные реакторы и материалы', + '14.05.01', + 'Специалитет', + 1, + 'ФГОС3+', + 1, + 'специальность', + 1 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Прикладная математика и информатика', + '010500', + 'Бакалавриат', + 0, + 'ГОС2', + 0, + 'направление', + 0 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Прикладные математика и физика', + '010600', + 'Бакалавриат', + 0, + 'ГОС2', + 0, + 'направление', + 0 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Информатика и вычислительная техника', + '09.03.01', + 'Бакалавриат', + 0, + 'ФГОС3+', + 1, + 'направление', + 0 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Программная инженерия', + '09.04.04', + 'Магистратура', + 2, + 'ФГОС3+', + 1, + 'направление', + 0 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Прикладная математика и информатика', + '010500', + 'Магистратура', + 2, + 'ГОС2', + 0, + 'направление', + 0 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Физика', + '010700', + 'Бакалавриат', + 0, + 'ГОС2', + 0, + 'направление', + 0 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Менеджмент', + '080500', + 'Бакалавриат', + 0, + 'ГОС2', + 0, + 'направление', + 0 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Физика', + '011200', + 'Магистратура', + 2, + 'ФГОС3+', + 1, + 'направление', + 0 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Информационная безопасность автоматизированных систем', + '10.05.03', + 'Специалитет', + 1, + 'ФГОС3+', + 1, + 'специальность', + 1 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Прикладные математика и физика', + '010900', + 'Магистратура', + 2, + 'ФГОС3+', + 1, + 'направление', + 0 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Материаловедение и технологии материалов', + '150100', + 'Бакалавриат', + 0, + 'ФГОС3+', + 1, + 'направление', + 0 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Математические методы в экономике', + '080116', + 'Специалитет', + 1, + 'ГОС2', + 0, + 'специальность', + 1 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Физика', + '011200', + 'Бакалавриат', + 0, + 'ФГОС3+', + 1, + 'направление', + 0 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Экономика и управление на предприятии (по отраслям)', + '080502', + 'Специалитет', + 1, + 'ГОС2', + 0, + 'специальность', + 1 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Международные отношения', + '41.04.05', + 'Магистратура', + 2, + 'ФГОС3+', + 1, + 'направление', + 0 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Физика', + '03.04.02', + 'Магистратура', + 2, + 'ФГОС3+', + 1, + 'направление', + 0 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Прикладные математика и физика', + '010600', + 'Магистратура', + 2, + 'ГОС2', + 0, + 'направление', + 0 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Электроника и микроэлектроника', + '210100', + 'Магистратура', + 2, + 'ГОС2', + 0, + 'направление', + 0 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Менеджмент', + '38.03.02', + 'Бакалавриат', + 0, + 'ФГОС3+', + 1, + 'направление', + 0 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Финансы и кредит', + '080105', + 'Специалитет', + 1, + 'ГОС2', + 0, + 'специальность', + 1 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Информатика и вычислительная техника', + '230100', + 'Магистратура', + 2, + 'ФГОС3+', + 1, + 'направление', + 0 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Экономика', + '080100', + 'Бакалавриат', + 0, + 'ГОС2', + 0, + 'направление', + 0 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Физика конденсированного состояния вещества', + '140301', + 'Специалитет', + 1, + 'ГОС2', + 0, + 'специальность', + 1 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Ядерные реакторы и энергетические установки', + '140305', + 'Специалитет', + 1, + 'ГОС2', + 0, + 'специальность', + 1 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Информационная безопасность автоматизированных систем', + '090303', + 'Специалитет', + 1, + 'ФГОС3+', + 1, + 'специальность', + 1 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Физика атомного ядра и частиц', + '140302', + 'Специалитет', + 1, + 'ГОС2', + 0, + 'специальность', + 1 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Менеджмент', + '38.04.02', + 'Магистратура', + 2, + 'ФГОС3+', + 1, + 'направление', + 0 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Информационные системы и технологии', + '09.03.02', + 'Бакалавриат', + 0, + 'ФГОС3+', + 1, + 'направление', + 0 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Бухгалтерский учет, анализ и аудит', + '080109', + 'Специалитет', + 1, + 'ГОС2', + 0, + 'специальность', + 1 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Программная инженерия', + '231000', + 'Магистратура', + 2, + 'ФГОС3+', + 1, + 'направление', + 0 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Прикладные математика и физика', + '03.03.01', + 'Бакалавриат', + 0, + 'ФГОС3+', + 1, + 'направление', + 0 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Экономика', + '38.04.01', + 'Магистратура', + 2, + 'ФГОС3+', + 1, + 'направление', + 0 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Ядерные физика и технологии', + '140800', + 'Магистратура', + 2, + 'ФГОС3+', + 1, + 'направление', + 0 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Конструкторско-технологическое обеспечение машиностроительных производств', + '15.04.05', + 'Магистратура', + 2, + 'ФГОС3+', + 1, + 'направление', + 0 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Автоматизированные системы обработки информации и управления', + '230102', + 'Специалитет', + 1, + 'ГОС2', + 0, + 'специальность', + 1 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Прикладная математика', + '01.04.04', + 'Магистратура', + 2, + 'ФГОС3+', + 1, + 'направление', + 0 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Экономическая безопасность', + '38.05.01', + 'Специалитет', + 1, + 'ФГОС3+', + 1, + 'специальность', + 1 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Радиационная безопасность человека и окружающей среды', + '140307', + 'Специалитет', + 1, + 'ГОС2', + 0, + 'специальность', + 1 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Экономика', + '080100', + 'Магистратура', + 2, + 'ФГОС3+', + 1, + 'направление', + 0 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Менеджмент', + '080200', + 'Бакалавриат', + 0, + 'ФГОС3+', + 1, + 'направление', + 0 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Программная инженерия', + '09.03.04', + 'Бакалавриат', + 0, + 'ФГОС3+', + 1, + 'направление', + 0 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Системный анализ и управление', + '27.04.03', + 'Магистратура', + 2, + 'ФГОС3+', + 1, + 'направление', + 0 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Менеджмент', + '080200', + 'Магистратура', + 2, + 'ФГОС3+', + 1, + 'направление', + 0 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Ядерная энергетика и теплофизика', + '140700', + 'Магистратура', + 2, + 'ФГОС3+', + 1, + 'направление', + 0 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Электроника и автоматика физических установок', + '140306', + 'Специалитет', + 1, + 'ГОС2', + 0, + 'специальность', + 1 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Дифференциальные уравнения', + '01.01.02', + 'Аспирантура', + 3, + 'ГОС2', + 0, + 'специальность', + 1 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Приборы и методы экспериментальной физики', + '01.04.01', + 'Аспирантура', + 3, + 'ГОС2', + 0, + 'специальность', + 1 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Физика и астрономия', + '03.06.01', + 'Аспирантура', + 3, + 'ФГОС3+', + 1, + 'направление', + 0 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Теоретическая физика', + '01.04.02', + 'Аспирантура', + 3, + 'ГОС2', + 0, + 'специальность', + 1 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Физика конденсированного состояния', + '01.04.07', + 'Аспирантура', + 3, + 'ГОС2', + 0, + 'специальность', + 1 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Физика плазмы', + '01.04.08', + 'Аспирантура', + 3, + 'ГОС2', + 0, + 'специальность', + 1 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Электрофизика, электрофизические установки', + '01.04.13', + 'Аспирантура', + 3, + 'ГОС2', + 0, + 'специальность', + 1 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Теплофизика и теоретическая теплотехника', + '01.04.14', + 'Аспирантура', + 3, + 'ГОС2', + 0, + 'специальность', + 1 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Электро- и теплотехника', + '13.06.01', + 'Аспирантура', + 3, + 'ФГОС3+', + 1, + 'направление', + 0 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Физика атомного ядра и элементарных частиц', + '01.04.16', + 'Аспирантура', + 3, + 'ГОС2', + 0, + 'специальность', + 1 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Физика пучков заряженных частиц и ускорительная техника', + '01.04.20', + 'Аспирантура', + 3, + 'ГОС2', + 0, + 'специальность', + 1 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Лазерная физика', + '01.04.21', + 'Аспирантура', + 3, + 'ГОС2', + 0, + 'специальность', + 1 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Физика высоких энергий', + '01.04.23', + 'Аспирантура', + 3, + 'ГОС2', + 0, + 'специальность', + 1 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Информационно-измерительные и управляющие системы (по отраслям)', + '05.11.16', + 'Аспирантура', + 3, + 'ГОС2', + 0, + 'специальность', + 1 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Управление в технических системах', + '27.06.01', + 'Аспирантура', + 3, + 'ФГОС3+', + 1, + 'направление', + 0 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Системный анализ, управление и обработка информации (по отраслям)', + '05.13.01', + 'Аспирантура', + 3, + 'ГОС2', + 0, + 'специальность', + 1 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Информатика и вычислительная техника', + '09.06.01', + 'Аспирантура', + 3, + 'ФГОС3+', + 1, + 'направление', + 0 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Элементы и устройства вычислительной техники и систем управления', + '05.13.05', + 'Аспирантура', + 3, + 'ГОС2', + 0, + 'специальность', + 1 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Автоматизация и управление технологическими процессами и производствами (по отраслям)', + '05.13.06', + 'Аспирантура', + 3, + 'ГОС2', + 0, + 'специальность', + 1 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Математическое и программное обеспечение вычислительных машин, комплексов и компьютерных сетей', + '05.13.11', + 'Аспирантура', + 3, + 'ГОС2', + 0, + 'специальность', + 1 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Математическое моделирование, численные методы и комплексы программ', + '05.13.18', + 'Аспирантура', + 3, + 'ГОС2', + 0, + 'специальность', + 1 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Компьютерные и информационные науки ', + '02.06.01', + 'Аспирантура', + 3, + 'ФГОС3+', + 1, + 'направление', + 0 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Методы и системы защиты информации, информационная безопасность', + '05.13.19', + 'Аспирантура', + 3, + 'ГОС2', + 0, + 'специальность', + 1 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Информационная безопасность', + '10.06.01', + 'Аспирантура', + 3, + 'ФГОС3+', + 1, + 'направление', + 0 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Ядерные энергетические установки, включая проектирование, эксплуатацию и вывод из эксплуатации', + '05.14.03', + 'Аспирантура', + 3, + 'ГОС2', + 0, + 'специальность', + 1 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Ядерная, тепловая и возобновляемая энергетика и сопутствующие технологии', + '14.06.01', + 'Аспирантура', + 3, + 'ФГОС3+', + 1, + 'направление', + 0 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Твердотельная электроника, радиоэлектронные компоненты, микро- и наноэлектроника на квантовых эффектах', + '05.27.01', + 'Аспирантура', + 3, + 'ГОС2', + 0, + 'специальность', + 1 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Электроника, радиотехника и системы связи', + '11.06.01', + 'Аспирантура', + 3, + 'ФГОС3+', + 1, + 'направление', + 0 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Экономика и управление народным хозяйством (по отраслям и сферам деятельности)', + '08.00.05', + 'Аспирантура', + 3, + 'ГОС2', + 0, + 'специальность', + 1 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Экономика', + '38.06.01', + 'Аспирантура', + 3, + 'ФГОС3+', + 1, + 'направление', + 0 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Бухгалтерский учет, статистика', + '08.00.12', + 'Аспирантура', + 3, + 'ГОС2', + 0, + 'специальность', + 1 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Математические и инструментальные методы экономики', + '08.00.13', + 'Аспирантура', + 3, + 'ГОС2', + 0, + 'специальность', + 1 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Административное право, финансовое право, информационное право', + '12.00.14', + 'Аспирантура', + 3, + 'ГОС2', + 0, + 'специальность', + 1 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Юриспруденция', + '40.06.01', + 'Аспирантура', + 3, + 'ФГОС3+', + 1, + 'направление', + 0 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Материаловедение', + '05.16.09', + 'Аспирантура', + 3, + 'ГОС2', + 0, + 'специальность', + 1 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Химическая технология', + '18.06.01', + 'Аспирантура', + 3, + 'ФГОС3+', + 1, + 'направление', + 0 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Порошковая металлургия и композиционные материалы', + '05.16.06', + 'Аспирантура', + 3, + 'ГОС2', + 0, + 'специальность', + 1 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Технологии материалов', + '22.06.01', + 'Аспирантура', + 3, + 'ФГОС3+', + 1, + 'направление', + 0 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Лазерная техника и лазерные технологии', + '12.03.05', + 'Бакалавриат', + 0, + 'ФГОС3+', + 1, + 'направление', + 0 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Математика и механика', + '01.06.01', + 'Аспирантура', + 3, + 'ФГОС3+', + 1, + 'направление', + 0 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Юриспруденция', + '030900', + 'Магистратура', + 2, + 'ФГОС3+', + 1, + 'направление', + 0 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Компьютерные и информаионные науки', + '02.06.01', + 'Аспирантура', + 3, + 'ФГОС3+', + 1, + 'направление', + 0 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Психология', + '37.04.01', + 'Магистратура', + 2, + 'ФГОС3+', + 1, + 'направление', + 0 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Лазерная техника и лазерные технологии', + '12.04.05', + 'Магистратура', + 2, + 'ФГОС3+', + 1, + 'направление', + 0 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Физико-технические науки и технологии', + '16.06.01', + 'Аспирантура', + 3, + 'ФГОС3+', + 1, + 'направление', + 0 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Экономическая безопасность', + '080101', + 'Специалитет', + 1, + 'ФГОС3+', + 1, + 'специальность', + 1 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Химические науки', + '04.06.01', + 'Аспирантура', + 3, + 'ФГОС3+', + 1, + 'направление', + 0 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Фотоника, приборостроение, оптические и биотехнические системы и технологии', + '12.06.01', + 'Аспирантура', + 3, + 'ФГОС3+', + 1, + 'направление', + 0 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Машиностроение', + '15.06.01', + 'Аспирантура', + 3, + 'ФГОС3+', + 1, + 'направление', + 0 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Психологические науки', + '37.06.01', + 'Аспирантура', + 3, + 'ФГОС3+', + 1, + 'направление', + 0 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Биологические науки', + '06.06.01', + 'Аспирантура', + 3, + 'ФГОС3+', + 1, + 'направление', + 0 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Электроника и наноэлектроника', + '11.04.04', + 'Магистратура', + 2, + 'ФГОС3+', + 1, + 'направление', + 0 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Электроника и наноэлектроника', + '11.03.04', + 'Бакалавриат', + 0, + 'ФГОС3+', + 1, + 'направление', + 0 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Авиационная и ракетно-космическая техника', + '24.06.01', + 'Аспирантура', + 3, + 'ФГОС3+', + 1, + 'направление', + 0 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Биология', + '06.03.01', + 'Бакалавриат', + 0, + 'ФГОС3+', + 1, + 'направление', + 0 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Лечебное дело', + '31.05.01', + 'Специалитет', + 1, + 'ФГОС3+', + 1, + 'специальность', + 1 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Менеджмент организации', + '080507', + 'Специалитет', + 1, + 'ГОС2', + 0, + 'специальность', + 1 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Приборостроение', + '12.03.01', + 'Бакалавриат', + 0, + 'ФГОС3+', + 1, + 'направление', + 0 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Химия', + '04.03.01', + 'Бакалавриат', + 0, + 'ФГОС3+', + 1, + 'направление', + 0 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Химия, физика и механика материалов', + '04.04.02', + 'Магистратура', + 2, + 'ФГОС3+', + 1, + 'направление', + 0 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Экология и природопользование', + '05.03.06', + 'Бакалавриат', + 0, + 'ФГОС3+', + 1, + 'направление', + 0 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Атомные электрические станции и установки', + '140404', + 'Специалитет', + 1, + 'ГОС2', + 0, + 'специальность', + 1 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Ядерная энергетика и теплофизика', + '14.03.01', + 'Бакалавриат', + 0, + 'ФГОС3+', + 1, + 'направление', + 0 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Технология редких, рассеянных и радиоактивных элементов', + '05.17.02', + 'Аспирантура', + 3, + 'ГОС2', + 0, + 'специальность', + 1 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Технология электрохимических процессов и защита от коррозии', + '05.17.03', + 'Аспирантура', + 3, + 'ГОС2', + 0, + 'специальность', + 1 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Химическая технология топлива и высокоэнергетических веществ', + '05.17.07', + 'Аспирантура', + 3, + 'ГОС2', + 0, + 'специальность', + 1 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Фотоника и оптоинформатика', + '12.04.03', + 'Магистратура', + 2, + 'ФГОС3+', + 1, + 'направление', + 0 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Биотехнические системы и технологии', + '12.03.04', + 'Бакалавриат', + 0, + 'ФГОС3+', + 1, + 'направление', + 0 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Фотоника и оптоинформатика', + '12.03.03', + 'Бакалавриат', + 0, + 'ФГОС3+', + 1, + 'направление', + 0 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Высокотехнологические плазменные и энергетические установки', + '16.03.02', + 'Бакалавриат', + 0, + 'ФГОС3+', + 1, + 'направление', + 0 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Высокотехнологические плазменные и энергетические установки', + '16.04.02', + 'Магистратура', + 2, + 'ФГОС3+', + 1, + 'направление', + 0 +);
+
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + 'Мехатроника и робототехника', + '15.03.06', + 'Бакалавриат', + 0, + 'ФГОС3+', + 1, + 'направление', + 0 +);
+ + diff --git a/LR1/specialities.xsl b/LR1/specialities.xsl new file mode 100644 index 0000000..7b7dd57 --- /dev/null +++ b/LR1/specialities.xsl @@ -0,0 +1,299 @@ + + + + + + + + + + + + + + +
Нужен: NOT NULL
+
+
+ + + + + NOT NULL + + + + + + + + + CHECK ( + + IN ( + + ' + + ' + + , + + + )) + + + + + + + + + CHECK ( + + IN ( + + + + , + + + )) + + + + + +
+
Анализ поля id
+
Тип данных: integer
+
Число пустых:
+ +
+
+ + + +
+
Анализ поля name
+
Тип данных: Текст
+
Самый длинный элемент: + + + , длина: + +
+
Число пустых:
+ +
+
+ + + +
+
Анализ поля code
+
Тип данных: Текст
+
Самый длинный элемент: + + + , длина: + +
+
Число пустых:
+ +
+
+ + + +
+
Анализ поля level
+
Тип данных: Текст
+
Самый длинный элемент: + + + , длина: + +
+
Число пустых:
+ +
Нужен: CHECK (level IN( + + '' + , + + ))
+
+
+ + + +
+
Анализ поля level-id
+
Тип данных: integer
+
Число пустых:
+ +
Нужен: CHECK (level_id IN( + + '' + , + + ))
+
+
+ + + +
+
Анализ поля generation
+
Тип данных: Текст
+
Самый длинный элемент: + + + , длина: + +
+
Число пустых:
+ +
Нужен: CHECK (generation IN( + + '' + , + + ))
+
+
+ + + +
+
Анализ поля generation-id
+
Тип данных: integer
+
Число пустых:
+ +
Нужен: CHECK (generation_id IN( + + '' + , + + ))
+
+
+ + + +
+
Анализ поля type
+
Тип данных: Текст
+
Самый длинный элемент: + + + , длина: + +
+
Число пустых:
+ +
Нужен: CHECK (type IN( + + '' + , + + ))
+
+
+ + + +
+
Анализ поля type-id
+
Тип данных: integer
+
Число пустых:
+ +
Нужен: CHECK (type_id IN( + + '' + , + + ))
+
+
+ + + + + + Анализ данных файла specialities.xml + + + +

Анализ данных файла specialities.xml (specialities.xml)

+ + + + + + + + + + + +

SQL-файл

+
DROP TABLE IF EXISTS specialities; +DROP SEQUENCE IF EXISTS specialities_id_seq; + +CREATE SEQUENCE specialities_id_seq + START WITH 1 + INCREMENT BY 1; + +CREATE TABLE specialities ( + id INTEGER, + + name VARCHAR( + ), + + code VARCHAR( + ), + + level VARCHAR( + ), + + level_id INTEGER, + + generation VARCHAR( + ), + + generation_id INTEGER, + + type VARCHAR( + ), + + type_id INTEGER, + CONSTRAINT pk_specialities PRIMARY KEY (id) +);
+ +

SQL: INSERT-запросы, сформированные из XML

+ +
INSERT INTO specialities (id, name, code, level, level_id, generation, generation_id, type, type_id) +VALUES ( + nextval('specialities_id_seq'), + '', + '', + '', + , + '', + , + '', + +);
+
+ + +
+
diff --git a/LR1/transform.py b/LR1/transform.py new file mode 100644 index 0000000..aa3f5f1 --- /dev/null +++ b/LR1/transform.py @@ -0,0 +1,14 @@ +from lxml import etree + +xml = etree.parse("specialities.xml") + +xslt = etree.parse("specialities.xsl") + +transform = etree.XSLT(xslt) + +result = transform(xml) + +with open("specialities.html", "wb") as f: + f.write(etree.tostring(result, pretty_print=True, encoding="UTF-8")) + +print("HTML успешно создан: specialities.html") diff --git a/LR2/irfm_lr2.ipynb b/LR2/irfm_lr2.ipynb new file mode 100644 index 0000000..b918549 --- /dev/null +++ b/LR2/irfm_lr2.ipynb @@ -0,0 +1,681 @@ +{ + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "name": "python3", + "language": "python" + }, + "language_info": { + "name": "python", + "version": "3.12.13", + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "pygments_lexer": "ipython3", + "mimetype": "text/x-python", + "nbconvert_exporter": "python", + "file_extension": ".py" + }, + "colab": { + "provenance": [] + } + }, + "nbformat": 4, + "nbformat_minor": 5, + "cells": [ + { + "cell_type": "code", + "id": "2e2f8a4c-7063-4650-ace5-8f230c8d994a", + "metadata": { + "id": "5tecyK1Y5y_0" + }, + "execution_count": 1, + "source": [ + "import pandas as pd\n", + "import seaborn as sns\n", + "import matplotlib.pyplot as plt\n", + "import numpy as np\n", + "from scipy.stats import pearsonr, spearmanr, kendalltau\n", + "import sqlite3\n", + "import kagglehub\n" + ], + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "/home/ada/Documents/Files/files_mephi/Работы/ИРФМ/.venv/lib/python3.12/site-packages/tqdm/auto.py:21: TqdmWarning: IProgress not\n", + " found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html\n", + " from .autonotebook import tqdm as notebook_tqdm\n" + ] + } + ] + }, + { + "cell_type": "code", + "id": "8f16c784-75c9-44a1-8f9c-6555bdf38a08", + "metadata": { + "id": "-kxc18fy5gMU", + "colab": { + "base_uri": "https://localhost:8080/" + }, + "outputId": "3db947c3-f4c3-4449-91eb-1a5722ba2deb" + }, + "execution_count": 2, + "source": [ + "# https://www.kaggle.com/datasets/ziya07/financial-transaction-dataset-for-risk-prediction?select=financial_transactions.csv\n", + "dataset_dir = kagglehub.dataset_download(\n", + " \"mchirico/montcoalert\",\n", + " output_dir=\"../data/montcoalert\",\n", + " # force_download=True, # раскомментируйте, если нужно перекачать датасет\n", + ")\n", + "\n", + "print(\"Path to dataset files:\", dataset_dir)\n" + ], + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "Path to dataset files: ../data/montcoalert\n" + ] + } + ] + }, + { + "cell_type": "code", + "id": "8228deb7-1ef3-4b6a-b16d-795c5b80a10b", + "metadata": { + "id": "jjxxafuj5twF", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 597 + }, + "outputId": "07ffb386-df17-4830-daa5-20e36a68e0c5" + }, + "execution_count": 3, + "source": [ + "import os\n", + "\n", + "df = pd.read_csv(os.path.join(dataset_dir, \"911.csv\"))\n", + "df\n" + ], + "outputs": [] + }, + { + "cell_type": "code", + "id": "bcd5db7c-b149-4e05-a1c5-d5df628572d4", + "metadata": { + "id": "JFENAQ6x6M-2", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 424 + }, + "outputId": "69f2c9f2-256e-4184-f6cc-7895b3065557" + }, + "execution_count": 4, + "source": [ + "df = df.drop(columns=['desc', 'zip', 'addr', 'e'])\n", + "df['town'] = df['twp']\n", + "df = df.drop(columns=['twp'])\n", + "df\n" + ], + "outputs": [] + }, + { + "cell_type": "code", + "id": "8322a532-24e5-406f-b019-cbf264676259", + "metadata": { + "id": "kjx88uH06yXh", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 241 + }, + "outputId": "b4525822-dc37-4baf-ef06-2429efb9d9b9" + }, + "execution_count": 5, + "source": [ + "df.isnull().sum()\n" + ], + "outputs": [ + { + "output_type": "display_data", + "data": { + "text/plain": [ + "lat 0\n", + "lng 0\n", + "title 0\n", + "timeStamp 0\n", + "town 293\n", + "dtype: int64\n" + ] + }, + "metadata": {} + } + ] + }, + { + "cell_type": "code", + "id": "9ea98f73-7ab5-4b31-a3c7-d4031b65636c", + "metadata": { + "id": "CVwu4mZY7j38", + "outputId": "10c839ff-e230-4429-8ec1-dd1160e0e52a", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 241 + } + }, + "execution_count": 6, + "source": [ + "df = df.dropna()\n", + "df.isnull().sum()\n" + ], + "outputs": [ + { + "output_type": "display_data", + "data": { + "text/plain": [ + "lat 0\n", + "lng 0\n", + "title 0\n", + "timeStamp 0\n", + "town 0\n", + "dtype: int64\n" + ] + }, + "metadata": {} + } + ] + }, + { + "cell_type": "code", + "id": "1e0859b5-80a7-45d3-b681-4e3f5e97944f", + "metadata": { + "id": "BVziGRoT74je", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 300 + }, + "outputId": "cb96454a-a04b-4ea0-d044-981fdddcc008" + }, + "execution_count": 7, + "source": [ + "df.describe()\n", + "\n", + "# штат Пенсильвания (PA) находится примерно в следующих координатах:\n", + "# Широта (lat): от 39.7° N до 42.5° N\n", + "# Долгота (lng): от -80.5° W до -74.7° W\n" + ], + "outputs": [] + }, + { + "cell_type": "code", + "id": "6931cd95-26a2-43da-98f0-90d69e3a7afe", + "metadata": { + "id": "YZyG4DIl8uQE", + "outputId": "0f7ec0ed-aeed-426b-f367-640113d8057d", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 300 + } + }, + "execution_count": 8, + "source": [ + "df_clean = df[\n", + " (df['lat'].between(39.7, 42.5)) &\n", + " (df['lng'].between(-80.5, -74.7))\n", + "]\n", + "df_clean.describe()\n" + ], + "outputs": [] + }, + { + "cell_type": "code", + "id": "76fd2b05-51a2-420d-a7c4-6a41cf922cfb", + "metadata": { + "id": "9UHU8d6s8597", + "outputId": "f822f2bb-1bcb-44b2-9371-e1bd0480a509", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 424 + } + }, + "execution_count": 9, + "source": [ + "df_grouped = df_clean.groupby('town').size().reset_index(name='count')\n", + "df_grouped = df_grouped[df_grouped['count'] >= 5]\n", + "df_grouped.sort_values(by='count', ascending=False)\n" + ], + "outputs": [] + }, + { + "cell_type": "code", + "id": "7204f62a-c6a3-4b60-8a6c-ae055c771276", + "metadata": { + "id": "8XxEu-5I_6oz", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 526 + }, + "outputId": "831e0639-0ffe-4a9d-e309-e6d19745375a" + }, + "execution_count": 10, + "source": [ + "plt.figure(figsize=(8, 6))\n", + "sns.boxplot(y=df_grouped['count'])\n", + "plt.title('Распределение количества вызовов по городам')\n", + "plt.ylabel('Количество вызовов')\n", + "plt.show()\n" + ], + "outputs": [] + }, + { + "cell_type": "code", + "id": "8e69711f-ea64-4139-bd42-bab3ffe02750", + "metadata": { + "id": "hL-4vAqy_gsN", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 300 + }, + "outputId": "50f07e22-0a9c-4b43-87a4-94c18e7601e6" + }, + "execution_count": 11, + "source": [ + "df_grouped.describe()\n" + ], + "outputs": [] + }, + { + "cell_type": "code", + "id": "2f9d95cf-4449-4b59-918e-7662c1eba9da", + "metadata": { + "id": "lFjeZjICF-C-", + "colab": { + "base_uri": "https://localhost:8080/" + }, + "outputId": "9c2c08fa-ae97-4b74-f3a4-92148999c037" + }, + "execution_count": 12, + "source": [ + "df_grouped = df_grouped.sort_values(by='count')\n", + "counts = df_grouped['count'].values\n", + "towns = df_grouped['town'].values\n", + "n = len(counts)\n", + "\n", + "total_range = counts.max() - counts.min() # Размах\n", + "gap_threshold = 0.1 * total_range # Порог\n", + "\n", + "# Отсекаем нижние и верхние 10% по порядку наблюдений\n", + "bottom_10_idx = int(n * 0.10)\n", + "top_10_idx = int(n * 0.90)\n", + "\n", + "towns_to_drop = set()\n", + "\n", + "# Проверка нижних 10% (идем от центра к краям)\n", + "# Ищем разрыв между y (индекс i) и соседом ближе к центру (индекс i+1)\n", + "for i in range(bottom_10_idx, -1, -1): # (6, 5, 4, 3, 2, 1, 0)\n", + " if i + 1 < n:\n", + " gap = counts[i+1] - counts[i]\n", + " if gap > gap_threshold:\n", + " # Нашли разрыв. Удаляем всё от y до края\n", + " for j in range(i, -1, -1):\n", + " towns_to_drop.add(towns[j])\n", + " break\n", + "\n", + "# Проверка верхних 10% (идем от центра к краям)\n", + "# Ищем разрыв между y (индекс i) и соседом ближе к центру (индекс i-1)\n", + "for i in range(top_10_idx, n):\n", + " if i - 1 >= 0:\n", + " gap = counts[i] - counts[i-1]\n", + " if gap > gap_threshold:\n", + " # Нашли разрыв. Удаляем всё от y до края\n", + " for j in range(i, n):\n", + " towns_to_drop.add(towns[j])\n", + " break\n", + "\n", + "towns_to_drop\n" + ], + "outputs": [ + { + "output_type": "display_data", + "data": { + "text/plain": [ + "{'LOWER MERION'}\n" + ] + }, + "metadata": {} + } + ] + }, + { + "cell_type": "code", + "id": "401fa973-2d94-440b-ae9a-65b7fa31c5e2", + "metadata": { + "id": "2Nch3p_tHwOf", + "colab": { + "base_uri": "https://localhost:8080/" + }, + "outputId": "cd95841f-df8d-496f-a39e-a6c4877e067a" + }, + "execution_count": 13, + "source": [ + "df_clean = df_clean[~df_clean['town'].isin(towns_to_drop)]\n", + "\n", + "df_clean.info()\n" + ], + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "\n", + "Index: 607557 entries, 0 to 663520\n", + "Data columns (total 5 columns):\n", + " # Column Non-Null Count Dtype\n", + "--- ------ -------------- -----\n", + " 0 lat 607557 non-null float64\n", + " 1 lng 607557 non-null float64\n", + " 2 title 607557 non-null str\n", + " 3 timeStamp 607557 non-null str\n", + " 4 town 607557 non-null str\n", + "dtypes: float64(2), str(3)\n", + "memory usage: 27.8 MB\n" + ] + } + ] + }, + { + "cell_type": "code", + "id": "a71317e7-7d15-4878-88f0-f201c15bf64d", + "metadata": { + "id": "pORHOk6xAe6b", + "outputId": "4151cbca-371f-4cab-d8e1-b91e9712703a", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 526 + } + }, + "execution_count": 14, + "source": [ + "df_clean_grouped = df_clean.groupby('town').size().reset_index(name='count')\n", + "plt.figure(figsize=(8, 6))\n", + "sns.boxplot(y=df_clean_grouped['count'])\n", + "plt.title('Распределение количества вызовов по городам')\n", + "plt.ylabel('Количество вызовов')\n", + "plt.show()\n" + ], + "outputs": [] + }, + { + "cell_type": "code", + "id": "29af2c22-e4b2-401d-80bc-43c812867c4e", + "metadata": { + "id": "xFeEAU27DVWV", + "outputId": "d26f3a5f-6857-45e7-fc33-dce0818419f1", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 300 + } + }, + "execution_count": 15, + "source": [ + "df_clean_grouped.describe()\n" + ], + "outputs": [] + }, + { + "cell_type": "code", + "id": "6c425257-1b4d-41e8-8c17-1b26ade1bbeb", + "metadata": { + "id": "bace27bc", + "colab": { + "base_uri": "https://localhost:8080/" + }, + "outputId": "6f3cd65b-abb6-4e9d-c880-c0d3162bb064" + }, + "execution_count": 16, + "source": [ + "df_clean['timeStamp'] = pd.to_datetime(df_clean['timeStamp'])\n", + "df_clean.info()\n" + ], + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "\n", + "Index: 607557 entries, 0 to 663520\n", + "Data columns (total 5 columns):\n", + " # Column Non-Null Count Dtype\n", + "--- ------ -------------- -----\n", + " 0 lat 607557 non-null float64\n", + " 1 lng 607557 non-null float64\n", + " 2 title 607557 non-null str\n", + " 3 timeStamp 607557 non-null datetime64[us]\n", + " 4 town 607557 non-null str\n", + "dtypes: datetime64[us](1), float64(2), str(2)\n", + "memory usage: 27.8 MB\n" + ] + } + ] + }, + { + "cell_type": "code", + "id": "cc0a488b-ce3f-4860-ac73-cc086623ad68", + "metadata": { + "id": "9d0eeaf8", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 206 + }, + "outputId": "d158ac82-85e5-464c-854b-f1264a32406b" + }, + "execution_count": 17, + "source": [ + "df_clean['hour'] = df_clean['timeStamp'].dt.hour\n", + "df_clean.head()\n" + ], + "outputs": [] + }, + { + "cell_type": "code", + "id": "36b114ae-9647-4555-84ad-96cc3ca7ace4", + "metadata": { + "id": "91a1edc3", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 206 + }, + "outputId": "04806088-c1be-4fae-e382-0240b286ffe5" + }, + "execution_count": 18, + "source": [ + "calls_by_hour = df_clean.groupby('hour').size().reset_index(name='count')\n", + "calls_by_hour.head()\n" + ], + "outputs": [] + }, + { + "cell_type": "code", + "id": "153435e0-d311-47ce-9934-527aa4918935", + "metadata": { + "id": "0ef31758", + "outputId": "4a0e5512-4174-4037-f749-697c2ca60963", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 607 + } + }, + "execution_count": 19, + "source": [ + "plt.figure(figsize=(10, 6))\n", + "sns.lineplot(x='hour', y='count', data=calls_by_hour, marker='o', label='Calls Count')\n", + "plt.title('Общее количество вызовов 911 по часам суток')\n", + "plt.xlabel('Час суток')\n", + "plt.ylabel('Количество вызовов')\n", + "plt.xticks(calls_by_hour['hour'])\n", + "plt.grid(True, linestyle='--', alpha=0.7)\n", + "plt.legend()\n", + "plt.tight_layout()\n", + "plt.show()\n" + ], + "outputs": [] + }, + { + "cell_type": "code", + "id": "fe76bee3-d0a0-4dad-9867-ce6c3c711d08", + "metadata": { + "id": "jg4PAmmUQ_9o", + "colab": { + "base_uri": "https://localhost:8080/" + }, + "outputId": "512127d4-5308-419f-a7dd-cab7399473af" + }, + "execution_count": 20, + "source": [ + "def analyze_correlations(df, col1, col2):\n", + " x = df[col1].values\n", + " y = df[col2].values\n", + "\n", + " results = {\n", + " 'Пирсон': pearsonr(x, y),\n", + " 'Спирмен': spearmanr(x, y),\n", + " 'Кендалл': kendalltau(x, y)\n", + " }\n", + "\n", + " for method, (corr, p_value) in results.items():\n", + " abs_corr = abs(corr)\n", + "\n", + " if method == 'Кендалл':\n", + " thresholds = [0.2, 0.4, 0.6, 0.8]\n", + " else:\n", + " thresholds = [0.3, 0.5, 0.7, 0.9]\n", + "\n", + " if abs_corr < thresholds[0]:\n", + " strength = \"слабая (или отсутствует)\"\n", + " elif abs_corr < thresholds[1]:\n", + " strength = \"умеренная\"\n", + " elif abs_corr < thresholds[2]:\n", + " strength = \"заметная\"\n", + " elif abs_corr < thresholds[3]:\n", + " strength = \"высокая\"\n", + " else:\n", + " strength = \"весьма высокая\"\n", + "\n", + " status = \"Значима\" if p_value < 0.05 else \"НЕ значима\"\n", + " direction = \"положительная\" if corr > 0 else \"отрицательная\"\n", + "\n", + " print(f\"[{method}]\")\n", + " print(f\" Коэффициент: {corr:.4f} ({direction})\")\n", + " print(f\" P-value: {p_value:.4e} ({status})\")\n", + "\n", + " if p_value < 0.05:\n", + " print(f\" Вывод: Наблюдается {strength} связь.\")\n", + " else:\n", + " print(f\" Вывод: Недостаточно данных для подтверждения связи.\")\n", + " print(\"-\" * 40)\n", + "\n", + "analyze_correlations(calls_by_hour, 'hour', 'count')\n" + ], + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "[Пирсон]\n", + " Коэффициент: 0.5114 (положительная)\n", + " P-value: 1.0638e-02 (Значима)\n", + " Вывод: Наблюдается заметная связь.\n", + "----------------------------------------\n", + "[Спирмен]\n", + " Коэффициент: 0.4991 (положительная)\n", + " P-value: 1.3028e-02 (Значима)\n", + " Вывод: Наблюдается умеренная связь.\n", + "----------------------------------------\n", + "[Кендалл]\n", + " Коэффициент: 0.3623 (положительная)\n", + " P-value: 1.2905e-02 (Значима)\n", + " Вывод: Наблюдается умеренная связь.\n", + "----------------------------------------\n" + ] + } + ] + }, + { + "cell_type": "code", + "id": "8ee4c692-afde-4bad-b7a5-bb0dda83a5aa", + "metadata": {}, + "execution_count": 24, + "source": [ + "conn = sqlite3.connect('../data/calls.db')\n", + "df_clean.to_sql('calls', conn, if_exists='replace', index=False)\n", + "conn.close()\n" + ], + "outputs": [] + }, + { + "cell_type": "code", + "id": "4e3cb3c7-62d9-4d2b-b7d0-5d209464fac2", + "metadata": { + "id": "1e5d291c", + "outputId": "783c15e5-5dce-46e2-c666-1f917a832051", + "colab": { + "base_uri": "https://localhost:8080/" + } + }, + "execution_count": 25, + "source": [ + "conn = sqlite3.connect('../data/calls.db')\n", + "query = \"SELECT * FROM calls LIMIT 5\"\n", + "curr = conn.cursor()\n", + "\n", + "data = curr.execute(query).fetchall()\n", + "\n", + "conn.close()\n", + "data\n" + ], + "outputs": [ + { + "output_type": "display_data", + "data": { + "text/plain": [ + "[(40.2978759,\n", + " -75.5812935,\n", + " 'EMS: BACK PAINS/INJURY',\n", + " '2015-12-10 17:10:52',\n", + " 'NEW HANOVER',\n", + " 17),\n", + " (40.2580614,\n", + " -75.2646799,\n", + " 'EMS: DIABETIC EMERGENCY',\n", + " '2015-12-10 17:29:21',\n", + " 'HATFIELD TOWNSHIP',\n", + " 17),\n", + " (40.1211818,\n", + " -75.3519752,\n", + " 'Fire: GAS-ODOR/LEAK',\n", + " '2015-12-10 14:39:21',\n", + " 'NORRISTOWN',\n", + " 14),\n", + " (40.116153,\n", + " -75.343513,\n", + " 'EMS: CARDIAC EMERGENCY',\n", + " '2015-12-10 16:47:36',\n", + " 'NORRISTOWN',\n", + " 16),\n", + " (40.251492,\n", + " -75.6033497,\n", + " 'EMS: DIZZINESS',\n", + " '2015-12-10 16:56:52',\n", + " 'LOWER POTTSGROVE',\n", + " 16)]\n" + ] + }, + "metadata": {} + } + ] + } + ] +} \ No newline at end of file diff --git a/LR3/cli_client.py b/LR3/cli_client.py new file mode 100644 index 0000000..e8662a1 --- /dev/null +++ b/LR3/cli_client.py @@ -0,0 +1,168 @@ +import json + +import requests + + +BASE_URL = "http://127.0.0.1:5000" + + +def ask_format() -> str: + """Запрашивает желаемый формат ответа и возвращает json или wsdl.""" + raw = input("Формат ответа (json/wsdl) [json]: ").strip().lower() + return raw if raw in {"json", "wsdl"} else "json" + + +def print_response(resp: requests.Response) -> None: + """Печатает HTTP-статус и тело ответа в JSON или сыром виде.""" + print(f"\nHTTP {resp.status_code}") + try: + print(json.dumps(resp.json(), ensure_ascii=False, indent=2)) + except ValueError: + print(resp.text) + + +def input_payload() -> dict: + """Собирает поля объекта из консоли и возвращает payload для POST/PUT.""" + print("Оставьте поле пустым, если не хотите его передавать") + payload = {} + + lat = input("lat: ").strip() + if lat: + payload["lat"] = float(lat) + + lng = input("lng: ").strip() + if lng: + payload["lng"] = float(lng) + + title = input("title: ").strip() + if title: + payload["title"] = title + + timestamp = input("timeStamp (YYYY-MM-DD HH:MM:SS): ").strip() + if timestamp: + payload["timeStamp"] = timestamp + + town = input("town: ").strip() + if town: + payload["town"] = town + + hour = input("hour (0-23): ").strip() + if hour: + payload["hour"] = int(hour) + + return payload + + +def list_calls() -> None: + """Запрашивает и выводит пагинированный список объектов calls.""" + page = input("page [1]: ").strip() or "1" + per_page = input("per_page [20]: ").strip() or "20" + fmt = ask_format() + + resp = requests.get( + f"{BASE_URL}/api/calls", + params={"page": page, "per_page": per_page, "format": fmt}, + timeout=30, + ) + print_response(resp) + + +def get_call() -> None: + """Запрашивает и выводит один объект calls по ID.""" + call_id = input("ID объекта: ").strip() + fmt = ask_format() + resp = requests.get( + f"{BASE_URL}/api/calls/{call_id}", params={"format": fmt}, timeout=30 + ) + print_response(resp) + + +def create_call() -> None: + """Создает новый объект calls из введенных пользователем данных.""" + payload = input_payload() + fmt = ask_format() + resp = requests.post( + f"{BASE_URL}/api/calls", params={"format": fmt}, json=payload, timeout=30 + ) + print_response(resp) + + +def update_call() -> None: + """Обновляет существующий объект calls по ID введенными полями.""" + call_id = input("ID объекта: ").strip() + payload = input_payload() + fmt = ask_format() + resp = requests.put( + f"{BASE_URL}/api/calls/{call_id}", + params={"format": fmt}, + json=payload, + timeout=30, + ) + print_response(resp) + + +def delete_call() -> None: + """Удаляет объект calls по ID и выводит результат операции.""" + call_id = input("ID объекта: ").strip() + fmt = ask_format() + resp = requests.delete( + f"{BASE_URL}/api/calls/{call_id}", params={"format": fmt}, timeout=30 + ) + print_response(resp) + + +def stats_by_hour() -> None: + """Запрашивает статистику количества обращений по выбранному часу.""" + hour = input("Час (0-23): ").strip() + fmt = ask_format() + resp = requests.get( + f"{BASE_URL}/api/stats/hour/{hour}", params={"format": fmt}, timeout=30 + ) + print_response(resp) + + +def show_wsdl() -> None: + """Получает и выводит WSDL-описание API.""" + resp = requests.get(f"{BASE_URL}/api/wsdl", timeout=30) + print_response(resp) + + +def menu() -> None: + """Запускает интерактивное меню CLI и обрабатывает выбор пользователя.""" + actions = { + "1": ("Список объектов", list_calls), + "2": ("Один объект по ID", get_call), + "3": ("Добавить объект", create_call), + "4": ("Изменить объект", update_call), + "5": ("Удалить объект", delete_call), + "6": ("Общее число обращений в час", stats_by_hour), + "7": ("Показать WSDL", show_wsdl), + "0": ("Выход", None), + } + + while True: + print("\n=== CLI для API LR3 ===") + for key, (name, _) in actions.items(): + print(f"{key}. {name}") + + choice = input("Выберите метод: ").strip() + action = actions.get(choice) + + if not action: + print("Неизвестный пункт меню") + continue + + if choice == "0": + print("Завершение работы") + break + + try: + action[1]() + except requests.RequestException as exc: + print(f"Ошибка запроса: {exc}") + except ValueError as exc: + print(f"Ошибка ввода: {exc}") + + +if __name__ == "__main__": + menu() diff --git a/LR3/irfm_lr3.py b/LR3/irfm_lr3.py new file mode 100644 index 0000000..2c71a91 --- /dev/null +++ b/LR3/irfm_lr3.py @@ -0,0 +1,300 @@ +import sqlite3 +from pathlib import Path +from xml.etree.ElementTree import Element, SubElement, tostring + +from flask import Flask, Response, jsonify, request + +BASE_DIR = Path(__file__).resolve().parent.parent +DB_PATH = BASE_DIR / "data" / "calls.db" + +app = Flask(__name__) + + +ALLOWED_FIELDS = ("lat", "lng", "title", "timeStamp", "town", "hour") + + +def parse_positive_int(raw_value: str, field_name: str) -> tuple[int | None, str | None]: + """Преобразует строку в положительное целое число или возвращает текст ошибки.""" + try: + value = int(raw_value) + except (TypeError, ValueError): + return None, f"{field_name} должен быть целым числом" + + if value <= 0: + return None, f"{field_name} должен быть положительным целым числом" + + return value, None + + +def get_db_connection() -> sqlite3.Connection: + """Создает и возвращает подключение к SQLite с доступом к колонкам по имени.""" + conn = sqlite3.connect(DB_PATH) + conn.row_factory = sqlite3.Row + return conn + + +def wants_wsdl() -> bool: + """Проверяет, запросил ли клиент XML/WSDL-формат через query-параметр format.""" + return request.args.get("format", "json").lower() == "wsdl" + + +def dict_to_xml(payload: dict) -> bytes: + """Преобразует словарь (включая вложенные dict/list) в XML-документ.""" + root = Element("response") + + for key, value in payload.items(): + if isinstance(value, dict): + obj_node = SubElement(root, str(key)) + for child_key, child_value in value.items(): + child = SubElement(obj_node, str(child_key)) + child.text = "" if child_value is None else str(child_value) + continue + + if isinstance(value, list): + list_node = SubElement(root, str(key)) + for item in value: + item_node = SubElement(list_node, "item") + if isinstance(item, dict): + for item_key, item_value in item.items(): + child = SubElement(item_node, str(item_key)) + child.text = "" if item_value is None else str(item_value) + else: + item_node.text = "" if item is None else str(item) + continue + + node = SubElement(root, str(key)) + node.text = "" if value is None else str(value) + + return tostring(root, encoding="utf-8", xml_declaration=True) + + +def format_response(payload: dict, status: int = 200) -> Response: + """Формирует ответ API: XML при format=wsdl, иначе JSON.""" + if wants_wsdl(): + xml_payload = dict_to_xml(payload) + return Response(xml_payload, status=status, mimetype="application/wsdl+xml") + resp = jsonify(payload) + resp.status_code = status + return resp + + +def fetch_call_by_id(conn: sqlite3.Connection, call_id: int): + """Возвращает запись calls по rowid или None, если запись не найдена.""" + query = """ + SELECT rowid AS id, lat, lng, title, timeStamp, town, hour + FROM calls + WHERE rowid = ? + """ + return conn.execute(query, (call_id,)).fetchone() + + +def parse_payload() -> tuple[dict, str | None]: + """Читает JSON-тело запроса, валидирует и оставляет только разрешенные поля.""" + if not request.is_json: + return {}, "Body должен быть в формате JSON" + + payload = request.get_json(silent=True) + if not isinstance(payload, dict): + return {}, "Некорректный JSON-объект" + + filtered = {k: payload[k] for k in ALLOWED_FIELDS if k in payload} + if not filtered: + return {}, "Не переданы поля для записи" + + return filtered, None + + +@app.get("/api/calls") +def list_calls() -> Response: + """Возвращает пагинированный список объектов calls.""" + page = max(request.args.get("page", default=1, type=int), 1) + per_page = min(max(request.args.get("per_page", default=20, type=int), 1), 100) + offset = (page - 1) * per_page + + conn = get_db_connection() + total = conn.execute("SELECT COUNT(*) AS total FROM calls").fetchone()["total"] + rows = conn.execute( + """ + SELECT rowid AS id, lat, lng, title, timeStamp, town, hour + FROM calls + ORDER BY rowid + LIMIT ? OFFSET ? + """, + (per_page, offset), + ).fetchall() + conn.close() + + payload = { + "page": page, + "per_page": per_page, + "total": total, + "items": [dict(row) for row in rows], + } + return format_response(payload) + + +@app.get("/api/calls/") +def get_call(call_id: int) -> Response: + """Возвращает один объект calls по его идентификатору.""" + if call_id <= 0: + return format_response({"error": "id должен быть положительным целым числом"}, status=400) + + conn = get_db_connection() + row = fetch_call_by_id(conn, call_id) + conn.close() + + if row is None: + return format_response({"error": "Объект не найден"}, status=404) + + return format_response({"item": dict(row)}) + + +@app.post("/api/calls") +def create_call() -> Response: + """Создает новый объект calls из данных JSON-тела запроса.""" + payload, error = parse_payload() + if error: + return format_response({"error": error}, status=400) + + columns = ", ".join(payload.keys()) + placeholders = ", ".join(["?"] * len(payload)) + + conn = get_db_connection() + cur = conn.execute( + f"INSERT INTO calls ({columns}) VALUES ({placeholders})", + tuple(payload.values()), + ) + conn.commit() + created_id = cur.lastrowid + if created_id is None: + conn.close() + return format_response({"error": "Не удалось создать объект"}, status=500) + + created_row = fetch_call_by_id(conn, int(created_id)) + conn.close() + if created_row is None: + return format_response( + {"error": "Не удалось получить созданный объект"}, status=500 + ) + + return format_response({"item": dict(created_row)}, status=201) + + +@app.put("/api/calls/") +def update_call(call_id: int) -> Response: + """Обновляет существующий объект calls по id частичным набором полей.""" + if call_id <= 0: + return format_response({"error": "id должен быть положительным целым числом"}, status=400) + + payload, error = parse_payload() + if error: + return format_response({"error": error}, status=400) + + assignments = ", ".join([f"{key} = ?" for key in payload.keys()]) + values = tuple(payload.values()) + (call_id,) + + conn = get_db_connection() + exists = fetch_call_by_id(conn, call_id) + if exists is None: + conn.close() + return format_response({"error": "Объект не найден"}, status=404) + + conn.execute(f"UPDATE calls SET {assignments} WHERE rowid = ?", values) + conn.commit() + updated_row = fetch_call_by_id(conn, call_id) + conn.close() + if updated_row is None: + return format_response( + {"error": "Не удалось получить обновленный объект"}, status=500 + ) + + return format_response({"item": dict(updated_row)}) + + +@app.delete("/api/calls/") +def delete_call(call_id: int) -> Response: + """Удаляет объект calls по id и возвращает статус операции.""" + if call_id <= 0: + return format_response({"error": "id должен быть положительным целым числом"}, status=400) + + conn = get_db_connection() + exists = fetch_call_by_id(conn, call_id) + if exists is None: + conn.close() + return format_response({"error": "Объект не найден"}, status=404) + + conn.execute("DELETE FROM calls WHERE rowid = ?", (call_id,)) + conn.commit() + conn.close() + + return format_response({"message": f"Объект {call_id} удален"}) + + +@app.get("/api/stats/hour/") +def stats_by_hour(hour: int) -> Response: + """Возвращает количество обращений в таблице calls для заданного часа (0-23).""" + if hour < 0 or hour > 23: + return format_response({"error": "Час должен быть от 0 до 23"}, status=400) + + conn = get_db_connection() + total = conn.execute( + "SELECT COUNT(*) AS total FROM calls WHERE hour = ?", (hour,) + ).fetchone()["total"] + conn.close() + + payload = { + "hour": hour, + "total_calls": total, + } + return format_response(payload) + + +@app.route("/api/calls/", methods=["GET", "PUT", "DELETE"]) +def invalid_call_id(call_id: str) -> Response: + """Возвращает понятную ошибку, если id в URL не является корректным числом.""" + _, error = parse_positive_int(call_id, "id") + if error: + return format_response({"error": error}, status=400) + return format_response({"error": "Некорректный запрос"}, status=400) + + +@app.get("/api/stats/hour/") +def invalid_hour(hour: str) -> Response: + """Возвращает понятную ошибку, если hour в URL задан некорректно.""" + try: + parsed_hour = int(hour) + except (TypeError, ValueError): + return format_response({"error": "Час должен быть целым числом"}, status=400) + + if parsed_hour < 0 or parsed_hour > 23: + return format_response({"error": "Час должен быть от 0 до 23"}, status=400) + + return format_response({"error": "Некорректный запрос"}, status=400) + + +@app.get("/api/wsdl") +def wsdl_description() -> Response: + """Отдает статическое WSDL-описание доступных операций сервиса.""" + wsdl = """ + + + REST API для сущности calls из LR2. + + + + + + + + + + +""" + return Response(wsdl, mimetype="application/wsdl+xml") + + +if __name__ == "__main__": + app.run(debug=True) diff --git a/LR3/task3.pdf b/LR3/task3.pdf new file mode 100644 index 0000000000000000000000000000000000000000..948a58adc2a53111c6af5509d77d30f8e4014133 GIT binary patch literal 70900 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 literal 0 HcmV?d00001 diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..b0684b9 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,17 @@ +[project] +name = "irfm" +version = "0.1.0" +description = "Add your description here" +readme = "README.md" +requires-python = ">=3.12" +dependencies = [ + "flask>=3.1.2", + "jupyterlab>=4.5.6", + "kagglehub>=1.0.0", + "matplotlib>=3.10.8", + "numpy>=2.4.4", + "pandas>=3.0.2", + "requests>=2.32.5", + "scipy>=1.17.1", + "seaborn>=0.13.2", +]