Виконала

студентка 2-го курсу, групи ІМ-31 Прилуцька Катерина Telegram: @kate_pril

Керівник

доцент кафедри ОТ ФІОТ, к.т.н., доцент Андрій БОЛДАК

НТУУ "КИЇВСЬКИЙ ПОЛІТЕХНІЧНИЙ ІНСТИТУТ імені ІГОРЯ СІКОРСЬКОГО

Факультет інформатики та обчислювальної техніки

Кафедра обчислювальної техніки

Київ

Вступ

Результатом даної роботи на тему "Система організації та управління опитуваннями експертів" стала платформа MESS (Modern Easy Social Survey).

Дослідження та розробка за даним напрямком є надзвичайно актуальними сьогодні, адже стрімкий технологічний розвиток суспільства сприяє збільшенню кількості даних та зросту необхідності аналізувати їх. Не зважаючи на велику кількість уже існуючих рішень цієї проблеми, більшість з них досі не пропонує достатньо можливостей для аналітики даних, зібраних під час проведення опитувань, а також не надає безкоштовний доступ до просунутих функцій. Дослідження вже наявних рішень домогло визначитись з необхідним функціоналом платформи MESS та сформулювати вимоги до готового продукту.

Так, ми прагнемо створити продукт, який залучить велику кількість користувачів, завдяки простому та зручному інтерфейсу, широкому функціоналу та безпеці даних, яку гарантує наша платформа.

Розроблення загальних вимог до системи

Аналіз предметної області

Вступ

У даному розділі представлено всебічний аналіз предметної області управління та проведення опитувань. У практиці соціальних досліджень опитування є критично важливим інструментом для збору даних, що дозволяє аналізувати думки та поведінку респондентів у різних сферах. Розуміння складових опитувань, анкет, їх класифікації, правильного формулювання питань, вибору цільової аудиторії та інших аспектів суттєво впливає на якість отриманих результатів. Ця частина документації аналізує основні компоненти опитувань, типи питань, правила їх складання, а також методи проведення експертних опитувань. Додатково представлено порівняльний аналіз програмних засобів для проведення опитувань з використанням SWOT-аналізу, що охоплює їх переваги, недоліки, можливості та загрози.

Основні визначення

Експерт

Експерт – це висококваліфікований фахівець у певній галузі діяльності, який володіє глибокими теоретичними знаннями та практичним досвідом, достатнім для об’єктивного аналізу та оцінки складних питань. Експерт має здатність проводити незалежну експертизу, надавати рекомендації, робити висновки на основі доказів та даних, і його думка може мати вагоме значення в процесах прийняття рішень.

Критерії вибору експерта

  • Високий рівень фахової компетентності: глибокі знання і досвід у певній галузі. Експерт має повністю розуміти складність своєї роботи, а також володіти сучасними методами та інструментами для її виконання. Фаховість формується через освіту, професійне навчання та роки практики
  • Незалежність: здатність приймати рішення без стороннього впливу, не піддаючись масовим думкам чи тиску з боку зацікавлених осіб. Експерт повинен мати власну точку зору та діяти відповідно до своїх знань і аналізу
  • Наукова об’єктивність: принцип, за яким експерт оцінює ситуацію, ґрунтуючись на наукових фактах, а не на особистих переконаннях чи почуттях. Об'єктивність важлива для того, щоб його висновки були точними і неупередженими
  • Аналітичність, широта та конструктивність мислення: вміння розбиратися в деталях і систематично підходити до проблем, здатність бачити загальну картину та вміння знаходити рішення, що реально працюють і є корисними
  • Здатність бачити проблему з різних точок зору: здатність враховувати різні аспекти проблеми, розуміти різні точки зору та аналізувати їх перед прийняттям рішення
  • Професійні сертифікати та акредитації: підтверджують, що експерт пройшов необхідну підготовку та відповідає вимогам у своїй галузі. Це формальний доказ його компетентності та кваліфікації
  • Здатність до комунікації: важлива риса, через необхідність не лише робити правильні висновки, а й вміти їх донести до інших (колег, керівників, замовників)
  • Результати попередньої роботи: показник досвіду та успішності. Може включати реалізовані проєкти, наукові публікації, що підтверджують його професійну компетентність

Опитування

Опиитування — це метод збору соціологічної інформації про досліджуваний об'єкт, що базується на безпосередньому (усне опитування, інтерв'ю) або опосередкованому (письмове опитування, анкетування) спілкуванні з респондентами.

Класифікація опитувань

Залежно від предмету дослідження:

  • Соціологічні - метод збору даних, спрямований на отримання інформації про думки, поведінку, соціальні установки та інші аспекти життя громадян. Вони дають можливість аналізувати суспільні тенденції та вимірювати суспільні настрої, оцінювати рівень підтримки політичних лідерів, урядових ініціатив або соціальних програм
  • Політологічні - науковий метод вивчення політичних явищ, процесів та інститутів. Вони спрямовані на аналіз політичних систем, ідей, поведінки, міжнародних відносин, функціонування органів влади та політичних рішень. Основною метою таких досліджень є глибше розуміння того, як працює політика в різних країнах, а також як на неї впливають соціальні, економічні та культурні фактори
  • Маркетингові - вид бізнес-досліджень і напрямок прикладної соціології, який спрямований на аналіз поведінки, бажань та потреб споживачів, а також конкурентів і ринкових умов. Цей тип досліджень дозволяє зрозуміти, як ринок реагує на різні товари та послуги, і допомагає компаніям формувати стратегії щодо розвитку продуктів, цінової політики, реклами та просування.
  • Психологічні - метод збору інформації, який використовується для дослідження психічних процесів, поведінки, емоційних реакцій, мотивації, установок та інших психологічних аспектів індивідуальної або групової поведінки. Вони дозволяють глибше зрозуміти внутрішній світ людини, її реакції на різні ситуації, а також діагностувати психологічні стани.

Залежно від кількості опитуваних:

  • Масові - це метод збору інформації, який використовується для вивчення громадської думки серед широких верств населення, які не є фахівцями у певній галузі. Вони дають можливість отримати уявлення про ставлення різних соціальних груп до різних аспектів суспільного життя, подій, проблем або явищ
  • Вибіркові - метод збору даних, у якому інформація отримується від частини загальної сукупності респондентів (вибіркової сукупності), а не від усього населення. Такий підхід дозволяє отримати репрезентативні результати щодо загальної сукупності, використовуючи меншу кількість респондентів, що значно економить ресурси та час
  • Індивідуальні - метод збору інформації, при якому дослідник або інтерв'юер спілкується з респондентом особисто. Метою такого опитування є отримання детальних і глибоких відповідей від кожного респондента. Цей формат дозволяє досліджувати особисту думку, ставлення, переконання та поведінку кожної людини, що може бути важко досягти в вибіркових або масових опитуваннях
  • Експертні - метод збору інформації, де респондентами є фахівці у певній сфері, які глибоко розуміють проблематику дослідження. Відмінність від масових опитувань полягає в тому, що експерти не відповідають анонімно та несуть відповідальність за свої відповіді, оскільки їхня кваліфікація та досвід є критично важливими для точності результатів

Експертні опитування

Експертне опитування - метод збору інформації та оцінки певних явищ або процесів, який базується на думках групи компетентних фахівців, тобто експертів. Воно використовується для отримання якісних оцінок або прогнозів у складних, невизначених або мало досліджених ситуаціях. Цей метод допомагає отримати погляди людей, які мають високий рівень знань і досвіду в певній сфері, щоб зменшити ризики й невизначеності в процесі прийняття рішень.

Види експертних опитувань

За ступенем взаємодії експертів поділяють на:

  • індивідуальні (використовуються для отримання індивідуальних думок експертів. Задля максимального очищення від зовнішнього впливу фахівці не знають про позиції інших експертів або взагалі не знають, що інші експерти також опитуються)
  • індивідуально-колективні (після того як кожен експерт дав свою оцінку, проводитсья оцінка думок фахівців і кожному з них повідомляють про усереднину оцінку висловлених думок. Експерти можуть змінити початкову оцінку або обґрунтувати свою точку зору. Ці етапи повторюються доки всі оцінки фахівців не наблизяться достатньо для того, щоб кожну з них можна було вважати надійною)
  • групові (декілька експертів відкрито обговорюють проблему задля формування колективної позиції)

За ступенем відкритості поділяють на:

  • очні (особисті зустрічі та бесіди з фахівцями)
  • заочні (анкети надсилаються поштою)

Складові опитування

  • Мета опитування: визначає, які питання потрібно ставити, а також як інтерпретувати отримані відповіді.
  • Цільова аудиторія: вибір респондентів повинен відповідати меті опитування.
  • Питання: основа будь-якого опитування. Вони можуть бути закритими (з вибором відповідей) або відкритими (вільна відповідь). Важливо, щоб питання були сформульовані чітко та не двозначно.
  • Форма опитування: опитування може бути проведене у формі інтерв’ю, анкетування (письмового або онлайн), телефонного опитування або групової дискусії.
  • Інструменти для збору даних: прикладом є паперові анкети, онлайн-форми, мобільні додатки, телефонні дзвінки або інтерв’ю.
  • Аналіз результатів: зібрані дані обробляються з використанням кількісних або якісних методів. Кількісний аналіз застосовується до закритих питань (статистика, графіки), а якісний аналіз допомагає інтерпретувати відповіді на відкриті питання.
  • Звітування результатів: після аналізу даних готується звіт, який включає висновки та рекомендації на основі зібраної інформації. Це допомагає зрозуміти основні тенденції або проблеми, які виявило опитування.

Анкета

Анкета - структурно організований набір запитань, кожне з яких має логічний зв'язок із метою дослідження. Основна функція полягає в тому, щоб зібрати інформацію від респондентів через опитування. Запитання можуть бути закритими (з варіантами відповідей) або відкритими (де респонденти можуть давати вільні відповіді).

Структура анкети

  1. Вступна частина
    • Назва анкети: відображає тему або мету дослідження
    • Інструкція для респондентів - коротке пояснення як заповнювати анкету, тривалість опитування, гарантії конфіденційності, мета опитування
  2. Основна частина
    • Питання, що безпосередньо стосуються теми дослідження
  3. Фінальна частина
    • Підсумкові або уточнювальні питання, що можуть стосуватися загального враження або додаткових коментарів респондентів. Це дає можливість респонденту висловити свою думку чи уточнити попередні відповіді
  4. Ідентифікація респондента (опціонально)
    • Збір контактної інформації або ідентифікації респондентів

Типи питань в опитуваннях

За формою формою відповідей питання поділяють на:

  • закриті (респондент обирає відповідь із запропонованих варіантів). Закриті опитування бувають:
    • дихотомічні (передбачають варіанти відповідей так/ні)
    • поліваріативні (пропонують декілька варіантів відповідей)
    • шкальні (згоден/частково згоден/не згоден)
  • напівзакриті (окрім запропонованих відповідей респондент також може внести власну)
  • відкриті (респондент дає відповідь у вільній формі, зазвичай розгорнуту)

За формулюванням питання поділяють на:

  • прямі (стосуються конкретної ситуації)
  • непрямі (в питаннях цього типу використовується уявна/змодельована ситуація)

За змістом питання поділяють на:

  • особистісні (про вік, стать, професію тощо)
  • питання про знання (орієнтовані на визначення наявності та обсягу знань респондента щодо теми, проблеми ситуації)
  • питання про ставлення (наприклад, до події, товару тощо)
  • питання про поведінку (напрямленні на визначення певних паттернів у поведінці користувача/поведінку користувача в запропонованій ситуації)
  • питання про мотивацію (орієнтовані на з'ясування суб'єктивних уявлень респодентів про мотиви їх вчинків чи оцінок)

