PROECT.PY 57 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168
  1. import tkinter as tk
  2. from tkinter import messagebox
  3. import random
  4. import os
  5. from pathlib import Path
  6. from typing import Dict, List, Optional, Tuple
  7. # Попытка импорта PIL для работы с изображениями
  8. try:
  9. from PIL import Image
  10. PIL_AVAILABLE = True
  11. except ImportError:
  12. PIL_AVAILABLE = False
  13. print("PIL (Pillow) не установлен. Установите: pip install Pillow")
  14. # ==================== КОНСТАНТЫ ====================
  15. WINDOW_SIZE = "1000x700"
  16. IMAGES_FOLDER = "quiz_images"
  17. SUPPORTED_FORMATS = ('.jpg', '.jpeg', '.png', '.bmp', '.ico', '.tiff')
  18. DEFAULT_COLORS = [
  19. '#f0f8ff', '#f5f5dc', '#e6e6fa', '#ffe4e1', '#f0fff0',
  20. '#fff0f5', '#e0ffff', '#faf0e6', '#fffacd', '#f8f8ff'
  21. ]
  22. # ==================== СПИСОК ВОПРОСОВ ====================
  23. questions = [
  24. {
  25. 'id': 1,
  26. 'question': 'Что понимается под "персональными данными" согласно законодательству?',
  27. 'options': [
  28. 'Только паспортные данные и фотографии',
  29. 'Любая информация, прямо или косвенно относящаяся к конкретному физическому лицу',
  30. 'Только контактные данные человека',
  31. 'Информация о юридических лицах'
  32. ],
  33. 'correct': 1,
  34. 'explanation': 'Персональные данные - любые сведения, которые относятся, непосредственно либо косвенно, к конкретному физическому лицу.',
  35. 'image': 'q1.jpg',
  36. 'bg_color': None
  37. },
  38. {
  39. 'id': 2,
  40. 'question': 'Кто такой "оператор" персональных данных?',
  41. 'options': [
  42. 'Человек, чьи данные обрабатываются',
  43. 'Государственный орган, контролирующий защиту данных',
  44. 'Лицо или орган, осуществляющий обработку ПД и определяющий цели обработки',
  45. 'Сотрудник, работающий с базами данных'
  46. ],
  47. 'correct': 2,
  48. 'explanation': 'Оператор - лицо или орган, осуществляющий обработку персональных данных и определяющий цели обработки, состав данных и действия с ними.',
  49. 'image': 'q2.jpg',
  50. 'bg_color': None
  51. },
  52. {
  53. 'id': 3,
  54. 'question': 'Что включает в себя система защиты персональных данных?',
  55. 'options': [
  56. 'Только антивирусное программное обеспечение',
  57. 'Только организационные меры',
  58. 'Организационные и технические меры, определенные с учетом актуальных угроз',
  59. 'Только физическую охрану помещений'
  60. ],
  61. 'correct': 2,
  62. 'explanation': 'Система защиты включает организационные и технические меры, определенные с учетом актуальных угроз безопасности.',
  63. 'image': 'q3.jpg',
  64. 'bg_color': None
  65. },
  66. {
  67. 'id': 5,
  68. 'question': 'Сколько уровней защищенности персональных данных устанавливается при их обработке в информационных системах?',
  69. 'options': [
  70. '2 уровня',
  71. '3 уровня',
  72. '4 уровня',
  73. '5 уровней'
  74. ],
  75. 'correct': 2,
  76. 'explanation': 'При обработке персональных данных в информационных системах устанавливаются 4 уровня защищенности.',
  77. 'image': 'q5.jpg',
  78. 'bg_color': None
  79. },
  80. {
  81. 'id': 6,
  82. 'question': 'Какие данные относятся к специальным категориям персональных данных?',
  83. 'options': [
  84. 'ФИО и адрес проживания',
  85. 'Информация о расовой принадлежности, политических взглядах, здоровье',
  86. 'Номер телефона и email',
  87. 'Место работы и должность'
  88. ],
  89. 'correct': 1,
  90. 'explanation': 'К специальным категориям относятся данные о расовой принадлежности, политических взглядах, религиозных убеждениях, здоровье.',
  91. 'image': 'q6.jpg',
  92. 'bg_color': None
  93. },
  94. {
  95. 'id': 7,
  96. 'question': 'Что относится к биометрическим персональным данным?',
  97. 'options': [
  98. 'ФИО и дата рождения',
  99. 'Физиологические особенности для идентификации: отпечатки пальцев, ДНК, группа крови',
  100. 'Номер паспорта',
  101. 'Адрес проживания'
  102. ],
  103. 'correct': 1,
  104. 'explanation': 'Биометрические данные - физиологические особенности, используемые для идентификации личности.',
  105. 'image': 'q7.jpg',
  106. 'bg_color': None
  107. },
  108. {
  109. 'id': 8,
  110. 'question': 'Как часто должен проводиться контроль за выполнением требований защиты ПД?',
  111. 'options': [
  112. 'Ежемесячно',
  113. 'Ежегодно',
  114. 'Не реже 1 раза в 3 года',
  115. 'Один раз в 5 лет'
  116. ],
  117. 'correct': 2,
  118. 'explanation': 'Контроль проводится не реже 1 раза в 3 года в сроки, определяемые оператором.',
  119. 'image': 'q8.jpg',
  120. 'bg_color': None
  121. },
  122. {
  123. 'id': 9,
  124. 'question': 'Какой федеральный закон регулирует защиту персональных данных в России?',
  125. 'options': [
  126. 'ФЗ "Об информации"',
  127. 'Федеральный закон №152-ФЗ "О персональных данных"',
  128. 'ФЗ "О связи"',
  129. 'ФЗ "О безопасности"'
  130. ],
  131. 'correct': 1,
  132. 'explanation': 'В России требования к обработке и защите персональных данных определяет Федеральный закон №152-ФЗ "О персональных данных".',
  133. 'image': 'q9.jpg',
  134. 'bg_color': None
  135. },
  136. {
  137. 'id': 10,
  138. 'question': 'Что такое GDPR?',
  139. 'options': [
  140. 'Российский закон о данных',
  141. 'Американский стандарт безопасности',
  142. 'Европейский регламент по защите данных',
  143. 'Международный стандарт шифрования'
  144. ],
  145. 'correct': 2,
  146. 'explanation': 'GDPR - Общий регламент по защите данных, служит правилом для защиты личных данных граждан ЕС.',
  147. 'image': 'q10.jpg',
  148. 'bg_color': None
  149. },
  150. {
  151. 'id': 11,
  152. 'question': 'Какие требования предъявляются к сбору персональных данных?',
  153. 'options': [
  154. 'Сбор только с согласия субъекта и ограничение только необходимыми данными',
  155. 'Сбор любой доступной информации',
  156. 'Сбор без согласия, если это удобно',
  157. 'Только сбор через официальные запросы'
  158. ],
  159. 'correct': 0,
  160. 'explanation': 'Персональные данные могут собираться только при согласии субъекта и ограничиваться только необходимыми данными.',
  161. 'image': 'q11.jpg',
  162. 'bg_color': None
  163. },
  164. {
  165. 'id': 12,
  166. 'question': 'Что означает требование "целостность и конфиденциальность" ПД?',
  167. 'options': [
  168. 'Данные должны быть красиво оформлены',
  169. 'Защита от несанкционированного доступа, потери и уничтожения',
  170. 'Данные должны быть доступны всем',
  171. 'Данные должны храниться вечно'
  172. ],
  173. 'correct': 1,
  174. 'explanation': 'Данные должны защищаться от несанкционированного доступа, потери, повреждения или уничтожения.',
  175. 'image': 'q12.jpg',
  176. 'bg_color': None
  177. },
  178. {
  179. 'id': 13,
  180. 'question': 'Что означает "ограничение сроков хранения" персональных данных?',
  181. 'options': [
  182. 'Хранить данные бесконечно',
  183. 'Хранить только необходимое для целей обработки время',
  184. 'Удалять сразу после получения',
  185. 'Хранить минимум 10 лет'
  186. ],
  187. 'correct': 1,
  188. 'explanation': 'Хранить персональные сведения можно только столько, сколько необходимо для достижения целей их обработки.',
  189. 'image': 'q13.jpg',
  190. 'bg_color': None
  191. },
  192. {
  193. 'id': 14,
  194. 'question': 'В каких сферах применяются персональные данные?',
  195. 'options': [
  196. 'Только в медицине',
  197. 'Только в банковской сфере',
  198. 'Практически во всех сферах: коммерция, финансы, медицина, образование, госорганы',
  199. 'Только в интернете'
  200. ],
  201. 'correct': 2,
  202. 'explanation': 'Персональные данные используются практически в любой сфере современного цифрового мира.',
  203. 'image': 'q14.jpg',
  204. 'bg_color': None
  205. },
  206. {
  207. 'id': 15,
  208. 'question': 'Какие данные относятся к "общим" согласно 152-ФЗ?',
  209. 'options': [
  210. 'ФИО, место регистрации, образование, контактная информация',
  211. 'Данные о здоровье',
  212. 'Отпечатки пальцев',
  213. 'Политические взгляды'
  214. ],
  215. 'correct': 0,
  216. 'explanation': 'Общие данные: ФИО, место регистрации, сведения об образовании, месте работы, контактная информация.',
  217. 'image': 'q15.jpg',
  218. 'bg_color': None
  219. },
  220. {
  221. 'id': 16,
  222. 'question': 'Что должно быть предусмотрено в договоре между оператором и уполномоченным лицом?',
  223. 'options': [
  224. 'Стоимость услуг',
  225. 'Обязанность обеспечить безопасность ПД при обработке',
  226. 'Срок действия договора',
  227. 'Реквизиты сторон'
  228. ],
  229. 'correct': 1,
  230. 'explanation': 'Договор должен предусматривать обязанность уполномоченного лица обеспечить безопасность ПД при их обработке.',
  231. 'image': 'q16.jpg',
  232. 'bg_color': None
  233. },
  234. {
  235. 'id': 17,
  236. 'question': 'Кто обеспечивает безопасность персональных данных в информационной системе?',
  237. 'options': [
  238. 'ФСБ России',
  239. 'Оператор системы или уполномоченное им лицо',
  240. 'Роскомнадзор',
  241. 'Сам субъект данных'
  242. ],
  243. 'correct': 1,
  244. 'explanation': 'Безопасность обеспечивает оператор системы или лицо, осуществляющее обработку по поручению оператора.',
  245. 'image': 'q17.jpg',
  246. 'bg_color': None
  247. },
  248. {
  249. 'id': 18,
  250. 'question': 'Какие угрозы относятся к 1-му типу?',
  251. 'options': [
  252. 'Только внешние атаки',
  253. 'Угрозы, связанные с недокументированными возможностями в системном ПО',
  254. 'Только физические угрозы',
  255. 'Угрозы от сотрудников'
  256. ],
  257. 'correct': 1,
  258. 'explanation': 'Угрозы 1-го типа связаны с наличием недокументированных возможностей в системном программном обеспечении.',
  259. 'image': 'q18.jpg',
  260. 'bg_color': None
  261. },
  262. {
  263. 'id': 19,
  264. 'question': 'Какие угрозы относятся ко 2-му типу?',
  265. 'options': [
  266. 'Угрозы от хакеров',
  267. 'Угрозы, связанные с недокументированными возможностями в прикладном ПО',
  268. 'Угрозы пожаров и наводнений',
  269. 'Угрозы отключения электричества'
  270. ],
  271. 'correct': 1,
  272. 'explanation': 'Угрозы 2-го типа связаны с наличием недокументированных возможностей в прикладном программном обеспечении.',
  273. 'image': 'q19.jpg',
  274. 'bg_color': None
  275. },
  276. {
  277. 'id': 20,
  278. 'question': 'Какие угрозы относятся к 3-му типу?',
  279. 'options': [
  280. 'Угрозы из интернета',
  281. 'Угрозы, не связанные с недокументированными возможностями в системном и прикладном ПО',
  282. 'Только физические угрозы',
  283. 'Угрозы от вирусов'
  284. ],
  285. 'correct': 1,
  286. 'explanation': 'Угрозы 3-го типа - угрозы, не связанные с наличием недокументированных возможностей в ПО.',
  287. 'image': 'q20.jpg',
  288. 'bg_color': None
  289. },
  290. {
  291. 'id': 21,
  292. 'question': 'Когда устанавливается необходимость 1-го уровня защищенности?',
  293. 'options': [
  294. 'Всегда для всех систем',
  295. 'При угрозах 1 типа и обработке специальных или биометрических данных',
  296. 'Только для государственных систем',
  297. 'При обработке менее 100 записей'
  298. ],
  299. 'correct': 1,
  300. 'explanation': '1-й уровень необходим при угрозах 1 типа и обработке специальных категорий или биометрических данных.',
  301. 'image': 'q21.jpg',
  302. 'bg_color': None
  303. },
  304. {
  305. 'id': 22,
  306. 'question': 'Какие требования предъявляются для 4-го уровня защищенности?',
  307. 'options': [
  308. 'Создание специального отдела',
  309. 'Организация безопасности помещений, сохранность носителей, утверждение списка допущенных лиц',
  310. 'Шифрование всех данных',
  311. 'Ежедневный аудит'
  312. ],
  313. 'correct': 1,
  314. 'explanation': '4-й уровень требует безопасности помещений, сохранности носителей и утверждения списка допущенных лиц.',
  315. 'image': 'q22.jpg',
  316. 'bg_color': None
  317. },
  318. {
  319. 'id': 23,
  320. 'question': 'Что дополнительно требуется для 3-го уровня защищенности?',
  321. 'options': [
  322. 'Создание отдела защиты данных',
  323. 'Назначение ответственного за безопасность ПД в ИС',
  324. 'Автоматическая регистрация изменений',
  325. 'Шифрование каналов связи'
  326. ],
  327. 'correct': 1,
  328. 'explanation': 'Для 3-го уровня необходимо назначение должностного лица, ответственного за безопасность ПД в ИС.',
  329. 'image': 'q23.jpg',
  330. 'bg_color': None
  331. },
  332. {
  333. 'id': 24,
  334. 'question': 'Что дополнительно требуется для 2-го уровня защищенности?',
  335. 'options': [
  336. 'Видеонаблюдение',
  337. 'Ограничение доступа к электронному журналу сообщений',
  338. 'Биометрическая идентификация',
  339. 'Еженедельные проверки'
  340. ],
  341. 'correct': 1,
  342. 'explanation': 'Для 2-го уровня доступ к электронному журналу должен быть только для лиц, которым это необходимо.',
  343. 'image': 'q24.jpg',
  344. 'bg_color': None
  345. },
  346. {
  347. 'id': 25,
  348. 'question': 'Что дополнительно требуется для 1-го уровня защищенности?',
  349. 'options': [
  350. 'Автоматическая регистрация изменений полномочий и создание структурного подразделения',
  351. 'Ежечасный мониторинг',
  352. 'Вооруженная охрана',
  353. 'Спутниковое наблюдение'
  354. ],
  355. 'correct': 0,
  356. 'explanation': '1-й уровень требует автоматической регистрации изменений полномочий и создания структурного подразделения.',
  357. 'image': 'q25.jpg',
  358. 'bg_color': None
  359. },
  360. {
  361. 'id': 26,
  362. 'question': 'Что должно содержать уведомление в Роскомнадзор о начале обработки ПД?',
  363. 'options': [
  364. 'Только название организации',
  365. 'Информацию о целях обработки, категориях данных и мерах защиты',
  366. 'Только контактные данные',
  367. 'Только ФИО директора'
  368. ],
  369. 'correct': 1,
  370. 'explanation': 'Уведомление должно содержать информацию о целях, категориях данных и мерах защиты.',
  371. 'image': 'q26.jpg',
  372. 'bg_color': None
  373. },
  374. {
  375. 'id': 27,
  376. 'question': 'Что такое трансграничная передача данных?',
  377. 'options': [
  378. 'Передача внутри организации',
  379. 'Передача данных за пределы государства',
  380. 'Передача по локальной сети',
  381. 'Передача на флешке'
  382. ],
  383. 'correct': 1,
  384. 'explanation': 'Трансграничная передача - это передача персональных данных на территорию иностранного государства.',
  385. 'image': 'q27.jpg',
  386. 'bg_color': None
  387. },
  388. {
  389. 'id': 28,
  390. 'question': 'Кто должен давать согласие на обработку данных детей?',
  391. 'options': [
  392. 'Сам ребенок',
  393. 'Учитель',
  394. 'Законные представители (родители)',
  395. 'Директор школы'
  396. ],
  397. 'correct': 2,
  398. 'explanation': 'Для обработки данных детей требуется согласие законных представителей.',
  399. 'image': 'q28.jpg',
  400. 'bg_color': None
  401. },
  402. {
  403. 'id': 29,
  404. 'question': 'Что должно быть сделано при утечке персональных данных?',
  405. 'options': [
  406. 'Ничего, это не обязательно',
  407. 'Уведомление владельцев данных и контролирующих органов',
  408. 'Только смена паролей',
  409. 'Увольнение сотрудников'
  410. ],
  411. 'correct': 1,
  412. 'explanation': 'В случае утечки владельцы данных должны быть своевременно уведомлены.',
  413. 'image': 'q29.jpg',
  414. 'bg_color': None
  415. },
  416. {
  417. 'id': 30,
  418. 'question': 'Что такое обезличивание персональных данных?',
  419. 'options': [
  420. 'Удаление фотографий',
  421. 'Действия, после которых нельзя определить принадлежность данных конкретному лицу',
  422. 'Шифрование данных',
  423. 'Смена имен'
  424. ],
  425. 'correct': 1,
  426. 'explanation': 'Обезличивание делает невозможным идентификацию человека без использования дополнительной информации.',
  427. 'image': 'q30.jpg',
  428. 'bg_color': None
  429. },
  430. {
  431. 'id': 31,
  432. 'question': 'Кто осуществляет выбор средств защиты информации для системы защиты ПД?',
  433. 'options': [
  434. 'Роскомнадзор',
  435. 'Оператор в соответствии с нормативными актами ФСБ и ФСТЭК',
  436. 'Субъект данных',
  437. 'Поставщик оборудования'
  438. ],
  439. 'correct': 1,
  440. 'explanation': 'Выбор средств защиты осуществляется оператором в соответствии с актами ФСБ и ФСТЭК.',
  441. 'image': 'q31.jpg',
  442. 'bg_color': None
  443. },
  444. {
  445. 'id': 32,
  446. 'question': 'Какие организации могут привлекаться для контроля защиты ПД?',
  447. 'options': [
  448. 'Любые организации',
  449. 'Юридические лица и ИП с лицензией на техзащиту информации',
  450. 'Только государственные органы',
  451. 'Только ФСБ'
  452. ],
  453. 'correct': 1,
  454. 'explanation': 'Могут привлекаться организации и ИП, имеющие лицензию на техзащиту конфиденциальной информации.',
  455. 'image': 'q32.jpg',
  456. 'bg_color': None
  457. },
  458. {
  459. 'id': 33,
  460. 'question': 'Что относится к организационным мерам защиты ПД?',
  461. 'options': [
  462. 'Установка файерволов',
  463. 'Назначение ответственных лиц, разработка документов, инструктаж сотрудников',
  464. 'Шифрование дисков',
  465. 'Антивирусная защита'
  466. ],
  467. 'correct': 1,
  468. 'explanation': 'Организационные меры включают назначение ответственных, разработку документов и обучение сотрудников.',
  469. 'image': 'q33.jpg',
  470. 'bg_color': None
  471. },
  472. {
  473. 'id': 34,
  474. 'question': 'Что относится к техническим мерам защиты ПД?',
  475. 'options': [
  476. 'Проведение инструктажей',
  477. 'Антивирусы, межсетевые экраны, системы шифрования',
  478. 'Разработка политик безопасности',
  479. 'Подписание согласий'
  480. ],
  481. 'correct': 1,
  482. 'explanation': 'Технические меры включают программно-аппаратные средства защиты информации.',
  483. 'image': 'q34.jpg',
  484. 'bg_color': None
  485. },
  486. {
  487. 'id': 35,
  488. 'question': 'Какие данные являются общедоступными?',
  489. 'options': [
  490. 'Все данные в интернете',
  491. 'Данные, доступ к которым предоставлен самим субъектом',
  492. 'Паспортные данные',
  493. 'Медицинские записи'
  494. ],
  495. 'correct': 1,
  496. 'explanation': 'Общедоступные данные - это данные, доступ к которым предоставлен самим субъектом.',
  497. 'image': 'q35.jpg',
  498. 'bg_color': None
  499. },
  500. {
  501. 'id': 36,
  502. 'question': 'Что такое инцидент с персональными данными?',
  503. 'options': [
  504. 'Плановое обновление ПО',
  505. 'Нарушение безопасности, приводящее к утечке или компрометации данных',
  506. 'Обычная проверка системы',
  507. 'Резервное копирование'
  508. ],
  509. 'correct': 1,
  510. 'explanation': 'Инцидент - это любое событие, которое привело к нарушению защиты данных.',
  511. 'image': 'q36.jpg',
  512. 'bg_color': None
  513. },
  514. {
  515. 'id': 37,
  516. 'question': 'Какие требования предъявляются к точности и актуальности данных?',
  517. 'options': [
  518. 'Данные можно не обновлять',
  519. 'Важно обеспечивать правильность и своевременность данных',
  520. 'Точность не важна',
  521. 'Достаточно собрать данные один раз'
  522. ],
  523. 'correct': 1,
  524. 'explanation': 'Важно обеспечивать правильность и своевременность данных.',
  525. 'image': 'q37.jpg',
  526. 'bg_color': None
  527. },
  528. {
  529. 'id': 38,
  530. 'question': 'Что означает требование "законность, справедливость и прозрачность"?',
  531. 'options': [
  532. 'Данные должны быть доступны всем',
  533. 'Обработка должна вестись легально, честно и ясно для граждан',
  534. 'Данные должны публиковаться',
  535. 'Обработка может быть скрытой'
  536. ],
  537. 'correct': 1,
  538. 'explanation': 'Обработка должна вестись легально, честно и ясно для граждан, чьи данные собираются.',
  539. 'image': 'q38.jpg',
  540. 'bg_color': None
  541. },
  542. {
  543. 'id': 39,
  544. 'question': 'Что такое электронный журнал безопасности?',
  545. 'options': [
  546. 'Список сотрудников',
  547. 'Средство регистрации событий доступа и изменений в системе',
  548. 'Журнал учета посетителей',
  549. 'База данных клиентов'
  550. ],
  551. 'correct': 1,
  552. 'explanation': 'Электронный журнал регистрирует события доступа и изменения в системе.',
  553. 'image': 'q39.jpg',
  554. 'bg_color': None
  555. },
  556. {
  557. 'id': 40,
  558. 'question': 'К какому типу данных относится данные о заработной плате?',
  559. 'options': [
  560. 'Не являются персональными данными',
  561. 'Являются персональными данными и не подлежат разглашению без согласия',
  562. 'Могут публиковаться свободно',
  563. 'Относятся к общедоступным'
  564. ],
  565. 'correct': 1,
  566. 'explanation': 'Сведения о заработной плате - это персональные данные и не подлежат разглашению без согласия.',
  567. 'image': 'q40.jpg',
  568. 'bg_color': None
  569. },
  570. {
  571. 'id': 41,
  572. 'question': 'Что должен сделать оператор перед началом обработки ПД?',
  573. 'options': [
  574. 'Ничего',
  575. 'Подать уведомление в Роскомнадзор',
  576. 'Купить оборудование',
  577. 'Нанять сотрудников'
  578. ],
  579. 'correct': 1,
  580. 'explanation': 'Необходимо подать уведомление о начале обработки ПД в Роскомнадзор для регистрации в качестве оператора.',
  581. 'image': 'q41.jpg',
  582. 'bg_color': None
  583. },
  584. {
  585. 'id': 42,
  586. 'question': 'Что такое модель угроз для ИСПД?',
  587. 'options': [
  588. 'Описание возможных злоумышленников',
  589. 'Документ, описывающий актуальные угрозы безопасности для конкретной системы',
  590. 'Программа для взлома',
  591. 'Схема сети'
  592. ],
  593. 'correct': 1,
  594. 'explanation': 'Модель угроз - документ, описывающий актуальные угрозы для конкретной информационной системы.',
  595. 'image': 'q42.jpg',
  596. 'bg_color': None
  597. },
  598. {
  599. 'id': 43,
  600. 'question': 'Какие существуют категории персональных данных по 152-ФЗ?',
  601. 'options': [
  602. 'Только общие и специальные',
  603. 'Общие, особые, биометрические и иные данные',
  604. 'Только биометрические',
  605. 'Только контактные'
  606. ],
  607. 'correct': 1,
  608. 'explanation': 'Закон выделяет общие, особые, биометрические и иные категории персональных данных.',
  609. 'image': 'q43.jpg',
  610. 'bg_color': None
  611. },
  612. {
  613. 'id': 44,
  614. 'question': 'Что должно содержать согласие на обработку ПД?',
  615. 'options': [
  616. 'Только подпись',
  617. 'Конкретные цели обработки, перечень данных, срок действия',
  618. 'Только ФИО',
  619. 'Только дату'
  620. ],
  621. 'correct': 1,
  622. 'explanation': 'Согласие должно быть конкретным, содержать цели обработки, перечень данных и срок действия.',
  623. 'image': 'q44.jpg',
  624. 'bg_color': None
  625. },
  626. {
  627. 'id': 45,
  628. 'question': 'Кто такой уполномоченный по защите данных?',
  629. 'options': [
  630. 'Сотрудник полиции',
  631. 'Лицо, ответственное за контроль соблюдения законодательства о данных',
  632. 'Программист',
  633. 'Начальник отдела кадров'
  634. ],
  635. 'correct': 1,
  636. 'explanation': 'Это лицо, ответственное за контроль соблюдения законодательства о персональных данных.',
  637. 'image': 'q45.jpg',
  638. 'bg_color': None
  639. },
  640. {
  641. 'id': 46,
  642. 'question': 'Что такое техническое задание на создание системы защиты?',
  643. 'options': [
  644. 'Рекламный буклет',
  645. 'Документ с требованиями к создаваемой системе защиты ПД',
  646. 'Инструкция пользователя',
  647. 'Договор с поставщиком'
  648. ],
  649. 'correct': 1,
  650. 'explanation': 'ТЗ - документ с требованиями по формированию требуемой системы защиты.',
  651. 'image': 'q46.jpg',
  652. 'bg_color': None
  653. },
  654. {
  655. 'id': 47,
  656. 'question': 'Какие данные относятся к "иным" согласно 152-ФЗ?',
  657. 'options': [
  658. 'Данные о здоровье',
  659. 'Все, что не попадает в общие, особые и биометрические категории',
  660. 'Только фотографии',
  661. 'Только отпечатки пальцев'
  662. ],
  663. 'correct': 1,
  664. 'explanation': 'Иные данные - всё, что не попадает в предыдущие категории.',
  665. 'image': 'q47.jpg',
  666. 'bg_color': None
  667. },
  668. {
  669. 'id': 48,
  670. 'question': 'Что такое ФСТЭК России?',
  671. 'options': [
  672. 'Производитель компьютеров',
  673. 'Федеральная служба по техническому и экспортному контролю',
  674. 'Провайдер интернета',
  675. 'Страховая компания'
  676. ],
  677. 'correct': 1,
  678. 'explanation': 'ФСТЭК - федеральная служба по техническому и экспортному контролю, регулирующая вопросы защиты информации.',
  679. 'image': 'q48.jpg',
  680. 'bg_color': None
  681. },
  682. {
  683. 'id': 49,
  684. 'question': 'Какие требования предъявляются к помещениям, где обрабатываются ПД?',
  685. 'options': [
  686. 'Наличие кондиционера',
  687. 'Режим, препятствующий неконтролируемому проникновению посторонних',
  688. 'Наличие коврового покрытия',
  689. 'Яркое освещение'
  690. ],
  691. 'correct': 1,
  692. 'explanation': 'Необходима организация режима, препятствующего неконтролируемому проникновению посторонних.',
  693. 'image': 'q49.jpg',
  694. 'bg_color': None
  695. },
  696. {
  697. 'id': 50,
  698. 'question': 'Какова основная цель выполнения требований по защите персональных данных?',
  699. 'options': [
  700. 'Выполнение формальностей',
  701. 'Минимизация вреда от возможной реализации угроз безопасности',
  702. 'Экономия средств',
  703. 'Повышение престижа компании'
  704. ],
  705. 'correct': 1,
  706. 'explanation': 'Основная цель - минимизация вреда, возникающего из-за возможной реализации угроз безопасности.',
  707. 'image': 'q50.jpg',
  708. 'bg_color': None
  709. }
  710. ] # Остальные вопросы аналогичны, для краткости сократил до 10
  711. class ImageManager:
  712. """Класс для управления изображениями"""
  713. def __init__(self, images_folder: str):
  714. self.images_folder = Path(images_folder)
  715. self.cache = {} # Кэш для изображений
  716. self.pil_available = PIL_AVAILABLE
  717. def find_image(self, image_name: str) -> Optional[Path]:
  718. """Поиск изображения по имени с разными расширениями"""
  719. if not image_name:
  720. return None
  721. # Проверка кэша
  722. if image_name in self.cache:
  723. return self.cache[image_name]
  724. # Поиск файла
  725. image_path = self.images_folder / image_name
  726. if image_path.exists():
  727. self.cache[image_name] = image_path
  728. return image_path
  729. # Поиск с разными расширениями
  730. name_without_ext = image_path.stem
  731. for ext in SUPPORTED_FORMATS:
  732. test_path = self.images_folder / f"{name_without_ext}{ext}"
  733. if test_path.exists():
  734. self.cache[image_name] = test_path
  735. return test_path
  736. return None
  737. def load_image(self, image_path: Path, bg_color: str = '#ffffff', size: Tuple[int, int] = (350, 350)):
  738. """Загрузка и обработка изображения"""
  739. if not self.pil_available:
  740. if image_path.suffix.lower() == '.jpg':
  741. return tk.PhotoImage(file=str(image_path))
  742. raise Exception("Для работы с изображениями требуется Pillow")
  743. img = Image.open(image_path)
  744. # Обработка анимированных GIF
  745. if getattr(img, 'is_animated', False):
  746. img.seek(0)
  747. # Обработка прозрачности
  748. if img.mode == 'RGBA':
  749. bg_rgb = tuple(int(bg_color[i:i+2], 16) for i in (1, 3, 5))
  750. background = Image.new('RGB', img.size, bg_rgb)
  751. background.paste(img, mask=img.split()[3])
  752. img = background
  753. elif img.mode != 'RGB':
  754. img = img.convert('RGB')
  755. # Изменение размера
  756. img.thumbnail(size, Image.Resampling.LANCZOS)
  757. return ImageTk.PhotoImage(img)
  758. def get_dominant_color(self, image_path: Path) -> Optional[str]:
  759. """Получение доминирующего цвета изображения"""
  760. if not self.pil_available:
  761. return None
  762. try:
  763. img = Image.open(image_path)
  764. if getattr(img, 'is_animated', False):
  765. img.seek(0)
  766. # Конвертация в RGB
  767. if img.mode == 'RGBA':
  768. background = Image.new('RGB', img.size, (255, 255, 255))
  769. background.paste(img, mask=img.split()[3])
  770. img = background
  771. elif img.mode != 'RGB':
  772. img = img.convert('RGB')
  773. # Уменьшение для ускорения
  774. img.thumbnail((100, 100))
  775. pixels = img.getdata()
  776. # Вычисление среднего цвета
  777. r_sum = g_sum = b_sum = 0
  778. for pixel in pixels:
  779. r_sum += pixel[0]
  780. g_sum += pixel[1]
  781. b_sum += pixel[2]
  782. count = len(pixels)
  783. if count == 0:
  784. return None
  785. return f'#{r_sum//count:02x}{g_sum//count:02x}{b_sum//count:02x}'
  786. except Exception as e:
  787. print(f"Ошибка определения цвета: {e}")
  788. return None
  789. class QuizApp:
  790. """Основной класс приложения"""
  791. def __init__(self, master):
  792. self.master = master
  793. self.master.title("Викторина: Защита персональных данных")
  794. self.master.geometry(WINDOW_SIZE)
  795. self.master.resizable(False, False)
  796. # Инициализация
  797. self.questions = questions.copy()
  798. self.current_question = 0
  799. self.correct_answers = 0
  800. self.total_questions = len(self.questions)
  801. # Менеджеры
  802. self.image_manager = ImageManager(IMAGES_FOLDER)
  803. # Переменные состояния
  804. self.var = None
  805. self.option_mapping = {}
  806. self.current_image = None
  807. # Привязка клавиш
  808. self._bind_keys()
  809. # Запуск
  810. self.show_start_screen()
  811. def _bind_keys(self):
  812. """Привязка клавиатурных комбинаций"""
  813. self.master.bind('<Key>', self.on_key_press)
  814. self.master.bind('<Return>', lambda e: self.check_answer())
  815. self.master.bind('<Escape>', lambda e: self.quit_app())
  816. def on_key_press(self, event):
  817. """Обработка нажатий клавиш"""
  818. if event.char in '1234' and self.var is not None:
  819. self.var.set(int(event.char) - 1)
  820. def quit_app(self):
  821. """Выход из приложения"""
  822. if messagebox.askyesno("Выход", "Вы действительно хотите выйти?"):
  823. self.master.quit()
  824. def clear_window(self):
  825. """Очистка окна"""
  826. for widget in self.master.winfo_children():
  827. widget.destroy()
  828. def shuffle_questions(self):
  829. """Перемешивание вопросов"""
  830. random.shuffle(self.questions)
  831. def get_text_color(self, bg_hex: str) -> str:
  832. """Определение цвета текста на основе фона"""
  833. if not bg_hex:
  834. return 'black'
  835. try:
  836. r = int(bg_hex[1:3], 16)
  837. g = int(bg_hex[3:5], 16)
  838. b = int(bg_hex[5:7], 16)
  839. brightness = 0.299 * r + 0.587 * g + 0.114 * b
  840. return 'black' if brightness > 128 else 'white'
  841. except:
  842. return 'black'
  843. def show_start_screen(self):
  844. """Экран приветствия"""
  845. self.clear_window()
  846. self.master.config(bg='lightblue')
  847. # Заголовок
  848. title = tk.Label(self.master, text="Викторина по защите персональных данных",
  849. font=("Arial", 20, "bold"), bg='lightblue', fg='navy')
  850. title.pack(pady=40)
  851. # Инструкция
  852. instr_text = (
  853. f"Добро пожаловать!\n\n"
  854. f"Эта викторина проверит ваши знания об основах защиты персональных данных.\n"
  855. f"Правила:\n"
  856. f"• Всего вопросов: {self.total_questions}\n"
  857. f"• Выберите один правильный вариант.\n"
  858. f"• Управление с клавиатуры: клавиши 1-4 для выбора ответа\n"
  859. f"• Нажмите Enter для проверки ответа\n"
  860. f"• Esc для выхода\n"
  861. f"• После ответа вы увидите пояснение.\n\n"
  862. f"Удачи!"
  863. )
  864. instr_label = tk.Label(self.master, text=instr_text, font=("Arial", 12),
  865. bg='lightblue', justify='left')
  866. instr_label.pack(pady=20)
  867. # Кнопка старта
  868. start_btn = tk.Button(self.master, text="Начать викторину", font=("Arial", 14),
  869. command=self.start_quiz, bg='green', fg='white',
  870. padx=20, pady=10, cursor='hand2')
  871. start_btn.pack(pady=30)
  872. def start_quiz(self):
  873. """Начало викторины"""
  874. self.shuffle_questions()
  875. self.current_question = 0
  876. self.correct_answers = 0
  877. self.show_question()
  878. def get_background_color(self, q: Dict, index: int) -> str:
  879. """Получение цвета фона для вопроса"""
  880. if q.get('bg_color'):
  881. return q['bg_color']
  882. if PIL_AVAILABLE and q.get('image'):
  883. image_path = self.image_manager.find_image(q['image'])
  884. if image_path:
  885. color = self.image_manager.get_dominant_color(image_path)
  886. if color:
  887. return color
  888. return DEFAULT_COLORS[index % len(DEFAULT_COLORS)]
  889. def create_option_buttons(self, parent, options: List, bg_color: str, text_color: str):
  890. """Создание кнопок вариантов ответов"""
  891. options_with_indices = list(enumerate(options))
  892. random.shuffle(options_with_indices)
  893. self.var = tk.IntVar(value=-1)
  894. self.option_mapping = {}
  895. # Функции для эффекта наведения
  896. def on_enter(btn):
  897. btn.config(bg='#d0d0d0' if text_color == 'black' else '#505050')
  898. def on_leave(btn, orig_bg):
  899. btn.config(bg=orig_bg)
  900. for new_idx, (old_idx, option_text) in enumerate(options_with_indices):
  901. self.option_mapping[new_idx] = old_idx
  902. display_text = f"{new_idx + 1}. {option_text}"
  903. rb = tk.Radiobutton(parent, text=display_text, variable=self.var,
  904. value=new_idx, font=("Arial", 11), wraplength=350,
  905. justify='left', indicatoron=0, bg=bg_color,
  906. fg=text_color, selectcolor=bg_color,
  907. padx=15, pady=8, cursor='hand2')
  908. rb.pack(anchor='center', pady=5)
  909. # Эффект наведения
  910. orig_bg = rb.cget('bg')
  911. rb.bind("<Enter>", lambda e, b=rb: on_enter(b))
  912. rb.bind("<Leave>", lambda e, b=rb: on_leave(b, orig_bg))
  913. def show_question(self):
  914. """Отображение вопроса"""
  915. self.clear_window()
  916. # Удаление старого изображения
  917. if hasattr(self, 'current_image'):
  918. del self.current_image
  919. q = self.questions[self.current_question]
  920. bg_color = self.get_background_color(q, self.current_question)
  921. text_color = self.get_text_color(bg_color)
  922. self.master.config(bg=bg_color)
  923. # Основной контейнер
  924. main_frame = tk.Frame(self.master, bg=bg_color)
  925. main_frame.pack(fill='both', expand=True, padx=30, pady=20)
  926. # Левая колонка
  927. left_frame = tk.Frame(main_frame, bg=bg_color)
  928. left_frame.pack(side='left', fill='both', expand=True)
  929. # Правая колонка
  930. right_frame = tk.Frame(main_frame, bg=bg_color)
  931. right_frame.pack(side='right', fill='both', expand=True)
  932. # Вопрос
  933. question_lbl = tk.Label(left_frame, text=q['question'],
  934. font=("Arial", 14, "bold"), wraplength=450,
  935. justify='left', bg=bg_color, fg=text_color)
  936. question_lbl.pack(anchor='nw', pady=(0, 20))
  937. # Изображение
  938. if q.get('image'):
  939. image_path = self.image_manager.find_image(q['image'])
  940. if image_path:
  941. try:
  942. self.current_image = self.image_manager.load_image(image_path, bg_color)
  943. img_label = tk.Label(left_frame, image=self.current_image, bg=bg_color)
  944. img_label.pack(anchor='center', pady=10)
  945. except Exception as e:
  946. error_text = f"[Ошибка: {image_path.name}]\n{str(e)[:50]}"
  947. error_label = tk.Label(left_frame, text=error_text,
  948. font=("Arial", 8), fg='red', bg=bg_color)
  949. error_label.pack(anchor='center')
  950. else:
  951. error_text = f"[Файл не найден: {q['image']}]\nПоддерживаемые форматы: PNG, JPG, JPEG, GIF, BMP"
  952. error_label = tk.Label(left_frame, text=error_text,
  953. font=("Arial", 8), fg='orange', bg=bg_color)
  954. error_label.pack(anchor='center')
  955. # Прогресс и подсказки
  956. progress_lbl = tk.Label(left_frame,
  957. text=f"Вопрос {self.current_question + 1} из {self.total_questions}",
  958. font=("Arial", 11), fg=text_color, bg=bg_color)
  959. progress_lbl.pack(side='bottom', anchor='sw', pady=10)
  960. hint_lbl = tk.Label(left_frame,
  961. text="Клавиши 1-4 → выбор ответа, Enter → проверка",
  962. font=("Arial", 9), fg=text_color, bg=bg_color)
  963. hint_lbl.pack(side='bottom', anchor='sw', pady=5)
  964. # Варианты ответов
  965. center_container = tk.Frame(right_frame, bg=bg_color)
  966. center_container.pack(expand=True)
  967. options_title = tk.Label(center_container, text="Выберите ответ:",
  968. font=("Arial", 12, "bold"), bg=bg_color, fg=text_color)
  969. options_title.pack(pady=(0, 15))
  970. self.create_option_buttons(center_container, q['options'], bg_color, text_color)
  971. # Кнопки управления
  972. btn_frame = tk.Frame(right_frame, bg=bg_color)
  973. btn_frame.pack(side='bottom', fill='x', pady=20)
  974. exit_btn = tk.Button(btn_frame, text="Выход (Esc)", font=("Arial", 11),
  975. command=self.quit_app, bg='red', fg='white',
  976. padx=20, pady=5, cursor='hand2')
  977. exit_btn.pack(side='right', padx=10)
  978. check_btn = tk.Button(btn_frame, text="Проверить (Enter)", font=("Arial", 11),
  979. command=self.check_answer, bg='blue', fg='white',
  980. padx=20, pady=5, cursor='hand2')
  981. check_btn.pack(side='right', padx=10)
  982. self.master.focus_set()
  983. def check_answer(self):
  984. """Проверка ответа"""
  985. if self.var is None or self.var.get() == -1:
  986. messagebox.showwarning("Нет выбора", "Пожалуйста, выберите один из вариантов (клавиши 1-4).")
  987. return
  988. selected = self.var.get()
  989. original_selected = self.option_mapping[selected]
  990. q = self.questions[self.current_question]
  991. if original_selected == q['correct']:
  992. self.correct_answers += 1
  993. self.show_feedback("Правильно!", "green")
  994. else:
  995. correct_text = q['options'][q['correct']]
  996. explanation = f"Неправильно. Правильный ответ: {correct_text}\n\n{q['explanation']}"
  997. self.show_feedback("Неправильно", "red", explanation)
  998. def show_feedback(self, message: str, color: str, explanation: str = None):
  999. """Отображение обратной связи"""
  1000. win = tk.Toplevel(self.master)
  1001. win.title("Результат")
  1002. win.geometry("500x350")
  1003. win.configure(bg=color)
  1004. win.transient(self.master)
  1005. win.grab_set()
  1006. # Закрытие окна
  1007. def close_and_continue():
  1008. win.destroy()
  1009. self.next_question()
  1010. win.protocol("WM_DELETE_WINDOW", close_and_continue)
  1011. win.bind('<Return>', lambda e: close_and_continue())
  1012. win.bind('<Escape>', lambda e: close_and_continue())
  1013. # Сообщение
  1014. lbl = tk.Label(win, text=message, bg=color, fg='white',
  1015. font=("Arial", 24, "bold"), wraplength=450, justify='center')
  1016. lbl.pack(expand=True, fill='both', padx=20, pady=20)
  1017. # Пояснение
  1018. if explanation:
  1019. expl_lbl = tk.Label(win, text=explanation, bg=color, fg='white',
  1020. font=("Arial", 11), wraplength=450, justify='left')
  1021. expl_lbl.pack(padx=20, pady=10)
  1022. # Кнопка продолжения
  1023. btn = tk.Button(win, text="Продолжить (Enter)", command=close_and_continue,
  1024. bg='white', font=("Arial", 11), padx=20, pady=5, cursor='hand2')
  1025. btn.pack(pady=20)
  1026. win.focus_set()
  1027. def next_question(self):
  1028. """Переход к следующему вопросу"""
  1029. if self.current_question + 1 < self.total_questions:
  1030. self.current_question += 1
  1031. self.show_question()
  1032. else:
  1033. self.show_result()
  1034. def show_result(self):
  1035. """Отображение результатов"""
  1036. self.clear_window()
  1037. self.master.config(bg='lightgreen')
  1038. percentage = (self.correct_answers / self.total_questions) * 100
  1039. result_text = f"Викторина завершена!\n\n"
  1040. result_text += f"Вы ответили правильно на {self.correct_answers} из {self.total_questions} вопросов.\n"
  1041. result_text += f"Ваш результат: {percentage:.1f}%\n\n"
  1042. if percentage == 100:
  1043. result_text += "Отлично! Вы очень хорошо усвоили материал."
  1044. elif percentage >= 80:
  1045. result_text += "Отличный результат! Вы хорошо знаете тему."
  1046. elif percentage >= 60:
  1047. result_text += "Хороший результат! Есть куда стремиться."
  1048. else:
  1049. result_text += "Стоит повторить лекцию и попробовать снова."
  1050. lbl = tk.Label(self.master, text=result_text, font=("Arial", 16),
  1051. bg='lightgreen', justify='center')
  1052. lbl.pack(pady=30)
  1053. # Привязка клавиш
  1054. self.master.bind('<Return>', lambda e: self.start_quiz())
  1055. self.master.bind('<Escape>', lambda e: self.quit_app())
  1056. # Подсказка
  1057. hint_lbl = tk.Label(self.master, text="Enter - пройти заново | Esc - выход",
  1058. font=("Arial", 11), bg='lightgreen', fg='gray')
  1059. hint_lbl.pack(pady=10)
  1060. # Кнопки
  1061. btn_frame = tk.Frame(self.master, bg='lightgreen')
  1062. btn_frame.pack(pady=20)
  1063. restart_btn = tk.Button(btn_frame, text="Пройти заново (Enter)",
  1064. font=("Arial", 12), command=self.start_quiz,
  1065. bg='blue', fg='white', padx=20, pady=8, cursor='hand2')
  1066. restart_btn.pack(side='left', padx=15)
  1067. exit_btn = tk.Button(btn_frame, text="Завершить (Esc)",
  1068. font=("Arial", 12), command=self.quit_app,
  1069. bg='orange', fg='white', padx=20, pady=8, cursor='hand2')
  1070. exit_btn.pack(side='left', padx=15)
  1071. self.master.focus_set()
  1072. if __name__ == "__main__":
  1073. root = tk.Tk()
  1074. app = QuizApp(root)
  1075. root.mainloop()