{"id":27110093,"url":"https://github.com/jirufik/magicball","last_synced_at":"2026-04-24T16:03:01.047Z","repository":{"id":101970667,"uuid":"145323994","full_name":"jirufik/magicball","owner":"jirufik","description":" This is Magic 8 ball. PhaserJS","archived":false,"fork":false,"pushed_at":"2026-02-23T16:47:12.000Z","size":1226,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2026-02-24T00:31:16.279Z","etag":null,"topics":["jrf","phaser","phaser-game","phaserjs"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jirufik.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2018-08-19T17:29:35.000Z","updated_at":"2026-02-23T16:47:16.000Z","dependencies_parsed_at":null,"dependency_job_id":"da9aca0e-0bb4-4fa2-ac55-5daffe0a910f","html_url":"https://github.com/jirufik/magicball","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/jirufik/magicball","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jirufik%2Fmagicball","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jirufik%2Fmagicball/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jirufik%2Fmagicball/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jirufik%2Fmagicball/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jirufik","download_url":"https://codeload.github.com/jirufik/magicball/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jirufik%2Fmagicball/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32230421,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-24T13:21:15.438Z","status":"ssl_error","status_checked_at":"2026-04-24T13:21:15.005Z","response_time":64,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["jrf","phaser","phaser-game","phaserjs"],"created_at":"2025-04-06T23:49:28.811Z","updated_at":"2026-04-24T16:03:01.041Z","avatar_url":"https://github.com/jirufik.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Magic Ball\n\nВеб-реализация классической игрушки «Магический шар 8» (Magic 8-Ball) — интерактивный гадательный шар, который даёт случайные ответы на вопросы пользователя.\n\n[Demo](https://rufus.pro/magicball/) | [Wikipedia RU](https://ru.wikipedia.org/wiki/Magic_8_ball) | [Wikipedia EN](https://en.wikipedia.org/wiki/Magic_8-Ball)\n\n---\n\n## Стек технологий\n\n| Компонент | Технология |\n|---|---|\n| Игровой движок | [Phaser 3](https://phaser.io/) |\n| Язык | TypeScript 5 |\n| Сборщик (клиент) | Vite 6 |\n| Сервер | Node.js + Express 4 |\n| Шаблонизатор | Pug 3 |\n| Тесты | Vitest |\n| Линтинг | ESLint 9 + Prettier |\n| Контейнеризация | Docker |\n\n---\n\n## Архитектура\n\n### Клиент — 4 сцены Phaser 3\n\n```\nBoot → Preload → MagicBall → Settings\n```\n\n1. **BootScene** — инициализация, загрузка лого\n2. **PreloadScene** — загрузка всех ассетов (28 PNG, 7 спрайтшитов, 2 MP3)\n3. **MagicBallScene** — основной экран: шар с анимацией ответа, череп (следит за курсором), паук на паутине, облака, панель «About»\n4. **SettingsScene** — управление ответами: добавление/удаление, смена языка (RU/EN), сброс к дефолтным\n\n### Сервер\n\nМинимальный Express-сервер, отдаёт статику (собранный Vite-бандл, изображения, звуки) и рендерит HTML через Pug.\n\n### Структура проекта\n\n```\nmagicball/\n├── src/\n│   ├── client/\n│   │   ├── index.ts                    # Точка входа, конфиг Phaser\n│   │   ├── index.html                  # HTML для Vite dev server\n│   │   ├── config/\n│   │   │   ├── gameConfig.ts           # Константы игры (размеры, физика, анимации)\n│   │   │   ├── assetManifest.ts        # Реестр всех ассетов\n│   │   │   └── defaultAnswers.ts       # 20 двуязычных ответов по умолчанию\n│   │   ├── scenes/\n│   │   │   ├── BootScene.ts            # Инициализация\n│   │   │   ├── PreloadScene.ts         # Загрузка ассетов\n│   │   │   ├── MagicBallScene.ts       # Основная игровая сцена\n│   │   │   └── SettingsScene.ts        # Настройки ответов\n│   │   ├── services/\n│   │   │   ├── MagicBallService.ts     # Логика ответов (add/delete/get/sort)\n│   │   │   └── StorageService.ts       # Обёртка над localStorage\n│   │   ├── animations/\n│   │   │   └── AnimationController.ts  # Tween-анимации (scale, rotate, alpha, move)\n│   │   ├── utils/\n│   │   │   └── TextLayoutAlgorithm.ts  # Алгоритм разбиения текста на 5 строк\n│   │   └── types/\n│   │       └── index.ts                # TypeScript интерфейсы\n│   └── server/\n│       ├── app.ts                      # Конфигурация Express\n│       ├── bin/\n│       │   └── www.ts                  # Точка входа сервера (порт 4001)\n│       └── routes/\n│           └── index.ts                # Маршрут /\n├── public/\n│   ├── images/                         # 28 PNG-спрайтов\n│   ├── sounds/                         # 2 MP3-файла\n│   └── stylesheets/\n│       └── style.css                   # Стили\n├── views/\n│   ├── layout.pug                      # Базовый шаблон\n│   ├── index.pug                       # Главная страница\n│   └── error.pug                       # Страница 404\n├── package.json\n├── tsconfig.json                       # TypeScript (общий)\n├── tsconfig.server.json                # TypeScript (сервер)\n├── vite.config.ts                      # Конфигурация Vite\n├── vitest.config.ts                    # Конфигурация тестов\n├── eslint.config.js                    # ESLint 9 flat config\n├── .prettierrc                         # Prettier\n├── Dockerfile                          # Multi-stage Docker build\n└── docker-compose.yml                  # Docker Compose\n```\n\n---\n\n## Запуск\n\n### Требования\n\n- Node.js \u003e= 18\n- npm\n\n### Установка\n\n```bash\nnpm install\n```\n\n### Разработка\n\n```bash\nnpm run dev\n```\n\nЗапускает параллельно:\n- **Vite dev server** — горячая перезагрузка клиента\n- **Nodemon** — автоперезапуск сервера при изменениях\n\n### Продакшн-сборка\n\n```bash\nnpm run build\nnpm start\n```\n\nПриложение будет доступно на http://localhost:4001\n\n### Docker\n\n```bash\ndocker compose up --build\n```\n\nПриложение будет доступно на http://localhost:4001\n\n---\n\n## Скрипты\n\n| Команда | Описание |\n|---|---|\n| `npm run dev` | Запуск в режиме разработки (Vite + Nodemon) |\n| `npm run build` | Сборка сервера и клиента |\n| `npm start` | Запуск продакшн-сервера |\n| `npm test` | Запуск тестов (Vitest) |\n| `npm run type-check` | Проверка типов TypeScript |\n| `npm run lint` | Проверка ESLint |\n| `npm run format` | Форматирование Prettier |\n\n---\n\n## Тесты\n\n31 unit-тест в 3 файлах:\n\n- **MagicBallService** (13 тестов) — defaults, add/delete answers, random answer, language switch, sorting, persistence, reset\n- **StorageService** (8 тестов) — save/load, invalid JSON, empty data, QuotaExceededError, clear\n- **TextLayoutAlgorithm** (10 тестов) — short/long text, word break, all 20 RU and 20 EN default answers\n\n```bash\nnpm test\n```\n\n---\n\n## Игровая механика\n\n### Ответы\n\n- 20 ответов по умолчанию: 10 положительных, 5 нейтральных, 5 негативных\n- Двуязычность: русский и английский\n- Пользователь может добавлять, удалять и сбрасывать ответы\n- Данные сохраняются в localStorage\n\n### Анимации\n\n- **Шар**: появление с масштабированием, тряска (9 кадров движения), показ треугольника с ответом\n- **Текст ответа**: распределяется по 5 строкам треугольной формой, масштабируется с шаром\n- **Череп**: следит за курсором мыши (десктоп) или движется случайно (мобильные)\n- **Паук**: сидит на паутине, при столкновении с черепом отлетает и возвращается\n- **Облака**: плывут по экрану с случайной скоростью и масштабом\n\n### Модель данных\n\n```typescript\ninterface Answer {\n  text: string;\n  type: 'positive' | 'neutral' | 'negative';\n}\n```\n\n---\n\n## Автор\n\n**Jirufik** — jirufik@gmail.com\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjirufik%2Fmagicball","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjirufik%2Fmagicball","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjirufik%2Fmagicball/lists"}