AAYMA
RU
Войти

Mereke

Браузерный прототип подбора до трёх подрядчиков из каталога 66 профилей с объяснениями, причинами исключения, сравнением дат и избранным, без…

Рабочий MVP
Команда «CYB3RGIRLS» 3💬 0 комментариевс 23 сентября 2026 г.

О проекте

Команда: CYB3RGIRLS
Кейс HackAlem.ai: Креативные индустрии — Firebird
Стадия: Рабочий MVP

Задача кейса: «#79-lite»: подобрать до 3 подрядчиков для мероприятия и объяснить выбор

Суть

Браузерный прототип подбора до трёх подрядчиков из каталога 66 профилей с объяснениями, причинами исключения, сравнением дат и избранным, без внешних AI-моделей.

Как устроено

Модуль engine.js проверяет ввод и отбирает профили по городу и категории. Затем исключает кандидатов по календарю, бюджету, формату, языку и длительности. Оставшиеся сортируются лексикографически: число совпадений слов пожелания с описанием (с простыми русскими окончаниями), упоминание формата, цена, id. Объяснения собираются из полей и фрагментов описания. Возможны статусы matched, no_match и category_absent; для пустой выдачи есть счётчики причин и кнопка «+30% бюджета».

Ключевые решения

  • жёсткие фильтры
  • лексическое сопоставление пожеланий
  • многоуровневая сортировка
  • сравнительные метки карточек
  • WebMCP registerTool find_contractors

Особенности

Сознательный отказ от LLM: весь подбор объяснимый и детерминированный. Тесты проверяют 204 комбинации город×категория×дата. Есть условная регистрация инструмента через document.modelContext. README описывает папку dist/, но в дереве её нет (коммит «Delete dist directory»).

Стек

HTML5 · CSS3 · JavaScript · Node.js · Vercel · localStorage


Проект создан за 5 часов на финале хакатона HackAlem.ai (23 сентября 2026, Астана). Код — BAITC-Hacks/hack-8153b212-cyb3rgirls.

README

README.md

Mereke / Мереке

Подбор подрядчиков для мероприятий · команда CYB3RGIRLS

1. О проекте

Mereke помогает организаторам мероприятий и частным заказчикам выбрать подрядчиков из заданного каталога. Пользователь указывает условия события, а сервис показывает до трёх подходящих вариантов с ценами, объяснениями и различиями между ними.

Проект сокращает ручное сравнение анкет: проверяет город, категорию, занятость на дату, бюджет, формат мероприятия, язык и длительность. Текущая версия — браузерный прототип для хакатона с локальным набором из 66 профилей.

2. Что реализовано

  • Форма подбора: город, дата, формат, категория и бюджет; дополнительно — язык, длительность и пожелания до 500 символов.
  • Фильтрация по обязательным условиям: занятые на выбранную дату и неподходящие по параметрам профили исключаются из результата.
  • До трёх карточек: стартовая цена в тенге, факты о соответствии запросу и цитата из описания подрядчика.
  • Учёт пожеланий: совпадения слов и простых русских окончаний в описаниях влияют на порядок подходящих кандидатов.
  • Сравнение карточек: самая низкая стартовая цена, наибольший лимит присутствия и языки, которых нет у остальных показанных вариантов. Метки выводятся только при выполнении условий сравнения.
  • Объяснение пустой или короткой подборки: отдельно обрабатываются отсутствие категории в городе и отсутствие кандидатов, прошедших условия; выводятся счётчики причин исключения.
  • Сравнение дат: если изменена только дата, отображается изменение числа подходящих кандидатов и доступности подрядчиков из предыдущей и новой подборок.
  • Полный профиль: описание, категории, город, языки, форматы мероприятий, длительность и признаки происхождения данных.
  • Избранное: добавление и удаление профилей, сохранение в браузере и повторная проверка соответствия текущим условиям.
  • Шесть готовых примеров, адаптивная вёрстка и проверка вводимых параметров.

Если никто не подошёл и есть исключения по бюджету, пользователь может нажать «Увеличить бюджет на 30%». Без этого действия бюджет не меняется.

