cloned from code.mipt.ru
This commit is contained in:
@@ -0,0 +1,401 @@
|
||||
#
|
||||
# "contingent-movement" project;
|
||||
# author: gazakbayev.net
|
||||
# ver: 1.0
|
||||
#
|
||||
|
||||
from faker import Faker
|
||||
import random
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
from manager import *
|
||||
|
||||
Database.initialize()
|
||||
|
||||
fake = Faker('ru_RU')
|
||||
|
||||
class DataStorage:
|
||||
physicals = []
|
||||
supervisors = []
|
||||
faculties = []
|
||||
departments = []
|
||||
programs = []
|
||||
groups = []
|
||||
students = []
|
||||
disciplines = []
|
||||
|
||||
def generate_physicals(count=30):
|
||||
for _ in range(count):
|
||||
access_level = random.choice(['КАМПУС', 'ОБЩЕЖИТИЯ', 'ПОЛНЫЙ'])
|
||||
access_card = ":".join(f"{random.randint(0, 255):02X}" for _ in range(6))
|
||||
|
||||
data = [
|
||||
fake.unique.passport_number(),
|
||||
fake.first_name(),
|
||||
fake.last_name(),
|
||||
fake.date_of_birth(minimum_age=18, maximum_age=80),
|
||||
fake.phone_number(),
|
||||
fake.email(),
|
||||
fake.country(),
|
||||
fake.address(),
|
||||
access_card,
|
||||
access_level
|
||||
]
|
||||
DataStorage.physicals.append(data[0])
|
||||
physicals_write(data)
|
||||
|
||||
def generate_supervisors(count=5):
|
||||
if not DataStorage.physicals:
|
||||
generate_physicals(10)
|
||||
|
||||
for _ in range(count):
|
||||
data = [
|
||||
random.choice(DataStorage.physicals),
|
||||
random.randint(1, 30),
|
||||
round(random.uniform(0.3, 1.0), 2),
|
||||
random.choice(['МЛАДШИЙ НАУЧНЫЙ СОТРУДНИК', 'СТАРШИЙ НАУЧНЫЙ СОТРУДНИК',
|
||||
'ВЕДУЩИЙ НАУЧНЫЙ СОТРУДНИК', 'ГЛАВНЫЙ НАУЧНЫЙ СОТРУДНИК', 'НАУЧНЫЙ СОТРУДНИК'])
|
||||
]
|
||||
DataStorage.supervisors.append(data[0])
|
||||
supervisors_write(data)
|
||||
|
||||
def generate_faculties(count=3):
|
||||
faculty_names = [
|
||||
"Факультет компьютерных наук",
|
||||
"Физико-математический факультет",
|
||||
"Факультет экономики",
|
||||
"Юридический факультет",
|
||||
"Филологический факультет"
|
||||
]
|
||||
|
||||
if not DataStorage.physicals:
|
||||
generate_physicals(10)
|
||||
|
||||
for i in range(count):
|
||||
head = random.choice(DataStorage.physicals)
|
||||
vice = random.choice([p for p in DataStorage.physicals if p != head] + [None])
|
||||
|
||||
data = [
|
||||
faculty_names[i],
|
||||
faculty_names[i][:3].upper(),
|
||||
head,
|
||||
vice,
|
||||
fake.address()
|
||||
]
|
||||
DataStorage.faculties.append(data)
|
||||
faculties_write(data)
|
||||
|
||||
def generate_departments(count=5):
|
||||
department_names = [
|
||||
"Кафедра программной инженерии",
|
||||
"Кафедра искусственного интеллекта",
|
||||
"Кафедра теоретической физики",
|
||||
"Кафедра прикладной математики",
|
||||
"Кафедра экономической теории",
|
||||
"Кафедра системного анализа",
|
||||
"Кафедра кибербезопасности",
|
||||
"Кафедра биоинформатики"
|
||||
]
|
||||
|
||||
if not DataStorage.faculties:
|
||||
generate_faculties()
|
||||
|
||||
if not DataStorage.physicals:
|
||||
generate_physicals(10)
|
||||
|
||||
actual_count = min(count, len(department_names))
|
||||
|
||||
for i in range(actual_count):
|
||||
head = random.choice(DataStorage.physicals)
|
||||
vice = random.choice([p for p in DataStorage.physicals if p != head] + [None])
|
||||
secretary = random.choice([p for p in DataStorage.physicals if p != head and p != vice] + [None])
|
||||
|
||||
data = [
|
||||
department_names[i],
|
||||
department_names[i][:3].upper(),
|
||||
fake.date_between(start_date='-30y', end_date='-5y'),
|
||||
head,
|
||||
vice,
|
||||
secretary,
|
||||
random.choice(range(1, len(DataStorage.faculties)+1))
|
||||
]
|
||||
DataStorage.departments.append(data)
|
||||
departments_write(data)
|
||||
|
||||
for i in range(actual_count, count):
|
||||
dept_name = f"Кафедра {fake.unique.word().capitalize()}"
|
||||
head = random.choice(DataStorage.physicals)
|
||||
vice = random.choice([p for p in DataStorage.physicals if p != head] + [None])
|
||||
secretary = random.choice([p for p in DataStorage.physicals if p != head and p != vice] + [None])
|
||||
|
||||
data = [
|
||||
dept_name,
|
||||
dept_name[:3].upper(),
|
||||
fake.date_between(start_date='-30y', end_date='-5y'),
|
||||
head,
|
||||
vice,
|
||||
secretary,
|
||||
random.choice(range(1, len(DataStorage.faculties)+1))
|
||||
]
|
||||
DataStorage.departments.append(data)
|
||||
departments_write(data)
|
||||
|
||||
def generate_programs(count=8):
|
||||
program_names = [
|
||||
"Программная инженерия",
|
||||
"Искусственный интеллект и машинное обучение",
|
||||
"Теоретическая физика",
|
||||
"Прикладная математика и информатика",
|
||||
"Экономика и финансы",
|
||||
"Юриспруденция",
|
||||
"Филология и лингвистика",
|
||||
"Бизнес-информатика",
|
||||
"Биоинженерия",
|
||||
"Кибербезопасность",
|
||||
"Международные отношения",
|
||||
"Психология"
|
||||
]
|
||||
|
||||
actual_count = min(count, len(program_names))
|
||||
|
||||
for i in range(actual_count):
|
||||
parent_id = random.choice([None] + list(range(1, i+1)))
|
||||
|
||||
data = [
|
||||
f"SPEC-{fake.unique.bothify(text='??-####')}",
|
||||
random.choice(['BACHELOR', 'MAGISTER', 'ASPIRANT']),
|
||||
program_names[i],
|
||||
parent_id
|
||||
]
|
||||
DataStorage.programs.append(data)
|
||||
programs_write(data)
|
||||
|
||||
for i in range(actual_count, count):
|
||||
program_name = f"{fake.word().capitalize()} {fake.word().capitalize()}"
|
||||
parent_id = random.choice([None] + list(range(1, len(DataStorage.programs)+1)))
|
||||
|
||||
data = [
|
||||
f"SPEC-{fake.unique.bothify(text='??-####')}",
|
||||
random.choice(['BACHELOR', 'MAGISTER', 'ASPIRANT']),
|
||||
program_name,
|
||||
parent_id
|
||||
]
|
||||
DataStorage.programs.append(data)
|
||||
programs_write(data)
|
||||
|
||||
def generate_groups(count=5):
|
||||
if not DataStorage.faculties or not DataStorage.programs or not DataStorage.departments:
|
||||
generate_faculties()
|
||||
generate_programs()
|
||||
generate_departments()
|
||||
|
||||
group_prefixes = ['А', 'Б', 'М']
|
||||
cyrillic_lower = [chr(c) for c in range(1072, 1104)]
|
||||
|
||||
for _ in range(count):
|
||||
prefix = random.choice(group_prefixes)
|
||||
year = fake.numerify(text='##')
|
||||
num = fake.numerify(text='###')
|
||||
letter = random.choice([''] + cyrillic_lower)
|
||||
group_id = f"{prefix}{year}-{num}{letter}"
|
||||
|
||||
study_starts = fake.date_between(start_date='-4y', end_date='today')
|
||||
study_ends = study_starts + timedelta(days=1460)
|
||||
|
||||
|
||||
data = [
|
||||
group_id,
|
||||
random.choice(range(1, len(DataStorage.faculties)+1)),
|
||||
random.choice(range(1, len(DataStorage.programs)+1)),
|
||||
random.choice(range(1, len(DataStorage.departments)+1)),
|
||||
study_starts,
|
||||
study_ends
|
||||
]
|
||||
DataStorage.groups.append(data)
|
||||
groups_write(data)
|
||||
|
||||
def generate_students(count=10):
|
||||
if not DataStorage.physicals or not DataStorage.groups or not DataStorage.supervisors:
|
||||
generate_physicals(150)
|
||||
generate_groups()
|
||||
generate_supervisors()
|
||||
|
||||
statuses = ['УЧИТСЯ', 'В АКАДЕМИЧЕСКОМ ОТПУСКЕ', 'ОТЧИСЛЕН']
|
||||
education_forms = ['ОЧНАЯ', 'ЗАОЧНАЯ', 'ВЕЧЕРНЯЯ']
|
||||
|
||||
for _ in range(count):
|
||||
data = [
|
||||
random.choice(DataStorage.physicals),
|
||||
random.choice([g[0] for g in DataStorage.groups]),
|
||||
random.choice(DataStorage.supervisors + [None]),
|
||||
random.choice(education_forms),
|
||||
random.choices(statuses, weights=[0.85, 0.1, 0.05])[0]
|
||||
]
|
||||
DataStorage.students.append(data)
|
||||
students_write(data)
|
||||
|
||||
def generate_family(count=20):
|
||||
if not DataStorage.students:
|
||||
generate_students()
|
||||
|
||||
kinships = ['MOTHER', 'FATHER', 'BROTHER', 'SISTER', 'ANOTHER']
|
||||
|
||||
for _ in range(count):
|
||||
student = random.choice(DataStorage.students)[0]
|
||||
kinship = random.choice(kinships)
|
||||
|
||||
data = [
|
||||
student,
|
||||
fake.first_name(),
|
||||
fake.last_name(),
|
||||
kinship,
|
||||
fake.phone_number(),
|
||||
fake.address()
|
||||
]
|
||||
family_write(data)
|
||||
|
||||
def generate_disciplines(count=7):
|
||||
if not DataStorage.departments:
|
||||
generate_departments()
|
||||
|
||||
discipline_names = [
|
||||
"Программирование на Python",
|
||||
"Базы данных",
|
||||
"Машинное обучение",
|
||||
"Теоретическая механика",
|
||||
"Дифференциальные уравнения",
|
||||
"Эконометрика",
|
||||
"Гражданское право",
|
||||
"История литературы"
|
||||
]
|
||||
|
||||
for _ in range(count):
|
||||
academic_hours = random.randint(36, 72)
|
||||
general_hours = academic_hours + random.randint(1, 36)
|
||||
data = [
|
||||
f"{random.choice(discipline_names)} {fake.numerify(text='###')}",
|
||||
random.choice(range(1, len(DataStorage.departments)+1)),
|
||||
random.randint(2, 6),
|
||||
academic_hours,
|
||||
general_hours,
|
||||
random.choice([True, False])
|
||||
]
|
||||
DataStorage.disciplines.append(data)
|
||||
disciplines_write(data)
|
||||
|
||||
def generate_statements(count=300):
|
||||
if not DataStorage.students or not DataStorage.disciplines or not DataStorage.physicals:
|
||||
generate_students()
|
||||
generate_disciplines()
|
||||
generate_physicals()
|
||||
|
||||
for _ in range(count):
|
||||
data = [
|
||||
random.choice(range(1, len(DataStorage.students)+1)),
|
||||
random.choice(range(1, len(DataStorage.disciplines)+1)),
|
||||
random.choice(DataStorage.physicals),
|
||||
random.randint(0, 2),
|
||||
random.randint(3, 10),
|
||||
fake.date_between(start_date='-2y', end_date='today')
|
||||
]
|
||||
statements_write(data)
|
||||
|
||||
def generate_movement(count=50):
|
||||
if not DataStorage.students or not DataStorage.groups:
|
||||
generate_students()
|
||||
generate_groups()
|
||||
|
||||
movement_types = ['ЗАЧИСЛЕН', 'ВОССТАНОВЛЕН', 'ОТЧИСЛЕН', 'В АКАДЕМИЧЕСКИЙ ОТПУСК', 'ПЕРЕВОД В ДРУГУЮ ГРУППУ']
|
||||
statuses = ['УЧИТСЯ', 'В АКАДЕМИЧЕСКОМ ОТПУСКЕ', 'ОТЧИСЛЕН']
|
||||
|
||||
for _ in range(count):
|
||||
movement_type = random.choice(movement_types)
|
||||
|
||||
if movement_type == 'ПЕРЕВОД В ДРУГУЮ ГРУППУ':
|
||||
new_group = random.choice([g[0] for g in DataStorage.groups if g[0] != random.choice([g[0] for g in DataStorage.groups])])
|
||||
new_status = 'УЧИТСЯ'
|
||||
elif movement_type == 'В АКАДЕМИЧЕСКИЙ ОТПУСК':
|
||||
new_group = None
|
||||
new_status = 'В АКАДЕМИЧЕСКОМ ОТПУСКЕ'
|
||||
else:
|
||||
new_group = None
|
||||
new_status = random.choice(statuses)
|
||||
|
||||
data = [
|
||||
random.choice(range(1, len(DataStorage.students)+1)),
|
||||
movement_type,
|
||||
new_group,
|
||||
new_status,
|
||||
fake.date_between(start_date='-2y', end_date='today')
|
||||
]
|
||||
movement_write(data)
|
||||
|
||||
def generate_files(count=100):
|
||||
if not DataStorage.students:
|
||||
generate_students()
|
||||
|
||||
extensions = ['PNG', 'JPEG', 'PDF']
|
||||
|
||||
for _ in range(count):
|
||||
data = [
|
||||
random.choice(range(1, len(DataStorage.students)+1)),
|
||||
fake.file_name(),
|
||||
fake.sentence(),
|
||||
random.choice(extensions),
|
||||
round(random.uniform(0.1, 20.0), 2),
|
||||
f"/uploads/{fake.unique.uuid4()}"
|
||||
]
|
||||
files_write(data)
|
||||
|
||||
import debug_data.limits as lim
|
||||
|
||||
def generate_all_data():
|
||||
generate_physicals(lim.PHYSICALS)
|
||||
generate_supervisors(lim.SUPERVISORS)
|
||||
generate_faculties(lim.FACULTIES)
|
||||
generate_departments(lim.DEPARTMENTS)
|
||||
generate_programs(lim.PROGRAMS)
|
||||
generate_groups(lim.GROUPS)
|
||||
generate_students(lim.STUDENTS)
|
||||
generate_family(lim.FAMILY)
|
||||
generate_disciplines(lim.DISCIPLINES)
|
||||
generate_statements(lim.STATEMENTS)
|
||||
generate_movement(lim.MOVEMENTS)
|
||||
generate_files(lim.FILES)
|
||||
|
||||
if __name__ == "__main__":
|
||||
generate_all_data()
|
||||
print("Генерация тестовых данных завершена!")
|
||||
|
||||
|
||||
# /$$$$$$ /$$ /$$ /$$
|
||||
# /$$__ $$ | $$ |__/ | $$
|
||||
# | $$ \__/ /$$$$$$ /$$$$$$$ /$$$$$$ /$$ /$$$$$$$ /$$$$$$ /$$$$$$ /$$$$$$$ /$$$$$$
|
||||
# | $$ /$$__ $$| $$__ $$|_ $$_/ | $$| $$__ $$ /$$__ $$ /$$__ $$| $$__ $$|_ $$_/
|
||||
# | $$ | $$ \ $$| $$ \ $$ | $$ | $$| $$ \ $$| $$ \ $$| $$$$$$$$| $$ \ $$ | $$
|
||||
# | $$ $$| $$ | $$| $$ | $$ | $$ /$$| $$| $$ | $$| $$ | $$| $$_____/| $$ | $$ | $$ /$$
|
||||
# | $$$$$$/| $$$$$$/| $$ | $$ | $$$$/| $$| $$ | $$| $$$$$$$| $$$$$$$| $$ | $$ | $$$$/
|
||||
# \______/ \______/ |__/ |__/ \___/ |__/|__/ |__/ \____ $$ \_______/|__/ |__/ \___/
|
||||
# /$$ \ $$
|
||||
# | $$$$$$/
|
||||
# \______/
|
||||
# /$$ /$$ /$$
|
||||
# | $$$ /$$$ | $$
|
||||
# | $$$$ /$$$$ /$$$$$$ /$$ /$$ /$$$$$$ /$$$$$$/$$$$ /$$$$$$ /$$$$$$$ /$$$$$$
|
||||
# | $$ $$/$$ $$ /$$__ $$| $$ /$$//$$__ $$| $$_ $$_ $$ /$$__ $$| $$__ $$|_ $$_/
|
||||
# | $$ $$$| $$| $$ \ $$ \ $$/$$/| $$$$$$$$| $$ \ $$ \ $$| $$$$$$$$| $$ \ $$ | $$
|
||||
# | $$\ $ | $$| $$ | $$ \ $$$/ | $$_____/| $$ | $$ | $$| $$_____/| $$ | $$ | $$ /$$
|
||||
# | $$ \/ | $$| $$$$$$/ \ $/ | $$$$$$$| $$ | $$ | $$| $$$$$$$| $$ | $$ | $$$$/
|
||||
# |__/ |__/ \______/ \_/ \_______/|__/ |__/ |__/ \_______/|__/ |__/ \___/
|
||||
|
||||
# /$$ /$$ /$$ /$$
|
||||
# | $$ | $$ | $$ | $$
|
||||
# | $$$$$$$ /$$ /$$ /$$$$$$ /$$$$$$ /$$$$$$$$ /$$$$$$ | $$ /$$| $$$$$$$ /$$$$$$ /$$ /$$ /$$$$$$ /$$ /$$ /$$$$$$$ /$$$$$$ /$$$$$$
|
||||
# | $$__ $$| $$ | $$ /$$__ $$ |____ $$|____ /$$/ |____ $$| $$ /$$/| $$__ $$ |____ $$| $$ | $$ /$$__ $$| $$ /$$/| $$__ $$ /$$__ $$|_ $$_/
|
||||
# | $$ \ $$| $$ | $$ | $$ \ $$ /$$$$$$$ /$$$$/ /$$$$$$$| $$$$$$/ | $$ \ $$ /$$$$$$$| $$ | $$| $$$$$$$$ \ $$/$$/ | $$ \ $$| $$$$$$$$ | $$
|
||||
# | $$ | $$| $$ | $$ | $$ | $$ /$$__ $$ /$$__/ /$$__ $$| $$_ $$ | $$ | $$ /$$__ $$| $$ | $$| $$_____/ \ $$$/ | $$ | $$| $$_____/ | $$ /$$
|
||||
# | $$$$$$$/| $$$$$$$ | $$$$$$$| $$$$$$$ /$$$$$$$$| $$$$$$$| $$ \ $$| $$$$$$$/| $$$$$$$| $$$$$$$| $$$$$$$ \ $//$$| $$ | $$| $$$$$$$ | $$$$/
|
||||
# |_______/ \____ $$ \____ $$ \_______/|________/ \_______/|__/ \__/|_______/ \_______/ \____ $$ \_______/ \_/|__/|__/ |__/ \_______/ \___/
|
||||
# /$$ | $$ /$$ \ $$ /$$ | $$
|
||||
# | $$$$$$/ | $$$$$$/ | $$$$$$/
|
||||
# \______/ \______/ \______/
|
||||
@@ -0,0 +1,47 @@
|
||||
#
|
||||
# "contingent-movement" project
|
||||
# author: gazakbayev.net
|
||||
# ver: 1.0
|
||||
#
|
||||
|
||||
import os
|
||||
|
||||
CREDS = {
|
||||
"dbname": "edu",
|
||||
"user": "edu",
|
||||
"password": os.getenv("EDU_DB_PASSWORD"),
|
||||
"host": "demo.labinn.ru",
|
||||
"port": "5432",
|
||||
}
|
||||
|
||||
# /$$$$$$ /$$ /$$ /$$
|
||||
# /$$__ $$ | $$ |__/ | $$
|
||||
# | $$ \__/ /$$$$$$ /$$$$$$$ /$$$$$$ /$$ /$$$$$$$ /$$$$$$ /$$$$$$ /$$$$$$$ /$$$$$$
|
||||
# | $$ /$$__ $$| $$__ $$|_ $$_/ | $$| $$__ $$ /$$__ $$ /$$__ $$| $$__ $$|_ $$_/
|
||||
# | $$ | $$ \ $$| $$ \ $$ | $$ | $$| $$ \ $$| $$ \ $$| $$$$$$$$| $$ \ $$ | $$
|
||||
# | $$ $$| $$ | $$| $$ | $$ | $$ /$$| $$| $$ | $$| $$ | $$| $$_____/| $$ | $$ | $$ /$$
|
||||
# | $$$$$$/| $$$$$$/| $$ | $$ | $$$$/| $$| $$ | $$| $$$$$$$| $$$$$$$| $$ | $$ | $$$$/
|
||||
# \______/ \______/ |__/ |__/ \___/ |__/|__/ |__/ \____ $$ \_______/|__/ |__/ \___/
|
||||
# /$$ \ $$
|
||||
# | $$$$$$/
|
||||
# \______/
|
||||
# /$$ /$$ /$$
|
||||
# | $$$ /$$$ | $$
|
||||
# | $$$$ /$$$$ /$$$$$$ /$$ /$$ /$$$$$$ /$$$$$$/$$$$ /$$$$$$ /$$$$$$$ /$$$$$$
|
||||
# | $$ $$/$$ $$ /$$__ $$| $$ /$$//$$__ $$| $$_ $$_ $$ /$$__ $$| $$__ $$|_ $$_/
|
||||
# | $$ $$$| $$| $$ \ $$ \ $$/$$/| $$$$$$$$| $$ \ $$ \ $$| $$$$$$$$| $$ \ $$ | $$
|
||||
# | $$\ $ | $$| $$ | $$ \ $$$/ | $$_____/| $$ | $$ | $$| $$_____/| $$ | $$ | $$ /$$
|
||||
# | $$ \/ | $$| $$$$$$/ \ $/ | $$$$$$$| $$ | $$ | $$| $$$$$$$| $$ | $$ | $$$$/
|
||||
# |__/ |__/ \______/ \_/ \_______/|__/ |__/ |__/ \_______/|__/ |__/ \___/
|
||||
|
||||
# /$$ /$$ /$$ /$$
|
||||
# | $$ | $$ | $$ | $$
|
||||
# | $$$$$$$ /$$ /$$ /$$$$$$ /$$$$$$ /$$$$$$$$ /$$$$$$ | $$ /$$| $$$$$$$ /$$$$$$ /$$ /$$ /$$$$$$ /$$ /$$ /$$$$$$$ /$$$$$$ /$$$$$$
|
||||
# | $$__ $$| $$ | $$ /$$__ $$ |____ $$|____ /$$/ |____ $$| $$ /$$/| $$__ $$ |____ $$| $$ | $$ /$$__ $$| $$ /$$/| $$__ $$ /$$__ $$|_ $$_/
|
||||
# | $$ \ $$| $$ | $$ | $$ \ $$ /$$$$$$$ /$$$$/ /$$$$$$$| $$$$$$/ | $$ \ $$ /$$$$$$$| $$ | $$| $$$$$$$$ \ $$/$$/ | $$ \ $$| $$$$$$$$ | $$
|
||||
# | $$ | $$| $$ | $$ | $$ | $$ /$$__ $$ /$$__/ /$$__ $$| $$_ $$ | $$ | $$ /$$__ $$| $$ | $$| $$_____/ \ $$$/ | $$ | $$| $$_____/ | $$ /$$
|
||||
# | $$$$$$$/| $$$$$$$ | $$$$$$$| $$$$$$$ /$$$$$$$$| $$$$$$$| $$ \ $$| $$$$$$$/| $$$$$$$| $$$$$$$| $$$$$$$ \ $//$$| $$ | $$| $$$$$$$ | $$$$/
|
||||
# |_______/ \____ $$ \____ $$ \_______/|________/ \_______/|__/ \__/|_______/ \_______/ \____ $$ \_______/ \_/|__/|__/ |__/ \_______/ \___/
|
||||
# /$$ | $$ /$$ \ $$ /$$ | $$
|
||||
# | $$$$$$/ | $$$$$$/ | $$$$$$/
|
||||
# \______/ \______/ \______/
|
||||
@@ -0,0 +1,70 @@
|
||||
#
|
||||
# "contingent-movement" project;
|
||||
# author: gazakbayev.net
|
||||
# ver: 1.0
|
||||
#
|
||||
|
||||
FACULTIES = [
|
||||
("Физтех-школа прикладной математики и информатики", "ФПМИ"),
|
||||
("Физтех-школа радиотехники и компьютерных технологий", "ФРКТ"),
|
||||
("Физтех-школа биологической и медицинской физики", "ФБМФ"),
|
||||
("Физтех-школа Электроники, Фотоники и Молекулярной Физики", "ФЭФМ"),
|
||||
("Факультет общей и прикладной физики", "ФОПФ")
|
||||
]
|
||||
|
||||
PROGRAMS = [
|
||||
("01.03.02", "BACHELOR", "Прикладная математика и информатика"),
|
||||
("10.03.01", "BACHELOR", "Информационная безопасность"),
|
||||
("12.04.02", "MAGISTER", "Фотоника и оптоинформатика"),
|
||||
("03.06.01", "ASPIRANT", "Физика и астрономия"),
|
||||
("27.03.03", "BACHELOR", "Системный анализ и управление"),
|
||||
("09.04.01", "MAGISTER", "Информатика и вычислительная техника"),
|
||||
("02.06.01", "ASPIRANT", "Математика и механика"),
|
||||
("11.04.03", "MAGISTER", "Конструирование и технология электронных средств")
|
||||
]
|
||||
|
||||
QUALIFICATIONS = [
|
||||
"МЛАДШИЙ НАУЧНЫЙ СОТРУДНИК", "СТАРШИЙ НАУЧНЫЙ СОТРУДНИК",
|
||||
"ВЕДУЩИЙ НАУЧНЫЙ СОТРУДНИК", "ГЛАВНЫЙ НАУЧНЫЙ СОТРУДНИК", "НАУЧНЫЙ СОТРУДНИК"
|
||||
]
|
||||
|
||||
DEGREES = ["BACHELOR", "MAGISTER", "ASPIRANT"]
|
||||
ACCESS_LEVELS = ["КАМПУС", "ОБЩЕЖИТИЯ", "ПОЛНЫЙ"]
|
||||
KINSHIP_TYPES = ["МАТЬ", "ОТЕЦ", "БРАТ", "СЕСТРА", "ДРУГИЕ"]
|
||||
EDUCATION_FORMS = ["ОЧНАЯ", "ЗАОЧНАЯ", "ВЕЧЕРНЯЯ"]
|
||||
STATUSES = ["УЧИТСЯ", "В АКАДЕМИЧЕСКОМ ОТПУСКЕ", "ОТЧИСЛЕН"]
|
||||
FILE_EXTENSIONS = ["PNG", "JPEG", "PDF"]
|
||||
MOVEMENT_TYPES = ["ЗАЧИСЛЕН", "ВОССТАНОВЛЕН", "ОТЧИСЛЕН", "ПЕРЕВЕДЁН"]
|
||||
|
||||
|
||||
# /$$$$$$ /$$ /$$ /$$
|
||||
# /$$__ $$ | $$ |__/ | $$
|
||||
# | $$ \__/ /$$$$$$ /$$$$$$$ /$$$$$$ /$$ /$$$$$$$ /$$$$$$ /$$$$$$ /$$$$$$$ /$$$$$$
|
||||
# | $$ /$$__ $$| $$__ $$|_ $$_/ | $$| $$__ $$ /$$__ $$ /$$__ $$| $$__ $$|_ $$_/
|
||||
# | $$ | $$ \ $$| $$ \ $$ | $$ | $$| $$ \ $$| $$ \ $$| $$$$$$$$| $$ \ $$ | $$
|
||||
# | $$ $$| $$ | $$| $$ | $$ | $$ /$$| $$| $$ | $$| $$ | $$| $$_____/| $$ | $$ | $$ /$$
|
||||
# | $$$$$$/| $$$$$$/| $$ | $$ | $$$$/| $$| $$ | $$| $$$$$$$| $$$$$$$| $$ | $$ | $$$$/
|
||||
# \______/ \______/ |__/ |__/ \___/ |__/|__/ |__/ \____ $$ \_______/|__/ |__/ \___/
|
||||
# /$$ \ $$
|
||||
# | $$$$$$/
|
||||
# \______/
|
||||
# /$$ /$$ /$$
|
||||
# | $$$ /$$$ | $$
|
||||
# | $$$$ /$$$$ /$$$$$$ /$$ /$$ /$$$$$$ /$$$$$$/$$$$ /$$$$$$ /$$$$$$$ /$$$$$$
|
||||
# | $$ $$/$$ $$ /$$__ $$| $$ /$$//$$__ $$| $$_ $$_ $$ /$$__ $$| $$__ $$|_ $$_/
|
||||
# | $$ $$$| $$| $$ \ $$ \ $$/$$/| $$$$$$$$| $$ \ $$ \ $$| $$$$$$$$| $$ \ $$ | $$
|
||||
# | $$\ $ | $$| $$ | $$ \ $$$/ | $$_____/| $$ | $$ | $$| $$_____/| $$ | $$ | $$ /$$
|
||||
# | $$ \/ | $$| $$$$$$/ \ $/ | $$$$$$$| $$ | $$ | $$| $$$$$$$| $$ | $$ | $$$$/
|
||||
# |__/ |__/ \______/ \_/ \_______/|__/ |__/ |__/ \_______/|__/ |__/ \___/
|
||||
|
||||
# /$$ /$$ /$$ /$$
|
||||
# | $$ | $$ | $$ | $$
|
||||
# | $$$$$$$ /$$ /$$ /$$$$$$ /$$$$$$ /$$$$$$$$ /$$$$$$ | $$ /$$| $$$$$$$ /$$$$$$ /$$ /$$ /$$$$$$ /$$ /$$ /$$$$$$$ /$$$$$$ /$$$$$$
|
||||
# | $$__ $$| $$ | $$ /$$__ $$ |____ $$|____ /$$/ |____ $$| $$ /$$/| $$__ $$ |____ $$| $$ | $$ /$$__ $$| $$ /$$/| $$__ $$ /$$__ $$|_ $$_/
|
||||
# | $$ \ $$| $$ | $$ | $$ \ $$ /$$$$$$$ /$$$$/ /$$$$$$$| $$$$$$/ | $$ \ $$ /$$$$$$$| $$ | $$| $$$$$$$$ \ $$/$$/ | $$ \ $$| $$$$$$$$ | $$
|
||||
# | $$ | $$| $$ | $$ | $$ | $$ /$$__ $$ /$$__/ /$$__ $$| $$_ $$ | $$ | $$ /$$__ $$| $$ | $$| $$_____/ \ $$$/ | $$ | $$| $$_____/ | $$ /$$
|
||||
# | $$$$$$$/| $$$$$$$ | $$$$$$$| $$$$$$$ /$$$$$$$$| $$$$$$$| $$ \ $$| $$$$$$$/| $$$$$$$| $$$$$$$| $$$$$$$ \ $//$$| $$ | $$| $$$$$$$ | $$$$/
|
||||
# |_______/ \____ $$ \____ $$ \_______/|________/ \_______/|__/ \__/|_______/ \_______/ \____ $$ \_______/ \_/|__/|__/ |__/ \_______/ \___/
|
||||
# /$$ | $$ /$$ \ $$ /$$ | $$
|
||||
# | $$$$$$/ | $$$$$$/ | $$$$$$/
|
||||
# \______/ \______/ \______/
|
||||
@@ -0,0 +1,50 @@
|
||||
#
|
||||
# "contingent-movement" project
|
||||
# author: gazakbayev.net
|
||||
# ver: 1.0
|
||||
#
|
||||
|
||||
PHYSICALS = 300
|
||||
SUPERVISORS = 10
|
||||
FACULTIES = 4
|
||||
DEPARTMENTS = 5
|
||||
PROGRAMS = 8
|
||||
GROUPS = 6
|
||||
STUDENTS = 40
|
||||
FAMILY = 100
|
||||
DISCIPLINES = 7
|
||||
STATEMENTS = 500
|
||||
MOVEMENTS = 100
|
||||
FILES = 100
|
||||
|
||||
# /$$$$$$ /$$ /$$ /$$
|
||||
# /$$__ $$ | $$ |__/ | $$
|
||||
# | $$ \__/ /$$$$$$ /$$$$$$$ /$$$$$$ /$$ /$$$$$$$ /$$$$$$ /$$$$$$ /$$$$$$$ /$$$$$$
|
||||
# | $$ /$$__ $$| $$__ $$|_ $$_/ | $$| $$__ $$ /$$__ $$ /$$__ $$| $$__ $$|_ $$_/
|
||||
# | $$ | $$ \ $$| $$ \ $$ | $$ | $$| $$ \ $$| $$ \ $$| $$$$$$$$| $$ \ $$ | $$
|
||||
# | $$ $$| $$ | $$| $$ | $$ | $$ /$$| $$| $$ | $$| $$ | $$| $$_____/| $$ | $$ | $$ /$$
|
||||
# | $$$$$$/| $$$$$$/| $$ | $$ | $$$$/| $$| $$ | $$| $$$$$$$| $$$$$$$| $$ | $$ | $$$$/
|
||||
# \______/ \______/ |__/ |__/ \___/ |__/|__/ |__/ \____ $$ \_______/|__/ |__/ \___/
|
||||
# /$$ \ $$
|
||||
# | $$$$$$/
|
||||
# \______/
|
||||
# /$$ /$$ /$$
|
||||
# | $$$ /$$$ | $$
|
||||
# | $$$$ /$$$$ /$$$$$$ /$$ /$$ /$$$$$$ /$$$$$$/$$$$ /$$$$$$ /$$$$$$$ /$$$$$$
|
||||
# | $$ $$/$$ $$ /$$__ $$| $$ /$$//$$__ $$| $$_ $$_ $$ /$$__ $$| $$__ $$|_ $$_/
|
||||
# | $$ $$$| $$| $$ \ $$ \ $$/$$/| $$$$$$$$| $$ \ $$ \ $$| $$$$$$$$| $$ \ $$ | $$
|
||||
# | $$\ $ | $$| $$ | $$ \ $$$/ | $$_____/| $$ | $$ | $$| $$_____/| $$ | $$ | $$ /$$
|
||||
# | $$ \/ | $$| $$$$$$/ \ $/ | $$$$$$$| $$ | $$ | $$| $$$$$$$| $$ | $$ | $$$$/
|
||||
# |__/ |__/ \______/ \_/ \_______/|__/ |__/ |__/ \_______/|__/ |__/ \___/
|
||||
|
||||
# /$$ /$$ /$$ /$$
|
||||
# | $$ | $$ | $$ | $$
|
||||
# | $$$$$$$ /$$ /$$ /$$$$$$ /$$$$$$ /$$$$$$$$ /$$$$$$ | $$ /$$| $$$$$$$ /$$$$$$ /$$ /$$ /$$$$$$ /$$ /$$ /$$$$$$$ /$$$$$$ /$$$$$$
|
||||
# | $$__ $$| $$ | $$ /$$__ $$ |____ $$|____ /$$/ |____ $$| $$ /$$/| $$__ $$ |____ $$| $$ | $$ /$$__ $$| $$ /$$/| $$__ $$ /$$__ $$|_ $$_/
|
||||
# | $$ \ $$| $$ | $$ | $$ \ $$ /$$$$$$$ /$$$$/ /$$$$$$$| $$$$$$/ | $$ \ $$ /$$$$$$$| $$ | $$| $$$$$$$$ \ $$/$$/ | $$ \ $$| $$$$$$$$ | $$
|
||||
# | $$ | $$| $$ | $$ | $$ | $$ /$$__ $$ /$$__/ /$$__ $$| $$_ $$ | $$ | $$ /$$__ $$| $$ | $$| $$_____/ \ $$$/ | $$ | $$| $$_____/ | $$ /$$
|
||||
# | $$$$$$$/| $$$$$$$ | $$$$$$$| $$$$$$$ /$$$$$$$$| $$$$$$$| $$ \ $$| $$$$$$$/| $$$$$$$| $$$$$$$| $$$$$$$ \ $//$$| $$ | $$| $$$$$$$ | $$$$/
|
||||
# |_______/ \____ $$ \____ $$ \_______/|________/ \_______/|__/ \__/|_______/ \_______/ \____ $$ \_______/ \_/|__/|__/ |__/ \_______/ \___/
|
||||
# /$$ | $$ /$$ \ $$ /$$ | $$
|
||||
# | $$$$$$/ | $$$$$$/ | $$$$$$/
|
||||
# \______/ \______/ \______/
|
||||
@@ -0,0 +1,257 @@
|
||||
#
|
||||
# "contingent-movement" project;
|
||||
# author: gazakbayev.net
|
||||
# ver: 1.0
|
||||
#
|
||||
|
||||
import psycopg2
|
||||
from debug_data.database_creds import CREDS
|
||||
|
||||
class Database:
|
||||
@staticmethod
|
||||
def __connection__():
|
||||
return psycopg2.connect(**CREDS)
|
||||
@staticmethod
|
||||
def initialize():
|
||||
conn = Database.__connection__()
|
||||
try:
|
||||
with conn.cursor() as cur, open("../docs/schema.sql", "r", encoding="utf-8") as f:
|
||||
cur.execute(f.read())
|
||||
conn.commit()
|
||||
print("[Contingent-movement] Initialized database with relations.")
|
||||
except Exception as e:
|
||||
print(f"[Contingent-movement] [Contingent Movement] Error: {e}")
|
||||
conn.rollback()
|
||||
finally:
|
||||
conn.close()
|
||||
|
||||
def physicals_write(data: list):
|
||||
conn = Database.__connection__()
|
||||
try:
|
||||
with conn.cursor() as cur:
|
||||
cur.execute("""
|
||||
INSERT INTO Physicals (passport_no, name, surname, birthday, phone, mail, citizenship, address, access_card, access_level)
|
||||
VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s)
|
||||
""", data)
|
||||
conn.commit()
|
||||
except Exception as e:
|
||||
conn.rollback()
|
||||
print(f"[Contingent Movement] Error inserting into Physicals: {e}")
|
||||
finally:
|
||||
conn.close()
|
||||
|
||||
def supervisors_write(data: list):
|
||||
conn = Database.__connection__()
|
||||
try:
|
||||
with conn.cursor() as cur:
|
||||
cur.execute("""
|
||||
INSERT INTO Supervisors (person, experience, defended_ratio, qualification)
|
||||
VALUES (%s, %s, %s, %s)
|
||||
""", data)
|
||||
conn.commit()
|
||||
except Exception as e:
|
||||
conn.rollback()
|
||||
print(f"[Contingent Movement] Error inserting into Supervisors: {e}")
|
||||
finally:
|
||||
conn.close()
|
||||
|
||||
def faculties_write(data: list):
|
||||
conn = Database.__connection__()
|
||||
try:
|
||||
with conn.cursor() as cur:
|
||||
cur.execute("""
|
||||
INSERT INTO Faculties (name, acronym, head, vice, address)
|
||||
VALUES (%s, %s, %s, %s, %s)
|
||||
""", data)
|
||||
conn.commit()
|
||||
except Exception as e:
|
||||
conn.rollback()
|
||||
print(f"[Contingent Movement] Error inserting into Faculties: {e}")
|
||||
finally:
|
||||
conn.close()
|
||||
|
||||
def departments_write(data: list):
|
||||
conn = Database.__connection__()
|
||||
try:
|
||||
with conn.cursor() as cur:
|
||||
cur.execute("""
|
||||
INSERT INTO Departments (name, acronym, founded, head, vice, secretary, faculty_id)
|
||||
VALUES (%s, %s, %s, %s, %s, %s, %s)
|
||||
""", data)
|
||||
conn.commit()
|
||||
except Exception as e:
|
||||
conn.rollback()
|
||||
print(f"[Contingent Movement] Error inserting into Departments: {e}")
|
||||
finally:
|
||||
conn.close()
|
||||
|
||||
def programs_write(data: list):
|
||||
conn = Database.__connection__()
|
||||
try:
|
||||
with conn.cursor() as cur:
|
||||
cur.execute("""
|
||||
INSERT INTO Programs (specification, degree, name, parent_id)
|
||||
VALUES (%s, %s, %s, %s)
|
||||
""", data)
|
||||
conn.commit()
|
||||
except Exception as e:
|
||||
conn.rollback()
|
||||
print(f"[Contingent Movement] Error inserting into Programs: {e}")
|
||||
finally:
|
||||
conn.close()
|
||||
|
||||
def groups_write(data: list):
|
||||
conn = Database.__connection__()
|
||||
try:
|
||||
with conn.cursor() as cur:
|
||||
cur.execute("""
|
||||
INSERT INTO Groups (group_id, faculty_id, program_id, department_id, study_starts, study_ends)
|
||||
VALUES (%s, %s, %s, %s, %s, %s)
|
||||
""", data)
|
||||
conn.commit()
|
||||
except Exception as e:
|
||||
conn.rollback()
|
||||
print(f"[Contingent Movement] Error inserting into Groups: {e}")
|
||||
finally:
|
||||
conn.close()
|
||||
|
||||
def students_write(data: list):
|
||||
conn = Database.__connection__()
|
||||
try:
|
||||
with conn.cursor() as cur:
|
||||
# 1. Сначала проверяем существование всех внешних ключей
|
||||
cur.execute("""
|
||||
SELECT 1 FROM physicals WHERE passport_no = %s
|
||||
UNION ALL
|
||||
SELECT 1 FROM groups WHERE group_id = %s
|
||||
UNION ALL
|
||||
SELECT 1 FROM physicals WHERE passport_no = %s OR %s IS NULL
|
||||
""", [data[0], data[1], data[2], data[2]])
|
||||
|
||||
if len(cur.fetchall()) < 2 + (1 if data[2] is not None else 0):
|
||||
raise ValueError("Invalid foreign key references")
|
||||
|
||||
cur.execute("""
|
||||
INSERT INTO Students (person, group_id, supervisor, education_form, status)
|
||||
VALUES (%s, %s, %s, %s, %s)
|
||||
RETURNING id
|
||||
""", data)
|
||||
|
||||
inserted_id = cur.fetchone()[0]
|
||||
conn.commit()
|
||||
return inserted_id
|
||||
|
||||
except Exception as e:
|
||||
conn.rollback()
|
||||
print(f"[Contingent Movement] Error inserting into Students: {e}")
|
||||
return None
|
||||
finally:
|
||||
conn.close()
|
||||
|
||||
def family_write(data: list):
|
||||
conn = Database.__connection__()
|
||||
try:
|
||||
with conn.cursor() as cur:
|
||||
cur.execute("""
|
||||
INSERT INTO Family (person, name, surname, kinship, phone, address)
|
||||
VALUES (%s, %s, %s, %s, %s, %s)
|
||||
""", data)
|
||||
conn.commit()
|
||||
except Exception as e:
|
||||
conn.rollback()
|
||||
print(f"[Contingent Movement] Error inserting into Family: {e}")
|
||||
finally:
|
||||
conn.close()
|
||||
|
||||
def files_write(data: list):
|
||||
conn = Database.__connection__()
|
||||
try:
|
||||
with conn.cursor() as cur:
|
||||
cur.execute("""
|
||||
INSERT INTO Files (student_id, name, description, extension, size, path)
|
||||
VALUES (%s, %s, %s, %s, %s, %s)
|
||||
""", data)
|
||||
conn.commit()
|
||||
except Exception as e:
|
||||
conn.rollback()
|
||||
print(f"[Contingent Movement] Error inserting into Files: {e}")
|
||||
finally:
|
||||
conn.close()
|
||||
|
||||
def disciplines_write(data: list):
|
||||
conn = Database.__connection__()
|
||||
try:
|
||||
with conn.cursor() as cur:
|
||||
cur.execute("""
|
||||
INSERT INTO Disciplines (name, department_id, credit_units, academic_hours, general_hours, is_annual)
|
||||
VALUES (%s, %s, %s, %s, %s, %s)
|
||||
""", data)
|
||||
conn.commit()
|
||||
except Exception as e:
|
||||
conn.rollback()
|
||||
print(f"[Contingent Movement] Error inserting into Disciplines: {e}")
|
||||
finally:
|
||||
conn.close()
|
||||
|
||||
def statements_write(data: list):
|
||||
conn = Database.__connection__()
|
||||
try:
|
||||
with conn.cursor() as cur:
|
||||
cur.execute("""
|
||||
INSERT INTO Statements (student_id, discipline_id, examiner, try_no, grade, conducted_at)
|
||||
VALUES (%s, %s, %s, %s, %s, %s)
|
||||
""", data)
|
||||
conn.commit()
|
||||
except Exception as e:
|
||||
conn.rollback()
|
||||
print(f"[Contingent Movement] Error inserting into Statements: {e}")
|
||||
finally:
|
||||
conn.close()
|
||||
|
||||
def movement_write(data: list):
|
||||
conn = Database.__connection__()
|
||||
try:
|
||||
with conn.cursor() as cur:
|
||||
cur.execute("""
|
||||
INSERT INTO Movement (student_id, type, new_group, new_status, issued_at)
|
||||
VALUES (%s, %s, %s, %s, %s)
|
||||
""", data)
|
||||
conn.commit()
|
||||
except Exception as e:
|
||||
conn.rollback()
|
||||
print(f"[Contingent Movement] Error inserting into Movement: {e}")
|
||||
finally:
|
||||
conn.close()
|
||||
|
||||
|
||||
# /$$$$$$ /$$ /$$ /$$
|
||||
# /$$__ $$ | $$ |__/ | $$
|
||||
# | $$ \__/ /$$$$$$ /$$$$$$$ /$$$$$$ /$$ /$$$$$$$ /$$$$$$ /$$$$$$ /$$$$$$$ /$$$$$$
|
||||
# | $$ /$$__ $$| $$__ $$|_ $$_/ | $$| $$__ $$ /$$__ $$ /$$__ $$| $$__ $$|_ $$_/
|
||||
# | $$ | $$ \ $$| $$ \ $$ | $$ | $$| $$ \ $$| $$ \ $$| $$$$$$$$| $$ \ $$ | $$
|
||||
# | $$ $$| $$ | $$| $$ | $$ | $$ /$$| $$| $$ | $$| $$ | $$| $$_____/| $$ | $$ | $$ /$$
|
||||
# | $$$$$$/| $$$$$$/| $$ | $$ | $$$$/| $$| $$ | $$| $$$$$$$| $$$$$$$| $$ | $$ | $$$$/
|
||||
# \______/ \______/ |__/ |__/ \___/ |__/|__/ |__/ \____ $$ \_______/|__/ |__/ \___/
|
||||
# /$$ \ $$
|
||||
# | $$$$$$/
|
||||
# \______/
|
||||
# /$$ /$$ /$$
|
||||
# | $$$ /$$$ | $$
|
||||
# | $$$$ /$$$$ /$$$$$$ /$$ /$$ /$$$$$$ /$$$$$$/$$$$ /$$$$$$ /$$$$$$$ /$$$$$$
|
||||
# | $$ $$/$$ $$ /$$__ $$| $$ /$$//$$__ $$| $$_ $$_ $$ /$$__ $$| $$__ $$|_ $$_/
|
||||
# | $$ $$$| $$| $$ \ $$ \ $$/$$/| $$$$$$$$| $$ \ $$ \ $$| $$$$$$$$| $$ \ $$ | $$
|
||||
# | $$\ $ | $$| $$ | $$ \ $$$/ | $$_____/| $$ | $$ | $$| $$_____/| $$ | $$ | $$ /$$
|
||||
# | $$ \/ | $$| $$$$$$/ \ $/ | $$$$$$$| $$ | $$ | $$| $$$$$$$| $$ | $$ | $$$$/
|
||||
# |__/ |__/ \______/ \_/ \_______/|__/ |__/ |__/ \_______/|__/ |__/ \___/
|
||||
|
||||
# /$$ /$$ /$$ /$$
|
||||
# | $$ | $$ | $$ | $$
|
||||
# | $$$$$$$ /$$ /$$ /$$$$$$ /$$$$$$ /$$$$$$$$ /$$$$$$ | $$ /$$| $$$$$$$ /$$$$$$ /$$ /$$ /$$$$$$ /$$ /$$ /$$$$$$$ /$$$$$$ /$$$$$$
|
||||
# | $$__ $$| $$ | $$ /$$__ $$ |____ $$|____ /$$/ |____ $$| $$ /$$/| $$__ $$ |____ $$| $$ | $$ /$$__ $$| $$ /$$/| $$__ $$ /$$__ $$|_ $$_/
|
||||
# | $$ \ $$| $$ | $$ | $$ \ $$ /$$$$$$$ /$$$$/ /$$$$$$$| $$$$$$/ | $$ \ $$ /$$$$$$$| $$ | $$| $$$$$$$$ \ $$/$$/ | $$ \ $$| $$$$$$$$ | $$
|
||||
# | $$ | $$| $$ | $$ | $$ | $$ /$$__ $$ /$$__/ /$$__ $$| $$_ $$ | $$ | $$ /$$__ $$| $$ | $$| $$_____/ \ $$$/ | $$ | $$| $$_____/ | $$ /$$
|
||||
# | $$$$$$$/| $$$$$$$ | $$$$$$$| $$$$$$$ /$$$$$$$$| $$$$$$$| $$ \ $$| $$$$$$$/| $$$$$$$| $$$$$$$| $$$$$$$ \ $//$$| $$ | $$| $$$$$$$ | $$$$/
|
||||
# |_______/ \____ $$ \____ $$ \_______/|________/ \_______/|__/ \__/|_______/ \_______/ \____ $$ \_______/ \_/|__/|__/ |__/ \_______/ \___/
|
||||
# /$$ | $$ /$$ \ $$ /$$ | $$
|
||||
# | $$$$$$/ | $$$$$$/ | $$$$$$/
|
||||
# \______/ \______/ \______/
|
||||
Reference in New Issue
Block a user