ESP32-S3 Bench Guide
ESP32‑S3 N16R8 벤치 가이드: 실시간 핀아웃, 강의, 시뮬레이터 및 벤치 로그
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기CampusProof — verified visual university profiles in 30 seconds. LOCUS Startup Hackathon 2026, Case 01.
저장소 README에서 가져옴
README 전체를 불러오는 중입니다. 아래는 저장된 발췌입니다.
Проверенный визуальный профиль университета за 30 секунд. Введите название университета — и получите фотографии кампуса, общежитий, аудиторий, библиотек и города, где у каждого снимка есть кликабельный источник, дата и уровень достоверности с объяснением. LOCUS Startup Hackathon 2026 · Кейс 01 «Визуальный профиль университета» · код кейса LOCUSCASE1 Статус: код заморожен 18.09 в 19:00, продакшен работает. Хакатон: 16.09 12:00 — 19.09 12:00, Астана.README 전문 보기 ↗
Проверенный визуальный профиль университета за 30 секунд. Введите название университета — и получите фотографии кампуса, общежитий, аудиторий, библиотек и города, где у каждого снимка есть кликабельный источник, дата и уровень достоверности с объяснением.
LOCUS Startup Hackathon 2026 · Кейс 01 «Визуальный профиль университета» · код кейса
LOCUSCASE1Статус: код заморожен 18.09 в 19:00, продакшен работает. Хакатон: 16.09 12:00 — 19.09 12:00, Астана.
Состояние на утро 19.09: визуальная проверка на проде работает с полуночи по Астане: исправлены ключ и модель Gemini (#96, #116–#125). Цифры в «Результатах» сняты уже с ней, 19.09 в 04:30 по Астане. Бесплатная квота Gemini небольшая. Если она кончится, профиль строится без визуальной проверки, с баннером «Визуальная проверка недоступна», и не сохраняется в кеш (#123).
Пошаговый сценарий (каждый пункт — отдельный запрос в поле поиска на главной):
| # | Что сделать | Что проверяем | Что должно произойти |
|---|---|---|---|
| 1 | КБТУ или Satbayev University. Если открылся сохранённый профиль — «Обновить» в его карточке | Скорость и прозрачность | Сразу идёт живой таймер, этапы «Поиск → Загрузка → Дубли → Проверка → Профиль» со счётчиками, чипы источников с пояснениями; затем фото с уровнями доверия. Медиана времени до готового профиля на проде 19.09 — 2,6 с |
| 2 | Кликнуть любое фото | Точность и доказательства | Уровень доверия и вердикт простыми словами, список доказательств ✓ / ✗, «Открыть источник», дата с типом (снято / загружено / опубликовано / получено), лицензия и автор, расстояние геометки от кампуса |
| 3 | MSU | Неоднозначный запрос | «Какой университет вы имели в виду?» — карточки с городом и страной (Московский государственный университет, Университет штата Мичиган); выбор ведёт на профиль нужного вуза |
| 4 | Harvrad, Nazarbaev Univercity | Опечатки | Harvrad → «Не нашли университет…» и «Возможно, вы искали» с Гарвардским университетом; Nazarbaev Univercity → опечатка исправляется сама, сразу профиль Назарбаев Университета |
| 5 | asdfgh | Мусорный запрос | Честное «не нашли», никаких чужих фото |
| 6 | https://campusproof.vercel.app/search?q=KBTU&simulate=web_search_down (также vision_down, wikimedia_down) | Недоступный источник | Профиль всё равно строится; чип источника «отключён (симуляция)», баннер объясняет, что это значит для результата. Такие запуски не кешируются |
| 7 | Небольшой региональный вуз, например Korkyt Ata Kyzylorda University | Мало данных | Разделы без подтверждённых фото показаны пустыми с объяснением; панель «Что удалось подтвердить»; переключатель «Показывать неподтверждённые» открывает слабые снимки с пометкой |
| 8 | Фильтры «Общежитие», «Спорт», «Лаборатории», «Студенческая жизнь» | R8 | У каждого фильтра счётчик; пустая категория — честное пустое состояние |
| 9 | Блок «Отфильтровано (N)» внизу профиля |
Шаги 3–6 проверены на проде smoke-тестом
node scripts/qa/smoke.mjs --refresh: 27 запросов 19.09.2026 в 04:30 по Астане, все прошли, отчёт с разбором. Шаги 1–12 пройдены вручную в браузере вечером 18.09 (отчёт); шаг 10 тогда не воспроизводился — без визуальной проверки профили не сохранялись. Теперь сохраняются: после утреннего прогона обычные профили из матрицы открываются за 0,3–0,5 с с бейджем «Сохранённый профиль».
Абитуриент выбирает вуз, который не может посетить. Официальный сайт показывает отретушированный маркетинг, а настоящие фото кампуса, общежитий, аудиторий, библиотек и города разбросаны по десяткам источников. Эти снимки дублируются, устаревают, бывают подписаны не тем вузом или вовсе непонятно откуда взялись. Поиск картинок смешивает университеты, стоки и рендеры и никак не говорит, чему можно верить.
Для кого: абитуриенты 16–19 лет из Казахстана и Центральной Азии, которые сравнивают местные и зарубежные вузы; их родители (важны общежития и реальность фото); консультанты по поступлению.
CampusProof превращает название вуза в проверенный визуальный профиль: Название → Поиск → Проверка → Категории → Профиль. Главное правило — лучше честное «не нашли», чем чужое фото. У каждого снимка есть источник, дата и уровень доверия с доказательствами; слабые снимки скрыты, пустые разделы честно помечены.
| # | Требование кейса | Как закрыто | Где в коде |
|---|---|---|---|
| R1 | Поиск по названию, неоднозначные запросы | Резолвер по Wikidata: нормализация (регистр, казахские буквы, слова «университет» / «university»), ранжирование. Один явный лидер → профиль; несколько близких → список выбора с городом и страной; ничего → «Не нашли» с подсказками | lib/resolver/*, components/search/PickList.tsx, NotFound.tsx |
| R2 | Фото кампуса, общежитий, аудиторий, библиотек, города | Отдельный раздел на каждую область. Нет подтверждённых фото → явное пустое состояние и строка в панели «Что удалось подтвердить» | components/profile/CategorySection.tsx, CoveragePanel.tsx, lib/config/categories.ts |
| R3 | Автоматическая категоризация | Категорию выставляет пайплайн: подсказки из категорий и названий файлов Commons плюс наблюдение нейросети; вручную ничего не размечается | lib/sources/commons.ts, lib/vision/*, lib/scoring/* |
| R4 | Убрать одинаковые, похожие и нерелевантные | Перцептивный хэш (dHash) убирает одинаковые и почти одинаковые снимки; логотипы, карты, документы, стоки, рендеры и крупные портреты отсеиваются. Всё убранное видно в «Отфильтровано (N)» с причиной | lib/images/dedup.ts, lib/scoring/score.ts, components/profile/FilteredOutTray.tsx |
| R5 | Проверить, что фото именно этого вуза | Сигналы происхождения, геометки, текста на снимке и совпадений между источниками записываются как доказательства. Баллы и уровень («Проверено» / «Вероятно» / «Не подтверждено») считает только код; «Не подтверждено» скрыто по умолчанию | lib/scoring/score.ts, components/profile/EvidenceDialog.tsx |
| R6 | Кликабельный источник и дата | Ссылка на страницу, где нашли фото; дата с типом: снято / загружено / опубликовано / получено. Дата получения есть у каждого фото | components/profile/PhotoCard.tsx, EvidenceDialog.tsx, lib/ui/format.ts |
| R7 | Краткое описание по источникам | 3–5 предложений по Википедии и Wikidata, у каждого ссылка [n] на источник; без нейросети — цитата из Википедии | lib/describe/description.ts, components/profile/DescriptionBlock.tsx |
Сверх обязательного:
?simulate= для проверки сбоев;/compare: два сохранённых профиля бок о бок по разделам и уровням. Новых проверок она не запускает.Кратко для пользователей — на странице /how-it-works; спецификация — docs/architecture.md §5.6.
Каждый найденный кандидат проходит один и тот же путь: загрузка → дубликаты → наблюдения нейросети → очки → уровень. Особых правил под отдельные вузы нет. Очки и уровень считает только код в lib/scoring (signals.ts, tiers.ts), он покрыт тестами. Каждое доказательство — отдельная строка в диалоге фото, скрытых очков нет. Очки — это не вероятность.
Доказательства и очки (значения из lib/scoring/signals.ts):
| Доказательство | Очки | Сильное |
|---|---|---|
| На Wikimedia Commons отмечено, что на фото изображён этот вуз | +45 | да |
| Фото в категории вуза на Commons | +40 | да |
| Геометка не дальше 1,5 км от кампуса | +35 | да |
| Фото города с геометкой в пределах 30 км (только раздел «Город») | +35 | да |
| Фото используется в статье Википедии о вузе | +30 | да |
Найдено на официальном сайте вуза: домен из Wikidata (P856) и его вариант в зоне edu/ac (kbtu.kz → kbtu.edu.kz) | +30 | да |
| …но похоже на сток или рендер | +10 | нет |
| На снимке читается название этого вуза (визуальная проверка) | +30 | да |
| Страница с фото упоминает вуз | +15 | нет |
| То же фото найдено ещё на одном сайте | +15 | нет |
| Новостная статья о вузе | +10 | нет |
| Сцена соответствует описанию вуза (визуальная проверка) | +10 | нет |
| Геометка в том же городе, до 30 км от кампуса | +10 | нет |
| Сцена не похожа на описание вуза | −25 | блокирует «Проверено» |
| Рендер или иллюстрация | −40 | блокирует «Проверено» |
| Проверено только по уменьшенной копии | −10 | нет |
Уровни (пороги из lib/config/limits.ts, правило — lib/scoring/tiers.ts):
| Уровень | Условие |
|---|---|
| ✓ Проверено | от 60 очков, есть хотя бы одно сильное доказательство, нет рендера и сцены, которая противоречит описанию вуза |
| ◐ Вероятно | от 35 очков. Если визуальная проверка недоступна — только при сильном доказательстве; фото, которое известно лишь из веб-поиска, остаётся «Не подтверждено» |
| ? Не подтверждено | от 10 очков. Скрыто по умолчанию, открывается переключателем «Показывать неподтверждённые» |
| Отклонено | меньше 10 очков — «Слишком мало доказательств» |
Отклоняем сразу, независимо от очков:
Всё отклонённое видно в блоке «Отфильтровано (N)» с причиной; у портретов нет превью. Снимки старше 10 лет получают пометку «возможно, устарело».
Без визуальной проверки (сбой Gemini, исчерпанная квота или посетитель из ЕЭЗ, Швейцарии, Великобритании) профиль всё равно строится. Уровень тогда опирается только на происхождение, геометки и совпадения источников, у каждой карточки есть пометка «Без визуальной проверки», а сверху — баннер.
Next.js 16 (App Router, TypeScript) на Vercel (fra1) · Tailwind CSS 4 + shadcn/ui · Google Gemini API, бесплатный тариф (vision и описание) · Wikidata / Wikipedia / Wikimedia Commons · Serper (бесплатные кредиты) и Openverse (поиск изображений) · Upstash Redis (бесплатный тариф). Только бесплатные API. Подробно: docs/architecture.md.
npm install
cp .env.example .env.local # заполните ключи
npm run dev # http://localhost:3000
npm run check # typecheck + lint + тесты
Python-скрипты (спайки, индекс университетов, оценка качества): scripts/python/README.md.
Только официальные API и открытые данные. Google Картинки, Instagram, Facebook, VK и 2ГИС не парсим, стоковые фотобанки не используем.
| Источник | Что берём | Лицензия и атрибуция |
|---|---|---|
| Wikidata | Какой это вуз (резолвер), официальный сайт и домены, координаты кампуса и города, факты: год основания, число студентов, город | CC0; у каждого факта в профиле ссылка на источник |
| Wikipedia | Тексты для краткого описания вуза | CC BY-SA; в описании у каждого предложения сноска [n] со ссылкой на статью |
| Wikimedia Commons | Фото с категориями вуза и города, отметками «на фото изображено», геометками и датами | Лицензия файла; в диалоге доказательств — лицензия, автор и ссылка на страницу файла |
| Openverse | Фото с открытыми лицензиями | Лицензия и автор из API, ссылка на исходную страницу |
| Serper | Веб-поиск изображений: официальные сайты вузов, СМИ, блоги | Лицензия обычно неизвестна — так и пишем («Не указана — права принадлежат владельцу источника»), ссылка на страницу, где найдено фото |
| OpenStreetMap | Подложка карты кампуса | ODbL; атрибуция «© OpenStreetMap» на карте и под ней |
Полноразмерные изображения мы не перезаливаем: карточки и диалог показывают фото по исходной ссылке (<img referrerPolicy="no-referrer">), а если хост его не отдаёт — честная заглушка и ссылка на источник.
| Модель / API | Для чего | ID модели |
|---|---|---|
| Google Gemini API, бесплатный тариф | Визуальные наблюдения по фото: тип изображения (фото, рендер, логотип, карта, документ, коллаж), похоже ли на сток, водяной знак, раздел (кампус, общежитие…), текст на снимке и называет ли он этот вуз или другой, соответствует ли сцена контексту, крупный ли это портрет, качество | gemini-flash-lite-latest (переменная VISION_MODEL) — псевдоним, который Google держит на действующей модели. Если модель перегружена или снята — запасная gemini-flash-latest (VISION_MODEL_FALLBACK) |
| Google Gemini API, бесплатный тариф | Краткое описание вуза 3–5 предложениями только по переданным источникам, каждое предложение со ссылкой на источник | gemini-flash-latest (переменная DESCRIPTION_MODEL) |
| Wikidata / Wikipedia / Commons API, Openverse API, Serper API | Поиск вуза, фактов, текстов и фото-кандидатов | — |
| Upstash Redis, бесплатный тариф | Кеш профилей (14 дней), ответов источников и наблюдений нейросети; ограничение частоты новых проверок | — |
Что решает нейросеть, а что — код. Нейросеть только описывает наблюдения в JSON; ответ проверяется схемой zod. Всё остальное — детерминированный код:
lib/scoring, покрыт тестами);Нейросеть не ставит оценку, не выбирает уровень и никогда не определяет людей на фото.
Бесплатные квоты и защита от перерасхода:
GEMINI_API_KEY может содержать несколько ключей. Визуальная проверка переходит на следующий ключ, если текущий отклонён или его квота исчерпана (#125); описание вуза использует только первый ключ;FRESH_RUNS_PER_CLIENT: судьи в одном зале часто выходят в сеть с одного IP) и дневной лимит новых профилей (MAX_FRESH_PROFILES_PER_DAY);Лимиты — в lib/config/limits.ts и lib/cache/ratelimit.ts. Для посетителей из ЕЭЗ, Швейцарии и Великобритании нейросеть не вызывается (условия бесплатного тарифа Gemini, lib/pipeline/regions.ts).
create-next-app и компоненты shadcn/ui добавлены 16.09 после старта хакатона.Co-authored-by. .env.local (не в репозитории, .env* в .gitignore); все вызовы внешних API идут с сервера, ключи в браузер не попадают.http(s) — javascript: и data: отбрасываются (lib/ui/format.ts, safeHttpUrl).<img loading="lazy" referrerPolicy="no-referrer"> без перезаливки, с заглушкой при ошибке./dev/*, повтор стрима) на продакшене отдают 404 (lib/devOnly.ts).lib/images/safeFetch.ts. Сервер скачивает фото для проверки, поэтому:
http(s);localhost, имена вида *.local и *.internal, частные, петлевые и link-local адреса (включая адрес метаданных облака 169.254.169.254), CGNAT и зарезервированные диапазоны IPv4 и IPv6;image/*, без SVG и GIF.Бесплатная квота Gemini мала. Когда она исчерпана, профиль строится по источникам и метаданным: происхождение, геометки, совпадения между сайтами. Тогда:
До полуночи 18.09 так строились все профили: Gemini не принимал ключ (#96). Если квота кончается посреди прогона, фото без наблюдения оцениваются как без визуальной проверки, а профиль не сохраняется (#123).
Не ищем, где ещё в интернете используется тот же снимок. Детектора повторного использования (стоковые копии, одно фото у разных вузов, #26) нет. Мы сравниваем только кандидатов внутри одного профиля (дубликаты и «Также найдено на»), а фотобанки отсекаем по домену.
Не определяем, сгенерировано ли фото нейросетью. Опираемся на происхождение: где снимок опубликован, кем и с какими метаданными.
Бесплатный Gemini. Его условия не разрешают бесплатный тариф для пользователей из Европейской экономической зоны, Швейцарии и Великобритании, поэтому для посетителей оттуда визуальная проверка и описание нейросетью отключены (lib/pipeline/regions.ts). Профиль строится в деградированном режиме с баннером, описание — цитата из Википедии.
Покрытие. Лучше всего протестировано на вузах Казахстана, Центральной Азии и крупных международных. У небольших вузов открытых фото мало — будут честно пустые разделы.
Даты. У фото из веба часто нет даты съёмки: тогда показываем дату публикации или получения — всегда с типом, никогда не выдавая её за дату съёмки.
Геометки есть не у всех фото; расстояния считаются по прямой.
Лимиты бесплатных API (Serper, Gemini, Upstash). Если источник недоступен или исчерпан, профиль строится без него, а баннер и чип источника об этом сообщают.
Сохранённые профили живут до 14 дней: изменения в источниках за это время видны только после «Обновить».
Люди. Нейросеть не просят узнавать людей; крупные портреты исключаются.
Точность уровней не измерена. Для неё нужна размеченная вручную выборка (#25). Ниже в «Результатах» — только то, что измерено: скорость, распределение уровней и соблюдение правил честности.
Измерено smoke-тестом на продакшене (node scripts/qa/smoke.mjs --base https://campusproof.vercel.app --refresh).
Выборка: 27 запросов в 9 группах (scripts/qa/queries.json), 19.09.2026, начало в 04:30 по Астане (23:30 UTC 18.09). Все 22 профиля собраны заново (refresh=1), визуальная проверка работала. Ответы источников и наблюдения модели брались из кеша Redis, где они уже были, поэтому время — это время пайплайна с тёплым кешем источников; холодные прогоны без кеша 18.09 укладывались в 10–11 с. Полный отчёт с разбором — docs/qa-report-2026-09-19.md.
| Что измерили | Результат |
|---|---|
| Исходы 27 запросов | 22 профиля (19 обычных и 3 симуляции сбоев), 1 список выбора (MSU), 4 «не нашли»: 3 мусорных запроса и Harvrad (с подсказкой «Гарвардский университет») |
| Время до готового профиля, 22 профиля | медиана 2,6 с, максимум 8,6 с при цели кейса до 30 с. Замер на клиенте, от отправки запроса |
| Время до первых фото | медиана 2,5 с, максимум 4,9 с |
| Время до определения вуза | медиана 0,3 с, максимум 1,4 с |
| Фото в профиле, 19 обычных профилей (14 разных вузов) | медиана 28, от 15 до 33 |
| Уровни фото в этих 19 профилях, всего 509 фото | ✓ Проверено — 172 (33,8 %) · ◐ Вероятно — 257 (50,5 %) · ? Не подтверждено — 80 (15,7 %) |
| Профили без единого «Проверено» | 1 из 19: Kozybayev University |
| Визуальная проверка | ok во всех 21 профиле, где её не отключали симуляцией |
| Правила честности, 22 профиля и 602 фото | 0 нарушений: у каждого фото есть ссылка на источник и дата получения, очки равны сумме доказательств, панель покрытия совпадает с фото |
Симуляция сбоев: web_search_down, vision_down, wikimedia_down | 3 из 3 — профиль с баннером деградации, без ошибки, в кеш не сохраняется |
Для сравнения: вечером 18.09 визуальная проверка не работала (Gemini не принимал ключ, #96), и из 534 фото «Проверено» было 70 (13,1 %), а профилей без единого «Проверено» — 5 из 18 (отчёт).
Что не измерено: точность уровня «Проверено» (доля фото, которые действительно относятся к этому вузу) и точность категорий. Для этого нужна размеченная вручную выборка (#25), а без неё мы цифр не приводим.
| Роль | Участник | Зона ответственности |
|---|---|---|
| P1 · Pipeline | имя | Бэкенд-пайплайн, стриминг, интеграция |
| P2 · Verification | имя | Поиск изображений, дедупликация, AI-проверка, скоринг |
| P3 · Data & Eval | имя | Индекс университетов, спайки, разметка, метрики |
| P4 · UI & Product | имя | Интерфейс, тексты, QA, презентация и видео |
| Дубли и мусор |
| Что убрано и почему, например: дубликаты, фотобанки, мало доказательств, далёкая геометка; с визуальной проверкой ещё другой вуз на снимке и «не фото». Портреты — без превью |
| 10 | Повторить запрос из шага 1 | Кеш | Бейдж «Сохранённый профиль · создан … за … с» и кнопка «Обновить». Сохраняются только полные профили: если визуальная проверка была недоступна, следующий запрос соберёт профиль заново |
| 11 | Блок «Карта» в профиле | Геопроверка | Кампус, центр города и точки фото с геометкой; клик по точке открывает доказательства; «≈ N км до центра по прямой» |
| 12 | Переключатель «Официальные / Независимые» | Маркетинг против реальности | «Независимые» скрывает фото с официального сайта вуза, «Официальные» оставляет только их; у каждой карточки бейдж типа источника. Нагляднее всего на вузе из шага 7: у него есть фото с сайта korkyt.edu.kz |
| R8 | Фильтры: общежитие, спорт, лаборатории, студенческая жизнь | Ровно четыре фильтра с этими подписями, счётчики, пустые состояния, плюс переключатель «Показывать неподтверждённые» | components/profile/FilterBar.tsx, lib/ui/filters.ts |