За функціями питання поділяють на:

  • інформаційні (основні)
  • фільтри (для випадків, в яких інформацію потрібно зібрати у певної категорії респондентів)
  • контрольні (дозволяють уточнити правильність відповіді респондента)

Правила складання опитувань

Задля отримання максимальної користі від проведених досліджень при складанні опитувань необхідно дотримуватись низки правил:

  • Кількість питань має бути достатньої (не замалою/не завеликою)
  • Ставити лише питання, відповіді на які є потрібними та стосуються теми дослідження
  • Не об'єднувати декілька питань в одне
  • Комбінувати відкриті та закриті запитання
  • Формулювати запитання у ствердній, а не заперечній формі
  • Дотримуватись граматичних норм

Також необхідно дотримуватись правил складання питань:

  • Кожне питання має бути логічним
  • Питання має бути коротким та лаконічним, проте може супроводжуватись поясненням
  • Питання має бути конкрентим
  • Питання має формулюватись мовою середовища, в якому воно буде застосовуватись
  • Питання не має містити підказок
  • Формулювання питання має забезпечити можливість точної відповіді на нього
  • Варіанти відповідей у закритих питаннях мають бути рівноприйнятними
  • Формулювання питання має запобігати отриманню шаблонних відповідей
  • Питання має бути нейтральним
  • Питання не має примушувати респондента давати неприємні для нього відповіді
  • Питання не має бути сугестивним

Послідовність питань відіграє важливу роль у сприйнятті респондентами опитування і може суттєво впливати на результати опитування. Нижче наведено одну з редомендованих послідовностей постановки питань:

  1. Скрінінгові (фільтраційні) питання
  2. Легкі (розігрівальні, мотиваційні) питання
  3. Питання щодо віку/статі
  4. Решта запитань (від загального до специфічного)
  5. Демографічні/персональні питання

Підходи та способи вирішення завдання

Існує низка методів проведення експертних опитувань.

Метод незалежних характеристик

Застосування цього методу дозволяє дати узагальнееу оцінку однєї проблеми/ситуації, інформація про яку надходить з декількох незалежних джерел (від різних експертів). Складається з трьох етапів:

  1. Порівняння та зіставлення різних думок
  2. Обробка думок за допомогою математико-статистичних процедур
  3. Формулювання достовірних висновків

Метод "Дельфи"

При використанні цього методу кожен експерт анонімно висловлює свою позицію щодо запропонованої проблеми. Потім кожен член групи отримує звіт про висловлені припущення (може бути включено як всі позиції, так і вибірково - крайні та середні). Спираючись на отриманий звіт, фахівці мають знову висловити свої думки. Подібні ітерації повторюються доти, доки оцінки експертів не перестануть змінюватись.

Метод "мозкової атаки" ("мозкового штурму")

Передбачає вільний, неструктурований процес генерування власних ідей навколо заданої теми, спонтанно запропонованих учасниками. Філософія цього методу сформована з припущення про те, що контрольні механізми свідомості, що сковують потік ідей під тиском звичних, стереотипних форм прийняття рішень, перешкоджають виникненню новаторських ідей під час звичайних обговорень.

Метод "мозкової атаки навпаки"

Схожий на звичайну мозкову атаку, але при цьому дозволяє висловлення критичних зауважень. Більше того, критика навмисно заохочується з метою виявлення якомога більшої кількості недоліків у запропонованих ідей.

Метод "635"

Є одним з різновидів мозкової атаки. Цифри в назві позначають наявність шести учасників, кожен з яких повинен записати по три ідеї протягом п'яти хвилин. Завдяки цьому за пів годин кожен есперт зможе записати по 18 ідей (загалом 108), при чому їх структура має бути чітко визначеною.

Метод прогнозних сценаріїв

Під час використання цього методу кожен експерт анонімно висловлює думку щодо запропонованої проблеми, після чого отримує загальний звіт про висловлені припущення (може бути представлено як всі думки, так і вибірково крайні та середні). Спираючись на отриманий звіт, фахівці знову висловлюють свою думку. Такі тури тривають поки думки експертів не перестануть змінюватись.

Метод поминальних груп

При реалізації цього методу спочатку проводяться індивідуальні опитування експертів. Потім результати інтерв'ю (незалежно один від одного) обоворюються іншими фахівцями, які можуть висловити згоду з раніше озвученими думками або ж не погодитись з ними, чітко аргументувавши свою позицію.

Метод написання сценарію

Цей метод передбачає встановлення послідовності подій, що розвиваютсья при переході від теперішньої ситуації до майбутньої. Сценарій - це ймовірний опис картини майбутнього, складеної на основі компетентних технічних суджень. Складання сценарію відбувається у кілька етапів:

  1. Структурування та формулювання питання (збір та аналіз вихідної інформації, узгодження завдання з усіма учасниками проєкту, виділення структурних характеристик проблеми)
  2. визначення факторів зовнішнього впливу
  3. знаходження показників, бажано альтернативних, майбутнього стану
  4. формування, відбір та узгодження наборів припущень за допомогою комп'ютерних програм
  5. розробка практичних рекомендацій до сценарію майбутнього і визначення можливих наслідків його реалізації

Метод колективного блокнота ("банку" ідей)

Метод ґрунтується на поєднанні незалежного висування ідей кожним ексептом з подальшою колективною оцінкою запропонованих думок на обговорені.

Метод KJ (діаграма спорідненості)

Цей метод застосовується для систематизації великої кількості асоціативно пов'язаної інформації, зокрема, впорядкування ідей, споживчих вимог або думок членів групи, які беруть участь в обговорені. Діаграма спорідненості вносить ясність в важливі, але не вирішені проблеми, збираючи неструктуровані усні дані з різних джерел і потім аналізуючи ці дані.

Експертне фокусування

Є формою спільного очного обговорення проблеми, під час якого експерти всебічно розглядають досліджувану проблему, тобто "фокусуються" на ній. Основна мета використання даного метода - з'ясувати структуру запропонованої проблеми, визначити фактори, що визначають дану ситуацію та встановити взаємозв'язки між ними.

Метод неспеціаліста

При застосуванні цього методу вирішення проблеми пропонуються особам, які ніколи не займались нею, проте є фахівцями в суміжних галузях.

Метод комісії

За використання даного методу експерти ведуть відкриту дискусію щодо запропонованої проблеми з метою формування єдиної думки експертів. Оброворення проходить як звичайний обмін думками, в ході якого кожен учасник має право ставити питання виступаючому, критикувати чи підтримувати будь-яку точку зору, виступати необмежену кількість разів, змінювати або уточнювати свою точку зору з урахуванням отриманої ним нової інформації. Група експертів збирається багаторазово для обговорення одного і того самого питання, при чому організатор експертизи не керує обговоренням, а лише забезпечує активну роботу кожного запрошеного фахівця.

Метод суду

Реальзація цього методу передбачає створення двох команд експертів, кожна з яких відстоює різний погляд на проблему. Перша група ("звинувачення") оголошується прибічниками розглянутого рішення і захищає його, наводячи аргуметни на користь. Друга група ("захист") висловлює аргументи проти запропонованої альтернативи. Третя група ("судді") регулює хід обговорення та виносить остаточне рішення. Остаточний вердикт щодо досліджуваної проблеми виноситься в два етапи: голосування "присяжних" і конкретизація рішення "суддями".

Порівняльна характеристика існуючих засобів вирішення завдання

Розділ містить опис існуючих програм, інформаційних систем, сервісів, тощо, призначених для вирішення завдання. Дається SWOT analysis кожної з платформ:

Google Forms

StrengthsWeaknesses
· Безкоштовний доступ (для усіх користувачів
облікового запису Google)
· Простота використання (інтуїтивний інтерфейс)
· Хмарне зберігання даних (доступ з будь-якого пристрою)
· Широкий спектр налаштувань (додавання різних типів запитань,
умовні розділи, можливість завантаження файлів)
· Інтеграція з іншими сервісами від Google

· Обмежена кастомізація дизайну
· Залежність від інтернет-з'єднання
· Обмежені можливості аналітики
OpportunitiesThreats
· Зростання потреби у віддаленій роботі та/або навчанні
· Розширення інтеграцій
· Розвиток функцій персоналізації
· Конкуренція з іншими платформами
· Проблеми з конфіденційністю
· Зміна політики Google => зміна вартості та/або умов
використання => зменшення привабливості для користувачів

Висновок: Хоча Google Forms активно конкурує з іншими платформами, його важливою перевагою є безкоштовний доступ для всіх користувачів облікового запису Google. Це робить його зручним інструментом для досягнення різних цілей. Серед слабких сторін — обмежені можливості кастомізації дизайну, залежність від інтернет-з'єднання та скромні аналітичні інструменти, що можуть обмежити його застосування у більш складних сценаріях. Незважаючи на це, платформа має потенціал для подальшого розвитку через розширення інтеграцій та вдосконалення функцій персоналізації.

SurveyMonkey

StrengthsWeaknesses

· Кастомізація дизайну (кольори, шрифти, використання логотипів
брендів)
· Розширені можливості аналітики (фільтрація, сегментація,
автоматичне створення звітів)
· Широка інтеграція (CRM-системи, маркетингові платформи,
аналітичні інструменти)
· Безпека та відповідність стандартам
· Висока вартість тарифного плану
· Складний для новачків інтерфейс
· Обмеженість безкоштовної версії
OpportunitiesThreats
· Зростаючий попит на інструменти збору даних
· Розширення інтеграцій
· Вдосконалення користувацького досвіду (розвиток
інтерфейсу, поліпшення навігації)
· Конкуренція з іншими платформами
· Проблеми з конфіденційністю
· Швидкі технологічні зміни

Висновок: SurveyMonkey має суттєві переваги перед своїми конкурентами завдяки розширеним можливостям кастомізації дизайну, аналітики та інтеграції з CRM-системами й маркетинговими платформами. Однак, через високу вартість платних тарифів, складний інтерфейс для новачків і обмеження у безкоштовній версії, цей сервіс має досить вузьку аудиторію. У порівнянні з Google Forms, SurveyMonkey займає нижчу позицію на ринку через свою складність і цінову політику, що обмежує його доступність для широкого кола користувачів.

Survio

StrengthsWeaknesses
· Простий та інтуїтивний інтерфейс
· Широкий вибір шаблонів
· Мультиплатформенність
· Безкоштовний план
· Обмеженість функціоналу безкоштовної версії
· Обмежені можливості кастомізації (невелика
кількість варіантів дизайну і налаштування брендових опитувань)
· Невеликий вибір інтеграцій
OpportunitiesThreats
· Збільшення попиту на інструменти для опитувань
· Розширення функціональності
· Вдосконалення інтерфейсу користувача
· Конкуренція з боку інших платформ
· Залежність від технологічних змін => потреба у постійній адаптації
· Проблеми з конфіденційністю даних

Висновок: серед основних переваг Survio — простий та інтуїтивний інтерфейс, мультиплатформенність та широкий вибір шаблонів. Платформа також пропонує безкоштовний план, хоча його функціонал досить обмежений, що ставить Survio в невигідне становище порівняно з конкурентами, наприклад Google Forms. Обмежена кількість інтеграцій та кастомізацій зменшує привабливість платформи для складніших бізнес-середовищ. У результаті, ці недоліки можуть посилювати загрозу конкуренції, що ставить під сумнів довготривалу актуальність платформи на ринку.