3. Как работает решение

  1. Пользователь открывает страницу и заполняет параметры либо выбирает готовый пример.
  2. Интерфейс передаёт запрос в модуль подбора. Результат пересчитывается при изменении полей или нажатии «Подобрать подрядчиков».
  3. Модуль проверяет ввод, выбирает профили нужного города и категории, затем исключает кандидатов по календарю, бюджету, формату, языку и длительности.
  4. Подходящие профили упорядочиваются последовательно:
    1. По убыванию числа совпадений с пожеланиями.
    2. По наличию буквального упоминания формата мероприятия в описании.
    3. По возрастанию стартовой цены.
    4. По идентификатору профиля при равенстве предыдущих признаков.
  5. Пользователь получает первые три варианта, объяснения и причины исключения остальных; может открыть полный профиль или сохранить вариант в избранное.

Пожелания меняют только порядок и не отменяют обязательные условия. Цена не используется как оценка качества. Объяснения составляются из проверяемых полей и фрагментов описания, а не генерируются AI-моделью.

4. Технологии

КомпонентРеализация
Страница и интерфейсHTML5, CSS3, JavaScript без фреймворков
Подбор и объясненияЛокальный JavaScript-модуль EventMatch
ДанныеМассив объектов globalThis.CONTRACTORS в dist/data.js
ИзбранноеBrowser localStorage, ключ mereke_shortlist
Форматирование ценВстроенный Intl.NumberFormat('ru-RU')
Окна профиля и избранногоHTML-элемент <dialog>
Автоматические проверкиNode.js, встроенный node:assert/strict, CommonJS

Внешние AI-модели, API и облачные сервисы для подбора не подключены. Обработка пожеланий — локальная эвристика сопоставления слов. Серверная часть, база данных, пакетные зависимости и этап сборки для работы приложения не требуются.

В dist/front.js также предусмотрена условная регистрация инструмента find_contractors через document.modelContext.registerTool, если среда браузера предоставляет этот API. Он вызывает тот же локальный подбор; для обычного использования страницы эта возможность не нужна.

5. Архитектура проекта

Приложение выполняется целиком в браузере. Рабочая версия находится в dist/.

Пользователь
    ↓ параметры мероприятия
 dist/index.html + dist/butter.css
    ↕ события и отображение результата
 dist/front.js ───────────────↔ localStorage (избранное)
    ↓ запрос                        
 dist/engine.js ← dist/data.js (каталог)
    ↓ фильтрация, ранжирование, объяснения
 dist/front.js
    ↓
 До 3 карточек, полный профиль, причины исключения
.
├── README.md          # Описание и инструкции
├── index.html         # Перенаправление на ./dist/
├── dist/
│   ├── index.html     # Основная страница
│   ├── butter.css     # Стили интерфейса
│   ├── data.js        # Каталог подрядчиков
│   ├── engine.js      # Валидация, фильтры, ранжирование, объяснения
│   └── front.js       # Форма, карточки, диалоги, избранное, примеры
├── tests.cjs          # Проверки данных и логики из dist/
├── data.js            # Дубликат каталога в корне
├── engine.js          # Дубликат логики подбора в корне
├── app.js             # Отдельная реализация интерфейса, не подключена в dist/
└── style.css          # Стили, не подключены к основной странице

Основная страница загружает только файлы из dist/. Тесты также импортируют dist/data.js и dist/engine.js. Изменения корневых копий автоматически в dist/ не переносятся: скрипта сборки в проекте нет.

Модуль подбора возвращает один из трёх статусов: matched — есть результат, no_match — кандидаты не прошли условия, category_absent — категории нет в выбранном городе.

6. Установка и запуск

Live demo

Open Mereke

Быстрый запуск без установки зависимостей

  1. Скачайте и распакуйте архив проекта.
  2. Откройте dist/index.html в современном браузере с поддержкой JavaScript и <dialog>.
  3. Оставьте все пять файлов папки dist/ рядом: страница использует относительные пути к стилям, данным и скриптам.

Для такого запуска не нужны Node.js, Python, npm install, ключи API или .env. Внешние шрифты, CDN и изображения приложение не загружает.

Запуск через локальный HTTP-сервер

Этот вариант удобен для работы через постоянный локальный адрес. Потребуется установленный Python 3; он используется только для раздачи статических файлов.

Из каталога, в который распакован проект:

cd hack-8153b212-cyb3rgirls-main
python -m http.server 8000 --bind 127.0.0.1 --directory dist

Если в Windows Python доступен через команду py, используйте:

py -3 -m http.server 8000 --bind 127.0.0.1 --directory dist

Откройте локальную версию. Для остановки сервера нажмите Ctrl+C в терминале. Если вы уже находитесь в корне проекта, команду cd выполнять не нужно.

