DatabaseCreation: skripta_najdi_mentor.py

File skripta_najdi_mentor.py, 42.0 KB (added by 231067, 7 days ago)
Line 
1"""
2 pip install faker
3"""
4
5import csv
6import os
7import random
8import time
9from faker import Faker
10
11OUTPUT_DIR = "csv_output"
12
13COUNTS = {
14 "User": 10_000_000,
15 "Message": 10_000_000,
16 "Notification": 10_000_000,
17 "Mentorship": 1_000_000,
18 "CommentOpinion": 1_000_000,
19 "Chat": 1_000_000,
20 "University": 10,
21 "Faculty": 60,
22 "Permission": 20,
23 "Role": 10,
24 "UserAttribute": 15,
25 "MentorshipAttribute": 10,
26 "Interest": 100,
27 "Subject": 500,
28 "StudyProgram": 200,
29 "MentorshipType": 10,
30 "User_Role": 200_000,
31 "Role_Permission": 50_000,
32 "User_Subject": 500_000,
33 "User_Interest": 500_000,
34 "Subject_StudyProgram": 50_000,
35 "TopicSuggestion": 2_000_000,
36 "UserAttributeValue": 500_000,
37 "Task": 2_000_000,
38 "MentorshipAttributeValue": 500_000,
39 "Notification_Type": 500_000,
40}
41
42BATCH = 10_000
43
44MK_MALE_NAMES = [
45 "Александар", "Борис", "Васил", "Горан", "Дарко", "Ѓорѓи", "Емил",
46 "Жарко", "Зоран", "Иван", "Јован", "Коста", "Лазар", "Марко", "Никола",
47 "Огнен", "Петар", "Роберт", "Сашо", "Тони", "Филип", "Христо", "Методи",
48 "Бошко", "Димитар", "Ѓоко", "Ненад", "Стефан", "Тодор", "Виктор",
49 "Ацо", "Благоја", "Влатко", "Далибор", "Елвис", "Зафир", "Илија",
50 "Јоце", "Кире", "Љупчо", "Митко", "Наум", "Оливер", "Предраг",
51 "Радован", "Симон", "Трајко", "Урош", "Фросина", "Цветан", "Чедомир",
52]
53
54MK_FEMALE_NAMES = [
55 "Александра", "Билјана", "Валентина", "Гордана", "Данела", "Ѓурѓица",
56 "Елена", "Жаклина", "Зорица", "Ивана", "Јасмина", "Катерина", "Лидија",
57 "Марија", "Наташа", "Оливера", "Петра", "Розита", "Сузана", "Тања",
58 "Фламурта", "Христина", "Цвета", "Шекерие", "Ана", "Бојана",
59 "Весна", "Дивна", "Емилија", "Зана", "Ирена", "Јованка", "Калина",
60 "Лилјана", "Маја", "Нада", "Олга", "Пауна", "Радица", "Сања",
61 "Теодора", "Ула", "Фатима", "Цеца", "Ангела", "Бисера", "Верица",
62 "Даница", "Евица", "Загорка",
63]
64
65MK_MALE_SURNAMES = [
66 "Петровски", "Јовановски", "Илиевски", "Димовски", "Стојановски",
67 "Николовски", "Георгиевски", "Марковски", "Ангеловски", "Василевски",
68 "Ристовски", "Христовски", "Тодоровски", "Поповски", "Коцевски",
69 "Мицевски", "Трајковски", "Атанасовски", "Блажевски", "Велјановски",
70 "Гелевски", "Дамјановски", "Ефтимовски", "Зафировски", "Иванов",
71 "Јаковлевски", "Крстевски", "Лазаревски", "Манчевски", "Наумовски",
72 "Огњановски", "Панчевски", "Радевски", "Симоновски", "Тасевски",
73 "Урдаревски", "Филиповски", "Цветановски", "Шаќири", "Апостолски",
74 "Бојаџиевски", "Велиновски", "Гулевски", "Дончевски", "Ѓоргиевски",
75 "Жежовски", "Зивковски", "Икономовски", "Јанчевски", "Китановски",
76]
77
78MK_FEMALE_SURNAMES = [
79 "Петровска", "Јовановска", "Илиевска", "Димовска", "Стојановска",
80 "Николовска", "Георгиевска", "Марковска", "Ангеловска", "Василевска",
81 "Ристовска", "Христовска", "Тодоровска", "Поповска", "Коцевска",
82 "Мицевска", "Трајковска", "Атанасовска", "Блажевска", "Велјановска",
83 "Гелевска", "Дамјановска", "Ефтимовска", "Зафировска", "Иванова",
84 "Јаковлевска", "Крстевска", "Лазаревска", "Манчевска", "Наумовска",
85 "Огњановска", "Панчевска", "Радевска", "Симоновска", "Тасевска",
86 "Урдаревска", "Филиповска", "Цветановска", "Шаќири", "Апостолска",
87 "Бојаџиевска", "Велиновска", "Гулевска", "Дончевска", "Ѓоргиевска",
88 "Жежовска", "Зивковска", "Икономовска", "Јанчевска", "Китановска",
89]
90
91MK_UNIVERSITIES = [
92 ("Универзитет Св. Кирил и Методиј", "Скопје", "02 3293 293", "проф. д-р Никола Јанкуловски"),
93 ("Универзитет Св. Климент Охридски", "Битола", "047 223 788", "проф. д-р Сашо Коруноски"),
94 ("Универзитет на Југоисточна Европа", "Тетово", "044 356 000", "проф. д-р Буњамин Јашари"),
95 ("Државен Универзитет во Тетово", "Тетово", "044 334 222", "проф. д-р Вјоса Садику"),
96 ("Универзитет Гоце Делчев", "Штип", "032 550 000", "проф. д-р Блажо Боев"),
97 ("Европски Универзитет", "Скопје", "02 3075 570", "проф. д-р Наталија Долтчинска"),
98 ("Меѓународен Балкански Универзитет", "Скопје", "02 3224 455", "проф. д-р Ериван Хасани"),
99 ("Универзитет на Информатичките Науки и Технологии", "Охрид", "046 270 170", "проф. д-р Горан Јаќимовски"),
100 ("МИТ Универзитет", "Скопје", "02 2408 920", "проф. д-р Петар Намичев"),
101 ("Американски Универзитет на Европа", "Скопје", "02 2463 156", "проф. д-р Роберт Никодиновски"),
102]
103
104MK_FACULTIES = [
105 # УКИМ — Скопје
106 ("Факултет за информатички науки и компјутерско инженерство", "бул. Партизански одреди б.б., Скопје", "02 3099 066", "проф. д-р Сашо Гелев"),
107 ("Природно-математички факултет", "бул. Гази Баба б.б., Скопје", "02 3249 900", "проф. д-р Зоран Десподов"),
108 ("Електротехнички факултет", "бул. Гурчинов 18, Скопје", "02 3099 198", "проф. д-р Методија Атанасовски"),
109 ("Машински факултет", "бул. Партизански одреди б.б., Скопје", "02 3099 260", "проф. д-р Атанасе Кочов"),
110 ("Економски факултет", "бул. Крсте Мисирков б.б., Скопје", "02 3286 800", "проф. д-р Горан Петревски"),
111 ("Правен факултет Јустинијан Први", "бул. Гоце Делчев б.б., Скопје", "02 3226 626", "проф. д-р Тодор Кошевалиски"),
112 ("Медицински факултет", "бул. Мајка Тереза 17, Скопје", "02 3125 044", "проф. д-р Никола Камчев"),
113 ("Филолошки факултет Блаже Конески", "бул. Гоце Делчев б.б., Скопје", "02 3227 701", "проф. д-р Елена Јованова-Грујовска"),
114 ("Филозофски факултет", "бул. Крсте Мисирков 2, Скопје", "02 3116 520", "проф. д-р Барбара Саракинска"),
115 ("Архитектонски факултет", "бул. Партизански одреди б.б., Скопје", "02 3099 270", "проф. д-р Мимоза Добрикова"),
116 ("Градежен факултет", "бул. Партизански одреди б.б., Скопје", "02 3099 200", "проф. д-р Зоран Рецески"),
117 ("Фармацевтски факултет", "Мајка Тереза 47, Скопје", "02 3126 032", "проф. д-р Марија Главаш Додов"),
118 # УКЛО — Битола
119 ("Технички факултет", "ул. Иво Лола Рибар б.б., Битола", "047 207 700", "проф. д-р Мишо Докузовски"),
120 ("Економски факултет Прилеп", "ул. Горце Петров б.б., Прилеп", "048 426 655", "проф. д-р Трајко Мицески"),
121 ("Факултет за туризам и угостителство", "ул. Маршал Тито б.б., Охрид", "046 262 147", "проф. д-р Лидија Симпсон"),
122 ("Биотехнички факултет", "ул. Борки б.б., Битола", "047 203 600", "проф. д-р Душан Спасов"),
123 ("Факултет за безбедност", "ул. Маршал Тито б.б., Битола", "047 237 011", "проф. д-р Никола Дујовски"),
124 # УГД — Штип
125 ("Факултет за информатика", "бул. Гоце Делчев б.б., Штип", "032 550 005", "проф. д-р Зоран Здравев"),
126 ("Земјоделски факултет", "бул. Гоце Делчев б.б., Штип", "032 550 013", "проф. д-р Љупчо Михајловски"),
127 ("Правен факултет", "бул. Гоце Делчев б.б., Штип", "032 550 018", "проф. д-р Јован Андоновски"),
128 # ДУТ — Тетово
129 ("Факултет за математички и природни науки", "ул. Илинден б.б., Тетово", "044 334 222", "проф. д-р Шефкет Арслани"),
130 ("Факултет за економски науки", "ул. Илинден б.б., Тетово", "044 334 233", "проф. д-р Арбен Ислами"),
131 # УЈИE — Тетово
132 ("Факултет за современи науки и технологии", "ул. Илинден б.б., Тетово", "044 356 020", "проф. д-р Бесарт Рамадани"),
133 ("Бизнис и економија", "ул. Илинден б.б., Тетово", "044 356 030", "проф. д-р Фатмир Азири"),
134]
135
136MK_STUDY_PROGRAMS = [
137 "Компјутерски науки", "Информатика", "Компјутерско инженерство",
138 "Електротехника и автоматика", "Телекомуникации",
139 "Математика", "Физика", "Хемија", "Биологија",
140 "Економија", "Финансии и сметководство", "Менаџмент", "Маркетинг",
141 "Право", "Криминалистика", "Безбедност",
142 "Медицина", "Стоматологија", "Фармација",
143 "Градежништво", "Архитектура", "Машинство",
144 "Туризам", "Угостителство",
145 "Македонски јазик", "Англиски јазик", "Германски јазик", "Француски јазик",
146 "Психологија", "Педагогија", "Социологија", "Философија",
147 "Земјоделство", "Хортикултура",
148 "Применета математика", "Статистика", "Актуарство",
149 "Кибербезбедност", "Вештачка интелигенција", "Анализа на податоци",
150]
151
152MK_SUBJECTS = [
153 "Математика 1", "Математика 2", "Математика 3",
154 "Дискретна математика", "Линеарна алгебра", "Нумерички методи",
155 "Веројатност и статистика", "Логика",
156 "Вовед во програмирање", "Програмирање во Јава", "Програмирање во Пајтон",
157 "Објектно-ориентирано програмирање", "Функционално програмирање",
158 "Алгоритми и структури на податоци", "Напредни алгоритми",
159 "Бази на податоци", "Напредни бази на податоци", "NoSQL бази",
160 "Оперативни системи", "Компјутерски мрежи", "Дистрибуирани системи",
161 "Компајлери", "Теорија на пресметување",
162 "Вештачка интелигенција", "Машинско учење", "Длабоко учење",
163 "Обработка на природен јазик", "Компјутерска визија",
164 "Веб програмирање", "Мобилни апликации", "Развој на игри",
165 "Кибербезбедност", "Криптографија", "Форензика",
166 "Софтверско инженерство", "Тестирање на софтвер", "Agile методологии",
167 "Анализа на податоци", "Визуелизација на податоци", "Big Data",
168 "Облак пресметување", "IoT системи", "Вградени системи",
169 "Електроника", "Дигитална електроника", "Електрични кола",
170 "Телекомуникации", "Безжични мрежи", "Оптички влакна",
171 "Микроконтролери", "Роботика", "Автоматско управување",
172 "Економија", "Микроекономија", "Макроекономија",
173 "Сметководство", "Финансиски менаџмент", "Банкарство",
174 "Маркетинг", "Стратегиски менаџмент", "Бизнис планирање",
175 "Право", "Граѓанско право", "Трговско право",
176 "Медицина", "Анатомија", "Физиологија", "Патологија",
177 "Фармакологија", "Биохемија", "Микробиологија",
178 "Психологија", "Педагогија", "Социологија",
179 "Математичка анализа", "Диференцијални равенки",
180 "Физика 1", "Физика 2", "Термодинамика",
181 "Хемија", "Органска хемија", "Аналитичка хемија",
182 "Градежна механика", "Архитектонско проектирање",
183 "Машинство", "Термотехника", "Хидраулика",
184 "Туризам", "Туристичка географија", "Хотелски менаџмент",
185 "Македонски јазик", "Англиски јазик", "Германски јазик",
186 "Француски јазик", "Руски јазик", "Шпански јазик",
187 "Историја на Македонија", "Политикологија",
188]
189
190MK_INTERESTS = [
191 "Вештачка интелигенција", "Машинско учење", "Длабоко учење",
192 "Веб развој", "Мобилен развој", "Игри", "Кибербезбедност",
193 "Бази на податоци", "Big Data", "Облак пресметување",
194 "IoT", "Роботика", "Блокчеин", "Криптографија",
195 "Отворен код", "DevOps", "Microservices", "API dizajn",
196 "Математика", "Статистика", "Теорија на графови",
197 "Физика", "Хемија", "Биологија", "Медицина",
198 "Право", "Економија", "Финансии", "Претприемаштво",
199 "Маркетинг", "Продажба", "Брендирање",
200 "Музика", "Сликарство", "Фотографија", "Видео",
201 "Спорт", "Планинарење", "Патување", "Готвење",
202 "Книги", "Филм", "Театар", "Танц",
203 "Волонтирање", "Еколошки прашања", "Одржлив развој",
204 "Јазици", "Превод", "Лингвистика",
205 "Психологија", "Педагогија", "Социологија", "Философија",
206 "Архитектура", "Урбанизам", "Дизајн", "UX/UI",
207 "Историја", "Политика", "Меѓународни односи",
208 "Биотехнологија", "Фармација", "Нанотехнологија",
209 "Астрономија", "Метеорологија", "Геологија",
210 "Земјоделство", "Хортикултура", "Ветерина",
211 "Туризам", "Угостителство", "Авантура",
212 "Фитнес", "Јога", "Медитација",
213 "Шах", "Стратешки игри", "Е-спорт",
214 "Хакатони", "Натпревари", "Олимпијади",
215 "Научни истражувања", "Академско пишување", "Публикации",
216 "Предавање", "Менторирање", "Студентски организации",
217 "Стартапи", "Иновации", "Трансфер на технологии",
218 "Дата новинарство", "Фект-чекинг", "Социјални медиуми",
219 "Аниме", "Стрипови", "Научна фантастика",
220 "Моделирање", "3D принтање", "Дронови",
221 "Сигурност на мрежи", "Пенетрациско тестирање", "CTF натпревари",
222 "Квантно пресметување", "Биоинформатика", "Геоинформатика",
223 "Правна регулатива на AI", "Дигитална трансформација",
224 "Финансиска технологија", "Криптовалути", "NFT",
225 "Образование", "Е-учење", "Едукативен софтвер",
226]
227
228MK_MENTORSHIP_TYPES = [
229 "Дипломска работа", "Магистерска теза", "Докторска дисертација",
230 "Практична настава", "Истражувачки проект", "Научна статија",
231 "Компаниска пракса", "Индустриски проект", "Семинарска работа",
232 "Студентски проект",
233]
234
235MK_USER_ATTRIBUTES = [
236 "Биографија", "Индекс", "Семестар", "Циклус", "Наслов",
237 "Линкедин профил", "GitHub профил", "Личен веб сајт",
238 "Дата на вработување", "Кабинет", "Работно искуство",
239 "Јазици кои ги зборува", "Сертификати", "Публикации",
240 "Истражувачки области",
241]
242
243MK_MENTORSHIP_ATTRIBUTES = [
244 "Цел на менторство", "Очекуван резултат", "Седмичен ангажман",
245 "Место на средби", "Главен предмет", "Дополнителни барања",
246 "Буџет", "Компанија партнер", "Оценка на завршување",
247 "Забелешки",
248]
249
250MK_PERMISSIONS = [
251 "view_profile", "edit_profile", "delete_profile",
252 "create_mentorship", "edit_mentorship", "delete_mentorship",
253 "view_mentorship", "approve_request", "reject_request",
254 "send_message", "delete_message", "view_comments",
255 "post_comment", "delete_comment", "manage_users",
256 "manage_roles", "manage_system", "view_reports",
257 "export_data", "admin_panel",
258]
259
260MK_ROLES = [
261 "Администратор", "Студент", "Ментор", "Модератор", "Гостин",
262 "Супер Администратор", "Поддршка", "Прегледувач", "Уредник", "Менаџер",
263]
264
265MK_TOPIC_KEYWORDS = [
266 "Анализа на", "Дизајн на", "Развој на", "Имплементација на",
267 "Оптимизација на", "Компарација на", "Евалуација на", "Истражување на",
268]
269
270MK_TOPIC_SUBJECTS = [
271 "систем за препораки", "алгоритам за машинско учење",
272 "веб апликација", "мобилна апликација", "база на податоци",
273 "мрежна безбедност", "блокчеин систем", "IoT платформа",
274 "систем за автентикација", "алатка за визуелизација",
275 "пребарувач", "chatbot", "систем за мониторирање",
276 "платформа за е-учење", "апликација за здравство",
277 "систем за управување со документи", "API gateway",
278 "микросервисна архитектура", "систем за верификација",
279 "платформа за менторство",
280]
281
282MK_CHAT_TOPICS = [
283 "Консултација за дипломска", "Прашање за проект", "Договор за средба",
284 "Повратна информација", "Следен чекор", "Техничко прашање",
285 "Преглед на код", "Коментар за теза", "Пракса",
286 "Истражување", "Подготовка за одбрана", "Корекции",
287]
288
289MK_CITIES = [
290 "Скопје", "Битола", "Куманово", "Прилеп", "Тетово",
291 "Велес", "Штип", "Охрид", "Гостивар", "Струmica",
292 "Кичево", "Кавадарци", "Гевгелија", "Дебар", "Ресен",
293]
294
295# ──────────────────────────────────────────────
296# HELPERS
297# ──────────────────────────────────────────────
298fake = Faker()
299
300def log(msg):
301 print(f"[{time.strftime('%H:%M:%S')}] {msg}")
302
303def dt():
304 return fake.date_time_between('-2y', 'now').strftime('%Y-%m-%d %H:%M:%S')
305
306def dt_past():
307 return fake.date_time_between('-60y', '-5y').strftime('%Y-%m-%d %H:%M:%S')
308
309def dt_future():
310 return fake.date_time_between('now', '+2y').strftime('%Y-%m-%d %H:%M:%S')
311
312def mk_name():
313 if random.random() < 0.5:
314 return random.choice(MK_MALE_NAMES), random.choice(MK_MALE_SURNAMES)
315 else:
316 return random.choice(MK_FEMALE_NAMES), random.choice(MK_FEMALE_SURNAMES)
317
318def mk_username(name, surname, uid):
319 n = name.lower().replace('ѓ','gj').replace('ќ','kj').replace('ж','zh')\
320 .replace('ш','sh').replace('ч','ch').replace('џ','dz')\
321 .replace('ц','c').replace('љ','lj').replace('њ','nj')\
322 .replace('а','a').replace('б','b').replace('в','v')\
323 .replace('г','g').replace('д','d').replace('е','e')\
324 .replace('з','z').replace('и','i').replace('ј','j')\
325 .replace('к','k').replace('л','l').replace('м','m')\
326 .replace('н','n').replace('о','o').replace('п','p')\
327 .replace('р','r').replace('с','s').replace('т','t')\
328 .replace('у','u').replace('ф','f').replace('х','h')\
329 .replace('ѕ','dz')
330 s = surname.lower().replace('ѓ','gj').replace('ќ','kj').replace('ж','zh')\
331 .replace('ш','sh').replace('ч','ch').replace('џ','dz')\
332 .replace('ц','c').replace('љ','lj').replace('њ','nj')\
333 .replace('а','a').replace('б','b').replace('в','v')\
334 .replace('г','g').replace('д','d').replace('е','e')\
335 .replace('з','z').replace('и','i').replace('ј','j')\
336 .replace('к','k').replace('л','l').replace('м','m')\
337 .replace('н','n').replace('о','o').replace('п','p')\
338 .replace('р','r').replace('с','s').replace('т','t')\
339 .replace('у','u').replace('ф','f').replace('х','h')\
340 .replace('ѕ','dz')
341 return f"{n}.{s}.{uid}"[:50]
342
343def mk_email(username):
344 domains = ["ukim.edu.mk", "uklo.edu.mk", "ugd.edu.mk", "unite.edu.mk",
345 "seeu.edu.mk", "gmail.com", "yahoo.com", "outlook.com",
346 "finki.ukim.mk", "tmf.ukim.mk"]
347 return f"{username}@{random.choice(domains)}"
348
349def mk_topic():
350 kw = random.choice(MK_TOPIC_KEYWORDS)
351 subj = random.choice(MK_TOPIC_SUBJECTS)
352 return f"{kw} {subj}"
353
354def mk_biography(role):
355 if role == "mentor":
356 titles = ["Редовен професор", "Вонреден професор", "Доцент", "Асистент", "Виш асистент"]
357 t = random.choice(titles)
358 areas = random.sample(MK_INTERESTS[:30], 2)
359 return f"{t} на {random.choice(MK_FACULTIES)[0][:40]}. Истражувачки интереси: {areas[0]}, {areas[1]}."
360 else:
361 yr = random.randint(1, 4)
362 prog = random.choice(MK_STUDY_PROGRAMS)
363 return f"Студент на {yr} год. — {prog}. Заинтересиран за {random.choice(MK_INTERESTS[:40])}."
364
365id_max = {}
366
367def rand_id(table):
368 return random.randint(1, id_max[table])
369
370def write_table(filename, columns, row_gen, total):
371 path = os.path.join(OUTPUT_DIR, filename)
372 with open(path, 'w', newline='', encoding='utf-8') as f:
373 writer = csv.writer(f)
374 writer.writerow(columns)
375 done = 0
376 while done < total:
377 chunk = min(BATCH, total - done)
378 writer.writerows(row_gen(done + 1, done + chunk))
379 done += chunk
380 print(f" {done:,} / {total:,}", end='\r')
381 print()
382 table = filename.replace('.csv', '')
383 id_max[table] = total
384 log(f" Saved → {path}")
385
386# ──────────────────────────────────────────────
387# ROW GENERATORS
388# ──────────────────────────────────────────────
389
390def rows_university(id_start, id_end):
391 rows = []
392 pool = MK_UNIVERSITIES * ((id_end - id_start + 2) // len(MK_UNIVERSITIES) + 1)
393 for i in range(id_start, id_end + 1):
394 u = pool[i - 1]
395 name, city, phone, rector = u
396 addr = f"бул. {random.choice(['Гоце Делчев', 'Партизански одреди', 'Кирил и Методиј'])} б.б., {city}"
397 rows.append((i, name, f"Државен универзитет во {city}.", dt_past(), addr, phone, rector))
398 return rows
399
400def rows_faculty(id_start, id_end):
401 rows = []
402 pool = MK_FACULTIES * ((id_end - id_start + 2) // len(MK_FACULTIES) + 1)
403 for i in range(id_start, id_end + 1):
404 f = pool[i - 1]
405 fname, addr, phone, dean = f
406 univ_id = random.randint(1, id_max['University'])
407 rows.append((i, fname, f"Акредитиран факултет.", dt_past(), addr, phone, dean, univ_id))
408 return rows
409
410def rows_permission(id_start, id_end):
411 pool = MK_PERMISSIONS
412 return [(i, pool[(i - 1) % len(pool)]) for i in range(id_start, id_end + 1)]
413
414def rows_role(id_start, id_end):
415 return [(i, MK_ROLES[(i - 1) % len(MK_ROLES)]) for i in range(id_start, id_end + 1)]
416
417def rows_user_attribute(id_start, id_end):
418 pool = MK_USER_ATTRIBUTES
419 return [(i, pool[(i - 1) % len(pool)]) for i in range(id_start, id_end + 1)]
420
421def rows_mentorship_attribute(id_start, id_end):
422 pool = MK_MENTORSHIP_ATTRIBUTES
423 return [(i, pool[(i - 1) % len(pool)]) for i in range(id_start, id_end + 1)]
424
425def rows_interest(id_start, id_end):
426 pool = MK_INTERESTS * ((id_end - id_start + 2) // len(MK_INTERESTS) + 1)
427 return [
428 (i, pool[i - 1], f"Интерес поврзан со областа на {pool[i-1].lower()}.")
429 for i in range(id_start, id_end + 1)
430 ]
431
432def rows_subject(id_start, id_end):
433 pool = MK_SUBJECTS * ((id_end - id_start + 2) // len(MK_SUBJECTS) + 1)
434 return [
435 (i, pool[i - 1], f"Предмет кој ги опфаќа основите на {pool[i-1].lower()}.")
436 for i in range(id_start, id_end + 1)
437 ]
438
439def rows_study_program(id_start, id_end):
440 pool = MK_STUDY_PROGRAMS * ((id_end - id_start + 2) // len(MK_STUDY_PROGRAMS) + 1)
441 return [
442 (i, pool[i - 1], f"Студиска програма за {pool[i-1].lower()}.", rand_id('Faculty'))
443 for i in range(id_start, id_end + 1)
444 ]
445
446def rows_mentorship_type(id_start, id_end):
447 pool = MK_MENTORSHIP_TYPES
448 return [
449 (i, pool[(i - 1) % len(pool)], rand_id('MentorshipAttribute'))
450 for i in range(id_start, id_end + 1)
451 ]
452
453def rows_user(id_start, id_end):
454 rows = []
455 for i in range(id_start, id_end + 1):
456 name, surname = mk_name()
457 uname = mk_username(name, surname, i)
458 email = mk_email(uname)
459 is_mentor = (i % 5 == 0) # ~20% mentori
460 bio = mk_biography("mentor" if is_mentor else "student")
461 rows.append((
462 i, uname, fake.sha256(), email,
463 name, surname, bio,
464 rand_id('Faculty')
465 ))
466 return rows
467
468def rows_user_role(id_start, id_end):
469 return [
470 (i, rand_id('User'), rand_id('Role'))
471 for i in range(id_start, id_end + 1)
472 ]
473
474def rows_role_permission(id_start, id_end):
475 return [
476 (i, rand_id('Role'), rand_id('Permission'))
477 for i in range(id_start, id_end + 1)
478 ]
479
480def rows_user_subject(id_start, id_end):
481 return [
482 (i, rand_id('Subject'), rand_id('User'), random.randint(1, 8))
483 for i in range(id_start, id_end + 1)
484 ]
485
486def rows_user_interest(id_start, id_end):
487 return [
488 (i, rand_id('User'), rand_id('Interest'))
489 for i in range(id_start, id_end + 1)
490 ]
491
492def rows_subject_study_program(id_start, id_end):
493 return [
494 (i, rand_id('Subject'), rand_id('StudyProgram'))
495 for i in range(id_start, id_end + 1)
496 ]
497
498def rows_topic_suggestion(id_start, id_end):
499 return [
500 (i, mk_topic(),
501 f"Предлог тема за истражување и анализа во областа на {random.choice(MK_INTERESTS[:40]).lower()}.",
502 dt(), random.choice([True, False]),
503 rand_id('User'), rand_id('User'), rand_id('Subject'))
504 for i in range(id_start, id_end + 1)
505 ]
506
507def rows_user_attribute_value(id_start, id_end):
508 sample_values = [
509 "2024/0001", "2023/0145", "2022/0312", "3", "4", "2", "1",
510 "прв циклус", "втор циклус", "трет циклус",
511 "linkedin.com/in/petar.petrovski", "github.com/petar",
512 "Скопје", "Битола", "Охрид", "Тетово", "Штип",
513 ]
514 return [
515 (i, random.choice(sample_values), rand_id('User'), rand_id('UserAttribute'))
516 for i in range(id_start, id_end + 1)
517 ]
518
519def rows_mentorship(id_start, id_end):
520 return [
521 (i, rand_id('User'), rand_id('User'),
522 rand_id('TopicSuggestion'), rand_id('MentorshipType'))
523 for i in range(id_start, id_end + 1)
524 ]
525
526def rows_mentorship_attribute_value(id_start, id_end):
527 sample_values = [
528 "Секоја недела", "Двапати месечно", "По потреба",
529 "Онлајн", "Во кабинет", "Хибридно",
530 "3 месеци", "6 месеци", "1 година",
531 "ФИНКИ", "Машински факултет", "Економски факултет",
532 ]
533 return [
534 (i, random.choice(sample_values),
535 rand_id('Mentorship'), rand_id('MentorshipAttribute'))
536 for i in range(id_start, id_end + 1)
537 ]
538
539def rows_task(id_start, id_end):
540 task_descriptions = [
541 "Напиши прв нацрт на вовед", "Имплементирај го модулот за автентикација",
542 "Подготви литературен преглед", "Постави база на податоци",
543 "Напиши единечни тестови", "Изработи UML дијаграми",
544 "Подготви презентација", "Направи истражување на корисници",
545 "Пополни поглавје 2", "Испрати нацрт за преглед",
546 "Поправи коментари од ментор", "Финализирај методологија",
547 "Собери податоци за истражување", "Анализирај резултати",
548 "Подготви заклучок",
549 ]
550 return [
551 (i, dt_future(), dt(), random.randint(0, 3),
552 random.choice(task_descriptions), rand_id('Mentorship'))
553 for i in range(id_start, id_end + 1)
554 ]
555
556def rows_chat(id_start, id_end):
557 return [
558 (i, random.choice(MK_CHAT_TOPICS),
559 f"Разговор за {random.choice(MK_MENTORSHIP_TYPES).lower()}",
560 random.randint(0, 2), dt(),
561 rand_id('User'), rand_id('User'))
562 for i in range(id_start, id_end + 1)
563 ]
564
565def rows_message(id_start, id_end):
566 messages_mk = [
567 "Здраво, можеме ли да закажеме средба оваа недела?",
568 "Ги прегледав вашите коментари и направив корекции.",
569 "Имам прашање во врска со методологијата.",
570 "Ве молам погледнете го последниот нацрт.",
571 "Кога сте слободни за консултација?",
572 "Ги завршив задачите за оваа недела.",
573 "Можете ли да ми препорачате литература?",
574 "Имам проблем со имплементацијата.",
575 "Благодарам за вашите совети!",
576 "Дали е добро вака или треба промени?",
577 "Подготвен сум за следната фаза.",
578 "Може ли да разговараме за оценувањето?",
579 "Пратив го финалниот документ на мејл.",
580 "Треба ли да додадам уште примери?",
581 "Работам на поглавје 3, наскоро ќе пратам.",
582 ]
583 return [
584 (i, random.choice(messages_mk), random.choice([True, False]),
585 dt(), rand_id('Chat'), rand_id('User'))
586 for i in range(id_start, id_end + 1)
587 ]
588
589def rows_comment_opinion(id_start, id_end):
590 comments_mk = [
591 "Одличен ментор, многу стручен и достапен.",
592 "Многу помагаше во текот на целиот процес.",
593 "Даваше јасни насоки и корисни совети.",
594 "Понекогаш тешко достапен, но кога се сретневме беше корисно.",
595 "Препорачувам го на сите студенти.",
596 "Прекрасно менторство, научив многу.",
597 "Беше флексибилен и разбирлив.",
598 "Даваше конструктивна критика.",
599 "Многу знае за областа, инспиративен.",
600 "Добар ментор, само понекогаш доцни со повратна информација.",
601 ]
602 return [
603 (i, random.choice(comments_mk), random.randint(1, 5),
604 dt(), random.randint(0, 2),
605 rand_id('User'), rand_id('User'))
606 for i in range(id_start, id_end + 1)
607 ]
608
609def rows_notification(id_start, id_end):
610 notifications_mk = [
611 "Имате ново барање за контакт.",
612 "Менторот го прифати вашето барање.",
613 "Имате нова порака.",
614 "Добивте нов коментар.",
615 "Вашата задача е оценета.",
616 "Новата тема е достапна.",
617 "Терминот е потврден.",
618 "Потсетување за претстојниот рок.",
619 "Вашето мислење е прифатено.",
620 "Системска нотификација.",
621 ]
622 return [
623 (i, random.choice(notifications_mk), dt(),
624 random.choice([True, False]),
625 rand_id('User'),
626 rand_id('CommentOpinion'),
627 rand_id('Message'))
628 for i in range(id_start, id_end + 1)
629 ]
630
631def rows_notification_type(id_start, id_end):
632 types = ["информација", "предупредување", "тревога", "порака", "систем"]
633 return [
634 (i, random.choice(types), rand_id('Notification'))
635 for i in range(id_start, id_end + 1)
636 ]
637
638# ──────────────────────────────────────────────
639# TABLE MANIFEST
640# ──────────────────────────────────────────────
641TABLES = [
642 ("University.csv", ["ID","Name","Description","DateFounded","Address","Contact","Rector"], rows_university),
643 ("Faculty.csv", ["ID","Name","Description","DateFounded","Address","Contact","Dean","UniversityID"], rows_faculty),
644 ("Permission.csv", ["ID","PermissionName"], rows_permission),
645 ("Role.csv", ["ID","RoleName"], rows_role),
646 ("UserAttribute.csv", ["ID","Name"], rows_user_attribute),
647 ("MentorshipAttribute.csv", ["ID","Name"], rows_mentorship_attribute),
648 ("Interest.csv", ["ID","Name","Description"], rows_interest),
649 ("Subject.csv", ["ID","Name","Description"], rows_subject),
650 ("StudyProgram.csv", ["ID","Name","Description","FacultyID"], rows_study_program),
651 ("MentorshipType.csv", ["ID","Type","MentorshipAttributeID"], rows_mentorship_type),
652 ("User.csv", ["ID","Username","Password","Email","Name","Surname","Biography","FacultyID"], rows_user),
653 ("User_Role.csv", ["ID","UserID","RoleID"], rows_user_role),
654 ("Role_Permission.csv", ["ID","RoleID","PermissionID"], rows_role_permission),
655 ("User_Subject.csv", ["ID","SubjectID","UserID","Semester"], rows_user_subject),
656 ("User_Interest.csv", ["ID","UserID","InterestID"], rows_user_interest),
657 ("Subject_StudyProgram.csv", ["ID","SubjectID","StudyProgramID"], rows_subject_study_program),
658 ("TopicSuggestion.csv", ["ID","Name","Description","Date","isAvailable","StudentID","MentorID","SubjectID"], rows_topic_suggestion),
659 ("UserAttributeValue.csv", ["ID","Value","UserID","UserAttributeID"], rows_user_attribute_value),
660 ("Mentorship.csv", ["ID","StudentID","MentorID","TopicSuggestionID","MentorshipTypeID"], rows_mentorship),
661 ("MentorshipAttributeValue.csv", ["ID","Value","MentorshipID","MentorshipAttributeID"], rows_mentorship_attribute_value),
662 ("Task.csv", ["ID","EndDate","StartDate","Status","Description","MentorshipID"], rows_task),
663 ("Chat.csv", ["ID","Title","Topic","Status","Date","StudentID","MentorID"], rows_chat),
664 ("Message.csv", ["ID","Content","isRead","Timestamp","ChatID","UserID"], rows_message),
665 ("CommentOpinion.csv", ["ID","Comment","MentorRating","Timestamp","Status","StudentID","MentorID"], rows_comment_opinion),
666 ("Notification.csv", ["ID","Content","Timestamp","isRead","UserToNotifyID","CommentOpinionID","MessageID"], rows_notification),
667 ("Notification_Type.csv", ["ID","Type","NotificationID"], rows_notification_type),
668]
669
670# ──────────────────────────────────────────────
671# MAIN
672# ──────────────────────────────────────────────
673def main():
674 os.makedirs(OUTPUT_DIR, exist_ok=True)
675 log(f"Запишување CSV во: {os.path.abspath(OUTPUT_DIR)}/")
676 log("Ова ќе потрае малку за поголемите табели — земи кафе.\n")
677
678 for filename, columns, gen_fn in TABLES:
679 table = filename.replace('.csv', '')
680 n = COUNTS[table]
681 log(f"Генерирање {n:,} редови → {filename}")
682 write_table(filename, columns, gen_fn, n)
683
684 log("\nГотово!")
685 log("Увоз: COPY \"TableName\" FROM '/full/path/csv_output/TableName.csv' CSV HEADER;")
686
687if __name__ == "__main__":
688 t0 = time.time()
689 main()
690 log(f"Вкупно време: {(time.time() - t0) / 60:.1f} мин")