SurveyJS

StrengthsWeaknesses
· Широкий спектр можливостей для створення та налаштування опитувань
· Підтримка різних платформ: React, Angular, Vue.js
· Створення опитувань з різноманітними типами питань
· Оpen-source продукт
· Складний інтерфейс для новачка
· Недостатня кількість готових шаблонів
· Складність використання нетехнічними користувачами
OpportunitiesThreats
· Великі можливості для впровадження у різних сферах бізнесу та освіти
· Додавання нових функцій: аналітика результатів опитувань, інтеграція зі штучним інтелектом
· Можливість інтеграції з CRM-системами, маркетинговими платформами, інструментами бізнес-аналітики
· Наявність конкуруючих платформ, що можуть запропонувати легший інтерфейс і ширший функціонал
· Додаткові ресурси для підтримки при змінах у фреймворках
· Технічні проблеми або помилки

Висновок: SurveyJS вирізняється широкими можливостями налаштування опитувань, підтримкою популярних фреймворків (React, Angular і Vue.js) та відкритим вихідним кодом, що робить його привабливим для розробників. Однак складний інтерфейс та обмежена кількість шаблонів можуть бути бар’єрами для новачків. SurveyJS має великі можливості для впровадження у різних сферах бізнесу та освіти завдяки інтеграціям із CRM-системами та маркетинговими платформами. Загрозами залишаються конкуренція з платформами, які пропонують простіший інтерфейс, ширший функціонал та додаткові ресурси для підтримки при змінах у фреймворках.

Система “ОСА”

StrengthsWeaknesses
· Локальна адаптація
· Функціонал достатній для базових потреб, що не вимагають складних інтеграцій
· Застаріла технологія
· Використання старих платформ
· Обмежений функціонал і масштабованість
· Відсутність мобільної підтримки
· Відсутність новітніх можливостей для аналітики
· Не передбачено інтеграцій з іншими платформами та візуалізації даних
· Відсутність легких інтеграцій з іншими сучасними інструментами для обробки даних, CRM-системами або хмарними платформами
OpportunitiesThreats
· Впровадження сучасних технологій: хмарні сервіси, інтеграції з аналітичними платформами або мобільними додатками
· Локалізація для українскього ринку
· Покращення UX/UI
· Неконкурентноспроможна серед сучасних систем
· Відсутність суттєвих оновлень та інвестицій
· Невідповідність сучасним стандартам безпеки та конфіденційності

Висновок: Система "OCA" має мінімальні переваги порівняно з конкурентами, такі як локальна адаптація та достатній функціонал для простих задач, які не потребують складних інтеграцій. Однак кількість недоліків значно переважає: використання застарілих технологій і платформ, відсутність мобільної підтримки та сучасних аналітичних інструментів, а також неможливість інтеграції з іншими платформами для обробки та візуалізації даних. Невідповідність сучасним стандартам безпеки та конфіденційності, а також недостатні інвестиції в оновлення загрожують подальшій життєздатності системи. Вона стає неконкурентоспроможною в порівнянні з новітніми технологічними рішеннями, що зменшує її актуальність на ринку.

Висновки

Проведений SWOT аналіз конкурентів платформи MESS допоміг дослідити тенденції розвитку основних конкуретнів, висвітлив схожі риси та відмінності.

Хоча і Google Forms, і Survio мають достатньо обмежені можливості кастомізації дизайну опитувань, через обмеженість функціоналу безкоштовного плану Survio суттєво програє за популярністю повністю безкоштовному Google Forms. Незважаючи на те, що обидві платформи мають проблеми з конфіденційністю, Google Forms має більше шансів на утримання позицій на ринку, оскільки Survio програє цій платформі і за кількістю корисних інтеграцій.

Складний інтерфейс SurveyJS та SurveyMonkey суттєво зменшує кількість їх потенційних користувачів, адже багато хто надає перевагу простішим в опануванні Google Forms та Survio, інтерфейс яких є інтуїтивним. Проте для вузького кола своєї цільової авдиторії, SurveyMonkey виграє у найближчих конкурентів, приміром Google Forms, завдяки широким аналітичним можливостям та великому спектру можливостей кастомізації дизайну. Аналогічно, SurveyJS пропонує унікальні можливості розробникам завдяки підтримці низки популярних фреймворків та відкритості вихідного коду.

Система "ОСА" залишається в найбільш невигідному становищі серед сучасніших конкурентів через невідповідність сучасним вимогам безпеки, обмежений фінкціонал та використання застарілих технологій. Ця платформа майже не має шансів захопити частку міжнародного ринку, тому найкращою стратегією розвитку для неї є концентрація на локалізації завдяки впровадженню оновлень, які б могли задовольнити потреби локальних користувачів.

Аналіз конкурентів також показав, що жодна з досліджених платформ не покриває життєвий цикл організації та управління експертним оптуванням. Швидкі технологічні зміни вимагають від продуктів постійної адаптації до нових вимог, що призводить до чималих витрат ресурсів, і призводять до втрати актуальності технологіями - це становить загрозу для кожної з платформ.

Посилання

  1. Експерт
  2. Критерії вибору експерта
  3. Опитування
  4. Експертні опитування
  5. Анкета
  6. Структура анкети, типи та види запитань
  7. Соціологічні опитування
  8. Маркетингові опитування
  9. Масові опитування
  10. Експертні
  11. Логіка запитань та відповідей
  12. Процедура складання анкети і вимоги до формулювання питань для опитування
  13. Формулювання запитань
  14. Види експертного опитування. Відбір експертів
  15. Види експертного опитування
  16. Метод Дельфі як метод кількісної оцінки думки експертів

Запити зацікавлених осіб

Вступ

У цьому розділі зібрано запитів зацікавлених осіб, а також представлено вимоги до платформи MESS (Modern easy social surveys), що розробляється для покращення процесу збору та аналізу даних опитувань. Розділ охоплює ключові аспекти роботи платформи, такі як функціональність, практичність, надійність, продуктивність та експлуатаційна придатність.

Мета

Основною метою цього розділу є визначення вимог, що відповідатимуть усім запитам зацікавлених осіб та допоможуть зробити платформу MESS максимально зручною, дієвою та ефективною у використанні. Це дозволить розробникам створити ефективний інструмент для збору і аналізу опитувань різних груп користувачів, що сприятиме збільшенню цільової авдиторії.

Контекст

Ця частина матеріалу впливає на планування та реалізацію функціональних можливостей платформи, визначаючи основні вимоги до її розробки. Цей розділ також включає аналіз потреб та очікувань потенційних користувачів платформи MESS, що полегшить процес розробки інструменту.

Основні визначення та скорочення

Аналітика - процес збору, обробки та аналізу даних з метою отримання інформації для прийняття певних рішень. Вона дозволяє виявляти закономірності, тенденції та взаємозв'язки в даних, що допомагає покращити ефективність бізнесу, оптимізувати процеси й визначити цільову аудиторію.

Дослідник - особа, що збирає дані через реалізацію опитувань.

Експерт дивитись в Аналіз предметної області

Цільова авдиторія - група людей, на яких розраховано певний товар, продукт, послугу чи інформаційний контент, що відповідає їхнім потребам, інтересам. Інформаційна панель (інфопанель, дашборд) - динамічний звіт, що дозволяє в режимі реального часу слідкувати за показниками.

SQL (Structured query language) - стандартна мова запитів, що використовується для запиту та внесення змін до бази даних, а також керування базами даних.

SQL-ін'єкція - метод отримання несанкціонованого доступу до бази даних; один з найбільш часто використовуваних способів взлому продуктів, що взаємодіють з базами даних.

FURPS - модель класифікації вимог, що включає:

  • Functionality
  • Usability
  • Reliability
  • Performance
  • Supportability

Короткий зміст

  1. Характеристика ділових процесів
  2. Короткий огляд продукту
  3. Функціональність
  4. Практичність
  5. Надійність
  6. Продуктивність
  7. Експлуатаційна придатність

Характеристика ділових процесів

IDBUC.01.00
НАЗВАПідготувати опитувальну анкету
УЧАСНИКИЗамовник, менеджер, аналітик, рецензент
ПЕРЕДУМОВИЗамовник звернувся для проведення опитування для збору конкретної інформації
РЕЗУЛЬТАТГотова до реалізації опитувальна анкета
ВИКЛЮЧНІ СИТУАЦІЇ1. Замовник повністю змінює цілі опитування
2. Стратегії, розроблені менеджером, виявляються неефективними
3. Замовник значно скорочує терміни розробки опитування
4. Менеджер отримує негативний зворотний зв'язок від замовника
ОСНОВНИЙ СЦЕНАРІЙ1. Замовник звертається до менеджера для обговорення розробки опитування відповідно до його запиту
2. Менеджер розробляє стратегії для розробки опитування, що максимально відповідають вимогам замовника
3. Аналітик проводить аналіз цільової аудиторії
4. Аналітик формулює запитання, що відповідають цілям опитування
5. Менеджер організовує роботу та оптимізує робочі процеси під час виготовлення опитування, забезпечуючи ефективний обмін інформацією всередині команди та з замовником
6. Рецензент оцінює якість та виявляє можливі недоліки готового опитування
7. Менеджер передає готову до реалізації опитувальну анкету

IDBUC.02.00
НАЗВАРеалізувати опитування
УЧАСНИКИДослідник, експерт
ПЕРЕДУМОВИДослідник отримав готове опитування для реалізації
РЕЗУЛЬТАТГотові результати опитування
ВИКЛЮЧНІ СИТУАЦІЇ1. Експерт не має змоги взяти участь в опитуванні у попередньо зазначений час
2. Дослідник не встиг провести опитування всіх експертів
ОСНОВНИЙ СЦЕНАРІЙ1. Дослідник підбирає експертів
2. Дослідник зв'язується з експертом для уточнення дати та часу проведення опитування
3. Дослідник визначається з методом опитування
4. Дослідник зустрічається з експертом для проведення опитування
5. Дослідник дає анкету експерту
6. Експерт заповнює анкету
7. Дослідник оформлює анкету
8. Дослідник керує опитуванням, залежно від методу, який він обрав
9. Дослідник передає готові результати опитувань на аналітику

IDBUC.03.00
НАЗВАПроаналізувати дані, отримані з опитувань
УЧАСНИКИАналітик Big Data/BI, замовник
ПЕРЕДУМОВИАналітики отримали зібрані результати опитування
РЕЗУЛЬТАТЗвіт за результатами аналізу
ВИКЛЮЧНІ СИТУАЦІЇ1. Кількість даних є недостатньої для об'єктивного аналізу
2. Аналітик виявив недоброчесність експерта
ОСНОВНИЙ СЦЕНАРІЙ1. Аналітик перевіряє об'єктивність отриманих результатів
2. Аналітик очищує дані
3. Аналітик упорядковує дані
4. Аналітик аналізує дані за допомогою статистичних оцінок та методів машинного навчання
5. Аналітик подає отримані результати у вигляді графіків, діаграм та інформаційних панелей
6. Аналітик складає звіт за результатами аналізу
7. Замовник отримує звіт

Короткий огляд продукту

MESS (Modern Easy Social Serveys) - це платформа, за допомогою якої користувачі можуть зручно створювати різноманітні опитування та аналізувати їх задля дослідження своєї цільової авдиторії.