Запуск автоматических проверок

Потребуется Node.js. Точная минимальная версия в репозитории не зафиксирована; тесты используют встроенные модули и не требуют установки npm-пакетов.

В корне проекта выполните:

node --version
node tests.cjs

Успешный запуск выводит две строки PASS и завершается с кодом 0. Первая строка содержит 204 real-data requests; время выполнения зависит от компьютера.

7. Как проверить решение

Основной сценарий для жюри

  1. Откройте приложение и нажмите пример «Ведущие · 15 октября».
  2. Проверьте параметры: Алматы, ведущий, корпоратив, 15.10.2026, бюджет 1 000 000 ₸, русский язык, 6 часов.
  3. Ожидаемый результат — «3 из 6 подходящих». В карточках должны быть цена «от», объяснение соответствия запросу и цитата из профиля.
  4. Нажмите «Та же заявка · 16 октября». Ожидается «3 из 4 подходящих» и блок сравнения дат с изменением числа кандидатов 6 → 4.
  5. Вернитесь к первому примеру: порядок карточек должен повториться.
  6. Откройте «Полный профиль», сохраните подрядчика в избранное и откройте избранное через значок сердца в шапке. Там отображается соответствие профиля текущим условиям.

Дополнительные примеры

Все перечисленные запросы доступны кнопками под формой. Число допустимых кандидатов указано до ограничения тремя карточками.

ПримерПараметрыОжидаемый результат
«Флористы · 2 варианта»Алматы, флорист, свадьба, 15.10.2026, 300 000 ₸; язык и часы не заданы2 подходящих профиля, 2 карточки
«Бюджет 100 000 ₸»Те же условия для флористов, бюджет 100 000 ₸Нет карточек; сообщение «Кандидаты есть, но условия не совпали» и причины исключения
«Нет категории в Астане»Астана, декоратор, свадьба, 15.10.2026, 300 000 ₸; язык и часы не заданыСообщение «В городе нет этой категории»
«С импровизацией»Основной запрос на 15.10.2026 + «импровизация и интерактивы»Совпадения с описаниями учитываются при сортировке и отмечаются в карточках

tests.cjs проверяет 204 сочетания города, категории и даты, повторяемость результатов, обязательные фильтры, границы бюджета, обработку max_hours = null, смену дат и числа кандидатов в примерах. Дополнительно проверяются ранжирование по пожеланиям, простые отрицания и корректность сравнительных меток. Это проверки данных и алгоритма; они не автоматизируют клики и визуальную проверку страницы.

8. Данные

Фактический источник данных приложения — включённый в проект файл dist/data.js. Он содержит:

  • 66 профилей с уникальными идентификаторами;
  • 17 категорий, при этом один профиль может относиться к нескольким категориям;
  • 50 профилей в Алматы, 15 в Астане и 1 со значением города «Зарубежье»;
  • 13 профилей с признаком synthetic;
  • 18 профилей с признаком price_imputed и 8 — с city_imputed.

В исходном README источником назван файл организаторов hackathon dataset anonymized .xlsx. Сам Excel-файл и скрипт его преобразования в архиве отсутствуют, поэтому соответствие исходной таблице отдельно проверить по этой версии нельзя.

Поля профиляНазначение
id, anon_nameИдентификатор и анонимизированное имя
categories, cityКатегории услуг и город
price_from_kztСтартовая стоимость в тенге
event_formats, languagesПоддерживаемые форматы и языки
max_hoursЛимит присутствия; null означает, что ограничение по часам не применяется
busy_datesСписок занятых дат
descriptionОписание для цитат и поиска совпадений с пожеланиями
synthetic, price_imputed, city_imputedПризнаки синтетического профиля и заполненных при подготовке данных цены/города

Допустимый период запроса — с 23 сентября по 31 декабря 2026 года включительно. Даты вне этого диапазона отклоняются. Свободной считается допустимая дата, которой нет в busy_dates профиля.

9. Интеграции и внешние сервисы

Для основного сценария внешних интеграций нет: каталог, фильтры и объяснения работают локально. Серверные API, авторизация, платёжные сервисы и синхронизация календарей не подключены.

Избранное хранит идентификаторы профилей в localStorage текущего браузера. Если сохранение недоступно, список остаётся только в памяти открытой страницы. Условная интеграция с document.modelContext описана в разделе технологий; она не добавляет внешнюю модель или источник данных.

10. Ограничения текущей версии

  • Каталог статический: интерфейса добавления подрядчиков, обновления цен и синхронизации реальной занятости нет.
  • Учебные календари и отсутствие даты в списке занятости не подтверждают реальную доступность подрядчика.
  • Цена «от» используется для фильтрации, но не гарантирует итоговую стоимость мероприятия.
  • За один запрос выбирается одна категория; расчёт общего бюджета набора из нескольких подрядчиков не реализован.
  • Пожелания обрабатываются по словам и простым окончаниям. Полноценное понимание смысла, всех синонимов и сложных отрицаний отсутствует; совпадение не гарантирует выполнение пожелания.
  • Показываются только первые три подходящих профиля. Просмотра всех результатов с пагинацией нет.
  • Бронирование, отправка заявок, оплата, отзывы, отдельное портфолио и личные кабинеты не реализованы.
  • Избранное не синхронизируется между устройствами или браузерами.
  • У одного профиля может быть несколько причин исключения, поэтому их счётчики нельзя складывать как независимые группы.
  • Числа в демонстрационных сценариях относятся к включённому набору и могут измениться при редактировании данных.

11. Развёрнутая версия

Подтверждённая публичная ссылка в предоставленной версии проекта не указана. Для проверки используйте локальный запуск из раздела 6.

Корневой index.html перенаправляет на ./dist/, а .nojekyll присутствует в проекте, но сами по себе эти файлы не подтверждают публикацию сайта.

Звёзды
⭐ 0
Форки
0
Язык
JavaScript
Последний push
в прошлом месяце
Коммиты
24
Авторы
2
Файлы
18
Ветки
3

Авторы коммитов

ajymzanamantaj-gif 16Alina Abdikarimova 8

История коммитов

  • 2026-09-23 16:58Merge pull request #2 from BAITC-Hacks/ajymzanamantaj-gif-patch-2ajymzanamantaj-gif
  • 2026-09-23 16:52Update README.mdAlina Abdikarimova
  • 2026-09-23 16:50Add files via uploadajymzanamantaj-gif
  • 2026-09-23 16:45Delete vercel.jsonajymzanamantaj-gif
  • 2026-09-23 16:45Delete server directoryajymzanamantaj-gif
  • 2026-09-23 16:45Delete scripts directoryajymzanamantaj-gif
  • 2026-09-23 16:44Delete dist directoryajymzanamantaj-gif
  • 2026-09-23 16:44Delete api directoryajymzanamantaj-gif
Все коммиты (24)
  • 2026-09-23 16:29Add files via uploadajymzanamantaj-gif
  • 2026-09-23 16:26Delete .github/codex/prompts directoryajymzanamantaj-gif
  • 2026-09-23 16:19Add files via uploadAlina Abdikarimova
  • 2026-09-23 16:18Add Codex review workflow for pull requestsajymzanamantaj-gif
  • 2026-09-23 16:18Create review template for pull requestsajymzanamantaj-gif
  • 2026-09-23 15:45new readmeAlina Abdikarimova
  • 2026-09-23 15:21Merge branch 'main' into ajymzanamantaj-gif-patch-1ajymzanamantaj-gif
  • 2026-09-23 15:17Update README.mdAlina Abdikarimova
  • 2026-09-23 15:16Revise README with project details and instructionsajymzanamantaj-gif
  • 2026-09-23 15:16Update README.mdAlina Abdikarimova
  • 2026-09-23 15:13Revise README with deployment and structure detailsajymzanamantaj-gif
  • 2026-09-23 15:11Add Codex review workflow for pull requestsajymzanamantaj-gif
  • 2026-09-23 15:10Add review prompt for pull request checks in Russianajymzanamantaj-gif
  • 2026-09-23 14:54Update Mereke frontend and butter yellow themeAlina Abdikarimova
  • 2026-09-23 14:352.0Alina Abdikarimova
  • 2026-09-23 14:10Add Mereke prototypeAlina Abdikarimova
Структура репозитория (18 файлов)
.gitignore
.nojekyll
README.md
api/health.mjs
api/recommend.mjs
app.js
data.js
download
engine.js
index.html
package.json
scripts/check-build.cjs
server/local.mjs
server/recommend.mjs
server/recommend.test.mjs
style.css
tests.cjs
vercel.json
Ветки (3)

Обсуждение 0 комментариев

Войдите, чтобы комментировать

Пока нет комментариев — будьте первым.