Наш сервіс є корисним для широкого кола користувачів:

  • представників великих, середніх та малих бізнесів для збирання та дослідження відгуків своїх користувачів
  • стартапів для визначення потенційної цільової авдиторії
  • фізичних осіб, наприклад студентів, для проведення соціологічних досліджень

Функціональність

На нашій платформі передбачено два типи користувачів: дослідник та експерт. Дослідник - це представник бізнесу, стартапу або фізична особа, що координує проведння опитувань. Експерт - той, хто користується сервісом для проходження опитувань.

Функціональність, доступна всім користувачам:

  • Створити акаунт
  • Редагувати дані акаунта
  • Видалити акаунт

Функціональність, доступна досліднику:

  • Створити опитування
  • Закрити опитування
  • Видалити опитування
  • Отримати аналітику опитування
  • Переглянути створені опитування
  • Створити категорію для опитувань
  • Додати категорію до опитування
  • Оцінити компетентність експерта
  • Залишити скаргу на експерта

Функціональність, доступна експерту:

  • Обрати категорію експертизи
  • Переглянути доступні опитування (доступні лише опитування, що відповідають категорії експертизи фахівця)
  • Пройти опитування
  • Змінити відповідь в опитуванні (якщо дослідник дозволив змінення відповідей)
  • Переглянути пройдені опитування
  • Залишити скаргу на опитування

Практичність

  • інтуїтивно зрозумілий інтерфейс
  • подання аналітики опитувань у зрозумілому вигляді
  • легкість створення та управління опитуваннями
  • легкість проходження опитувань
  • проста навігація
  • швидкість роботи

Надійність

  • обов'язкова реєстрація (перешкоджає доступу до платформи сторонніх осіб)
  • конфіденційність даних
  • збереження анонімності при проходженні опитувань
  • шифрування даних, зокрема для безпечного зберігання паролів
  • захист від SQL-ін'єкцій
  • регулярне оновлення механізмів безпеки
  • регулярне тестування для своєчасного виявлення вразливостей

Продуктивність

  • оптимізовані SQL запити
  • мінімалізовано час затримки виконання операцій в реальному часі
  • час завантаження платформи не перевищує 3 секунд
  • оптимізоване використання ресурсів серверу та пристрою користувача
  • велика пропускна здатність
  • обробка помилок з мінімальним впливом на роботу платформи

Експлуатаційна придатність

  • регулярні оновлення для покращення роботи платформи та виправлення помилок
  • регулярний рефакторинг коду для підвищення його читабельності та оптимізованості
  • швидке реагування у разі виникнення несподіваних помилок
  • актуальність та регулярне оновлення документації проєкту
  • відкритий вихідний код проєкту
  • використання сталих та актуальних технологій
  • використання системи контролю версій для зручності оновлення кодової бази проєкту
  • зворотний зв'язок з користувачами для покращення роботи платформи

Посилання

  1. Аналітика
  2. Користувач
  3. Цільова авдиторія
  4. Інформаційна панель
  5. SQL
  6. SQL-ін'єкція
  7. Акаунт
  8. Інтерфейс
  9. FURPS

Розроблення функціональних вимог до системи

У цьому розділі містяться діаграми прецедентів, зокрема загальна та конкретизовані, і діаграми активностей. Діаграми було побудовано з урахуванням розроблених характеристик ділових процесів та функціональних вимог, що містяться в Запитах зацікавлених осіб

Короткий зміст

  1. Діаграма use case для всіх бізнес акторів
  2. Діаграма use case для користувача
  3. Діаграма use case дослідника
  4. Діаграма use case для експерта
  5. Діаграма use case для адміністратора
  6. Діаграма активності для "Створити акаунт користувача"
  7. Діаграма активності для "Редагувати дані акаунта"
  8. Діаграма активності для "Видалити акаунт користувача"
  9. Діаграма активності для "Створити опитування"
  10. Діаграма активності для "Закрити опитування"
  11. Діаграма активності для "Видалити опитування"
  12. Діаграма активності для "Отримати аналітику опитування"
  13. Діаграма активності для "Показати створені опитування"
  14. Діаграма активності для "Пройти опитування"
  15. Діаграма активності для "Змінити відповіді"
  16. Діаграма активності для "Показати пройдені опитування"

Діаграми прецедентів бізнес акторів

Діаграма прецидентів (діаграма use case) - діаграма, що показує різноманітні сценарії взаємодії між акторами (користувачами) та прецидентами (випадками використання). [1] [2]

Діаграма use case для всіх бізнес акторів

Діаграма use case для користувача

Діаграма use case дослідника

Діаграма use case для експерта

Діаграма use case для адміністратора

Діаграми діяльностей

Діаграма діяльності (activity діаграма) - діаграма, що візуалізує процес використання та ілюструє потік повідомлень від однієї дії до іншої. [2]

Діаграма діяльності для "Створити акаунт користувача"

IDBUC.01.01
НАЗВАСтворити акаунт користувача
УЧАСНИКИКористувач, система
ПЕРЕДУМОВИКористувач попередньо не має зареєстрованого акаунта в системі MESS.
РЕЗУЛЬТАТНовий обліковий запис користувача.
ВИКЛЮЧНІ СИТУАЦІЇEX.01.01 Обліковий запис, зареєстрований за цією поштою, вже існує.
EX.01.02 Не всі обов'язкові дані заповнені.
EX.01.03 Пароль не відповідає вимогам.
EX.01.04 Поля "Пароль" та "Підтвердіть пароль" не збігаються.

Діаграма діяльності для "Редагувати дані акаунта"

IDBUC.01.02
НАЗВАРедагувати дані акаунта
УЧАСНИКИКористувач, система
ПЕРЕДУМОВИКористувач має створений обліковий запис та авторизований у системі.
РЕЗУЛЬТАТОновлені дані облікового запису.
ВИКЛЮЧНІ СИТУАЦІЇEX.01.05 Користувач намагається змінити дані на ті, які не відповідають вимогам.
EX.01.06 Користувач увів неправильний пароль для підтвердження операції.

Діаграма діяльності для "Видалити акаунт користувача"

IDBUC.01.03
НАЗВАВидалити акаунт користувача
УЧАСНИКИКористувач, система
ПЕРЕДУМОВИКористувач має створений обліковий запис та авторизований у системі.
РЕЗУЛЬТАТВидалення облікового запису користувача.
ВИКЛЮЧНІ СИТУАЦІЇEX.01.06 Користувач увів неправильний пароль для підтвердження операції.

Діаграма діяльності для "Створити опитування"

IDBUC.01.04
НАЗВАСтворити опитування
УЧАСНИКИДослідник, система
ПЕРЕДУМОВИДослідник вже авторизований у системі.
РЕЗУЛЬТАТНове опитування.
ВИКЛЮЧНІ СИТУАЦІЇEX.01.07 Дослідник не заповнив усі поля запитань та варіантів відповідей, що додав.
EX.01.08 Запитання містить однакові варіанти відповідей.
EX.01.09 Дослідник не додав жодного питання до опитування.

Діаграма діяльності для "Закрити опитування"

IDBUC.02.01
НАЗВАЗакрити опитування
УЧАСНИКИДослідник, система
ПЕРЕДУМОВИДослідник вже має створене опитування.
РЕЗУЛЬТАТЗакрите опитування (більше не є можливим для проходження).
ВИКЛЮЧНІ СИТУАЦІЇEX.02.01 При запиті "Ви точно бажаєте закрити опитування?" обрати варіант "Ні".
EX.02.02 Швидко натискає кнопку другий раз до того, як запит після першого натискання встиг обробитися.

Діаграма діяльності для "Видалити опитування"

IDBUC.02.02
НАЗВАВидалити опитування
УЧАСНИКИДослідник, система
ПЕРЕДУМОВИДослідник вже має закрите опитування.
РЕЗУЛЬТАТВидалення опитування.
ВИКЛЮЧНІ СИТУАЦІЇEX.02.02 Швидко натискає кнопку другий раз до того, як запит після першого натискання встиг обробитися.
EX.02.03 При запиті "Ви точно бажаєте видалити опитування?" обрати варіант "Ні".

Діаграма діяльності для "Отримати аналітику опитування"

IDBUC.03.01
НАЗВАОтримати аналітику опитування
УЧАСНИКИДослідник, система
ПЕРЕДУМОВИДослідник вже має створене опитування.
РЕЗУЛЬТАТАналітика опитування
ВИКЛЮЧНІ СИТУАЦІЇEX.03.01 Багаторазове швидке натискання на кнопку "Аналітика".
EX.03.02 Не вдалося отримати дані з бази.

Діаграма діяльності для "Показати створені опитування"

IDBUC.02.03
НАЗВАПоказати створені опитування
УЧАСНИКИДослідник, система
ПЕРЕДУМОВИДослідник вже авторизований у системі.
РЕЗУЛЬТАТСписок створених опитувань.
ВИКЛЮЧНІ СИТУАЦІЇEX.02.04 У користувача зник інтернет.
EX.02.05 Не вдалося отримати дані з бази.
EX.02.06 Запит на створення нового опитування система не встигла обробити, тому щойно створене опитування не відображається.

Діаграма діяльності для "Пройти опитування"

IDBUC.02.04
НАЗВАПройти опитування
УЧАСНИКИЕксперт, система
ПЕРЕДУМОВИЕксперт має бути зареєстрований у системі.
РЕЗУЛЬТАТВідповіді експерта.
ВИКЛЮЧНІ СИТУАЦІЇEX.02.04 У користувача зник інтернет.
EX.02.07 Експерт двічі натиснув на кнопку "Почати опитування".
EX.02.08 Користувач випадково оновив сторінку.

Діаграма діяльності для "Змінити відповіді"

IDBUC.02.05
НАЗВАЗмінити відповіді
УЧАСНИКИЕксперт, система
ПЕРЕДУМОВИЦя можливість повинна бути дозволена автором опитування.
РЕЗУЛЬТАТОновлені відповіді експерта
ВИКЛЮЧНІ СИТУАЦІЇEX.02.04 У користувача зник інтернет.
EX.02.08 Користувач випадково оновив сторінку.

Діаграма діяльності для "Показати пройдені опитування"

IDBUC.02.06
НАЗВАПоказати пройдені опитування
УЧАСНИКИЕксперт, система
ПЕРЕДУМОВИЕксперт авторизований у системі.
РЕЗУЛЬТАТСписок пройдених опитувань.
ВИКЛЮЧНІ СИТУАЦІЇEX.02.05 Не вдалося отримати дані з бази.

Посилання

  1. Діаграми Прецедентів (Use Case UML Diagram)
  2. Як будувати UML-діаграми. Розбираємо три найпопулярніші варіанти

Проєктування бази даних

Короткий зміст:

Модель бізнес-об'єктів

Модель бізнес-об'єктів - це опис системи, в рамках якої відображаються всі об’єкти (сутності) даної системи. [1]

ER-модель

ER-модель описує сутності системи та визначає зв'язки між ними. [2]

Реляційна схема

Реляційна схема - це набір таблиць, кожна з яких відповідає за одну з сутностей реляційної бази даних, та зв'язків між ними. Реляційна схема використовується для представлення реляційної бази даних. [3]

Реляційна схема

Посилання

  1. Бізнес-моделі підприємства: еволюція та класифікація
  2. Entity–relationship model
  3. Relational Schemas

Реалізація інформаційного та програмного забезпечення

SQL-скрипт для створення на початкового наповнення бази даних

SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0;
SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0;
SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION';

-- -----------------------------------------------------
-- Schema DB_labs
-- -----------------------------------------------------

-- -----------------------------------------------------
-- Schema DB_labs
-- -----------------------------------------------------
CREATE SCHEMA IF NOT EXISTS `DB_labs` DEFAULT CHARACTER SET utf8 ;
-- -----------------------------------------------------

USE `DB_labs` ;

-- -----------------------------------------------------
-- Table `DB_labs`.`User`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `DB_labs`.`User` (
  `id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
  `first_name` VARCHAR(45) NOT NULL,
  `last_name` VARCHAR(45) NOT NULL,
  `email` VARCHAR(45) NOT NULL,
  `phone_number` VARCHAR(45) NULL,
  `password` VARCHAR(45) NOT NULL,
  `is_admin` TINYINT NOT NULL,
  `description` TEXT NULL,
  `age` TINYINT NULL,
  `gender` VARCHAR(45) NULL,
  `company` VARCHAR(45) NULL,
  PRIMARY KEY (`id`),
  UNIQUE INDEX `idUser_UNIQUE` (`id` ASC) VISIBLE,
  UNIQUE INDEX `email_UNIQUE` (`email` ASC) VISIBLE,
  UNIQUE INDEX `phone_number_UNIQUE` (`phone_number` ASC) VISIBLE)
ENGINE = InnoDB;


-- -----------------------------------------------------
-- Table `DB_labs`.`ExpertComplaint`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `DB_labs`.`ExpertComplaint` (
  `id` INT NOT NULL AUTO_INCREMENT,
  `description` TEXT NULL,
  `date` DATETIME NOT NULL,
  `researcher_id` INT UNSIGNED NOT NULL,
  `expert_id` INT UNSIGNED NOT NULL,
  PRIMARY KEY (`id`, `researcher_id`, `expert_id`),
  INDEX `fk_ExpertComplaint_User2_idx` (`expert_id` ASC) VISIBLE,
  CONSTRAINT `fk_ExpertComplaint_User1`
    FOREIGN KEY (`researcher_id`)
    REFERENCES `DB_labs`.`User` (`id`)
    ON DELETE CASCADE
    ON UPDATE CASCADE,
  CONSTRAINT `fk_ExpertComplaint_User2`
    FOREIGN KEY (`expert_id`)
    REFERENCES `DB_labs`.`User` (`id`)
    ON DELETE CASCADE
    ON UPDATE CASCADE)
ENGINE = InnoDB;


-- -----------------------------------------------------
-- Table `DB_labs`.`Survey`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `DB_labs`.`Survey` (
  `id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
  `title` VARCHAR(45) NOT NULL,
  `description` TEXT NULL,
  `creation_date` DATETIME NOT NULL,
  `close_date` DATETIME NULL,
  `is_changable` TINYINT NOT NULL,
  `is_active` TINYINT NOT NULL,
  `owner_id` INT UNSIGNED NOT NULL,
  PRIMARY KEY (`id`, `owner_id`),
  UNIQUE INDEX `id_UNIQUE` (`id` ASC) VISIBLE,
  INDEX `fk_Survey_User1_idx` (`owner_id` ASC) VISIBLE,
  CONSTRAINT `fk_Survey_User1`
    FOREIGN KEY (`owner_id`)
    REFERENCES `DB_labs`.`User` (`id`)
    ON DELETE CASCADE
    ON UPDATE CASCADE)
ENGINE = InnoDB;


-- -----------------------------------------------------
-- Table `DB_labs`.`SurveyComplaint`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `DB_labs`.`SurveyComplaint` (
  `id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
  `description` TEXT NULL,
  `date` DATETIME NOT NULL,
  `survey_id` INT UNSIGNED NOT NULL,
  `expert_id` INT UNSIGNED NOT NULL,
  PRIMARY KEY (`id`, `survey_id`, `expert_id`),
  UNIQUE INDEX `id_UNIQUE` (`id` ASC) VISIBLE,
  INDEX `survey_id_idx` (`survey_id` ASC) VISIBLE,
  INDEX `fk_SurveyComplaint_User1_idx` (`expert_id` ASC) VISIBLE,
  CONSTRAINT `survey_1_id`
    FOREIGN KEY (`survey_id`)
    REFERENCES `DB_labs`.`Survey` (`id`)
    ON DELETE CASCADE
    ON UPDATE CASCADE,
  CONSTRAINT `expert_id`
    FOREIGN KEY (`expert_id`)
    REFERENCES `DB_labs`.`User` (`id`)
    ON DELETE CASCADE
    ON UPDATE CASCADE)
ENGINE = InnoDB;


-- -----------------------------------------------------
-- Table `DB_labs`.`Category`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `DB_labs`.`Category` (
  `id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
  `name` VARCHAR(45) NOT NULL,
  `parent_id` INT NULL,
  PRIMARY KEY (`id`),
  UNIQUE INDEX `id_UNIQUE` (`id` ASC) VISIBLE)
ENGINE = InnoDB;


-- -----------------------------------------------------
-- Table `DB_labs`.`Expertise`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `DB_labs`.`Expertise` (
  `id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
  `expertise_rate` DOUBLE NOT NULL,
  `category_id` INT UNSIGNED NOT NULL,
  `user_id` INT UNSIGNED NOT NULL,
  PRIMARY KEY (`id`, `category_id`, `user_id`),
  UNIQUE INDEX `id_UNIQUE` (`id` ASC) VISIBLE,
  INDEX `category_id_idx` (`category_id` ASC) VISIBLE,
  INDEX `fk_Expertise_User1_idx` (`user_id` ASC) VISIBLE,
  CONSTRAINT `fk_category_id`
    FOREIGN KEY (`category_id`)
    REFERENCES `DB_labs`.`Category` (`id`)
    ON DELETE CASCADE
    ON UPDATE CASCADE,
  CONSTRAINT `fk_Expertise_User1`
    FOREIGN KEY (`user_id`)
    REFERENCES `DB_labs`.`User` (`id`)
    ON DELETE CASCADE
    ON UPDATE CASCADE)
ENGINE = InnoDB;


-- -----------------------------------------------------
-- Table `DB_labs`.`Question`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `DB_labs`.`Question` (
  `id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
  `header` VARCHAR(60) NOT NULL,
  `description` TEXT NULL,
  `survey_id` INT UNSIGNED NOT NULL,
  PRIMARY KEY (`id`, `survey_id`),
  UNIQUE INDEX `id_UNIQUE` (`id` ASC) VISIBLE,
  INDEX `survey_id_idx` (`survey_id` ASC) VISIBLE,
  CONSTRAINT `fk_survey_id`
    FOREIGN KEY (`survey_id`)
    REFERENCES `DB_labs`.`Survey` (`id`)
    ON DELETE NO ACTION
    ON UPDATE NO ACTION)
ENGINE = InnoDB;


-- -----------------------------------------------------
-- Table `DB_labs`.`Option_q`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `DB_labs`.`Option_q` (
  `id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
  `content` TEXT NOT NULL,
  `question_id` INT UNSIGNED NOT NULL,
  PRIMARY KEY (`id`, `question_id`),
  UNIQUE INDEX `id_UNIQUE` (`id` ASC) VISIBLE,
  INDEX `question_id_idx` (`question_id` ASC) VISIBLE,
  CONSTRAINT `fk_question_id`
    FOREIGN KEY (`question_id`)
    REFERENCES `DB_labs`.`Question` (`id`)
    ON DELETE CASCADE
    ON UPDATE CASCADE)
ENGINE = InnoDB;


-- -----------------------------------------------------
-- Table `DB_labs`.`Answer`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `DB_labs`.`Answer` (
  `id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
  `option_id` INT UNSIGNED NOT NULL,
  `expert_id` INT UNSIGNED NOT NULL,
  PRIMARY KEY (`id`, `option_id`, `expert_id`),
  UNIQUE INDEX `id_UNIQUE` (`id` ASC) VISIBLE,
  INDEX `option_id_idx` (`option_id` ASC) VISIBLE,
  INDEX `fk_Answer_User2_idx` (`expert_id` ASC) VISIBLE,
  CONSTRAINT `fk_option_id`
    FOREIGN KEY (`option_id`)
    REFERENCES `DB_labs`.`Option_q` (`id`)
    ON DELETE CASCADE
    ON UPDATE CASCADE,
  CONSTRAINT `fk_Answer_User2`
    FOREIGN KEY (`expert_id`)
    REFERENCES `DB_labs`.`User` (`id`)
    ON DELETE CASCADE
    ON UPDATE CASCADE)
ENGINE = InnoDB;


-- -----------------------------------------------------
-- Table `DB_labs`.`SurveyCategory`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `DB_labs`.`SurveyCategory` (
  `id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
  `survey_id` INT UNSIGNED NOT NULL,
  `category_id` INT UNSIGNED NOT NULL,
  PRIMARY KEY (`id`, `survey_id`, `category_id`),
  INDEX `fk_Survey_has_Category_Survey1_idx` (`survey_id` ASC) VISIBLE,
  UNIQUE INDEX `id_UNIQUE` (`id` ASC) VISIBLE,
  INDEX `fk_SurveyCategory_Category1_idx` (`category_id` ASC) VISIBLE,
  CONSTRAINT `fk_survey_id1`
    FOREIGN KEY (`survey_id`)
    REFERENCES `DB_labs`.`Survey` (`id`)
    ON DELETE CASCADE
    ON UPDATE CASCADE,
  CONSTRAINT `fk_SurveyCategory_Category1`
    FOREIGN KEY (`category_id`)
    REFERENCES `DB_labs`.`Category` (`id`)
    ON DELETE CASCADE
    ON UPDATE CASCADE)
ENGINE = InnoDB;

SET SQL_MODE=@OLD_SQL_MODE;
SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS;
SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS;
-- Fill database with data
 USE db_labs;

INSERT INTO user (first_name, last_name, email, phone_number, password, is_admin) 
VALUES ("Dima", "Valai", "dima@gmail.com", "+380113223344", "jagiq273ty", 0);
INSERT INTO user (first_name, last_name, email, phone_number, password, is_admin) 
VALUES ("Vasya", "Vasylenko", "vasya@gmail.com", "+380113223334", "jagiq2732y", 1);
INSERT INTO user (first_name, last_name, email, phone_number, password, is_admin) 
VALUES ("Kate", "Pril", "kate@gmail.com", "+380112223344", "jagiq973ty", 1);
INSERT INTO user (first_name, last_name, email, phone_number, password, is_admin, description, age, gender) 
VALUES ("John", "Doe", "john.doe@example.com", "+1234567890", "q23xttrfg", 0, "Expert in psychology with 10 years of experience in behavioral research.", 45, "Male");
INSERT INTO user (first_name, last_name, email, phone_number, password, is_admin, company) 
VALUES ("Jane", "Smith", "jane.smith@example.com", "+0987654321", "gqd2ex3fc", 0, "MindTech Solutions");
INSERT INTO user (first_name, last_name, email, phone_number, password, is_admin, description, age, gender) 
VALUES ("Alice", "Johnson", "alice.johnson@example.com", "+1987654321", "p9lmdsk34", 0, "Data analyst specializing in machine learning and data-driven decision making.", 30, "Female");
INSERT INTO User(first_name, last_name, email, phone_number, password, is_admin, age, gender)
VALUES("Maksim", "Zinets", "Makson@example.com", "+123124124", "1234567890", 1, 18, "Male");
INSERT INTO User(first_name, last_name, email, phone_number, password, is_admin, description, age, gender, company)
VALUES("Immanuel", "Kant", "critic@example.com", "+14881488", "0987654321", 0, "No description given", 52, "Male", "Phenomen Industries");
INSERT INTO User(first_name, last_name, email, phone_number, password, is_admin, age, gender)
VALUES("Friedrich", "Nietzsche", "ubermensch@example.com", "+1357924680", "securepassword", 0, 56, "Male");
INSERT INTO User(first_name, last_name, email, phone_number, password, is_admin, description, age, gender, company)
VALUES("Margaret", "Thatcher", "godsavethequeen@example.com", "+23469346", "26343464", 0, "British Statewoman", 88, "Female", "British Parliament");
INSERT INTO User(first_name, last_name, email, phone_number, password, is_admin, description, age, gender, company)
VALUES("Napoleon", "Bonaparte", "vivalafrance@example.com", "+11111111", "11111111", 0, "Emperor of France", 45, "Male", "French Empire");
INSERT INTO user (first_name, last_name, email, phone_number, password, is_admin, description, age, gender, company)
VALUES ("Andrii", "Solomka", "asolomka@gmail.com", "+3806666666", "12345", 1, "Node js developer", 52, "Male", "Donbass Coil");
INSERT INTO User(first_name, last_name, email, phone_number, password, is_admin, description, age, gender, company)
VALUES("Loli", "Crop", "brawlstars@example.com", "+774329602", "pididivdidi", 0, "Beer-drink master", 25, "Male", "Beer World");
INSERT INTO User(first_name, last_name, email, phone_number, password, is_admin, description, age, gender, company)
VALUES("Andrii", "Cruco", "kapibara@example.com", "+0664326434", "********", 0, "Non expert expert", 39, "Male", "Beer World");



INSERT INTO category (name) VALUES ("psychology");
INSERT INTO category (name) VALUES ("math");
INSERT INTO category (name) VALUES ("music");
INSERT INTO category (name) VALUES ("machine learning");
INSERT INTO category (name, parent_id) VALUES ("deep learning", 2);
INSERT INTO category (name, parent_id) VALUES ("children psychology", 1);
INSERT INTO category (name) VALUES("IT");
INSERT INTO category (name) VALUES("Philosophy");
INSERT INTO category (name) VALUES("Politics");
INSERT INTO category (name, parent_id) VALUES("Analytical philosophy", 2);
INSERT INTO category (name, parent_id) VALUES("Continental philosophy", 2);
INSERT INTO category (name, parent_id) VALUES("Conquests", 3);
INSERT INTO category (name, parent_id) VALUES("Backend development", 7);
INSERT INTO category (name) VALUES("Physics");

INSERT INTO expertise (expertise_rate, category_id, user_id) VALUES (5, 1, 2);
INSERT INTO expertise (expertise_rate, category_id, user_id) VALUES (5, 6, 8);
INSERT INTO expertise (expertise_rate, category_id, user_id) VALUES (4.5, 5, 8);
INSERT INTO expertise (expertise_rate, category_id, user_id) VALUES (5, 5, 11);
INSERT INTO expertise (expertise_rate, category_id, user_id) VALUES (2, 1, 4);
INSERT INTO expertise (expertise_rate, category_id, user_id) VALUES (4.5, 2, 4);
INSERT INTO expertise (expertise_rate, category_id, user_id) VALUES (5, 3, 4);
INSERT INTO expertise(expertise_rate, category_id, user_id) VALUES (5, 2, 2);
INSERT INTO expertise(expertise_rate, category_id, user_id) VALUES (1, 1, 1);
INSERT INTO expertise(expertise_rate, category_id, user_id) VALUES (5, 4, 2);
INSERT INTO expertise(expertise_rate, category_id, user_id) VALUES (4, 2, 3);
INSERT INTO expertise(expertise_rate, category_id, user_id) VALUES (5, 5, 3);
INSERT INTO expertise(expertise_rate, category_id, user_id) VALUES (3, 3, 4);
INSERT INTO expertise(expertise_rate, category_id, user_id) VALUES (5, 3, 5);
INSERT INTO expertise(expertise_rate, category_id, user_id) VALUES (5, 6, 5);
INSERT INTO expertise (expertise_rate, category_id, user_id) VALUES (4, 13, 14);
INSERT INTO expertise (expertise_rate, category_id, user_id) VALUES (4, 14, 14);
INSERT INTO expertise (expertise_rate, category_id, user_id) VALUES (2, 14, 13);


INSERT INTO survey (title, description, creation_date, close_date, is_changable, is_active, owner_id) 
VALUES ("Psychology Behavior Survey", "A survey focused on understanding behavioral patterns in adults.", 
        '2024-10-14 09:00:00', '2024-11-14 23:59:59', 0, 1, 3);
INSERT INTO survey (title, description, creation_date, close_date, is_changable, is_active, owner_id) 
VALUES ("Discovery of the inheritance of Bach", "This survey explores the legacy and impact of Johann Sebastian Bach's compositions.", 
        '2024-10-14 14:00:00', '2024-11-14 23:59:59', 0, 1, 8);
INSERT INTO survey (title, description, creation_date, close_date, is_changable, is_active, owner_id) 
VALUES ("Children Psychology Survey", "A survey aimed at understanding the psychological development of children.", 
        '2024-10-14 10:00:00', '2024-12-01 23:59:59', 1, 1, 3);
INSERT INTO survey(title, description, creation_date, close_date, is_changable, is_active, owner_id)
VALUES("Pure reason critique", "This test is to show your knowledge about pure reason critique", '2024-11-14 23:59:59', '2024-12-14 23:59:59', 1, 1, 2);
INSERT INTO survey(title, description, creation_date, close_date, is_changable, is_active, owner_id)
VALUES("Margaret Thatcher presidency", "In this survey, we want you to rate Margaret Thatcher policies as a prime-minister", '1979-5-4 8:00:00', '1900-11-28 23:59:59', 0, 0, 4);
INSERT INTO survey (title, description, creation_date, close_date, is_changable, is_active, owner_id)
VALUES ("Importance of physics", "A survey focused on importance of physics for people.",
        '2024-10-14 23:00:00', '2024-11-16 23:59:59', 0, 1, 14);

INSERT INTO surveycategory (survey_id, category_id) VALUES (1, 1);
INSERT INTO surveycategory (survey_id, category_id) VALUES (2, 1);
INSERT INTO surveycategory (survey_id, category_id) VALUES (1, 4);
INSERT INTO surveycategory(category_id, survey_id) VALUES (2, 1);
INSERT INTO surveycategory(category_id, survey_id) VALUES (4, 1);
INSERT INTO surveycategory(category_id, survey_id) VALUES (3, 2);

INSERT INTO question (header, description, survey_id) 
VALUES 
("How often do you experience stress?", "Please select the frequency that best matches your experience of stress.", 1),
("How would you describe your overall emotional well-being?", "Rate your emotional well-being on a scale of 1 to 5.", 1);

INSERT INTO question (header, description, survey_id) 
VALUES 
("How does the child interact with peers?", "Select the option that best describes the child’s social interactions.", 2),
("How does the child usually respond to stressful situations?", "Select the typical response the child has to stress.", 2);
INSERT INTO question(header, description, survey_id)
VALUES("Economic policies", "How are you satisfied with Thatchers economic policies?", 2);
INSERT INTO question(header, description, survey_id)
VALUES("What is phenomenon in Kant`s philosophy?", "There`s only one right answer", 1);
INSERT INTO question (header, description, survey_id)
VALUES
("Physics is important?", "Many people mean that physics is unimportant. Do you think so?", 6),
("How dificult is it to answer the previous question?", "Scale of 1 to 5.", 6);

INSERT INTO option_q(content, question_id)
VALUES("An object that exists independently of our perception", 1);
INSERT INTO option_q(content, question_id)
VALUES("An object as it appears in our experience through the senses and cognitive faculties", 1);
INSERT INTO option_q(content, question_id)
VALUES("An abstract idea, unrelated to actual perception", 1);
INSERT INTO option_q(content, question_id)
VALUES("An emotional reaction of a person to external objects", 1);

INSERT INTO option_q(content, question_id) VALUES("Very satisfied", 1);
INSERT INTO option_q(content, question_id) VALUES("Satisfied", 1);
INSERT INTO option_q(content, question_id) VALUES("It didn`t affect me", 1);
INSERT INTO option_q(content, question_id) VALUES("Unsatisfied", 1);
INSERT INTO option_q(content, question_id) VALUES("Very unsatisfied", 1);
INSERT INTO option_q (content, question_id) VALUES ("Never", 3);
INSERT INTO option_q (content, question_id) VALUES ("Sometimes", 3);
INSERT INTO option_q (content, question_id) VALUES ("Always", 3);
INSERT INTO option_q (content, question_id) VALUES ("1", 4);
INSERT INTO option_q (content, question_id) VALUES ("2", 4);
INSERT INTO option_q (content, question_id) VALUES ("3", 4);
INSERT INTO option_q (content, question_id) VALUES ("5", 4);
INSERT INTO option_q (content, question_id) VALUES ("Very friendly", 5);
INSERT INTO option_q (content, question_id) VALUES ("Neutral", 5);
INSERT INTO option_q (content, question_id) VALUES ("Aggressive", 5);
INSERT INTO option_q (content, question_id) VALUES ("Remains calm", 6);
INSERT INTO option_q (content, question_id) VALUES ("Shows moderate anxiety", 6);
INSERT INTO option_q (content, question_id) VALUES ("Has a breakdown", 6);
INSERT INTO option_q(content, question_id) VALUES("Yes", 7);
INSERT INTO option_q(content, question_id) VALUES("No", 7);
INSERT INTO option_q(content, question_id) VALUES("Easy", 8);
INSERT INTO option_q(content, question_id) VALUES("Medium", 8);
INSERT INTO option_q(content, question_id) VALUES("Hard", 8);



INSERT INTO answer (option_id, expert_id) VALUES (2, 2);
INSERT INTO answer (option_id, expert_id) VALUES (3, 4);
INSERT INTO answer (option_id, expert_id) VALUES (5, 2);
INSERT INTO answer (option_id, expert_id) VALUES (6, 4);
INSERT INTO answer (option_id, expert_id) VALUES (8, 4);
INSERT INTO answer (option_id, expert_id) VALUES (12, 4);
INSERT INTO answer (option_id, expert_id) VALUES(7, 2);
INSERT INTO answer (option_id, expert_id) VALUES(24, 13);
INSERT INTO answer (option_id, expert_id) VALUES(27, 13);

INSERT INTO expertcomplaint (description, date, researcher_id, expert_id)
VALUES ('Complaint regarding expert feedback', '2024-10-14 09:30:00', 3, 4);
INSERT INTO surveycomplaint (description, date, survey_id, expert_id)
VALUES ('Complaint about survey data handling by expert', '2024-10-14 09:30:00', 1, 2);


INSERT INTO expertcomplaint (description, date, researcher_id, expert_id)
VALUES ('Complaint about expert`s options are biased', '2024-10-14 09:30:00', 4, 3);
INSERT INTO surveycomplaint (description, date, survey_id, expert_id)

VALUES ('Complaint about test`s complication', '2024-10-14 09:30:00', 2, 2);

INSERT INTO surveycategory (id, survey_id, category_id) VALUES (7, 5, 11);
INSERT INTO surveycategory (id, survey_id, category_id) VALUES (8, 3, 1);
INSERT INTO surveycategory (id, survey_id, category_id) VALUES (9, 2, 7);
INSERT INTO surveycategory (survey_id, category_id) VALUES (6, 14);
-- Example SELECT queries
SELECT content FROM option_q WHERE question_id=5;
SELECT first_name, last_name FROM user WHERE company IS NULL AND is_admin=0;
SELECT first_name, last_name FROM user WHERE age > 52;
SELECT id FROM question WHERE header LIKE "Economic policies";
SELECT option_id FROM answer WHERE id > 2 AND expert_id = 2;
SELECT * FROM user ORDER BY first_name DESC;
SELECT title FROM survey WHERE owner_id=3;
SELECT title FROM survey WHERE owner_id = (SELECT id FROM user WHERE email = 'critic@example.com');
SELECT name FROM category WHERE parent_id=2;
SELECT name from category WHERE parent_id=2 OR parent_id IS NULL;
SELECT email FROM user WHERE is_admin=1;

-- Count owner's number of surveys
SELECT COUNT(id) FROM survey WHERE owner_id = 1;

-- Get sorted categories
SELECT name FROM category ORDER BY name;

-- Select the content of option and name of expert, who selected it
SELECT content, first_name, last_name
FROM option_q INNER JOIN answer
INNER JOIN user WHERE option_q.id = answer.option_id AND answer.expert_id = user.id;

-- Select complaints and author's names
SELECT ec.description, first_name
FROM expertcomplaint AS ec, user AS u WHERE ec.expert_id = u.id;

-- Select category of the survey and survey title
SELECT c.name, s.title
FROM category AS c
INNER JOIN survey AS s
INNER JOIN surveycategory AS sc ON sc.survey_id = s.id AND sc.category_id = c.id;

-- Select survey author's name, title and description
SELECT user.first_name, survey.title, survey.description
FROM survey
INNER JOIN user
ON survey.owner_id = user.id;

-- Select expert's names and their expertise
SELECT user.first_name, expertise_rate, category.name
FROM expertise
RIGHT JOIN category
ON expertise.category_id = category.id
INNER JOIN user
ON expertise.user_id = user.id
ORDER BY user.first_name, category.name;

-- Select surveys' titles and headers of their question
SELECT survey.title, question.header
FROM question
INNER JOIN survey
ON question.survey_id = survey.id;

-- Select users' names and expertise if their expertise is equal to 5
SELECT user.first_name, expertise.expertise_rate, category.name
FROM expertise
RIGHT JOIN category
ON expertise.category_id = category.id
INNER JOIN user
ON expertise.user_id = user.id
WHERE expertise.expertise_rate = 5;

-- Select all the surveys' titles and matching questions
SELECT  question.header, survey.title
FROM question RIGHT JOIN survey ON survey.id = question.survey_id;

-- Select users, whose id is smaller than 4
SELECT user.first_name, user.last_name, survey.title, survey.description
FROM user INNER JOIN survey ON user.id = survey.owner_id
WHERE user.id < 4;

-- Select users' full names and expertise
SELECT user.first_name, user.last_name,category.name, expertise.expertise_rate
FROM user INNER JOIN expertise ON user.id = expertise.user_id
LEFT JOIN category ON  expertise.category_id=category.id;

-- Select surveys' titles, headers and descriptions of their question
SELECT survey.title AS survey_title,
       question.header AS question_header,
       question.description AS question_description
FROM survey INNER JOIN question ON survey.id = question.survey_id;

-- Select all the surveys and matching complaints
SELECT survey.title AS survey_title,
       surveycomplaint.description AS survey_complaint
FROM survey LEFT JOIN surveycomplaint ON survey.id = surveycomplaint.survey_id;

-- Select users and their expertise
SELECT expertise.expertise_rate,
       user.first_name AS user_first_name
FROM expertise CROSS JOIN user ON expertise.user_id = user.id;

-- Select emails of admins, whose expertise rate is higher than average
SELECT category.name AS category_name,
       user.email AS user_email,
       user.is_admin AS user_admin_status,
       expertise.expertise_rate
FROM user
RIGHT JOIN expertise ON expertise.user_id = user.id
LEFT JOIN category ON category.id = expertise.category_id
WHERE expertise.expertise_rate > (SELECT AVG(expertise_rate) FROM expertise)
AND user.is_admin = 1;

-- Count number of answers per option_q in survey
SELECT content, COUNT(expert_id) AS answer_count
FROM answer
RIGHT JOIN option_q ON answer.option_id = option_q.id
WHERE question_id = 7
GROUP BY content;

-- Get all expert responses to the survey
SELECT header AS question_header, content AS answer_name
FROM answer
JOIN option_q ON answer.option_id = option_q.id
JOIN question ON option_q.question_id = question.id
WHERE expert_id = 13 AND survey_id = 6
ORDER BY question.id;

-- Get experts with higher expertise_rate than average
SELECT user.id, CONCAT(first_name, " ", last_name), expertise_rate
FROM expertise
JOIN user ON expertise.user_id = user.id
WHERE expertise_rate > (SELECT AVG(expertise_rate) FROM expertise WHERE category_id =14)
AND category_id = 14;
-- Example UPDATE queries
UPDATE user SET email="kate.pril@gmail.com" WHERE id=3;
UPDATE survey SET close_date = "2024-12-14 23:59:59" WHERE id = 3;

UPDATE survey SET is_active = 0, close_date = "2024-10-14" WHERE id = 1;
UPDATE survey SET title = "Psychological skills" WHERE id = 3;
UPDATE survey SET title = "Best woman" WHERE owner_id = 2;
UPDATE user SET first_name = "Donald" WHERE first_name = "Friedrich";

UPDATE answer SET option_id = "1" WHERE id = 1;

UPDATE surveycategory SET survey_id=4 WHERE id=3;
UPDATE surveycategory SET category_id=1 WHERE survey_id=3;
UPDATE db_labs.expertise SET expertise_rate=3.5, user_id=11 WHERE category_id=4;
-- Example DELETE queries
DELETE FROM option_q WHERE id=13;
DELETE FROM option_q WHERE content = "Yes" AND question_id = 7;
DELETE FROM user WHERE id=5;
DELETE FROM surveycategory WHERE id=9;

RESTfull сервіс для управління даними

Файл pom.xml з залежностями

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>3.3.4</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
	<groupId>com.example</groupId>
	<artifactId>lab6</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>war</packaging>
	<name>lab6</name>
	<description>lab 6 for db</description>
	<url/>
	<licenses>
		<license/>
	</licenses>
	<developers>
		<developer/>
	</developers>
	<scm>
		<connection/>
		<developerConnection/>
		<tag/>
		<url/>
	</scm>
	<properties>
		<java.version>17</java.version>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-data-jpa</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-jdbc</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>

		<dependency>
			<groupId>com.mysql</groupId>
			<artifactId>mysql-connector-j</artifactId>
			<scope>runtime</scope>
		</dependency>
		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
			<optional>true</optional>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
				<configuration>
					<excludes>
						<exclude>
							<groupId>org.projectlombok</groupId>
							<artifactId>lombok</artifactId>
						</exclude>
					</excludes>
				</configuration>
			</plugin>
		</plugins>
	</build>

</project>

Підключення до бази даних

spring.application.name=lab6
spring.datasource.url=jdbc:mysql://localhost:3306/db_labs
spring.datasource.username=root
spring.datasource.password=1234567890qwerty
spring.jpa.hibernate.ddl-auto=update

DAO-об'єкти, що репрезентують сутності в базі даних

Користувач

package com.example.lab6.entities;

import jakarta.persistence.*;
import lombok.*;

@NoArgsConstructor
@AllArgsConstructor
@Getter
@Setter
@Entity
@Builder
@Table(name = "user")
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(name = "first_name", nullable = false)
    private String firstName;

    @Column(name = "last_name", nullable = false)
    private String lastName;

    @Column(name = "email", nullable = false)
    private String email;

    @Column(name = "phone_number")
    private String phoneNumber;

    @Column(nullable = false)
    private String password;

    @Column
    private String description;

    @Column
    private int age;

    @Column
    private String gender;

    @Column
    private String company;

    @Column(name = "is_admin")
    private int isAdmin;

}

Опитування

package com.example.lab6.entities;

import jakarta.persistence.*;
import lombok.*;

import java.sql.Date;

@NoArgsConstructor
@AllArgsConstructor
@Getter
@Setter
@Entity
@Builder
@Table(name = "survey")
public class Survey {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(nullable = false)
    private String title;

    @Column
    private String description;

    @Column(name = "creation_date", nullable = false)
    private Date creationDate;

    @Column(name = "close_date")
    private Date closeDate;

    @Column(name = "is_changable", nullable = false)
    private int isChangable;

    @Column(name = "is_active", nullable = false)
    private int isActive;

    @ManyToOne
    @JoinColumn(
            name = "owner_id",
            referencedColumnName = "id",
            foreignKey = @ForeignKey(name = "fk_survey_user"),
            nullable = false
    )
    private User owner;

}

Категорія

package com.example.lab6.entities;

import jakarta.persistence.*;
import lombok.*;

@NoArgsConstructor
@AllArgsConstructor
@Getter
@Setter
@Entity
@Builder
@Table(name = "category")
public class Category {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(nullable = false)
    private String name;

    @ManyToOne
    @JoinColumn(
            name = "parent_id",
            referencedColumnName = "id",
            foreignKey = @ForeignKey(name = "fk_category_category")
    )
    private Category category;
}

Репозиторії для взаємодії з DAO-об'єктами

Репозиторій для взаємодії з користувачем

package com.example.lab6.repositories;

import com.example.lab6.entities.User;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface UserRepository extends JpaRepository<User, Long> {
    boolean existsUserByEmail(String email);
}

Репозиторій для взаємодії з опитуванням

package com.example.lab6.repositories;

import com.example.lab6.entities.Survey;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface SurveyRepository extends JpaRepository<Survey, Long> {
}

Репозиторій для взаємодії з категорією

package com.example.lab6.repositories;

import com.example.lab6.entities.Category;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface CategoryRepository extends JpaRepository<Category, Long> {
}

Сервіси для взаємодії з репозиторіями

Сервіс для взаємодії з репозиторієм користувача

package com.example.lab6.services;

import com.example.lab6.entities.User;
import com.example.lab6.repositories.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class UserService {
    private final UserRepository userRepository;

    @Autowired
    public UserService(UserRepository userRepository) {
        this.userRepository = userRepository;
    }

    public Iterable<User> getAllUsers() {
        return userRepository.findAll();
    }

    public User getUserById(Long id) throws Exception {
        if (userRepository.existsById(id)) {
            return userRepository.findById(id).get();
        } else {
            throw new Exception("User not found");
        }
    }
    public User createUser(User user) throws Exception {
        if (userRepository.existsUserByEmail(user.getEmail())) {
            throw  new Exception("User with provided email already exists");
        } else {
            return userRepository.save(user);
        }
    }

    public User changeUserEmail(Long id, String email) throws Exception {
        if (userRepository.existsUserByEmail(email)) {
            throw  new Exception("User with provided email already exists");
        } else {
            if (userRepository.existsById(id)) {
                User user = userRepository.findById(id).get();
                user.setEmail(email);
                return userRepository.save(user);
            } else {
                throw new Exception("User with provided id doesn't exist");
            }
        }
    }

    public User changeUserPassword(Long id, String password) throws Exception {
        if (userRepository.existsById(id)) {
            User user = userRepository.findById(id).get();
            user.setPassword(password);
            return userRepository.save(user);
        } else {
            throw new Exception("User with provided id doesn't exist");
        }
    }

    public String deleteUserById(Long id) throws Exception {
        if (userRepository.existsById(id)) {
            userRepository.deleteById(id);
        } else {
            throw new Exception("Failed to delete user");
        }
        return String.format("User %d was deleted", id);
    }

}

Сервіс для взаємодії з репозиторієм опитування

package com.example.lab6.services;

import com.example.lab6.entities.Survey;
import com.example.lab6.repositories.SurveyRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class SurveyService {
    private final SurveyRepository surveyRepository;

    @Autowired
    public SurveyService(SurveyRepository surveyRepository) {
        this.surveyRepository = surveyRepository;
    }

    public Iterable<Survey> getAllSurveys() {
        return surveyRepository.findAll();
    }

    public Survey getSurveyById(Long id) throws Exception {
        if (surveyRepository.existsById(id)) {
            return surveyRepository.findById(id).get();
        } else {
            throw new Exception("Survey not found");
        }
    }

    public Survey createSurvey(Survey survey) {
        return surveyRepository.save(survey);
    }

    public Survey changeIsActive(Long id, int isActive) throws Exception {
        if (surveyRepository.existsById(id)) {
            Survey survey = surveyRepository.findById(id).get();
            survey.setIsActive(isActive);
            return surveyRepository.save(survey);
        } else {
            throw new Exception("Survey with provided id doesn't exist");
        }
    }

    public Survey changeSurveyTitle(Long id, String title) throws Exception {
        if (surveyRepository.existsById(id)) {
            Survey survey = surveyRepository.findById(id).get();
            survey.setTitle(title);
            return surveyRepository.save(survey);
        } else {
            throw new Exception("Survey with provided id doesn't exist");
        }
    }

    public String deleteSurveyById(Long id) throws Exception {
        if (surveyRepository.existsById(id)) {
            surveyRepository.deleteById(id);
        } else {
            throw new Exception("Failed to delete survey");
        }
        return String.format("Survey %d was deleted", id);
    }

}

Сервіс для взаємодії з репозиторієм категорії

package com.example.lab6.services;

import com.example.lab6.entities.Category;
import com.example.lab6.repositories.CategoryRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class CategoryService {
    private final CategoryRepository categoryRepository;

    @Autowired
    public CategoryService(CategoryRepository categoryRepository) {
        this.categoryRepository = categoryRepository;
    }

    public Iterable<Category> getAllCategories() {
        return categoryRepository.findAll();
    }

    public Category getCategoryById(Long id) throws Exception {
        if (categoryRepository.existsById(id)) {
            return categoryRepository.findById(id).get();
        } else {
            throw  new Exception("Category not found");
        }
    }

    public Category createCategory(Category category) {
        return categoryRepository.save(category);
    }

    public Category updateCategoryName(Long id, String name) throws Exception {
        if (categoryRepository.existsById(id)) {
            Category category = categoryRepository.findById(id).get();
            category.setName(name);
            return categoryRepository.save(category);
        } else {
            throw new Exception("Category with provided id doesn't exist");
        }
    }

    public String deleteCategoryById(Long id) throws Exception {
        if (categoryRepository.existsById(id)) {
            categoryRepository.deleteById(id);
        } else {
            throw new Exception("Failed to delete category");
        }
        return String.format("Category %d was deleted", id);
    }
}

Контроллери для взаємодії з сервісами

Контроллер для взаємодії з сервісом користувача

package com.example.lab6.controllers;

import com.example.lab6.entities.User;
import com.example.lab6.services.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping(value = "/users")
public class UserController {

    private final UserService userService;

    @Autowired
    public UserController(UserService userService) {
        this.userService = userService;
    }

    @GetMapping
    public ResponseEntity<?> getAllUsers() {
        try {
            return ResponseEntity.ok(userService.getAllUsers());
        } catch (Exception exception) {
            return ResponseEntity.badRequest().body(exception.getMessage());
        }
    }

    @GetMapping("/{id}")
    public ResponseEntity<?> getUser(@PathVariable Long id) {
        try {
            return ResponseEntity.ok(userService.getUserById(id));
        } catch (Exception exception) {
            return ResponseEntity.badRequest().body(exception.getMessage());
        }
    }

    @PostMapping("/create")
    public ResponseEntity<?> createUser(@RequestBody User user) {
        try {
            return ResponseEntity.ok(userService.createUser(user));
        } catch (Exception exception) {
            return ResponseEntity.badRequest().body(exception.getMessage());
        }
    }

    @PutMapping("/change_email")
    public ResponseEntity<?> updateEmail(@RequestParam Long id, @RequestParam String email) {
        try {
            return ResponseEntity.ok(userService.changeUserEmail(id, email));
        } catch (Exception exception) {
            return ResponseEntity.badRequest().body(exception.getMessage());
        }
    }

    @PutMapping("/change_password")
    public ResponseEntity<?> updatePassword(@RequestParam Long id, @RequestParam String password) {
        try {
            return ResponseEntity.ok(userService.changeUserPassword(id, password));
        } catch (Exception exception) {
            return ResponseEntity.badRequest().body(exception.getMessage());
        }
    }

    @DeleteMapping("/{id}")
    public ResponseEntity<?> deleteUser(@PathVariable Long id) {
        try {
            return ResponseEntity.ok(userService.deleteUserById(id));
        } catch (Exception exception) {
            return ResponseEntity.badRequest().body(exception.getMessage());
        }
    }
}

Контроллер для взаємодії з сервісом опитування

package com.example.lab6.controllers;

import com.example.lab6.entities.Survey;
import com.example.lab6.services.SurveyService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping(value = "/surveys")
public class SurveyController {
    private final SurveyService surveyService;

    @Autowired
    public SurveyController(SurveyService surveyService) {
        this.surveyService = surveyService;
    }

    @GetMapping
    public ResponseEntity<?> getAllSurvey() {
        try {
            return ResponseEntity.ok(surveyService.getAllSurveys());
        } catch (Exception exception) {
            return ResponseEntity.badRequest().body(exception.getMessage());
        }
    }

    @GetMapping("/{id}")
    public ResponseEntity<?> getSurvey(@PathVariable Long id) {
        try {
            return ResponseEntity.ok(surveyService.getSurveyById(id));
        } catch (Exception exception) {
            return ResponseEntity.badRequest().body(exception.getMessage());
        }
    }

    @PostMapping("/create")
    public ResponseEntity<?> createSurvey(@RequestBody Survey survey) {
        try {
            return ResponseEntity.ok(surveyService.createSurvey(survey));
        } catch (Exception exception) {
            return ResponseEntity.badRequest().body(exception.getMessage());
        }
    }

    @PutMapping("{id}/update_is_active/{isActive}")
    public ResponseEntity<?> updateIsActive(@PathVariable Long id, @PathVariable int isActive) {
        try {
            if (isActive == 0 || isActive == 1) {
                return ResponseEntity.ok(surveyService.changeIsActive(id, isActive));

            } else {
                throw new Exception("IsActive value should be either 0 or 1");
            }
        } catch (Exception exception) {
            return ResponseEntity.badRequest().body(exception.getMessage());
        }
    }

    @PutMapping("/update_title")
    public ResponseEntity<?> updateEmail(@RequestParam Long id, @RequestParam String title) {
        try {
            return ResponseEntity.ok(surveyService.changeSurveyTitle(id, title));
        } catch (Exception exception) {
            return ResponseEntity.badRequest().body(exception.getMessage());
        }
    }

    @DeleteMapping("/{id}")
    public ResponseEntity<?> deleteSurvey(@PathVariable Long id) {
        try {
            return ResponseEntity.ok(surveyService.deleteSurveyById(id));
        } catch (Exception exception) {
            return ResponseEntity.badRequest().body(exception.getMessage());
        }
    }

}

Контроллер для взаємодії з сервісом категорії

package com.example.lab6.controllers;

import com.example.lab6.entities.Category;
import com.example.lab6.services.CategoryService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping(value = "/categories")
public class CategoryController {
    private final CategoryService categoryService;

    @Autowired
    public CategoryController(CategoryService categoryService) {
        this.categoryService = categoryService;
    }

    @GetMapping
    public ResponseEntity<?> getAllCategory() {
        try {
            return ResponseEntity.ok(categoryService.getAllCategories());
        } catch (Exception exception) {
            return ResponseEntity.badRequest().body(exception.getMessage());
        }
    }

    @GetMapping("/{id}")
    public ResponseEntity<?> getCategory(@PathVariable Long id) {
        try {
            return ResponseEntity.ok(categoryService.getCategoryById(id));
        } catch (Exception exception) {
            return ResponseEntity.badRequest().body(exception.getMessage());
        }
    }

    @PostMapping("/create")
    public ResponseEntity<?> createCategory(@RequestBody Category category) {
        try {
            return ResponseEntity.ok(categoryService.createCategory(category));
        } catch (Exception exception) {
            return ResponseEntity.badRequest().body(exception.getMessage());
        }
    }

    @PutMapping("/change_name")
    public ResponseEntity<?> changeCategoryName(@RequestParam Long id, @RequestParam String name) {
        try {
            return ResponseEntity.ok(categoryService.updateCategoryName(id, name));
        } catch (Exception exception) {
            return ResponseEntity.badRequest().body(exception.getMessage());
        }
    }

    @DeleteMapping("/{id}")
    public ResponseEntity<?> deleteCategory(@PathVariable Long id) {
        try {
            return ResponseEntity.ok(categoryService.deleteCategoryById(id));
        } catch (Exception exception) {
            return ResponseEntity.badRequest().body(exception.getMessage());
        }
    }
}

Сервлет ініціалізатор

package com.example.lab6;

import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;

public class ServletInitializer extends SpringBootServletInitializer {

	@Override
	protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
		return application.sources(Lab6Application.class);
	}

}

Lab6Application.java - вхідна точка в програму

package com.example.lab6;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;

@SpringBootApplication
@EnableJpaRepositories(basePackages = "com.example.lab6.repositories")
public class Lab6Application {

	public static void main(String[] args) {
		SpringApplication.run(Lab6Application.class, args);
	}

}

Тестування працездатності системи

Для тестування було використано Postman

image image

image image

image image видалення користувача з не існуючим id

image image видалення користувача з існуючим id. Оскільки перший запит пройшов успішно і користувача було видалення, другий запит завершився помилкою, адже цього користувача більше немає в базі даних

image

image image image image

image

image запит категорії з не існуючим id

image

image запит категорії з існуючим id

Висновки

Протягом виконання цих лабораторних робіт було розроблено систему для організації та управління проєктами MESS.

На першому етапі було успішно проаналізовано предметну область та ринок конкурентів, на другому - сформульовано запити зацікавлених осіб. Далі на основі запитів зацікавлених осіб було розроблено детальні діаграми прецедентів та діаграми активності, що стали основою для подальшого проєктування бази даних. На четвертому етапі (проєктування бази даних) було розроблено модель бізнес-об'єктів, ER-модель та реляційну схему, після чого - написано скрипт для створення та наповнення MySQl бази даних, а також приклади запитів до бази даних. На останньому етапі було розроблено RESTfull сервіс із використанням Spring Boot.

Отже, працюючи над цим проєктом, ми не лише удосконалили свої технічні навички, зокрема, аналіз ринку та вимог замивника, проєктування баз даних та розроблення RESTfull API, а й навички роботи в команді, серед яких управління проєктами через GitHub Projects, комунікація з учасниками команди та ефективне розділення обов'язків.