diff --git a/.forgejo/README.md b/.forgejo/README.md deleted file mode 100644 index ee595b3..0000000 --- a/.forgejo/README.md +++ /dev/null @@ -1,39 +0,0 @@ -# Forgejo CI/CD для Mnemo Cards - -## Быстрый старт - -1. **Настройте секреты в Forgejo:** - ``` - DEPLOY_SSH_PRIVATE_KEY # SSH ключ для деплоя - ``` - -2. **Протестируйте локально:** - ```bash - ./test_ci_locally.sh - ``` - -3. **Push в main/master:** - ```bash - git push origin main - ``` - -## Workflows - -- `ci-main.yml` - Главный pipeline -- `ci-backend.yml` - Backend (Dart) -- `ci-web.yml` - Web app (Flutter) -- `ci-mobile.yml` - Mobile app (Flutter) -- `cd-deploy.yml` - Автоматический деплой -- `code-quality.yml` - Контроль качества -- `release.yml` - Автоматические релизы - -## Создание релиза - -```bash -git tag v1.2.3 -git push origin v1.2.3 -``` - -## Подробная документация - -Смотрите [CI_CD_SETUP.md](../CI_CD_SETUP.md) для полной информации. diff --git a/.forgejo/workflows b/.forgejo/workflows new file mode 120000 index 0000000..df1658a --- /dev/null +++ b/.forgejo/workflows @@ -0,0 +1 @@ +../tools/ci \ No newline at end of file diff --git a/README.md b/README.md index 51d9e51..11de3b9 100644 --- a/README.md +++ b/README.md @@ -1,215 +1,61 @@ -# Mnemo Cards - Мобильное приложение для изучения языков +# Mnemo Cards -Полнофункциональная система для изучения языков, включающая мобильное приложение, веб-сервер, телеграм-бот и веб-игры. +Проект для изучения языков с использованием мнемоники. -## 🏗️ Структура проекта +## Структура проекта -Проект состоит из нескольких взаимосвязанных компонентов: +- `mnemo_cards/` - мобильное приложение (Flutter) +- `mnemo_cards_web_v2/` - веб версия (Flutter Web) +- `mnemo_cards_backend/` - backend сервер (Dart) +- `mnemo_cards_common/` - общие библиотеки +- `@tools/` - инструменты разработки и деплоя -### 📱 Мобильное приложение (`mnemo_cards/`) -Основное Flutter приложение для iOS и Android с функциями: -- Изучение языков через карточки -- Интеграция с Firebase (Firestore, Analytics, Crashlytics) -- Система покупок (YooKassa, In-App Purchase) -- Реклама (Yandex Mobile Ads) -- Локальные уведомления -- Интеграция с веб-играми через WebView -- Поддержка Telegram Web App +## Быстрый старт -**Технологии:** Flutter, BLoC, Auto Route, Firebase, WebView +### Разработка -### 🌐 Веб-приложение (`mnemo_cards_web/`) -Веб-версия Flutter приложения с функциями: -- Изучение языков через карточки в браузере -- Интеграция с Firebase (Firestore, Analytics, Crashlytics) -- Адаптивный дизайн для различных устройств -- Синхронизация данных с мобильным приложением -- Поддержка PWA (Progressive Web App) -- Интеграция с веб-играми - -**Технологии:** Flutter Web, BLoC, Auto Route, Firebase, PWA - -### 🔧 Общие компоненты (`mnemo_cards_common/`) -Общие DTO и утилиты для мобильного приложения: -- Модели данных -- Сетевые утилиты -- JSON сериализация -- Криптографические функции - -### 🖥️ Backend сервер (`mnemo_cards_backend/`) -Dart сервер на базе Shelf framework: -- REST API для мобильного приложения -- База данных Isar -- Интеграция с Google APIs -- Система платежей YooKassa -- Периодические задачи -- Swagger документация - -**Технологии:** Dart, Shelf, Isar, Google APIs - -### 🔧 Backend общие компоненты (`mnemo_cards_common_backend/`) -Общие компоненты для backend: -- Модели данных -- Утилиты для работы с Isar -- Общие бизнес-логика - -### 🤖 Telegram бот (`mnemo_cards_telegram_bot/`) -Telegram бот для управления приложением: -- Административные функции -- Распространение APK файлов -- Управление пользователями -- Интеграция с основным backend - -**Технологии:** Dart, Teledart, Isar - -### 🎮 Веб-игры и WebView Bridge (`games/`) -Система веб-игр с безопасной коммуникацией через WebView: -- **Host приложение** - Flutter приложение-контейнер -- **Web приложения** - Flutter Web игры (bus_word_game, web_app1) -- **Bridge Core** - система безопасной коммуникации -- **Payloads** - типизированные сообщения между приложениями - -**Архитектура:** -- Изолированные payload'ы для каждого приложения -- JavaScript bridge для WebView коммуникации -- Типобезопасная обработка сообщений -- Поддержка сложных сценариев (авторизация, quiz, нативные диалоги) - -**Технологии:** Flutter Web, WebView, JavaScript Bridge, Melos - -## 🚀 Быстрый старт - -### Мобильное приложение ```bash -cd mnemo_cards +# Установка зависимостей flutter pub get -flutter run -``` -### Веб-приложение -```bash -cd mnemo_cards_web -flutter pub get +# Запуск веб версии +cd mnemo_cards_web_v2 flutter run -d chrome -``` -### Backend сервер -```bash +# Запуск backend cd mnemo_cards_backend -dart pub get -dart run +dart run bin/server.dart ``` -### Telegram бот +### Деплой + ```bash -cd mnemo_cards_telegram_bot -dart pub get -dart run +# Проверка готовности к деплою +tools/scripts/check_deploy_ready.sh + +# Локальное тестирование CI/CD +tools/scripts/test_ci_locally.sh + +# Запуск деплоя +git push origin main ``` -### Веб-игры -```bash -cd games -melos bootstrap -cd apps/host_app -flutter run -``` +## Документация -## 🔗 Зависимости между компонентами +- [CI/CD Setup](tools/docs/CI_CD_SETUP.md) - настройка автоматического деплоя +- [Web App](mnemo_cards_web_v2/README.md) - документация веб версии +- [Backend](mnemo_cards_backend/README.md) - документация backend + +## Структура tools/ ``` -mnemo_cards -├── mnemo_cards_common (DTO) -├── games/mnemo_cards_web_bridge (WebView интеграция) -└── Firebase/Backend API - -mnemo_cards_web -├── mnemo_cards_common (DTO) -├── mnemo_cards_frontend_common (общие компоненты) -├── games/payloads_shared (общие типы) -└── Firebase/Backend API - -mnemo_cards_backend -├── mnemo_cards_common (общие DTO) -├── mnemo_cards_common_backend (backend утилиты) -└── Isar Database - -mnemo_cards_telegram_bot -├── mnemo_cards_common_backend -└── Backend API - -games/ -├── bridge_core (WebView коммуникация) -├── payloads_shared (общие типы) -└── apps/ (веб-приложения) -``` - -## 📋 Основные функции - -### Мобильное приложение -- 📚 Изучение языков через карточки -- 🎮 Интеграция с веб-играми -- 💳 Система покупок и подписок -- 📊 Аналитика и статистика -- 🔔 Push уведомления -- 🌐 Telegram Web App поддержка - -### Веб-приложение -- 📚 Изучение языков через карточки в браузере -- 🎮 Интеграция с веб-играми -- 💳 Система покупок и подписок -- 📊 Аналитика и статистика -- 🔄 Синхронизация с мобильным приложением -- 📱 PWA поддержка для установки на устройство - -### Backend -- 🔐 Аутентификация и авторизация -- 💾 Управление данными пользователей -- 💰 Обработка платежей -- 📈 Аналитика и метрики -- 🔄 Периодические задачи -- 📚 API для мобильного приложения - -### Telegram бот -- 👨‍💼 Административные функции -- 📱 Распространение APK -- 👥 Управление пользователями -- 📊 Мониторинг системы - -### Веб-игры -- 🎯 Интерактивные игры для изучения языков -- 🔗 Безопасная интеграция с мобильным приложением -- 📊 Отслеживание прогресса -- 🎨 Современный UI/UX - -## 🛠️ Технологический стек - -- **Frontend:** Flutter, Flutter Web -- **Backend:** Dart, Shelf, Isar -- **База данных:** Isar (локальная), Firestore (облачная) -- **Аутентификация:** Firebase Auth, Google Sign-In -- **Платежи:** YooKassa, In-App Purchase -- **Аналитика:** Firebase Analytics, Crashlytics -- **Реклама:** Yandex Mobile Ads -- **Уведомления:** Firebase Messaging, Local Notifications -- **Коммуникация:** WebView Bridge, REST API -- **Мониторинг:** Telegram Bot - -## 📱 Поддерживаемые платформы - -- **iOS** - нативное приложение -- **Android** - нативное приложение -- **Web** - Flutter Web приложение и игры -- **Telegram** - Web App интеграция - -## 🔒 Безопасность - -- Шифрование данных -- Безопасная WebView коммуникация -- Защита от root/jailbreak -- Валидация платежей -- Изоляция payload'ов в веб-играх - -## 📄 Лицензия - -Проект является приватным и не предназначен для публикации. +tools/ +├── ci/ # CI/CD workflows для Forgejo +├── deploy/ # Скрипты деплоя +│ ├── backend-build_app.sh # Сборка backend +│ └── web-app/ # Скрипты деплоя веб приложения +├── docs/ # Документация +└── scripts/ # Вспомогательные скрипты + ├── check_deploy_ready.sh # Проверка готовности деплоя + └── test_ci_locally.sh # Локальное тестирование CI/CD +``` \ No newline at end of file diff --git a/mnemo_cards/coverage/lcov.info b/mnemo_cards/coverage/lcov.info new file mode 100644 index 0000000..ad8de32 --- /dev/null +++ b/mnemo_cards/coverage/lcov.info @@ -0,0 +1,7678 @@ +SF:lib/main.dart +DA:39,0 +DA:40,3 +DA:43,0 +DA:44,0 +DA:46,4 +DA:50,0 +DA:57,0 +DA:68,0 +DA:70,0 +DA:71,0 +DA:75,0 +DA:76,0 +DA:79,0 +DA:80,0 +DA:81,0 +DA:82,0 +DA:83,0 +DA:84,0 +DA:86,0 +DA:87,0 +DA:88,0 +DA:89,0 +DA:92,0 +DA:93,0 +DA:95,0 +DA:100,0 +DA:101,0 +DA:105,0 +DA:108,0 +DA:110,0 +DA:111,0 +DA:112,0 +DA:114,0 +DA:115,0 +DA:117,0 +DA:118,0 +DA:119,0 +DA:121,0 +DA:122,0 +DA:123,0 +DA:125,0 +DA:126,0 +DA:127,0 +DA:129,0 +DA:130,0 +DA:131,0 +DA:133,0 +DA:134,0 +DA:135,0 +DA:137,0 +DA:138,0 +DA:140,0 +DA:141,0 +DA:143,0 +DA:144,0 +DA:145,0 +DA:148,0 +DA:149,0 +DA:150,0 +DA:152,0 +DA:153,0 +DA:156,0 +DA:157,0 +DA:159,0 +DA:160,0 +DA:161,0 +DA:162,0 +DA:163,0 +DA:165,0 +DA:166,0 +DA:167,0 +DA:168,0 +DA:172,0 +DA:173,0 +DA:174,0 +DA:176,0 +DA:177,0 +DA:179,0 +DA:180,0 +DA:182,0 +DA:186,0 +DA:187,0 +DA:188,0 +DA:189,0 +DA:191,0 +DA:193,0 +DA:195,0 +DA:197,0 +DA:199,0 +DA:201,0 +DA:203,0 +DA:205,0 +DA:207,0 +DA:210,0 +DA:211,0 +DA:212,0 +DA:216,0 +DA:218,0 +DA:219,0 +DA:221,0 +DA:222,0 +DA:223,0 +DA:224,0 +DA:225,0 +DA:226,0 +DA:227,0 +DA:234,0 +DA:235,0 +DA:236,0 +DA:238,0 +DA:239,0 +DA:240,0 +DA:242,0 +DA:245,0 +DA:248,0 +DA:251,0 +DA:253,0 +DA:259,0 +DA:261,0 +DA:265,0 +DA:267,0 +DA:268,0 +DA:269,0 +DA:271,0 +DA:272,0 +DA:274,0 +DA:275,0 +DA:283,1 +DA:285,1 +DA:287,2 +DA:288,1 +DA:292,1 +DA:293,1 +DA:294,1 +DA:295,1 +DA:296,1 +DA:298,2 +DA:299,1 +DA:303,1 +DA:307,1 +DA:312,0 +DA:315,0 +DA:316,0 +DA:318,0 +DA:319,0 +DA:321,0 +DA:322,0 +DA:324,0 +DA:326,0 +DA:334,1 +DA:336,0 +DA:337,0 +DA:351,0 +DA:353,0 +DA:354,0 +DA:357,0 +DA:359,0 +DA:360,0 +DA:361,0 +DA:362,0 +DA:363,0 +DA:366,0 +DA:369,0 +DA:370,0 +DA:371,0 +DA:372,0 +DA:373,0 +DA:378,0 +DA:379,0 +DA:380,0 +DA:385,0 +DA:387,0 +DA:390,0 +DA:391,0 +DA:392,0 +DA:396,0 +DA:397,0 +DA:400,0 +DA:402,0 +DA:403,0 +DA:406,0 +DA:407,0 +DA:408,0 +DA:409,0 +DA:410,0 +DA:415,0 +DA:421,0 +DA:429,0 +DA:432,0 +DA:439,0 +DA:443,0 +DA:445,0 +DA:447,0 +DA:456,0 +DA:457,0 +DA:458,0 +DA:459,0 +DA:461,0 +DA:463,0 +DA:464,0 +DA:466,0 +DA:471,0 +DA:472,0 +DA:473,0 +DA:474,0 +DA:476,0 +DA:482,0 +DA:483,0 +DA:484,0 +DA:486,0 +DA:488,0 +DA:489,0 +DA:490,0 +DA:491,0 +DA:492,0 +DA:493,0 +DA:494,0 +DA:496,0 +DA:497,0 +DA:501,0 +DA:502,0 +DA:504,0 +DA:505,0 +DA:508,0 +DA:509,0 +DA:510,0 +DA:511,0 +DA:513,0 +DA:514,0 +DA:516,0 +DA:517,0 +DA:518,0 +DA:519,0 +DA:520,0 +DA:521,0 +DA:523,0 +DA:525,0 +DA:527,0 +DA:529,0 +DA:530,0 +LF:240 +LH:16 +end_of_record +SF:lib/admin/add_card.dart +DA:20,0 +DA:35,0 +DA:36,0 +DA:37,0 +DA:38,0 +DA:39,0 +DA:41,0 +DA:43,0 +DA:44,0 +DA:46,0 +DA:51,0 +DA:53,0 +DA:55,0 +DA:57,0 +DA:58,0 +DA:59,0 +DA:61,0 +DA:62,0 +DA:63,0 +DA:64,0 +DA:68,0 +DA:69,0 +DA:71,0 +DA:72,0 +DA:73,0 +DA:75,0 +DA:76,0 +DA:77,0 +DA:78,0 +DA:82,0 +DA:83,0 +DA:85,0 +DA:86,0 +DA:88,0 +DA:89,0 +DA:91,0 +DA:92,0 +DA:95,0 +DA:96,0 +DA:97,0 +DA:99,0 +DA:100,0 +DA:103,0 +DA:105,0 +DA:106,0 +DA:107,0 +DA:108,0 +DA:109,0 +DA:110,0 +DA:111,0 +DA:112,0 +DA:114,0 +DA:115,0 +DA:116,0 +DA:117,0 +DA:118,0 +DA:120,0 +DA:121,0 +DA:122,0 +DA:123,0 +DA:128,0 +DA:129,0 +DA:130,0 +DA:132,0 +DA:133,0 +DA:134,0 +DA:135,0 +DA:138,0 +DA:139,0 +DA:140,0 +DA:141,0 +DA:143,0 +DA:144,0 +DA:148,0 +DA:152,0 +DA:154,0 +DA:157,0 +DA:159,0 +DA:160,0 +DA:164,0 +DA:168,0 +DA:169,0 +DA:170,0 +DA:172,0 +DA:175,0 +DA:176,0 +DA:177,0 +DA:178,0 +DA:180,0 +DA:181,0 +DA:182,0 +DA:184,0 +DA:188,0 +DA:189,0 +DA:191,0 +DA:192,0 +DA:194,0 +DA:195,0 +DA:199,0 +DA:200,0 +DA:201,0 +DA:204,0 +DA:205,0 +DA:206,0 +DA:210,0 +DA:214,0 +DA:215,0 +DA:217,0 +DA:218,0 +DA:220,0 +DA:221,0 +DA:229,0 +DA:230,0 +DA:232,0 +DA:233,0 +DA:234,0 +DA:236,0 +DA:238,0 +DA:239,0 +DA:240,0 +DA:241,0 +DA:242,0 +DA:243,0 +DA:246,0 +DA:250,0 +DA:252,0 +DA:253,0 +DA:256,0 +DA:261,0 +DA:262,0 +DA:263,0 +DA:264,0 +DA:265,0 +DA:266,0 +DA:267,0 +DA:273,0 +DA:276,0 +DA:277,0 +DA:278,0 +DA:279,0 +DA:280,0 +DA:282,0 +DA:289,0 +DA:291,0 +DA:292,0 +DA:296,0 +DA:300,0 +DA:301,0 +DA:304,0 +DA:306,0 +DA:307,0 +DA:309,0 +DA:313,0 +DA:314,0 +LF:154 +LH:0 +end_of_record +SF:lib/domain/router/dialogs.dart +DA:10,0 +DA:16,0 +DA:17,0 +DA:18,0 +DA:21,0 +DA:22,0 +DA:23,0 +DA:25,0 +DA:26,0 +DA:27,0 +DA:28,0 +DA:29,0 +DA:30,0 +DA:31,0 +DA:32,0 +DA:33,0 +DA:36,0 +DA:38,0 +DA:40,0 +DA:41,0 +DA:42,0 +DA:43,0 +DA:46,0 +DA:47,0 +DA:48,0 +DA:51,0 +DA:53,0 +DA:54,0 +DA:57,0 +DA:58,0 +DA:59,0 +DA:60,0 +DA:64,0 +DA:65,0 +DA:69,0 +DA:74,0 +DA:75,0 +DA:76,0 +DA:77,0 +DA:78,0 +DA:80,0 +DA:81,0 +DA:84,0 +DA:87,0 +DA:98,0 +DA:100,0 +DA:103,0 +DA:105,0 +DA:106,0 +LF:49 +LH:0 +end_of_record +SF:lib/managers/repository/api.dart +DA:7,0 +DA:9,0 +DA:12,0 +LF:3 +LH:0 +end_of_record +SF:lib/admin/admin_api.dart +DA:15,0 +DA:17,0 +DA:21,0 +DA:22,0 +DA:23,0 +DA:24,0 +DA:25,0 +DA:26,0 +DA:27,0 +DA:29,0 +DA:30,0 +DA:31,0 +DA:34,0 +DA:37,0 +DA:38,0 +DA:39,0 +DA:40,0 +DA:42,0 +DA:45,0 +DA:46,0 +DA:47,0 +DA:50,0 +DA:51,0 +DA:52,0 +DA:53,0 +DA:55,0 +DA:58,0 +DA:59,0 +DA:60,0 +DA:61,0 +DA:63,0 +DA:64,0 +DA:65,0 +DA:66,0 +DA:69,0 +DA:70,0 +DA:71,0 +DA:74,0 +DA:75,0 +DA:76,0 +DA:77,0 +DA:79,0 +DA:80,0 +DA:81,0 +DA:82,0 +DA:85,0 +DA:86,0 +DA:87,0 +DA:88,0 +DA:90,0 +DA:93,0 +DA:94,0 +DA:95,0 +DA:96,0 +DA:98,0 +DA:101,0 +DA:102,0 +DA:103,0 +DA:106,0 +DA:107,0 +DA:108,0 +DA:109,0 +DA:111,0 +DA:114,0 +DA:115,0 +DA:116,0 +DA:117,0 +DA:119,0 +DA:122,0 +DA:123,0 +DA:125,0 +DA:126,0 +DA:127,0 +DA:128,0 +DA:129,0 +DA:130,0 +DA:133,0 +DA:134,0 +DA:135,0 +DA:136,0 +DA:138,0 +DA:141,0 +DA:142,0 +DA:143,0 +DA:146,0 +DA:147,0 +DA:148,0 +DA:151,0 +DA:152,0 +DA:153,0 +DA:154,0 +DA:156,0 +DA:159,0 +DA:160,0 +DA:161,0 +DA:162,0 +DA:163,0 +DA:164,0 +DA:167,0 +DA:168,0 +DA:169,0 +DA:172,0 +DA:173,0 +DA:174,0 +DA:175,0 +DA:177,0 +DA:180,0 +DA:181,0 +DA:182,0 +DA:183,0 +DA:184,0 +DA:185,0 +DA:188,0 +DA:190,0 +DA:191,0 +DA:193,0 +LF:116 +LH:0 +end_of_record +SF:lib/admin/add_discount_campaign.dart +DA:22,0 +DA:23,0 +DA:24,0 +DA:27,0 +DA:28,0 +DA:29,0 +DA:30,0 +DA:32,0 +DA:35,0 +DA:36,0 +DA:40,0 +DA:42,0 +DA:44,0 +DA:45,0 +DA:51,0 +DA:52,0 +DA:53,0 +DA:54,0 +DA:57,0 +DA:59,0 +DA:60,0 +DA:63,0 +DA:64,0 +DA:66,0 +DA:70,0 +DA:71,0 +DA:73,0 +DA:75,0 +DA:76,0 +DA:79,0 +DA:80,0 +DA:82,0 +DA:86,0 +DA:87,0 +DA:89,0 +DA:90,0 +DA:91,0 +DA:92,0 +DA:93,0 +DA:94,0 +DA:95,0 +DA:96,0 +DA:100,0 +DA:101,0 +DA:102,0 +DA:103,0 +DA:104,0 +DA:105,0 +DA:106,0 +DA:107,0 +DA:109,0 +DA:110,0 +DA:111,0 +DA:112,0 +DA:113,0 +DA:115,0 +DA:116,0 +DA:117,0 +DA:118,0 +DA:119,0 +DA:120,0 +DA:122,0 +DA:124,0 +DA:125,0 +DA:126,0 +DA:127,0 +DA:132,0 +DA:134,0 +DA:135,0 +DA:136,0 +DA:137,0 +DA:138,0 +DA:142,0 +DA:143,0 +DA:144,0 +DA:145,0 +DA:146,0 +DA:147,0 +DA:150,0 +DA:152,0 +DA:154,0 +DA:155,0 +DA:156,0 +DA:157,0 +DA:158,0 +DA:159,0 +DA:161,0 +DA:162,0 +DA:163,0 +DA:168,0 +DA:170,0 +DA:171,0 +DA:172,0 +DA:173,0 +DA:174,0 +DA:178,0 +DA:180,0 +DA:181,0 +DA:182,0 +DA:183,0 +DA:184,0 +DA:188,0 +DA:191,0 +DA:192,0 +DA:193,0 +DA:194,0 +DA:197,0 +DA:201,0 +DA:203,0 +DA:204,0 +DA:207,0 +DA:208,0 +DA:209,0 +DA:210,0 +DA:211,0 +DA:212,0 +DA:213,0 +DA:214,0 +DA:216,0 +DA:219,0 +DA:220,0 +DA:221,0 +DA:222,0 +DA:223,0 +DA:224,0 +DA:226,0 +DA:227,0 +DA:229,0 +DA:230,0 +DA:238,0 +DA:239,0 +DA:240,0 +DA:241,0 +DA:242,0 +DA:243,0 +DA:248,0 +DA:249,0 +DA:253,0 +DA:254,0 +DA:255,0 +DA:256,0 +DA:257,0 +DA:258,0 +DA:279,0 +DA:283,0 +DA:284,0 +DA:286,0 +DA:287,0 +DA:289,0 +DA:290,0 +DA:291,0 +DA:292,0 +DA:293,0 +DA:294,0 +DA:295,0 +DA:296,0 +DA:297,0 +DA:298,0 +DA:300,0 +DA:303,0 +DA:304,0 +DA:305,0 +DA:307,0 +DA:308,0 +DA:309,0 +DA:311,0 +DA:312,0 +DA:313,0 +DA:317,0 +DA:318,0 +DA:319,0 +DA:320,0 +DA:322,0 +DA:323,0 +DA:325,0 +DA:326,0 +DA:327,0 +DA:328,0 +DA:332,0 +DA:334,0 +DA:335,0 +DA:339,0 +DA:342,0 +DA:343,0 +DA:344,0 +DA:345,0 +DA:346,0 +DA:347,0 +DA:354,0 +DA:355,0 +DA:356,0 +DA:358,0 +DA:371,0 +DA:372,0 +DA:373,0 +DA:374,0 +DA:375,0 +DA:377,0 +DA:379,0 +DA:381,0 +LF:200 +LH:0 +end_of_record +SF:lib/di/injector.dart +DA:37,0 +DA:39,0 +DA:40,0 +DA:41,0 +DA:42,0 +DA:44,0 +DA:45,0 +DA:47,0 +DA:49,0 +DA:50,0 +DA:52,0 +DA:54,0 +DA:55,0 +DA:58,0 +DA:59,0 +DA:62,0 +DA:63,0 +DA:66,0 +DA:68,0 +DA:69,0 +DA:72,0 +DA:73,0 +DA:74,0 +DA:75,0 +DA:78,0 +DA:80,0 +DA:81,0 +DA:83,0 +DA:85,0 +DA:86,0 +DA:88,0 +DA:90,0 +DA:91,0 +DA:93,0 +DA:95,0 +DA:96,0 +DA:98,0 +DA:100,0 +DA:101,0 +DA:102,0 +DA:103,0 +DA:106,0 +DA:108,0 +DA:109,0 +DA:110,0 +DA:111,0 +DA:112,0 +DA:115,0 +DA:117,0 +DA:118,0 +DA:119,0 +DA:120,0 +DA:121,0 +DA:124,0 +DA:126,0 +DA:127,0 +DA:128,0 +DA:129,0 +DA:130,0 +DA:131,0 +DA:132,0 +DA:135,0 +DA:137,0 +DA:138,0 +DA:139,0 +DA:142,0 +DA:144,0 +DA:145,0 +DA:147,0 +DA:149,0 +DA:150,0 +DA:153,0 +DA:154,0 +DA:155,0 +DA:156,0 +DA:157,0 +DA:160,0 +DA:162,0 +DA:163,0 +DA:165,0 +DA:167,0 +DA:168,0 +DA:171,0 +DA:172,0 +DA:175,0 +DA:176,0 +DA:177,0 +DA:178,0 +DA:182,0 +DA:183,0 +DA:184,0 +DA:185,0 +DA:186,0 +DA:187,0 +DA:188,0 +DA:194,0 +DA:195,0 +DA:197,0 +LF:98 +LH:0 +end_of_record +SF:lib/admin/date_param.dart +DA:10,0 +DA:12,0 +DA:14,0 +DA:16,0 +DA:17,0 +DA:18,0 +DA:19,0 +DA:22,0 +DA:23,0 +DA:24,0 +DA:25,0 +DA:26,0 +DA:27,0 +DA:29,0 +DA:31,0 +DA:32,0 +DA:35,0 +DA:36,0 +DA:37,0 +DA:38,0 +DA:41,0 +DA:43,0 +DA:44,0 +DA:47,0 +DA:48,0 +DA:49,0 +DA:50,0 +DA:51,0 +DA:52,0 +DA:61,0 +DA:63,0 +DA:64,0 +DA:65,0 +DA:66,0 +LF:34 +LH:0 +end_of_record +SF:lib/admin/enum_param.dart +DA:12,0 +DA:21,0 +DA:23,0 +DA:25,0 +DA:26,0 +DA:28,0 +DA:29,0 +DA:30,0 +DA:33,0 +DA:34,0 +DA:35,0 +DA:36,0 +DA:37,0 +DA:38,0 +DA:42,0 +DA:45,0 +DA:46,0 +DA:47,0 +DA:49,0 +DA:50,0 +DA:51,0 +DA:52,0 +DA:56,0 +DA:57,0 +DA:59,0 +LF:25 +LH:0 +end_of_record +SF:lib/admin/int_param.dart +DA:9,0 +DA:11,0 +DA:13,0 +DA:15,0 +DA:16,0 +DA:17,0 +DA:18,0 +DA:21,0 +DA:22,0 +DA:24,0 +DA:25,0 +LF:11 +LH:0 +end_of_record +SF:lib/admin/text_param.dart +DA:10,0 +DA:12,0 +DA:14,0 +DA:16,0 +DA:17,0 +DA:18,0 +DA:21,0 +DA:22,0 +DA:23,0 +DA:24,0 +DA:25,0 +DA:26,0 +DA:30,0 +DA:33,0 +DA:34,0 +DA:35,0 +DA:36,0 +LF:17 +LH:0 +end_of_record +SF:lib/admin/add_package.dart +DA:21,0 +DA:22,0 +DA:24,0 +DA:25,0 +DA:26,0 +DA:27,0 +DA:28,0 +DA:31,0 +DA:32,0 +DA:34,0 +DA:35,0 +DA:36,0 +DA:39,0 +DA:40,0 +DA:46,0 +DA:48,0 +DA:49,0 +DA:52,0 +DA:53,0 +DA:55,0 +DA:59,0 +DA:60,0 +DA:62,0 +DA:63,0 +DA:66,0 +DA:67,0 +DA:69,0 +DA:73,0 +DA:74,0 +DA:76,0 +DA:77,0 +DA:78,0 +DA:79,0 +DA:81,0 +DA:82,0 +DA:83,0 +DA:84,0 +DA:86,0 +DA:87,0 +DA:88,0 +DA:89,0 +DA:90,0 +DA:92,0 +DA:93,0 +DA:94,0 +DA:95,0 +DA:100,0 +DA:102,0 +DA:103,0 +DA:104,0 +DA:107,0 +DA:109,0 +DA:110,0 +DA:111,0 +DA:114,0 +DA:116,0 +DA:117,0 +DA:119,0 +DA:121,0 +DA:122,0 +DA:123,0 +DA:124,0 +DA:128,0 +DA:130,0 +DA:131,0 +DA:132,0 +DA:135,0 +DA:137,0 +DA:138,0 +DA:139,0 +DA:142,0 +DA:144,0 +DA:145,0 +DA:146,0 +DA:149,0 +DA:151,0 +DA:152,0 +DA:153,0 +DA:156,0 +DA:157,0 +DA:158,0 +DA:159,0 +DA:160,0 +DA:161,0 +DA:162,0 +DA:163,0 +DA:164,0 +DA:170,0 +DA:171,0 +DA:172,0 +DA:173,0 +DA:174,0 +DA:175,0 +DA:176,0 +DA:177,0 +DA:178,0 +DA:179,0 +DA:184,0 +DA:185,0 +DA:188,0 +DA:190,0 +DA:192,0 +DA:193,0 +DA:195,0 +DA:196,0 +DA:202,0 +DA:203,0 +DA:204,0 +DA:205,0 +DA:206,0 +DA:207,0 +DA:209,0 +DA:210,0 +DA:211,0 +DA:212,0 +DA:213,0 +DA:214,0 +DA:217,0 +DA:221,0 +DA:223,0 +DA:224,0 +DA:227,0 +DA:232,0 +DA:233,0 +DA:234,0 +DA:235,0 +DA:236,0 +DA:237,0 +DA:241,0 +DA:244,0 +DA:245,0 +DA:246,0 +DA:249,0 +DA:251,0 +DA:258,0 +DA:260,0 +DA:261,0 +DA:263,0 +DA:264,0 +DA:265,0 +DA:266,0 +DA:269,0 +DA:271,0 +DA:272,0 +DA:273,0 +DA:274,0 +DA:278,0 +DA:280,0 +DA:281,0 +DA:283,0 +DA:284,0 +DA:285,0 +DA:286,0 +DA:287,0 +LF:154 +LH:0 +end_of_record +SF:lib/utils/string_helper.dart +DA:13,0 +DA:14,0 +DA:16,0 +DA:17,0 +DA:18,0 +DA:20,0 +DA:21,0 +DA:22,0 +DA:24,0 +DA:27,0 +DA:28,0 +DA:31,0 +DA:36,0 +DA:37,0 +DA:38,0 +DA:39,0 +DA:40,0 +DA:42,0 +DA:43,0 +DA:44,0 +DA:45,0 +DA:46,0 +DA:48,0 +DA:49,0 +DA:50,0 +DA:52,0 +DA:53,0 +DA:54,0 +DA:56,0 +DA:57,0 +DA:58,0 +DA:59,0 +DA:60,0 +DA:63,0 +DA:64,0 +DA:65,0 +DA:67,0 +DA:70,0 +DA:71,0 +DA:72,0 +DA:77,0 +LF:41 +LH:0 +end_of_record +SF:lib/admin/add_plan.dart +DA:22,0 +DA:23,0 +DA:24,0 +DA:27,0 +DA:28,0 +DA:43,0 +DA:46,0 +DA:47,0 +DA:48,0 +DA:52,0 +DA:53,0 +DA:54,0 +DA:55,0 +DA:59,0 +DA:60,0 +DA:63,0 +DA:64,0 +DA:66,0 +DA:70,0 +DA:71,0 +DA:72,0 +DA:74,0 +DA:75,0 +DA:78,0 +DA:79,0 +DA:81,0 +DA:85,0 +DA:86,0 +DA:88,0 +DA:89,0 +DA:90,0 +DA:91,0 +DA:92,0 +DA:93,0 +DA:94,0 +DA:95,0 +DA:99,0 +DA:100,0 +DA:101,0 +DA:102,0 +DA:103,0 +DA:104,0 +DA:105,0 +DA:106,0 +DA:108,0 +DA:109,0 +DA:110,0 +DA:111,0 +DA:112,0 +DA:113,0 +DA:115,0 +DA:117,0 +DA:118,0 +DA:119,0 +DA:121,0 +DA:122,0 +DA:123,0 +DA:124,0 +DA:125,0 +DA:127,0 +DA:129,0 +DA:130,0 +DA:131,0 +DA:132,0 +DA:137,0 +DA:139,0 +DA:140,0 +DA:141,0 +DA:142,0 +DA:143,0 +DA:147,0 +DA:148,0 +DA:149,0 +DA:150,0 +DA:151,0 +DA:152,0 +DA:155,0 +DA:157,0 +DA:159,0 +DA:160,0 +DA:162,0 +DA:163,0 +DA:164,0 +DA:165,0 +DA:169,0 +DA:170,0 +DA:171,0 +DA:172,0 +DA:174,0 +DA:175,0 +DA:176,0 +DA:180,0 +DA:182,0 +DA:183,0 +DA:184,0 +DA:185,0 +DA:188,0 +DA:190,0 +DA:191,0 +DA:192,0 +DA:193,0 +DA:198,0 +DA:199,0 +DA:202,0 +DA:203,0 +DA:205,0 +DA:206,0 +DA:207,0 +DA:208,0 +DA:209,0 +DA:210,0 +DA:211,0 +DA:212,0 +DA:213,0 +DA:215,0 +DA:216,0 +DA:220,0 +DA:221,0 +DA:223,0 +DA:227,0 +DA:228,0 +DA:230,0 +DA:231,0 +DA:232,0 +DA:235,0 +DA:236,0 +DA:239,0 +DA:241,0 +DA:242,0 +DA:243,0 +DA:246,0 +DA:247,0 +DA:250,0 +DA:252,0 +DA:253,0 +DA:254,0 +DA:257,0 +DA:258,0 +DA:261,0 +DA:263,0 +DA:264,0 +DA:265,0 +DA:268,0 +DA:269,0 +DA:272,0 +DA:274,0 +DA:275,0 +DA:276,0 +DA:279,0 +DA:280,0 +DA:283,0 +DA:285,0 +DA:286,0 +DA:287,0 +DA:290,0 +DA:291,0 +DA:294,0 +DA:296,0 +DA:297,0 +DA:298,0 +DA:301,0 +DA:302,0 +DA:305,0 +DA:307,0 +DA:308,0 +DA:309,0 +DA:312,0 +DA:313,0 +DA:316,0 +DA:319,0 +DA:320,0 +DA:321,0 +DA:322,0 +DA:323,0 +DA:324,0 +DA:326,0 +DA:328,0 +DA:329,0 +DA:332,0 +DA:333,0 +DA:334,0 +DA:335,0 +DA:336,0 +DA:340,0 +DA:341,0 +DA:342,0 +DA:343,0 +DA:344,0 +DA:357,0 +DA:359,0 +DA:360,0 +DA:361,0 +DA:384,0 +DA:385,0 +DA:386,0 +LF:195 +LH:0 +end_of_record +SF:lib/admin/add_promocode_campaign.dart +DA:31,0 +DA:32,0 +DA:33,0 +DA:36,0 +DA:37,0 +DA:38,0 +DA:39,0 +DA:40,0 +DA:45,0 +DA:49,0 +DA:53,0 +DA:55,0 +DA:57,0 +DA:58,0 +DA:64,0 +DA:66,0 +DA:68,0 +DA:69,0 +DA:70,0 +DA:73,0 +DA:74,0 +DA:80,0 +DA:81,0 +DA:83,0 +DA:84,0 +DA:87,0 +DA:88,0 +DA:90,0 +DA:94,0 +DA:95,0 +DA:97,0 +DA:99,0 +DA:100,0 +DA:103,0 +DA:104,0 +DA:106,0 +DA:110,0 +DA:111,0 +DA:113,0 +DA:114,0 +DA:115,0 +DA:116,0 +DA:117,0 +DA:118,0 +DA:119,0 +DA:120,0 +DA:124,0 +DA:125,0 +DA:126,0 +DA:127,0 +DA:128,0 +DA:130,0 +DA:131,0 +DA:132,0 +DA:133,0 +DA:135,0 +DA:136,0 +DA:137,0 +DA:138,0 +DA:139,0 +DA:140,0 +DA:141,0 +DA:143,0 +DA:145,0 +DA:147,0 +DA:148,0 +DA:149,0 +DA:151,0 +DA:152,0 +DA:153,0 +DA:154,0 +DA:155,0 +DA:156,0 +DA:158,0 +DA:160,0 +DA:161,0 +DA:162,0 +DA:163,0 +DA:168,0 +DA:170,0 +DA:171,0 +DA:172,0 +DA:173,0 +DA:174,0 +DA:178,0 +DA:179,0 +DA:180,0 +DA:181,0 +DA:182,0 +DA:183,0 +DA:186,0 +DA:188,0 +DA:190,0 +DA:191,0 +DA:192,0 +DA:193,0 +DA:194,0 +DA:195,0 +DA:197,0 +DA:198,0 +DA:199,0 +DA:204,0 +DA:206,0 +DA:207,0 +DA:208,0 +DA:215,0 +DA:217,0 +DA:218,0 +DA:219,0 +DA:223,0 +DA:225,0 +DA:226,0 +DA:227,0 +DA:232,0 +DA:234,0 +DA:235,0 +DA:236,0 +DA:241,0 +DA:243,0 +DA:244,0 +DA:245,0 +DA:246,0 +DA:247,0 +DA:251,0 +DA:253,0 +DA:254,0 +DA:255,0 +DA:256,0 +DA:257,0 +DA:261,0 +DA:264,0 +DA:265,0 +DA:266,0 +DA:267,0 +DA:270,0 +DA:274,0 +DA:276,0 +DA:277,0 +DA:280,0 +DA:281,0 +DA:282,0 +DA:283,0 +DA:284,0 +DA:285,0 +DA:286,0 +DA:288,0 +DA:291,0 +DA:292,0 +DA:299,0 +DA:300,0 +DA:301,0 +DA:302,0 +DA:303,0 +DA:304,0 +DA:309,0 +DA:310,0 +DA:314,0 +DA:315,0 +DA:316,0 +DA:317,0 +DA:318,0 +DA:319,0 +DA:326,0 +DA:329,0 +DA:330,0 +DA:332,0 +DA:333,0 +DA:334,0 +DA:354,0 +DA:358,0 +DA:359,0 +DA:361,0 +DA:362,0 +DA:364,0 +DA:365,0 +DA:367,0 +DA:368,0 +DA:369,0 +DA:371,0 +DA:374,0 +DA:375,0 +DA:376,0 +DA:379,0 +DA:380,0 +DA:381,0 +DA:383,0 +DA:394,0 +DA:395,0 +DA:396,0 +LF:189 +LH:0 +end_of_record +SF:lib/admin/add_user.dart +DA:17,0 +DA:19,0 +DA:20,0 +DA:21,0 +DA:23,0 +DA:24,0 +DA:27,0 +DA:28,0 +DA:30,0 +DA:34,0 +DA:35,0 +DA:37,0 +DA:38,0 +DA:41,0 +DA:42,0 +DA:44,0 +DA:48,0 +DA:49,0 +DA:52,0 +DA:55,0 +DA:57,0 +DA:59,0 +DA:60,0 +DA:61,0 +DA:62,0 +DA:63,0 +DA:64,0 +DA:65,0 +DA:66,0 +DA:68,0 +DA:69,0 +DA:70,0 +DA:71,0 +DA:72,0 +DA:74,0 +DA:75,0 +DA:76,0 +DA:77,0 +DA:82,0 +DA:83,0 +DA:84,0 +DA:85,0 +DA:86,0 +DA:87,0 +DA:88,0 +DA:89,0 +DA:90,0 +DA:91,0 +DA:94,0 +DA:96,0 +DA:97,0 +DA:99,0 +DA:100,0 +DA:102,0 +DA:104,0 +DA:105,0 +DA:108,0 +DA:109,0 +DA:110,0 +DA:111,0 +DA:112,0 +DA:113,0 +DA:114,0 +DA:115,0 +DA:116,0 +DA:117,0 +DA:123,0 +DA:125,0 +DA:127,0 +DA:128,0 +DA:129,0 +DA:130,0 +DA:131,0 +DA:132,0 +DA:133,0 +DA:134,0 +DA:135,0 +DA:136,0 +DA:139,0 +DA:141,0 +DA:142,0 +DA:149,0 +DA:150,0 +DA:151,0 +DA:153,0 +DA:154,0 +DA:156,0 +DA:157,0 +DA:172,0 +DA:174,0 +DA:176,0 +DA:177,0 +DA:179,0 +DA:180,0 +DA:182,0 +DA:184,0 +DA:186,0 +DA:187,0 +DA:190,0 +DA:191,0 +DA:193,0 +DA:194,0 +DA:196,0 +DA:198,0 +DA:199,0 +DA:201,0 +DA:202,0 +DA:203,0 +DA:204,0 +DA:205,0 +DA:206,0 +DA:209,0 +DA:210,0 +DA:211,0 +DA:212,0 +DA:213,0 +DA:218,0 +DA:226,0 +DA:227,0 +LF:119 +LH:0 +end_of_record +SF:lib/features/packs/packs_api.dart +DA:13,0 +DA:16,0 +DA:19,0 +DA:20,0 +DA:24,0 +DA:29,0 +DA:32,0 +DA:33,0 +DA:37,0 +DA:42,0 +DA:43,0 +DA:44,0 +DA:46,0 +DA:50,0 +DA:51,0 +DA:52,0 +DA:54,0 +DA:59,0 +DA:63,0 +DA:64,0 +DA:65,0 +DA:70,0 +DA:72,0 +LF:23 +LH:0 +end_of_record +SF:lib/features/worker/worker_ext.dart +DA:7,0 +DA:8,0 +DA:9,0 +DA:11,0 +DA:14,0 +DA:16,0 +DA:17,0 +DA:19,0 +DA:24,0 +DA:25,0 +DA:27,0 +LF:11 +LH:0 +end_of_record +SF:lib/admin/all_cards.dart +DA:19,0 +DA:20,0 +DA:22,1 +DA:26,0 +DA:27,0 +DA:29,0 +DA:32,0 +DA:33,0 +DA:35,0 +DA:37,0 +DA:39,0 +DA:41,0 +DA:42,0 +DA:43,0 +DA:44,0 +DA:45,0 +DA:47,0 +DA:48,0 +DA:49,0 +DA:50,0 +DA:52,0 +DA:53,0 +DA:54,0 +DA:56,0 +DA:57,0 +DA:59,0 +DA:64,0 +DA:65,0 +DA:66,0 +DA:69,0 +DA:70,0 +DA:71,0 +DA:74,0 +DA:76,0 +DA:77,0 +DA:81,0 +DA:84,0 +DA:87,0 +DA:88,0 +DA:90,0 +DA:91,0 +DA:94,0 +DA:95,0 +DA:97,0 +DA:98,0 +DA:102,0 +DA:104,0 +DA:105,0 +DA:107,0 +DA:109,0 +DA:112,0 +DA:115,0 +DA:117,0 +DA:118,0 +DA:119,0 +DA:120,0 +DA:121,0 +DA:122,0 +DA:123,0 +DA:124,0 +DA:125,0 +DA:126,0 +DA:127,0 +DA:128,0 +DA:131,0 +DA:132,0 +DA:133,0 +DA:135,0 +DA:137,0 +DA:138,0 +DA:139,0 +DA:140,0 +DA:141,0 +DA:142,0 +DA:144,0 +DA:146,0 +DA:147,0 +DA:149,0 +DA:150,0 +DA:151,0 +DA:152,0 +DA:153,0 +DA:154,0 +DA:159,0 +DA:160,0 +DA:161,0 +DA:162,0 +DA:163,0 +DA:165,0 +DA:171,0 +DA:172,0 +DA:173,0 +DA:174,0 +DA:175,0 +DA:176,0 +DA:177,0 +DA:178,0 +DA:179,0 +DA:180,0 +DA:186,0 +DA:187,0 +DA:189,0 +DA:191,0 +DA:193,0 +DA:194,0 +DA:195,0 +DA:196,0 +DA:197,0 +DA:198,0 +DA:200,0 +DA:202,0 +DA:203,0 +DA:204,0 +DA:205,0 +DA:206,0 +DA:212,0 +DA:213,0 +DA:214,0 +DA:215,0 +DA:216,0 +DA:217,0 +DA:218,0 +DA:220,0 +DA:221,0 +DA:223,0 +DA:225,0 +DA:226,0 +DA:228,0 +DA:231,0 +DA:232,0 +DA:233,0 +DA:235,0 +DA:236,0 +DA:238,0 +DA:240,0 +DA:241,0 +DA:243,0 +DA:249,0 +DA:250,0 +DA:251,0 +DA:252,0 +DA:254,0 +DA:256,0 +DA:257,0 +DA:259,0 +DA:272,0 +DA:273,0 +DA:274,0 +DA:275,0 +DA:276,0 +DA:278,0 +DA:280,0 +DA:283,0 +DA:284,0 +DA:285,0 +DA:286,0 +DA:288,0 +DA:292,0 +DA:296,0 +DA:298,0 +DA:301,0 +DA:305,0 +DA:306,0 +DA:307,0 +DA:308,0 +DA:309,0 +DA:310,0 +DA:311,0 +DA:312,0 +DA:315,0 +DA:316,0 +DA:318,0 +DA:320,0 +DA:322,0 +DA:325,0 +DA:326,0 +DA:327,0 +DA:339,0 +DA:341,0 +DA:343,0 +DA:344,0 +DA:345,0 +DA:346,0 +DA:347,0 +DA:348,0 +DA:349,0 +DA:350,0 +DA:352,0 +DA:353,0 +DA:354,0 +DA:356,0 +DA:357,0 +DA:358,0 +LF:193 +LH:1 +end_of_record +SF:lib/managers/repository/dio_provider.dart +DA:23,0 +DA:25,0 +DA:27,0 +DA:28,0 +DA:30,0 +DA:31,0 +DA:33,0 +DA:36,0 +DA:40,0 +DA:41,0 +DA:43,0 +DA:46,0 +DA:47,0 +DA:49,0 +DA:50,0 +DA:51,0 +DA:52,0 +DA:53,0 +DA:55,0 +DA:56,0 +DA:69,0 +DA:71,0 +DA:74,0 +DA:75,0 +DA:77,0 +DA:78,0 +DA:81,0 +DA:86,0 +DA:87,0 +DA:90,0 +DA:91,0 +DA:92,0 +DA:93,0 +DA:95,0 +DA:98,0 +DA:99,0 +DA:100,0 +DA:101,0 +DA:103,0 +DA:108,0 +DA:113,0 +DA:114,0 +DA:115,0 +DA:116,0 +DA:117,0 +DA:118,0 +DA:119,0 +DA:120,0 +DA:121,0 +DA:122,0 +DA:124,0 +DA:125,0 +DA:126,0 +DA:134,0 +DA:139,0 +DA:140,0 +DA:141,0 +DA:144,0 +DA:146,0 +DA:147,0 +DA:148,0 +LF:61 +LH:0 +end_of_record +SF:lib/theme/themes.dart +DA:4,3 +DA:21,3 +DA:34,3 +DA:47,3 +DA:52,1 +DA:54,2 +DA:55,2 +DA:56,2 +DA:59,1 +DA:60,1 +DA:61,2 +DA:64,1 +DA:65,1 +DA:66,1 +DA:67,1 +DA:68,1 +DA:69,1 +DA:70,1 +DA:71,1 +DA:72,1 +DA:73,1 +DA:74,1 +DA:75,1 +DA:76,1 +DA:77,1 +DA:78,1 +DA:79,1 +DA:81,2 +DA:82,1 +DA:84,3 +DA:89,1 +DA:90,2 +DA:94,1 +DA:95,2 +DA:97,1 +DA:98,1 +DA:99,2 +DA:101,2 +DA:102,1 +LF:39 +LH:39 +end_of_record +SF:lib/admin/all_users.dart +DA:15,0 +DA:16,0 +DA:18,1 +DA:22,0 +DA:23,0 +DA:28,0 +DA:30,0 +DA:32,0 +DA:34,0 +DA:35,0 +DA:36,0 +DA:37,0 +DA:39,0 +DA:40,0 +DA:41,0 +DA:42,0 +DA:43,0 +DA:45,0 +DA:50,0 +DA:51,0 +DA:52,0 +DA:55,0 +DA:57,0 +DA:58,0 +DA:62,0 +DA:65,0 +DA:68,0 +DA:69,0 +DA:71,0 +DA:72,0 +DA:75,0 +DA:76,0 +DA:81,0 +DA:82,0 +DA:83,0 +DA:84,0 +DA:85,0 +DA:86,0 +DA:89,0 +DA:92,0 +DA:94,0 +DA:95,0 +DA:96,0 +DA:97,0 +DA:98,0 +DA:99,0 +DA:100,0 +DA:101,0 +DA:103,0 +DA:104,0 +DA:105,0 +DA:108,0 +DA:109,0 +DA:111,0 +DA:113,0 +DA:114,0 +DA:115,0 +DA:116,0 +DA:117,0 +DA:119,0 +DA:121,0 +DA:122,0 +DA:124,0 +DA:125,0 +DA:126,0 +DA:127,0 +DA:128,0 +DA:129,0 +DA:147,0 +DA:148,0 +DA:152,0 +DA:153,0 +DA:155,0 +DA:157,0 +DA:159,0 +DA:160,0 +DA:161,0 +DA:162,0 +DA:163,0 +DA:165,0 +DA:167,0 +DA:168,0 +DA:169,0 +DA:183,0 +DA:184,0 +DA:185,0 +DA:186,0 +DA:189,0 +DA:190,0 +DA:191,0 +DA:192,0 +DA:194,0 +DA:198,0 +DA:202,0 +DA:203,0 +DA:204,0 +DA:205,0 +DA:207,0 +DA:219,0 +DA:221,0 +DA:223,0 +DA:224,0 +DA:225,0 +DA:226,0 +DA:227,0 +LF:105 +LH:1 +end_of_record +SF:lib/di/locator.dart +DA:26,0 +DA:28,1 +DA:30,0 +DA:32,0 +DA:34,0 +DA:36,0 +DA:38,0 +DA:40,0 +DA:41,0 +DA:43,0 +DA:45,0 +DA:47,0 +DA:49,0 +DA:51,0 +DA:53,0 +DA:55,0 +DA:56,0 +DA:58,0 +DA:60,0 +DA:62,0 +DA:64,0 +DA:65,0 +DA:67,0 +LF:23 +LH:1 +end_of_record +SF:lib/common_device_info.dart +DA:4,0 +LF:1 +LH:0 +end_of_record +SF:lib/features/games/games_repository.dart +DA:21,0 +DA:23,0 +DA:24,0 +DA:25,0 +DA:28,0 +DA:29,0 +DA:33,0 +DA:34,0 +DA:37,0 +DA:39,0 +DA:40,0 +DA:42,0 +DA:46,0 +DA:47,0 +DA:49,0 +DA:52,0 +DA:53,0 +DA:54,0 +DA:55,0 +DA:57,0 +DA:59,0 +DA:61,0 +DA:63,0 +DA:66,0 +DA:67,0 +DA:70,0 +DA:71,0 +DA:72,0 +DA:73,0 +DA:75,0 +DA:78,0 +LF:31 +LH:0 +end_of_record +SF:lib/features/packs/pack_cache_manager.dart +DA:21,0 +DA:23,0 +DA:24,0 +DA:25,0 +DA:28,0 +DA:30,0 +DA:37,0 +DA:39,0 +DA:40,0 +DA:41,0 +DA:42,0 +DA:43,0 +DA:44,0 +DA:47,0 +DA:48,0 +DA:56,0 +DA:61,0 +DA:63,0 +DA:64,0 +DA:65,0 +DA:66,0 +DA:67,0 +DA:69,0 +DA:71,0 +DA:72,0 +DA:73,0 +DA:74,0 +DA:75,0 +DA:76,0 +DA:77,0 +DA:79,0 +DA:84,0 +DA:85,0 +DA:93,0 +DA:94,0 +DA:99,0 +DA:101,0 +DA:103,0 +DA:104,0 +DA:105,0 +DA:106,0 +DA:107,0 +DA:108,0 +DA:112,0 +DA:116,0 +DA:117,0 +DA:118,0 +DA:120,0 +DA:124,0 +DA:125,0 +DA:128,0 +DA:133,0 +DA:134,0 +DA:135,0 +DA:136,0 +DA:138,0 +DA:143,0 +DA:145,0 +DA:151,0 +DA:153,0 +DA:154,0 +DA:156,0 +DA:158,0 +DA:161,0 +DA:162,0 +DA:166,0 +DA:167,0 +DA:170,0 +DA:171,0 +DA:174,0 +DA:175,0 +DA:176,0 +DA:177,0 +DA:179,0 +DA:182,0 +DA:186,0 +DA:187,0 +DA:188,0 +DA:189,0 +DA:190,0 +DA:191,0 +DA:192,0 +DA:195,0 +DA:196,0 +DA:197,0 +DA:198,0 +DA:200,0 +DA:201,0 +DA:202,0 +DA:203,0 +DA:204,0 +DA:205,0 +DA:207,0 +DA:208,0 +DA:214,0 +DA:217,0 +DA:218,0 +LF:97 +LH:0 +end_of_record +SF:lib/features/purchase/google_purchase_handler.dart +DA:20,0 +DA:22,0 +DA:28,0 +DA:29,0 +DA:32,0 +DA:33,0 +DA:36,0 +DA:37,0 +DA:38,0 +DA:39,0 +DA:40,0 +DA:42,0 +DA:51,0 +DA:52,0 +DA:53,0 +DA:55,0 +DA:57,0 +DA:58,0 +DA:60,0 +DA:62,0 +DA:69,0 +DA:71,0 +DA:73,0 +DA:75,0 +DA:76,0 +DA:78,0 +DA:87,0 +DA:89,0 +DA:90,0 +DA:93,0 +DA:94,0 +DA:95,0 +DA:97,0 +DA:99,0 +DA:100,0 +DA:101,0 +DA:104,0 +DA:107,0 +DA:110,0 +DA:111,0 +DA:113,0 +DA:114,0 +DA:119,0 +DA:126,0 +DA:127,0 +DA:130,0 +DA:132,0 +DA:133,0 +DA:134,0 +DA:137,0 +DA:140,0 +DA:142,0 +DA:143,0 +DA:145,0 +DA:147,0 +DA:150,0 +DA:154,0 +DA:158,0 +DA:160,0 +DA:163,0 +DA:168,0 +DA:171,0 +DA:176,0 +DA:177,0 +DA:178,0 +DA:179,0 +DA:180,0 +DA:182,0 +DA:183,0 +DA:184,0 +DA:185,0 +DA:187,0 +DA:189,0 +DA:190,0 +DA:191,0 +DA:192,0 +DA:195,0 +DA:204,0 +DA:205,0 +DA:206,0 +LF:80 +LH:0 +end_of_record +SF:lib/features/purchase/yookassa_purchase_handler.dart +DA:20,0 +DA:22,0 +DA:27,0 +DA:30,0 +DA:34,0 +DA:41,0 +DA:44,0 +DA:49,0 +DA:55,0 +DA:63,0 +DA:64,0 +DA:65,0 +DA:67,0 +DA:68,0 +DA:70,0 +DA:73,0 +DA:74,0 +DA:75,0 +DA:76,0 +DA:77,0 +DA:78,0 +DA:79,0 +DA:80,0 +DA:82,0 +DA:83,0 +DA:84,0 +DA:85,0 +DA:89,0 +DA:95,0 +DA:102,0 +DA:103,0 +DA:104,0 +DA:105,0 +DA:106,0 +DA:110,0 +DA:116,0 +DA:135,0 +DA:137,0 +DA:138,0 +DA:143,0 +LF:40 +LH:0 +end_of_record +SF:lib/features/subscription/subscription_api.dart +DA:11,0 +DA:13,0 +DA:14,0 +DA:15,0 +DA:16,0 +DA:17,0 +DA:18,0 +DA:21,0 +DA:26,0 +DA:27,0 +DA:28,0 +DA:29,0 +DA:33,0 +DA:35,0 +LF:14 +LH:0 +end_of_record +SF:lib/managers/favorite_cards.dart +DA:13,0 +DA:15,0 +DA:16,0 +DA:17,0 +DA:19,0 +DA:21,0 +DA:24,0 +DA:25,0 +DA:26,0 +DA:29,0 +DA:30,0 +DA:33,0 +DA:34,0 +DA:35,0 +DA:36,0 +DA:37,0 +DA:39,0 +DA:41,0 +DA:44,0 +DA:46,0 +DA:47,0 +DA:49,0 +LF:22 +LH:0 +end_of_record +SF:lib/managers/repository/http_repository.dart +DA:15,0 +DA:17,0 +DA:18,0 +DA:20,0 +DA:22,0 +DA:24,0 +DA:27,0 +DA:30,0 +DA:31,0 +DA:32,0 +DA:34,0 +DA:35,0 +DA:36,0 +DA:41,0 +DA:47,0 +DA:48,0 +DA:49,0 +DA:51,0 +DA:52,0 +DA:53,0 +DA:58,0 +DA:66,0 +DA:68,0 +DA:73,0 +DA:74,0 +DA:75,0 +DA:76,0 +DA:81,0 +DA:83,0 +DA:84,0 +DA:85,0 +DA:86,0 +DA:91,0 +DA:93,0 +DA:94,0 +DA:95,0 +DA:96,0 +DA:99,0 +DA:100,0 +DA:105,0 +DA:107,0 +DA:110,0 +DA:112,0 +DA:115,0 +DA:117,0 +DA:118,0 +DA:119,0 +DA:123,0 +DA:125,0 +DA:126,0 +DA:128,0 +DA:131,0 +DA:133,0 +DA:134,0 +DA:137,0 +DA:139,0 +DA:144,0 +DA:150,0 +DA:151,0 +DA:152,0 +DA:153,0 +DA:154,0 +DA:156,0 +DA:159,0 +DA:162,0 +DA:164,0 +DA:165,0 +DA:169,0 +DA:174,0 +DA:175,0 +DA:176,0 +DA:178,0 +DA:179,0 +DA:182,0 +DA:185,0 +DA:186,0 +DA:187,0 +DA:188,0 +DA:190,0 +LF:79 +LH:0 +end_of_record +SF:lib/features/deeplinks/deeplinks_manager_impl.dart +DA:15,0 +DA:20,0 +DA:21,0 +DA:24,0 +DA:25,0 +DA:26,0 +DA:29,0 +DA:31,0 +DA:32,0 +DA:39,0 +DA:40,0 +DA:42,0 +DA:43,0 +DA:44,0 +DA:45,0 +DA:48,0 +DA:49,0 +LF:17 +LH:0 +end_of_record +SF:lib/features/games/games_api.dart +DA:11,0 +DA:13,0 +DA:14,0 +DA:15,0 +DA:16,0 +DA:20,0 +DA:23,0 +DA:24,0 +DA:25,0 +DA:27,0 +LF:10 +LH:0 +end_of_record +SF:lib/features/games/games_manager.dart +DA:15,0 +DA:17,0 +DA:18,0 +DA:19,0 +DA:20,0 +DA:23,0 +DA:27,0 +DA:28,0 +DA:31,0 +DA:32,0 +DA:35,0 +DA:37,0 +LF:12 +LH:0 +end_of_record +SF:lib/features/packs/active_pack_cubit.dart +DA:15,0 +DA:27,0 +DA:31,0 +DA:34,0 +DA:35,0 +DA:36,0 +DA:40,0 +DA:41,0 +DA:43,0 +DA:46,0 +DA:47,0 +DA:49,0 +DA:52,0 +DA:57,0 +DA:58,0 +DA:59,0 +DA:60,0 +DA:63,0 +DA:65,0 +DA:66,0 +DA:70,0 +DA:72,0 +DA:73,0 +DA:74,0 +DA:76,0 +DA:81,0 +DA:83,0 +DA:85,0 +DA:86,0 +DA:88,0 +DA:91,0 +DA:96,0 +DA:98,0 +DA:99,0 +DA:100,0 +DA:103,0 +DA:104,0 +DA:105,0 +DA:108,0 +DA:113,0 +DA:114,0 +DA:116,0 +DA:117,0 +DA:118,0 +DA:121,0 +DA:126,0 +DA:131,0 +DA:132,0 +DA:134,0 +DA:141,0 +DA:142,0 +DA:143,0 +DA:147,0 +DA:148,0 +DA:149,0 +DA:150,0 +DA:151,0 +DA:153,0 +DA:155,0 +DA:156,0 +DA:157,0 +DA:158,0 +DA:163,0 +DA:164,0 +DA:165,0 +DA:170,0 +DA:171,0 +DA:172,0 +DA:177,0 +DA:178,0 +DA:179,0 +DA:184,0 +DA:185,0 +LF:73 +LH:0 +end_of_record +SF:lib/features/packs/images_holder.dart +DA:11,0 +DA:13,0 +DA:18,0 +DA:20,0 +DA:21,0 +DA:24,0 +DA:25,0 +DA:28,0 +DA:29,0 +DA:30,0 +DA:31,0 +DA:34,0 +DA:35,0 +DA:40,0 +DA:41,0 +DA:45,0 +DA:47,0 +DA:51,0 +DA:55,0 +LF:19 +LH:0 +end_of_record +SF:lib/features/packs/pack_updater.dart +DA:29,0 +DA:37,0 +DA:38,0 +DA:39,0 +DA:42,0 +DA:43,0 +DA:44,0 +DA:45,0 +DA:46,0 +DA:50,0 +DA:51,0 +DA:52,0 +DA:55,0 +DA:56,0 +DA:58,0 +DA:59,0 +DA:62,0 +DA:63,0 +DA:64,0 +DA:67,0 +DA:70,0 +DA:71,0 +DA:72,0 +DA:73,0 +DA:74,0 +DA:75,0 +DA:76,0 +DA:80,0 +DA:82,0 +DA:83,0 +DA:97,0 +DA:98,0 +DA:99,0 +DA:100,0 +DA:101,0 +DA:103,0 +DA:104,0 +DA:105,0 +DA:106,0 +DA:109,0 +DA:112,0 +DA:113,0 +DA:115,0 +DA:126,0 +DA:127,0 +DA:131,0 +DA:132,0 +DA:134,0 +DA:139,0 +DA:147,0 +DA:148,0 +DA:149,0 +DA:150,0 +DA:151,0 +DA:153,0 +DA:156,0 +DA:157,0 +DA:161,0 +DA:165,0 +DA:166,0 +DA:172,0 +DA:176,0 +DA:177,0 +DA:179,0 +DA:180,0 +DA:183,0 +DA:184,0 +DA:185,0 +DA:186,0 +DA:188,0 +DA:189,0 +DA:190,0 +DA:191,0 +DA:193,0 +DA:195,0 +DA:197,0 +DA:199,0 +DA:200,0 +DA:202,0 +DA:206,0 +DA:207,0 +DA:208,0 +DA:211,0 +DA:212,0 +DA:217,0 +DA:218,0 +DA:220,0 +DA:221,0 +DA:222,0 +DA:223,0 +DA:225,0 +DA:226,0 +DA:231,0 +LF:93 +LH:0 +end_of_record +SF:lib/features/packs/packs_holder.dart +DA:9,0 +DA:11,0 +DA:14,0 +DA:16,0 +DA:19,0 +DA:21,0 +DA:22,0 +DA:23,0 +DA:24,0 +DA:31,0 +DA:34,0 +DA:37,0 +DA:38,0 +DA:39,0 +DA:40,0 +DA:43,0 +DA:44,0 +DA:47,0 +DA:50,0 +DA:52,0 +DA:55,0 +DA:56,0 +DA:60,0 +DA:63,0 +DA:65,0 +DA:66,0 +DA:67,0 +DA:68,0 +DA:72,0 +DA:73,0 +DA:76,0 +DA:77,0 +LF:32 +LH:0 +end_of_record +SF:lib/features/packs/preview_packs_poller.dart +DA:12,0 +DA:14,0 +DA:15,0 +DA:16,0 +DA:20,0 +DA:21,0 +DA:23,0 +DA:24,0 +DA:25,0 +DA:27,0 +DA:28,0 +DA:29,0 +DA:30,0 +DA:31,0 +DA:35,0 +LF:15 +LH:0 +end_of_record +SF:lib/features/packs/web_pack_cache_manager.dart +DA:21,0 +DA:23,0 +DA:24,0 +DA:27,0 +DA:29,0 +DA:36,0 +DA:38,0 +DA:39,0 +DA:41,0 +DA:42,0 +DA:43,0 +DA:46,0 +DA:47,0 +DA:55,0 +DA:60,0 +DA:62,0 +DA:63,0 +DA:65,0 +DA:66,0 +DA:68,0 +DA:70,0 +DA:71,0 +DA:72,0 +DA:91,0 +DA:92,0 +DA:96,0 +DA:97,0 +DA:102,0 +DA:104,0 +DA:106,0 +DA:107,0 +DA:108,0 +DA:109,0 +DA:110,0 +DA:111,0 +DA:115,0 +DA:119,0 +DA:120,0 +DA:121,0 +DA:122,0 +DA:124,0 +DA:128,0 +DA:130,0 +DA:136,0 +DA:138,0 +DA:139,0 +DA:142,0 +DA:144,0 +DA:147,0 +DA:154,0 +DA:155,0 +DA:156,0 +DA:157,0 +DA:159,0 +DA:162,0 +DA:166,0 +DA:167,0 +DA:168,0 +DA:169,0 +DA:170,0 +DA:184,0 +DA:187,0 +DA:189,0 +DA:192,0 +DA:195,0 +DA:198,0 +DA:201,0 +DA:204,0 +LF:68 +LH:0 +end_of_record +SF:lib/features/purchase/in_app_purchase.dart +DA:29,0 +DA:61,0 +DA:67,0 +DA:68,0 +DA:72,0 +DA:73,0 +DA:75,0 +DA:76,0 +DA:77,0 +DA:78,0 +DA:85,0 +DA:86,0 +DA:88,0 +DA:90,0 +DA:93,0 +DA:96,0 +DA:97,0 +DA:98,0 +DA:99,0 +DA:100,0 +DA:102,0 +DA:105,0 +DA:109,0 +DA:111,0 +DA:112,0 +DA:113,0 +DA:115,0 +DA:116,0 +DA:117,0 +DA:118,0 +DA:121,0 +DA:124,0 +DA:175,0 +DA:176,0 +DA:177,0 +DA:180,0 +DA:181,0 +DA:182,0 +DA:183,0 +DA:186,0 +DA:187,0 +DA:194,0 +DA:196,0 +DA:198,0 +DA:200,0 +DA:201,0 +DA:202,0 +DA:203,0 +DA:206,0 +DA:207,0 +DA:208,0 +DA:211,0 +DA:212,0 +DA:215,0 +DA:217,0 +DA:218,0 +DA:220,0 +DA:222,0 +DA:225,0 +DA:227,0 +DA:230,0 +DA:236,0 +DA:238,0 +DA:239,0 +DA:240,0 +DA:241,0 +DA:243,0 +DA:244,0 +DA:245,0 +DA:246,0 +DA:254,0 +DA:255,0 +LF:72 +LH:0 +end_of_record +SF:lib/features/purchase/purchase_deeplink_handler.dart +DA:13,0 +DA:15,0 +DA:16,0 +DA:18,0 +DA:20,0 +DA:22,0 +DA:23,0 +DA:24,0 +DA:25,0 +DA:27,0 +DA:30,0 +DA:31,0 +DA:32,0 +DA:33,0 +DA:34,0 +DA:35,0 +DA:36,0 +DA:37,0 +DA:41,0 +DA:42,0 +DA:43,0 +DA:44,0 +DA:45,0 +DA:46,0 +DA:48,0 +DA:49,0 +DA:52,0 +DA:53,0 +DA:54,0 +DA:58,0 +DA:59,0 +DA:60,0 +LF:32 +LH:0 +end_of_record +SF:lib/features/purchase/purchase_manager.dart +DA:11,0 +DA:16,0 +DA:24,0 +DA:25,0 +DA:27,0 +DA:28,0 +DA:30,0 +DA:31,0 +DA:33,0 +DA:34,0 +DA:36,0 +DA:37,0 +DA:39,0 +DA:40,0 +DA:42,0 +DA:46,0 +DA:54,0 +DA:55,0 +DA:62,0 +DA:70,0 +DA:71,0 +DA:77,0 +DA:79,0 +DA:81,0 +DA:82,0 +DA:87,0 +DA:89,0 +DA:91,0 +DA:96,0 +DA:102,0 +DA:103,0 +DA:107,0 +DA:109,0 +DA:111,0 +DA:112,0 +DA:116,0 +DA:118,0 +DA:120,0 +LF:38 +LH:0 +end_of_record +SF:lib/features/subscription/subscription_deeplink_handler.dart +DA:7,0 +DA:8,0 +DA:10,0 +DA:11,0 +LF:4 +LH:0 +end_of_record +SF:lib/features/subscription/subscription_manager.dart +DA:14,0 +DA:19,0 +DA:20,0 +DA:22,0 +DA:26,0 +DA:28,0 +DA:29,0 +DA:30,0 +LF:8 +LH:0 +end_of_record +SF:lib/features/tests/test_manager.dart +DA:30,0 +DA:32,0 +DA:34,0 +DA:35,0 +DA:36,0 +DA:38,0 +DA:40,0 +DA:41,0 +DA:42,0 +DA:43,0 +DA:44,0 +DA:48,0 +DA:50,0 +DA:52,0 +DA:54,0 +DA:55,0 +DA:57,0 +DA:60,0 +DA:62,0 +DA:64,0 +DA:65,0 +DA:69,0 +DA:70,0 +DA:71,0 +DA:75,0 +DA:76,0 +DA:77,0 +DA:80,0 +DA:84,0 +DA:86,0 +DA:88,0 +DA:90,0 +DA:91,0 +DA:92,0 +DA:93,0 +DA:98,0 +DA:99,0 +DA:100,0 +DA:101,0 +DA:106,0 +DA:107,0 +DA:108,0 +DA:109,0 +DA:110,0 +DA:111,0 +DA:112,0 +DA:113,0 +DA:114,0 +DA:116,0 +DA:117,0 +DA:118,0 +DA:125,0 +DA:126,0 +DA:127,0 +DA:128,0 +DA:129,0 +DA:131,0 +DA:132,0 +DA:133,0 +DA:140,0 +DA:141,0 +DA:142,0 +DA:147,0 +DA:148,0 +DA:149,0 +DA:152,0 +DA:153,0 +DA:154,0 +DA:155,0 +DA:156,0 +DA:157,0 +DA:159,0 +DA:160,0 +DA:161,0 +DA:165,0 +DA:166,0 +DA:168,0 +DA:169,0 +DA:170,0 +DA:171,0 +DA:173,0 +DA:180,0 +DA:182,0 +LF:83 +LH:0 +end_of_record +SF:lib/features/packs/pack_manager.dart +DA:17,0 +DA:23,0 +DA:24,0 +DA:25,0 +DA:28,0 +DA:29,0 +DA:30,0 +DA:31,0 +DA:34,0 +DA:35,0 +DA:36,0 +DA:37,0 +DA:38,0 +LF:13 +LH:0 +end_of_record +SF:lib/features/packs/preview_pack_holder.dart +DA:13,0 +DA:15,0 +DA:16,0 +DA:17,0 +DA:21,0 +DA:22,0 +DA:23,0 +DA:24,0 +DA:27,0 +DA:28,0 +DA:30,0 +DA:31,0 +DA:33,0 +DA:36,0 +DA:39,0 +DA:40,0 +DA:41,0 +DA:42,0 +DA:44,0 +DA:45,0 +DA:47,0 +DA:50,0 +DA:51,0 +DA:54,0 +DA:55,0 +DA:57,0 +DA:59,0 +DA:62,0 +DA:64,0 +DA:70,0 +LF:30 +LH:0 +end_of_record +SF:lib/features/tests/tests_cache.dart +DA:7,0 +DA:8,0 +DA:9,0 +DA:12,0 +DA:13,0 +DA:14,0 +DA:16,0 +LF:7 +LH:0 +end_of_record +SF:lib/features/yandex_ads/ads_deeplink_handler.dart +DA:15,0 +DA:17,0 +DA:18,0 +DA:20,0 +DA:22,0 +DA:24,0 +DA:25,0 +DA:27,0 +DA:30,0 +DA:31,0 +DA:32,0 +DA:34,0 +DA:36,0 +DA:47,0 +DA:50,0 +LF:15 +LH:0 +end_of_record +SF:lib/features/yandex_ads/yandex_rewarded_ads.dart +DA:16,0 +DA:27,0 +DA:28,0 +DA:29,0 +DA:30,0 +DA:32,0 +DA:33,0 +DA:34,0 +DA:35,0 +DA:37,0 +DA:38,0 +DA:40,0 +DA:41,0 +DA:42,0 +DA:43,0 +DA:47,0 +DA:48,0 +DA:50,0 +DA:51,0 +DA:52,0 +DA:53,0 +DA:55,0 +DA:58,0 +DA:59,0 +DA:60,0 +DA:61,0 +DA:63,0 +DA:64,0 +DA:65,0 +DA:67,0 +DA:76,0 +DA:78,0 +DA:79,0 +DA:81,0 +DA:82,0 +DA:83,0 +DA:88,0 +DA:92,0 +DA:93,0 +DA:94,0 +DA:95,0 +DA:97,0 +LF:42 +LH:0 +end_of_record +SF:lib/managers/user_manager.dart +DA:28,0 +DA:30,0 +DA:32,0 +DA:34,0 +DA:36,0 +DA:38,0 +DA:42,0 +DA:45,0 +DA:46,0 +DA:49,0 +DA:54,0 +DA:55,0 +DA:57,0 +DA:58,0 +DA:60,0 +DA:65,0 +DA:68,0 +DA:72,0 +DA:73,0 +DA:75,0 +DA:79,0 +DA:80,0 +DA:81,0 +DA:82,0 +DA:83,0 +DA:86,0 +DA:92,0 +DA:98,0 +DA:99,0 +DA:102,0 +DA:103,0 +DA:104,0 +DA:107,0 +DA:108,0 +DA:111,0 +DA:112,0 +DA:115,0 +DA:116,0 +DA:120,0 +DA:124,0 +DA:128,0 +DA:129,0 +DA:131,0 +DA:133,0 +DA:134,0 +DA:137,0 +DA:138,0 +DA:151,0 +DA:152,0 +DA:153,0 +DA:154,0 +DA:156,0 +DA:157,0 +DA:164,0 +DA:165,0 +DA:168,0 +DA:171,0 +DA:173,0 +DA:176,0 +DA:177,0 +DA:178,0 +DA:179,0 +DA:180,0 +DA:181,0 +DA:182,0 +DA:185,0 +DA:186,0 +DA:189,0 +DA:190,0 +DA:191,0 +DA:192,0 +DA:194,0 +DA:195,0 +DA:197,0 +DA:204,0 +DA:208,0 +DA:209,0 +DA:210,0 +DA:214,0 +DA:215,0 +DA:216,0 +DA:218,0 +DA:219,0 +DA:223,0 +DA:226,0 +DA:227,0 +DA:228,0 +DA:229,0 +DA:230,0 +DA:232,0 +DA:236,0 +DA:237,0 +DA:238,0 +DA:239,0 +DA:240,0 +DA:248,0 +DA:249,0 +DA:250,0 +LF:98 +LH:0 +end_of_record +SF:lib/domain/router/app_router.dart +DA:13,1 +DA:15,1 +DA:16,1 +DA:17,1 +DA:19,1 +DA:21,1 +DA:22,1 +DA:23,1 +DA:27,1 +DA:28,1 +DA:32,1 +DA:33,1 +DA:37,1 +DA:38,1 +DA:42,1 +DA:43,1 +DA:49,1 +DA:50,1 +DA:51,1 +DA:52,1 +DA:55,1 +DA:56,1 +DA:59,1 +DA:60,1 +DA:63,1 +DA:64,1 +DA:72,0 +DA:73,0 +DA:74,0 +DA:75,0 +DA:79,0 +DA:80,0 +DA:81,0 +DA:82,0 +DA:86,0 +DA:87,0 +DA:88,0 +DA:90,0 +DA:94,0 +DA:95,0 +DA:96,0 +DA:97,0 +DA:98,0 +DA:100,0 +LF:44 +LH:26 +end_of_record +SF:lib/features/chat/chat_page.dart +DA:14,0 +DA:16,0 +DA:17,0 +DA:18,0 +DA:19,0 +DA:20,0 +DA:22,0 +DA:23,0 +LF:8 +LH:0 +end_of_record +SF:lib/features/games/games_page.dart +DA:17,0 +DA:19,0 +DA:20,0 +DA:21,0 +DA:22,0 +DA:23,0 +DA:24,0 +DA:26,0 +DA:27,0 +DA:28,0 +DA:29,0 +DA:31,0 +DA:32,0 +DA:33,0 +DA:34,0 +DA:35,0 +DA:36,0 +DA:37,0 +DA:38,0 +DA:46,0 +DA:51,0 +DA:52,0 +DA:53,0 +DA:54,0 +DA:55,0 +DA:56,0 +LF:26 +LH:0 +end_of_record +SF:lib/features/games/payloads/integration_example.dart +DA:11,0 +DA:12,0 +DA:15,0 +DA:17,0 +DA:20,0 +DA:25,0 +DA:30,0 +DA:32,0 +DA:33,0 +DA:34,0 +DA:35,0 +DA:36,0 +DA:37,0 +DA:42,0 +DA:47,0 +DA:53,0 +DA:54,0 +DA:62,0 +DA:76,0 +DA:80,0 +DA:89,0 +DA:95,0 +DA:96,0 +DA:103,0 +DA:105,0 +DA:106,0 +DA:109,0 +DA:112,0 +DA:115,0 +DA:116,0 +DA:117,0 +DA:121,0 +DA:122,0 +DA:123,0 +DA:124,0 +DA:128,0 +DA:130,0 +DA:131,0 +DA:132,0 +DA:133,0 +DA:134,0 +DA:135,0 +DA:136,0 +DA:138,0 +DA:145,0 +DA:146,0 +DA:147,0 +DA:148,0 +DA:153,0 +DA:155,0 +DA:156,0 +DA:157,0 +DA:167,0 +DA:173,0 +DA:175,0 +DA:176,0 +DA:177,0 +LF:57 +LH:0 +end_of_record +SF:lib/features/games/payloads_demo_page.dart +DA:8,1 +DA:10,0 +DA:11,0 +DA:18,0 +DA:20,0 +DA:21,0 +DA:24,0 +DA:27,0 +DA:28,0 +DA:29,0 +DA:34,0 +DA:35,0 +DA:36,0 +DA:37,0 +DA:38,0 +DA:43,0 +DA:45,0 +DA:46,0 +DA:48,0 +DA:50,0 +DA:51,0 +DA:53,0 +DA:55,0 +DA:56,0 +DA:63,0 +DA:65,0 +DA:67,0 +DA:73,0 +DA:74,0 +DA:75,0 +DA:76,0 +DA:77,0 +DA:82,0 +DA:83,0 +DA:84,0 +DA:91,0 +DA:92,0 +DA:93,0 +DA:94,0 +DA:95,0 +DA:100,0 +DA:101,0 +DA:102,0 +DA:113,0 +DA:116,0 +DA:117,0 +DA:118,0 +DA:120,0 +DA:122,0 +DA:128,0 +DA:129,0 +DA:130,0 +DA:131,0 +DA:132,0 +DA:134,0 +DA:135,0 +DA:150,0 +DA:152,0 +DA:153,0 +DA:154,0 +DA:156,0 +DA:160,0 +DA:162,0 +DA:163,0 +DA:171,0 +DA:181,0 +DA:182,0 +DA:184,0 +DA:188,0 +DA:190,0 +DA:195,0 +DA:198,0 +DA:199,0 +DA:201,0 +DA:205,0 +DA:207,0 +DA:208,0 +DA:210,0 +DA:211,0 +DA:213,0 +DA:217,0 +DA:219,0 +DA:220,0 +LF:83 +LH:1 +end_of_record +SF:lib/features/tests/test_page.dart +DA:21,0 +DA:22,0 +DA:24,0 +DA:28,0 +DA:33,0 +DA:35,0 +DA:36,0 +DA:37,0 +DA:38,0 +DA:41,0 +DA:43,0 +DA:44,0 +DA:47,0 +DA:48,0 +DA:51,0 +DA:52,0 +DA:54,0 +DA:55,0 +DA:56,0 +DA:57,0 +DA:58,0 +DA:60,0 +DA:63,0 +DA:64,0 +DA:65,0 +DA:66,0 +DA:69,0 +DA:76,0 +DA:79,0 +DA:80,0 +DA:81,0 +DA:82,0 +DA:83,0 +DA:84,0 +DA:85,0 +DA:86,0 +DA:91,0 +DA:93,0 +DA:94,0 +DA:95,0 +DA:96,0 +DA:97,0 +DA:98,0 +DA:99,0 +DA:100,0 +DA:101,0 +DA:106,0 +DA:107,0 +DA:110,0 +DA:111,0 +DA:112,0 +DA:113,0 +DA:117,0 +DA:118,0 +DA:119,0 +DA:120,0 +DA:121,0 +DA:122,0 +DA:123,0 +DA:124,0 +DA:125,0 +DA:126,0 +DA:129,0 +DA:130,0 +DA:133,0 +DA:134,0 +DA:135,0 +DA:136,0 +DA:138,0 +DA:139,0 +DA:140,0 +DA:141,0 +DA:144,0 +DA:145,0 +DA:146,0 +DA:147,0 +DA:148,0 +DA:153,0 +DA:154,0 +DA:155,0 +DA:157,0 +DA:159,0 +DA:160,0 +DA:162,0 +DA:164,0 +DA:165,0 +DA:167,0 +DA:168,0 +DA:182,0 +DA:183,0 +DA:184,0 +DA:185,0 +DA:190,0 +DA:192,0 +DA:195,0 +DA:196,0 +DA:197,0 +DA:200,0 +DA:202,0 +LF:99 +LH:0 +end_of_record +SF:lib/pages/auth_page.dart +DA:16,0 +DA:18,0 +DA:19,0 +DA:20,0 +DA:21,0 +DA:22,0 +DA:23,0 +DA:25,0 +DA:27,0 +DA:28,0 +DA:34,0 +DA:35,0 +DA:37,0 +DA:38,0 +DA:39,0 +DA:45,0 +DA:46,0 +DA:47,0 +DA:49,0 +DA:53,0 +DA:55,0 +DA:56,0 +DA:57,0 +DA:58,0 +DA:59,0 +DA:61,0 +DA:62,0 +DA:63,0 +DA:65,0 +DA:66,0 +DA:68,0 +DA:75,0 +DA:77,0 +DA:78,0 +DA:79,0 +DA:80,0 +DA:81,0 +DA:83,0 +DA:84,0 +DA:85,0 +DA:87,0 +DA:88,0 +DA:90,0 +DA:95,0 +DA:97,0 +DA:98,0 +DA:99,0 +DA:100,0 +DA:101,0 +DA:112,0 +DA:114,0 +DA:115,0 +DA:118,0 +DA:119,0 +DA:121,0 +DA:122,0 +LF:56 +LH:0 +end_of_record +SF:lib/pages/home_page.dart +DA:9,0 +DA:11,0 +DA:12,0 +DA:13,0 +DA:14,0 +DA:19,0 +LF:6 +LH:0 +end_of_record +SF:lib/pages/profile_page.dart +DA:22,0 +DA:24,0 +DA:25,0 +DA:26,0 +DA:27,0 +DA:28,0 +DA:29,0 +DA:30,0 +DA:31,0 +DA:32,0 +DA:34,0 +DA:35,0 +DA:36,0 +DA:37,0 +DA:38,0 +DA:39,0 +DA:45,0 +DA:50,0 +DA:52,0 +DA:53,0 +DA:54,0 +DA:56,0 +DA:59,0 +DA:61,0 +DA:64,0 +DA:66,0 +DA:68,0 +DA:69,0 +DA:70,0 +DA:71,0 +DA:78,0 +DA:80,0 +DA:83,0 +DA:85,0 +DA:86,0 +DA:89,0 +DA:91,0 +DA:93,0 +DA:94,0 +DA:95,0 +DA:97,0 +DA:98,0 +DA:99,0 +DA:101,0 +DA:102,0 +DA:104,0 +DA:105,0 +DA:108,0 +DA:110,0 +DA:111,0 +DA:114,0 +DA:116,0 +DA:118,0 +DA:119,0 +DA:132,0 +DA:133,0 +DA:134,0 +DA:135,0 +DA:138,0 +LF:59 +LH:0 +end_of_record +SF:lib/pages/settgins_page.dart +DA:27,0 +DA:28,0 +DA:29,0 +DA:30,0 +DA:31,0 +DA:35,0 +DA:37,0 +DA:38,0 +DA:39,0 +DA:40,0 +DA:41,0 +DA:42,0 +DA:47,0 +DA:48,0 +DA:50,0 +DA:52,0 +DA:54,0 +DA:55,0 +DA:56,0 +DA:57,0 +DA:59,0 +DA:60,0 +DA:61,0 +DA:62,0 +DA:63,0 +DA:64,0 +DA:66,0 +DA:73,0 +DA:75,0 +DA:76,0 +DA:81,0 +DA:83,0 +DA:88,0 +DA:90,0 +DA:91,0 +DA:96,0 +DA:98,0 +DA:100,0 +DA:101,0 +DA:106,0 +DA:108,0 +DA:110,0 +DA:111,0 +DA:116,0 +DA:118,0 +DA:120,0 +DA:122,0 +DA:123,0 +DA:126,0 +DA:129,0 +DA:130,0 +DA:132,0 +DA:133,0 +DA:138,0 +DA:141,0 +DA:146,0 +DA:147,0 +DA:149,0 +DA:151,0 +DA:154,0 +DA:155,0 +DA:156,0 +DA:157,0 +DA:159,0 +DA:160,0 +DA:161,0 +DA:179,0 +DA:180,0 +DA:182,0 +DA:183,0 +DA:184,0 +DA:187,0 +DA:189,0 +DA:190,0 +DA:191,0 +DA:194,0 +DA:196,0 +DA:197,0 +DA:198,0 +DA:201,0 +DA:203,0 +DA:204,0 +DA:205,0 +DA:208,0 +DA:210,0 +DA:211,0 +DA:212,0 +DA:215,0 +DA:217,0 +DA:218,0 +DA:219,0 +DA:222,0 +DA:223,0 +DA:224,0 +DA:230,0 +DA:234,0 +DA:235,0 +DA:236,0 +DA:237,0 +DA:240,0 +LF:100 +LH:0 +end_of_record +SF:lib/pages/vocabulary_page.dart +DA:7,1 +DA:9,0 +DA:11,0 +LF:3 +LH:1 +end_of_record +SF:lib/widgets/card_game/card_game_page.dart +DA:25,0 +DA:34,0 +DA:35,0 +DA:46,0 +DA:47,0 +DA:49,0 +DA:50,0 +DA:55,0 +DA:59,0 +DA:60,0 +DA:61,0 +DA:62,0 +DA:65,0 +DA:66,0 +DA:68,0 +DA:73,0 +DA:80,0 +DA:81,0 +DA:82,0 +DA:83,0 +DA:87,0 +DA:88,0 +DA:89,0 +DA:90,0 +DA:91,0 +DA:92,0 +DA:93,0 +DA:94,0 +DA:95,0 +DA:97,0 +DA:98,0 +DA:99,0 +DA:100,0 +DA:101,0 +DA:102,0 +DA:103,0 +DA:104,0 +DA:107,0 +DA:108,0 +DA:109,0 +DA:110,0 +DA:111,0 +DA:112,0 +DA:113,0 +DA:116,0 +DA:117,0 +DA:118,0 +DA:119,0 +DA:121,0 +DA:122,0 +DA:125,0 +DA:126,0 +DA:127,0 +DA:128,0 +DA:133,0 +DA:134,0 +DA:135,0 +DA:136,0 +DA:137,0 +DA:140,0 +DA:141,0 +DA:142,0 +DA:143,0 +DA:144,0 +DA:145,0 +DA:146,0 +DA:147,0 +DA:148,0 +DA:149,0 +DA:151,0 +DA:152,0 +DA:154,0 +DA:156,0 +DA:157,0 +DA:159,0 +DA:171,0 +DA:172,0 +DA:174,0 +DA:175,0 +DA:177,0 +DA:178,0 +DA:179,0 +DA:180,0 +DA:181,0 +DA:182,0 +DA:183,0 +DA:184,0 +DA:185,0 +DA:186,0 +DA:187,0 +DA:189,0 +DA:190,0 +DA:191,0 +DA:193,0 +DA:194,0 +DA:195,0 +DA:196,0 +DA:197,0 +DA:199,0 +DA:201,0 +DA:203,0 +DA:204,0 +DA:205,0 +DA:207,0 +DA:208,0 +DA:209,0 +DA:210,0 +DA:211,0 +DA:214,0 +DA:216,0 +DA:217,0 +DA:218,0 +DA:219,0 +DA:220,0 +DA:224,0 +DA:225,0 +DA:227,0 +DA:228,0 +DA:229,0 +DA:238,0 +DA:239,0 +DA:241,0 +DA:243,0 +DA:244,0 +DA:248,0 +DA:249,0 +DA:253,0 +DA:255,0 +DA:256,0 +DA:257,0 +DA:258,0 +DA:259,0 +DA:261,0 +DA:263,0 +DA:264,0 +DA:266,0 +DA:267,0 +DA:289,0 +DA:291,0 +DA:292,0 +DA:293,0 +DA:294,0 +DA:296,0 +DA:297,0 +DA:298,0 +DA:301,0 +DA:302,0 +DA:303,0 +DA:304,0 +DA:307,0 +DA:310,0 +DA:312,0 +DA:313,0 +DA:314,0 +DA:316,0 +DA:323,0 +DA:325,0 +DA:326,0 +DA:328,0 +LF:159 +LH:0 +end_of_record +SF:lib/widgets/card_pack/card_pack_page.dart +DA:23,0 +DA:25,0 +DA:26,0 +DA:30,0 +DA:32,0 +DA:33,0 +DA:34,0 +DA:35,0 +DA:36,0 +DA:37,0 +DA:39,0 +DA:46,0 +DA:48,0 +DA:50,0 +DA:51,0 +DA:53,0 +DA:55,0 +DA:56,0 +DA:58,0 +DA:59,0 +DA:60,0 +DA:62,0 +DA:63,0 +DA:64,0 +DA:65,0 +DA:68,0 +DA:69,0 +DA:70,0 +DA:74,0 +DA:75,0 +DA:76,0 +DA:77,0 +DA:78,0 +DA:79,0 +DA:88,0 +DA:90,0 +DA:91,0 +LF:37 +LH:0 +end_of_record +SF:lib/features/analytics/analytics.dart +DA:6,0 +DA:7,0 +DA:9,0 +DA:10,0 +DA:13,0 +DA:14,0 +DA:17,0 +DA:18,0 +DA:20,0 +DA:21,0 +DA:22,0 +DA:24,0 +DA:27,0 +DA:28,0 +DA:31,0 +DA:32,0 +DA:33,0 +DA:36,0 +DA:37,0 +DA:40,0 +DA:41,0 +DA:42,0 +DA:45,0 +DA:46,0 +DA:49,0 +DA:50,0 +DA:51,0 +DA:54,0 +DA:55,0 +DA:58,0 +DA:59,0 +DA:60,0 +DA:63,0 +DA:64,0 +DA:67,0 +DA:68,0 +DA:69,0 +DA:70,0 +DA:71,0 +DA:74,0 +DA:75,0 +DA:78,0 +DA:79,0 +DA:80,0 +DA:81,0 +DA:82,0 +DA:83,0 +DA:86,0 +DA:87,0 +DA:89,0 +DA:90,0 +DA:91,0 +DA:92,0 +DA:93,0 +DA:94,0 +DA:95,0 +DA:98,0 +DA:103,0 +DA:105,0 +DA:106,0 +DA:107,0 +DA:108,0 +DA:109,0 +DA:112,0 +DA:120,0 +DA:122,0 +DA:123,0 +DA:124,0 +DA:125,0 +DA:126,0 +DA:127,0 +DA:128,0 +DA:129,0 +DA:130,0 +DA:133,0 +DA:139,0 +DA:141,0 +DA:142,0 +DA:143,0 +DA:144,0 +DA:145,0 +DA:146,0 +DA:147,0 +DA:148,0 +DA:152,0 +DA:158,0 +DA:160,0 +DA:161,0 +DA:162,0 +DA:163,0 +DA:164,0 +DA:165,0 +DA:166,0 +DA:167,0 +DA:170,0 +DA:177,0 +DA:179,0 +DA:180,0 +DA:181,0 +DA:182,0 +DA:183,0 +DA:184,0 +DA:185,0 +DA:186,0 +DA:190,0 +DA:191,0 +DA:194,0 +DA:195,0 +DA:196,0 +DA:197,0 +DA:199,0 +DA:202,0 +DA:203,0 +DA:206,0 +DA:207,0 +DA:208,0 +DA:209,0 +DA:210,0 +DA:211,0 +DA:214,0 +DA:220,0 +DA:224,0 +DA:227,0 +DA:232,0 +DA:234,0 +DA:235,0 +DA:236,0 +DA:237,0 +DA:238,0 +DA:244,0 +DA:245,0 +DA:246,0 +LF:132 +LH:0 +end_of_record +SF:lib/features/card_flipper/flip_card.dart +DA:41,0 +DA:53,0 +DA:55,0 +DA:56,0 +DA:65,0 +DA:67,0 +DA:68,0 +DA:69,0 +DA:70,0 +DA:71,0 +DA:72,0 +DA:73,0 +DA:75,0 +DA:76,0 +DA:77,0 +DA:78,0 +DA:79,0 +DA:80,0 +DA:81,0 +DA:86,0 +DA:88,0 +DA:89,0 +DA:90,0 +DA:91,0 +DA:94,0 +DA:95,0 +DA:96,0 +DA:97,0 +DA:99,0 +DA:100,0 +DA:103,0 +DA:105,0 +DA:106,0 +DA:109,0 +DA:110,0 +DA:111,0 +DA:112,0 +DA:113,0 +DA:114,0 +DA:116,0 +DA:117,0 +DA:118,0 +DA:119,0 +DA:122,0 +DA:124,0 +DA:128,0 +DA:129,0 +DA:132,0 +DA:137,0 +DA:140,0 +LF:50 +LH:0 +end_of_record +SF:lib/features/card_flipper/flip_card_controllers.dart +DA:11,0 +DA:14,0 +DA:15,0 +DA:16,0 +DA:19,0 +DA:21,0 +DA:22,0 +LF:7 +LH:0 +end_of_record +SF:lib/features/games/game_button.dart +DA:19,0 +DA:24,0 +DA:26,0 +DA:28,0 +DA:29,0 +DA:30,0 +DA:31,0 +DA:32,0 +DA:33,0 +DA:34,0 +DA:35,0 +DA:37,0 +DA:38,0 +DA:39,0 +DA:40,0 +DA:41,0 +DA:42,0 +DA:45,0 +DA:48,0 +DA:50,0 +DA:51,0 +DA:52,0 +DA:53,0 +DA:55,0 +DA:56,0 +DA:57,0 +DA:58,0 +DA:60,0 +DA:62,0 +DA:63,0 +DA:65,0 +DA:66,0 +DA:68,0 +DA:69,0 +DA:71,0 +DA:73,0 +DA:74,0 +DA:76,0 +DA:77,0 +DA:78,0 +DA:80,0 +DA:85,0 +DA:86,0 +DA:88,0 +DA:89,0 +DA:90,0 +DA:92,0 +DA:96,0 +DA:97,0 +DA:98,0 +DA:100,0 +DA:116,0 +DA:118,0 +DA:121,0 +DA:123,0 +DA:124,0 +DA:125,0 +DA:127,0 +DA:128,0 +DA:129,0 +DA:130,0 +DA:131,0 +DA:132,0 +DA:133,0 +DA:137,0 +DA:141,0 +DA:144,0 +DA:150,0 +DA:152,0 +DA:153,0 +DA:154,0 +DA:155,0 +DA:156,0 +DA:157,0 +DA:160,0 +DA:163,0 +DA:164,0 +LF:77 +LH:0 +end_of_record +SF:lib/features/games/game_assets_loader.dart +DA:13,0 +DA:15,0 +DA:17,0 +DA:20,0 +DA:22,0 +LF:5 +LH:0 +end_of_record +SF:lib/managers/audio_player.dart +DA:6,0 +DA:7,0 +DA:9,0 +DA:10,0 +DA:11,0 +DA:13,0 +DA:14,0 +DA:15,0 +DA:17,0 +DA:21,0 +DA:23,0 +DA:26,0 +DA:28,0 +DA:29,0 +LF:14 +LH:0 +end_of_record +SF:lib/features/games/games_bloc.dart +DA:9,0 +DA:11,0 +DA:12,0 +DA:14,0 +DA:15,0 +DA:16,0 +DA:18,0 +DA:22,0 +DA:23,0 +DA:24,0 +DA:25,0 +DA:37,0 +DA:44,0 +LF:13 +LH:0 +end_of_record +SF:lib/widgets/choose_cards.dart +DA:18,0 +DA:20,0 +DA:21,0 +DA:27,0 +DA:29,0 +DA:30,0 +DA:31,0 +DA:32,0 +DA:34,0 +DA:37,0 +DA:39,0 +DA:40,0 +DA:42,0 +DA:45,0 +DA:48,0 +DA:50,0 +DA:51,0 +DA:52,0 +DA:57,0 +DA:58,0 +DA:60,0 +DA:61,0 +DA:62,0 +DA:63,0 +DA:64,0 +DA:65,0 +DA:66,0 +DA:67,0 +DA:71,0 +DA:72,0 +DA:73,0 +DA:75,0 +DA:77,0 +DA:78,0 +DA:82,0 +DA:83,0 +DA:85,0 +DA:88,0 +DA:93,0 +DA:111,0 +DA:113,0 +DA:115,0 +DA:117,0 +DA:118,0 +DA:121,0 +DA:122,0 +DA:123,0 +DA:125,0 +DA:130,0 +DA:131,0 +DA:134,0 +DA:135,0 +DA:136,0 +DA:138,0 +LF:54 +LH:0 +end_of_record +SF:lib/utils/archive_decoder.dart +DA:6,0 +DA:8,0 +DA:13,0 +DA:14,0 +DA:15,0 +DA:23,0 +DA:24,0 +DA:25,0 +DA:26,0 +DA:27,0 +DA:29,0 +DA:30,0 +DA:31,0 +DA:34,0 +DA:35,0 +DA:36,0 +DA:37,0 +DA:39,0 +DA:49,0 +LF:19 +LH:0 +end_of_record +SF:lib/features/games/payloads/bridge_webview.dart +DA:12,0 +DA:20,0 +DA:21,0 +DA:25,0 +DA:27,0 +DA:29,0 +DA:32,0 +DA:34,0 +DA:35,0 +DA:36,0 +DA:37,0 +DA:38,0 +DA:41,0 +DA:42,0 +DA:43,0 +DA:44,0 +DA:47,0 +DA:48,0 +DA:49,0 +DA:50,0 +DA:51,0 +DA:52,0 +DA:53,0 +DA:55,0 +DA:56,0 +DA:58,0 +DA:60,0 +DA:61,0 +DA:65,0 +DA:67,0 +LF:30 +LH:0 +end_of_record +SF:lib/features/games/payloads/bridge_webview_controller.dart +DA:14,0 +DA:15,0 +DA:18,0 +DA:19,0 +DA:20,0 +DA:21,0 +DA:24,0 +DA:26,0 +DA:29,0 +DA:30,0 +DA:33,0 +DA:36,0 +DA:37,0 +DA:38,0 +DA:40,0 +DA:45,0 +DA:46,0 +DA:47,0 +DA:51,0 +DA:54,0 +DA:56,0 +DA:58,0 +DA:61,0 +DA:65,0 +DA:66,0 +DA:67,0 +DA:72,0 +DA:73,0 +DA:74,0 +DA:76,0 +DA:79,0 +DA:80,0 +DA:81,0 +DA:82,0 +DA:89,0 +DA:90,0 +DA:91,0 +DA:96,0 +DA:97,0 +DA:98,0 +DA:102,0 +DA:103,0 +DA:107,0 +DA:111,0 +DA:113,0 +DA:114,0 +DA:115,0 +DA:116,0 +DA:117,0 +LF:49 +LH:0 +end_of_record +SF:lib/features/games/payloads/handlers/payload_handlers_manager.dart +DA:9,0 +DA:11,0 +DA:12,0 +DA:15,0 +DA:19,0 +DA:22,0 +DA:23,0 +DA:25,0 +DA:30,0 +DA:37,0 +DA:39,0 +DA:41,0 +DA:47,0 +DA:49,0 +DA:50,0 +DA:51,0 +DA:59,0 +DA:61,0 +DA:64,0 +DA:68,0 +DA:69,0 +DA:76,0 +DA:77,0 +DA:78,0 +DA:79,0 +DA:80,0 +DA:81,0 +DA:82,0 +DA:83,0 +DA:84,0 +DA:88,0 +DA:89,0 +DA:90,0 +DA:91,0 +DA:95,0 +DA:100,0 +DA:101,0 +DA:103,0 +LF:38 +LH:0 +end_of_record +SF:lib/features/games/payloads/registration.dart +DA:5,0 +DA:7,0 +LF:2 +LH:0 +end_of_record +SF:lib/features/games/payloads/handlers/user_cards_handler.dart +DA:7,0 +DA:9,0 +DA:12,0 +DA:14,0 +DA:19,0 +DA:20,0 +DA:27,0 +DA:32,0 +DA:33,0 +DA:41,0 +LF:10 +LH:0 +end_of_record +SF:lib/features/packs/active_pack_state.g.dart +DA:36,0 +DA:40,0 +DA:43,0 +DA:45,0 +DA:46,0 +DA:48,0 +DA:49,0 +DA:51,0 +DA:53,0 +DA:55,0 +DA:69,0 +DA:70,0 +DA:71,0 +DA:74,0 +DA:75,0 +DA:78,0 +DA:79,0 +DA:83,0 +DA:84,0 +DA:94,0 +DA:95,0 +LF:21 +LH:0 +end_of_record +SF:lib/features/packs/active_pack_state.dart +DA:14,1 +DA:22,0 +DA:27,0 +DA:28,0 +DA:36,0 +DA:37,0 +DA:45,0 +DA:46,0 +LF:8 +LH:1 +end_of_record +SF:lib/flags.dart +DA:12,1 +DA:14,0 +DA:15,0 +DA:18,0 +DA:20,0 +DA:21,0 +DA:22,0 +DA:23,0 +DA:25,0 +LF:9 +LH:1 +end_of_record +SF:lib/managers/user_state_holder.dart +DA:14,0 +DA:16,0 +DA:18,0 +DA:20,0 +DA:21,0 +DA:22,0 +DA:24,0 +DA:25,0 +DA:28,0 +DA:29,0 +DA:30,0 +DA:31,0 +DA:34,0 +DA:36,0 +DA:37,0 +DA:39,0 +LF:16 +LH:0 +end_of_record +SF:lib/features/subscription/subscription_page.dart +DA:13,0 +DA:15,0 +DA:17,0 +DA:18,0 +DA:19,0 +DA:20,0 +DA:21,0 +DA:22,0 +DA:25,0 +DA:26,0 +DA:27,0 +DA:31,0 +DA:41,0 +DA:43,0 +DA:45,0 +DA:46,0 +DA:47,0 +DA:48,0 +DA:49,0 +DA:50,0 +DA:52,0 +DA:53,0 +DA:54,0 +DA:55,0 +DA:56,0 +DA:57,0 +DA:58,0 +DA:59,0 +DA:60,0 +DA:62,0 +DA:63,0 +DA:64,0 +DA:65,0 +DA:66,0 +DA:68,0 +DA:70,0 +DA:71,0 +DA:72,0 +DA:73,0 +DA:74,0 +DA:80,0 +DA:81,0 +DA:82,0 +DA:83,0 +DA:85,0 +DA:86,0 +DA:87,0 +DA:88,0 +DA:90,0 +DA:91,0 +DA:92,0 +DA:93,0 +DA:102,0 +DA:103,0 +DA:106,0 +DA:107,0 +DA:108,0 +DA:109,0 +DA:110,0 +DA:111,0 +DA:112,0 +DA:113,0 +DA:115,0 +DA:116,0 +DA:117,0 +DA:118,0 +DA:123,0 +DA:127,0 +DA:128,0 +DA:129,0 +DA:130,0 +DA:131,0 +DA:132,0 +DA:133,0 +DA:140,0 +DA:141,0 +DA:142,0 +DA:143,0 +DA:144,0 +DA:145,0 +DA:146,0 +DA:157,0 +DA:158,0 +DA:159,0 +DA:162,0 +DA:163,0 +DA:164,0 +DA:165,0 +DA:166,0 +DA:167,0 +DA:169,0 +DA:170,0 +DA:171,0 +DA:175,0 +DA:177,0 +DA:179,0 +DA:185,0 +LF:97 +LH:0 +end_of_record +SF:lib/features/tests/progress_widget.dart +DA:17,0 +DA:18,0 +DA:20,0 +DA:21,0 +DA:22,0 +DA:24,0 +DA:30,0 +DA:51,0 +DA:53,0 +DA:55,0 +DA:57,0 +DA:58,0 +DA:59,0 +DA:60,0 +DA:62,0 +DA:63,0 +DA:64,0 +DA:65,0 +DA:66,0 +DA:68,0 +DA:70,0 +DA:72,0 +DA:73,0 +DA:75,0 +DA:76,0 +DA:77,0 +DA:87,0 +DA:88,0 +DA:89,0 +DA:90,0 +DA:91,0 +DA:92,0 +DA:93,0 +DA:94,0 +DA:95,0 +DA:96,0 +DA:97,0 +DA:99,0 +DA:100,0 +DA:101,0 +DA:102,0 +DA:103,0 +DA:105,0 +DA:107,0 +DA:108,0 +DA:109,0 +DA:110,0 +DA:111,0 +DA:112,0 +DA:113,0 +DA:114,0 +DA:126,0 +DA:127,0 +DA:128,0 +DA:129,0 +DA:131,0 +DA:132,0 +DA:133,0 +DA:136,0 +DA:137,0 +DA:138,0 +DA:139,0 +DA:141,0 +DA:142,0 +DA:143,0 +DA:146,0 +DA:147,0 +DA:148,0 +DA:149,0 +DA:155,0 +DA:156,0 +DA:157,0 +DA:158,0 +DA:159,0 +DA:160,0 +DA:166,0 +DA:172,0 +DA:174,0 +DA:176,0 +DA:177,0 +DA:178,0 +DA:179,0 +DA:180,0 +DA:182,0 +DA:183,0 +DA:184,0 +DA:186,0 +DA:188,0 +DA:191,0 +DA:192,0 +DA:194,0 +DA:195,0 +DA:196,0 +DA:198,0 +DA:199,0 +DA:201,0 +DA:203,0 +LF:97 +LH:0 +end_of_record +SF:lib/features/tests/question_states/input_buttons_test_state.dart +DA:19,0 +LF:1 +LH:0 +end_of_record +SF:lib/features/tests/question_states/input_buttons_test_state.g.dart +DA:47,0 +DA:51,0 +DA:52,0 +DA:54,0 +DA:55,0 +DA:57,0 +DA:58,0 +DA:60,0 +DA:62,0 +DA:64,0 +DA:65,0 +DA:67,0 +DA:69,0 +DA:71,0 +DA:72,0 +DA:74,0 +DA:76,0 +DA:78,0 +DA:96,0 +DA:97,0 +DA:98,0 +DA:101,0 +DA:102,0 +DA:105,0 +DA:106,0 +DA:109,0 +DA:110,0 +DA:113,0 +DA:114,0 +DA:118,0 +DA:119,0 +DA:122,0 +DA:123,0 +DA:126,0 +DA:127,0 +DA:137,0 +DA:138,0 +DA:145,0 +DA:147,0 +DA:148,0 +DA:149,0 +DA:150,0 +DA:151,0 +DA:152,0 +DA:154,0 +DA:155,0 +DA:156,0 +DA:158,0 +DA:159,0 +DA:160,0 +DA:162,0 +DA:166,0 +DA:168,0 +DA:169,0 +DA:170,0 +DA:171,0 +DA:172,0 +DA:173,0 +DA:174,0 +DA:175,0 +DA:176,0 +LF:61 +LH:0 +end_of_record +SF:lib/features/tests/question_states/test_question_state.g.dart +DA:34,0 +DA:38,0 +DA:40,0 +DA:42,0 +DA:43,0 +DA:45,0 +DA:46,0 +DA:48,0 +DA:49,0 +DA:51,0 +DA:65,0 +DA:66,0 +DA:67,0 +DA:70,0 +DA:71,0 +DA:75,0 +DA:76,0 +DA:79,0 +DA:80,0 +DA:90,0 +DA:91,0 +LF:21 +LH:0 +end_of_record +SF:lib/features/tests/question_states/test_question_state.dart +DA:10,0 +DA:17,0 +LF:2 +LH:0 +end_of_record +SF:lib/features/tests/question_states/simple_test_state.dart +DA:18,0 +LF:1 +LH:0 +end_of_record +SF:lib/features/tests/question_states/simple_test_state.g.dart +DA:43,0 +DA:47,0 +DA:48,0 +DA:50,0 +DA:51,0 +DA:53,0 +DA:54,0 +DA:56,0 +DA:57,0 +DA:59,0 +DA:60,0 +DA:62,0 +DA:63,0 +DA:65,0 +DA:67,0 +DA:69,0 +DA:86,0 +DA:87,0 +DA:88,0 +DA:91,0 +DA:92,0 +DA:95,0 +DA:96,0 +DA:99,0 +DA:100,0 +DA:104,0 +DA:105,0 +DA:108,0 +DA:109,0 +DA:112,0 +DA:113,0 +DA:123,0 +DA:130,0 +DA:131,0 +DA:132,0 +DA:133,0 +DA:134,0 +DA:135,0 +DA:136,0 +DA:137,0 +DA:139,0 +DA:143,0 +DA:144,0 +DA:145,0 +DA:146,0 +DA:147,0 +DA:148,0 +DA:149,0 +DA:150,0 +DA:151,0 +LF:50 +LH:0 +end_of_record +SF:lib/features/tests/scroll_physics.dart +DA:23,0 +DA:28,0 +DA:30,0 +DA:32,0 +DA:33,0 +DA:34,0 +DA:35,0 +DA:39,0 +DA:40,0 +DA:42,0 +DA:43,0 +DA:45,0 +DA:47,0 +DA:48,0 +DA:49,0 +DA:50,0 +DA:52,0 +DA:61,0 +DA:63,0 +DA:64,0 +DA:65,0 +DA:68,0 +DA:69,0 +DA:71,0 +DA:74,0 +DA:75,0 +DA:77,0 +DA:80,0 +DA:81,0 +DA:83,0 +DA:87,0 +DA:88,0 +DA:89,0 +DA:93,0 +DA:94,0 +DA:97,0 +DA:98,0 +DA:106,0 +DA:107,0 +DA:114,0 +DA:118,0 +DA:133,0 +DA:135,0 +DA:137,0 +DA:139,0 +DA:140,0 +DA:156,0 +DA:159,0 +DA:161,0 +DA:163,0 +DA:164,0 +LF:51 +LH:0 +end_of_record +SF:lib/features/tests/test_complete_widget.dart +DA:17,0 +DA:19,0 +DA:24,0 +DA:26,0 +DA:27,0 +DA:28,0 +DA:29,0 +DA:31,0 +DA:32,0 +DA:33,0 +DA:34,0 +DA:35,0 +DA:36,0 +DA:38,0 +DA:39,0 +DA:40,0 +DA:41,0 +DA:42,0 +DA:44,0 +DA:45,0 +DA:47,0 +DA:51,0 +DA:52,0 +DA:53,0 +DA:55,0 +DA:57,0 +DA:59,0 +DA:60,0 +DA:61,0 +DA:62,0 +DA:64,0 +DA:65,0 +DA:66,0 +DA:68,0 +DA:69,0 +DA:70,0 +DA:71,0 +DA:72,0 +DA:73,0 +DA:74,0 +DA:75,0 +DA:80,0 +DA:81,0 +DA:82,0 +DA:83,0 +DA:85,0 +DA:86,0 +DA:88,0 +DA:89,0 +DA:92,0 +DA:93,0 +DA:95,0 +DA:96,0 +DA:98,0 +DA:99,0 +DA:102,0 +DA:103,0 +DA:105,0 +DA:106,0 +DA:108,0 +DA:109,0 +DA:117,0 +DA:118,0 +DA:119,0 +DA:136,0 +DA:138,0 +DA:140,0 +DA:142,0 +DA:143,0 +DA:144,0 +DA:145,0 +DA:150,0 +DA:152,0 +DA:153,0 +DA:154,0 +DA:155,0 +DA:160,0 +DA:161,0 +DA:162,0 +DA:163,0 +DA:164,0 +DA:165,0 +DA:166,0 +DA:189,0 +DA:191,0 +DA:193,0 +DA:195,0 +DA:196,0 +DA:197,0 +DA:198,0 +DA:201,0 +DA:202,0 +DA:203,0 +DA:204,0 +LF:94 +LH:0 +end_of_record +SF:lib/utils/color_helper.dart +DA:4,0 +DA:5,0 +DA:7,0 +DA:8,0 +DA:10,0 +DA:13,0 +DA:14,0 +DA:16,0 +DA:18,0 +DA:20,0 +LF:10 +LH:0 +end_of_record +SF:lib/features/tests/test_state_holder.dart +DA:13,0 +DA:15,0 +DA:16,0 +DA:17,0 +DA:18,0 +DA:19,0 +DA:21,0 +DA:22,0 +DA:24,0 +DA:26,0 +DA:27,0 +DA:29,0 +DA:32,0 +DA:35,0 +DA:37,0 +DA:43,0 +DA:44,0 +DA:45,0 +DA:46,0 +DA:47,0 +DA:52,0 +DA:53,0 +DA:56,0 +DA:60,0 +DA:61,0 +DA:62,0 +DA:63,0 +DA:64,0 +DA:65,0 +DA:67,0 +DA:69,0 +DA:70,0 +DA:72,0 +DA:74,0 +DA:75,0 +DA:76,0 +DA:80,0 +DA:83,0 +DA:85,0 +DA:87,0 +DA:88,0 +DA:95,0 +DA:97,0 +DA:99,0 +LF:44 +LH:0 +end_of_record +SF:lib/features/tests/test_widgets/test_image.dart +DA:14,0 +DA:16,0 +DA:17,0 +DA:21,0 +DA:25,0 +DA:27,0 +DA:28,0 +DA:31,0 +DA:38,0 +DA:40,0 +DA:43,0 +DA:45,0 +DA:47,0 +DA:50,0 +DA:53,0 +DA:54,0 +DA:56,0 +DA:57,0 +DA:59,0 +DA:60,0 +DA:61,0 +DA:65,0 +DA:67,0 +DA:68,0 +DA:69,0 +DA:71,0 +DA:73,0 +DA:83,0 +DA:88,0 +DA:90,0 +DA:93,0 +DA:94,0 +DA:97,0 +DA:98,0 +DA:100,0 +DA:103,0 +DA:104,0 +DA:105,0 +DA:106,0 +DA:108,0 +DA:112,0 +DA:114,0 +LF:42 +LH:0 +end_of_record +SF:lib/features/tests/test_progress_widget.dart +DA:11,0 +DA:12,0 +DA:14,1 +DA:25,0 +DA:26,0 +DA:27,0 +DA:28,0 +DA:32,0 +DA:33,0 +DA:36,0 +DA:37,0 +DA:38,0 +DA:39,0 +DA:40,0 +DA:41,0 +DA:44,0 +DA:46,0 +DA:47,0 +DA:49,0 +DA:52,0 +DA:53,0 +DA:54,0 +DA:56,0 +DA:59,0 +DA:61,0 +DA:62,0 +DA:63,0 +DA:68,0 +DA:71,0 +DA:73,0 +DA:74,0 +DA:75,0 +DA:76,0 +DA:77,0 +LF:34 +LH:1 +end_of_record +SF:lib/features/tests/test_widgets/input_buttons_test.dart +DA:16,0 +DA:18,0 +DA:19,0 +DA:21,0 +DA:23,0 +DA:25,0 +DA:27,0 +DA:28,0 +DA:29,0 +DA:30,0 +DA:31,0 +DA:33,0 +DA:34,0 +DA:35,0 +DA:37,0 +DA:38,0 +DA:40,0 +DA:41,0 +DA:42,0 +DA:43,0 +DA:46,0 +DA:48,0 +DA:50,0 +DA:51,0 +DA:69,0 +DA:70,0 +DA:72,0 +DA:73,0 +DA:75,0 +DA:77,0 +DA:79,0 +DA:80,0 +DA:82,0 +DA:83,0 +DA:86,0 +DA:87,0 +DA:88,0 +DA:89,0 +DA:90,0 +DA:92,0 +DA:97,0 +DA:99,0 +DA:100,0 +DA:101,0 +DA:106,0 +DA:108,0 +DA:109,0 +DA:110,0 +DA:111,0 +DA:112,0 +DA:113,0 +DA:114,0 +DA:117,0 +DA:118,0 +DA:119,0 +DA:120,0 +DA:121,0 +DA:122,0 +DA:124,0 +DA:125,0 +DA:126,0 +DA:127,0 +DA:129,0 +DA:132,0 +DA:137,0 +DA:138,0 +DA:139,0 +DA:141,0 +DA:143,0 +DA:146,0 +DA:148,0 +DA:152,0 +DA:153,0 +DA:154,0 +DA:155,0 +DA:156,0 +DA:157,0 +DA:158,0 +DA:159,0 +DA:160,0 +DA:161,0 +DA:164,0 +DA:165,0 +DA:166,0 +DA:175,0 +DA:183,0 +DA:186,0 +DA:187,0 +DA:188,0 +DA:190,0 +DA:191,0 +DA:192,0 +DA:193,0 +DA:195,0 +DA:197,0 +DA:198,0 +DA:200,0 +DA:202,0 +DA:203,0 +DA:204,0 +DA:205,0 +DA:206,0 +DA:207,0 +DA:208,0 +DA:209,0 +DA:213,0 +DA:222,0 +DA:224,0 +DA:225,0 +DA:226,0 +DA:227,0 +DA:229,0 +DA:231,0 +DA:232,0 +DA:234,0 +DA:237,0 +DA:238,0 +DA:244,0 +DA:260,0 +DA:270,0 +DA:274,0 +DA:276,0 +DA:283,0 +DA:285,0 +DA:286,0 +DA:289,0 +DA:290,0 +DA:291,0 +DA:293,0 +DA:294,0 +DA:295,0 +DA:296,0 +DA:298,0 +DA:299,0 +DA:300,0 +DA:301,0 +DA:302,0 +LF:137 +LH:0 +end_of_record +SF:lib/features/tests/test_widgets/simple_test.dart +DA:17,0 +DA:19,0 +DA:21,0 +DA:23,0 +DA:25,0 +DA:27,0 +DA:29,0 +DA:31,0 +DA:32,0 +DA:34,0 +DA:35,0 +DA:37,0 +DA:39,0 +DA:40,0 +DA:41,0 +DA:42,0 +DA:43,0 +DA:44,0 +DA:47,0 +DA:50,0 +DA:51,0 +DA:52,0 +DA:53,0 +DA:54,0 +DA:55,0 +DA:60,0 +DA:61,0 +DA:62,0 +DA:64,0 +DA:68,0 +DA:69,0 +DA:70,0 +DA:71,0 +DA:76,0 +DA:77,0 +DA:80,0 +DA:81,0 +DA:84,0 +DA:85,0 +DA:86,0 +DA:90,0 +DA:91,0 +DA:92,0 +DA:93,0 +DA:94,0 +DA:95,0 +DA:96,0 +DA:97,0 +DA:98,0 +DA:101,0 +DA:102,0 +DA:103,0 +DA:104,0 +DA:105,0 +DA:108,0 +DA:111,0 +DA:112,0 +DA:113,0 +DA:114,0 +DA:117,0 +DA:118,0 +DA:119,0 +DA:120,0 +DA:121,0 +DA:125,0 +LF:65 +LH:0 +end_of_record +SF:lib/features/tests/test_widgets/common_test_question_widget.dart +DA:14,0 +DA:21,0 +DA:23,0 +DA:25,0 +DA:27,0 +DA:28,0 +DA:29,0 +DA:30,0 +DA:33,0 +DA:35,0 +DA:37,0 +DA:38,0 +DA:39,0 +DA:41,0 +DA:42,0 +DA:43,0 +DA:45,0 +DA:46,0 +DA:47,0 +DA:49,0 +DA:50,0 +DA:53,0 +DA:55,0 +DA:63,0 +DA:64,0 +DA:65,0 +DA:66,0 +DA:67,0 +DA:71,0 +DA:73,0 +DA:77,0 +DA:78,0 +DA:81,0 +DA:84,0 +DA:85,0 +DA:86,0 +DA:87,0 +DA:89,0 +DA:90,0 +DA:91,0 +DA:92,0 +DA:93,0 +DA:96,0 +DA:97,0 +DA:99,0 +DA:105,0 +DA:106,0 +DA:109,0 +DA:110,0 +DA:111,0 +LF:50 +LH:0 +end_of_record +SF:lib/widgets/game_card_widget.dart +DA:28,0 +DA:38,0 +DA:39,0 +DA:47,0 +DA:49,0 +DA:50,0 +DA:51,0 +DA:52,0 +DA:53,0 +DA:54,0 +DA:55,0 +DA:56,0 +DA:58,0 +DA:60,0 +DA:62,0 +DA:63,0 +DA:64,0 +DA:66,0 +DA:67,0 +DA:70,0 +DA:71,0 +DA:73,0 +DA:74,0 +DA:75,0 +DA:77,0 +DA:81,0 +DA:82,0 +DA:83,0 +DA:85,0 +DA:91,0 +DA:93,0 +DA:95,0 +DA:96,0 +DA:98,0 +DA:99,0 +DA:103,0 +DA:104,0 +DA:106,0 +DA:107,0 +DA:108,0 +DA:110,0 +DA:111,0 +DA:113,0 +DA:114,0 +DA:115,0 +DA:116,0 +DA:117,0 +DA:120,0 +DA:122,0 +DA:126,0 +DA:127,0 +DA:129,0 +DA:130,0 +DA:132,0 +DA:133,0 +DA:137,0 +DA:141,0 +DA:154,0 +DA:156,0 +DA:158,0 +DA:159,0 +DA:160,0 +DA:162,0 +DA:165,0 +DA:167,0 +DA:168,0 +DA:169,0 +DA:170,0 +DA:184,0 +DA:186,0 +DA:188,0 +DA:189,0 +DA:190,0 +DA:191,0 +DA:192,0 +DA:193,0 +DA:194,0 +DA:197,0 +DA:198,0 +DA:199,0 +DA:201,0 +DA:203,0 +DA:204,0 +DA:207,0 +DA:209,0 +DA:210,0 +DA:211,0 +DA:212,0 +DA:214,0 +DA:216,0 +DA:219,0 +DA:220,0 +DA:221,0 +DA:222,0 +DA:223,0 +DA:224,0 +DA:225,0 +DA:226,0 +DA:231,0 +DA:232,0 +DA:233,0 +DA:234,0 +DA:240,0 +DA:241,0 +DA:242,0 +DA:243,0 +DA:244,0 +DA:245,0 +DA:251,0 +DA:252,0 +DA:253,0 +DA:254,0 +DA:256,0 +DA:257,0 +DA:262,0 +DA:263,0 +DA:264,0 +DA:265,0 +DA:266,0 +DA:267,0 +DA:268,0 +DA:269,0 +DA:270,0 +DA:271,0 +DA:272,0 +DA:273,0 +DA:278,0 +DA:279,0 +DA:280,0 +DA:281,0 +DA:292,0 +DA:293,0 +DA:294,0 +DA:296,0 +DA:297,0 +DA:298,0 +DA:299,0 +DA:300,0 +DA:304,0 +DA:305,0 +DA:306,0 +DA:313,0 +DA:314,0 +DA:315,0 +DA:318,0 +DA:319,0 +DA:323,0 +DA:324,0 +DA:325,0 +DA:327,0 +DA:328,0 +DA:336,0 +DA:337,0 +DA:338,0 +DA:341,0 +DA:343,0 +DA:344,0 +DA:345,0 +DA:352,0 +DA:353,0 +DA:354,0 +DA:355,0 +DA:358,0 +DA:359,0 +DA:360,0 +DA:362,0 +DA:363,0 +DA:367,0 +DA:368,0 +DA:369,0 +DA:370,0 +DA:371,0 +DA:373,0 +DA:374,0 +DA:376,0 +DA:377,0 +DA:379,0 +DA:380,0 +DA:381,0 +LF:179 +LH:0 +end_of_record +SF:lib/features/tests/test_widgets/test_button.dart +DA:13,0 +DA:22,0 +DA:24,0 +DA:25,0 +DA:26,0 +DA:27,0 +DA:28,0 +DA:29,0 +DA:31,0 +DA:32,0 +DA:34,0 +DA:42,0 +DA:44,0 +DA:46,0 +DA:48,0 +DA:49,0 +DA:50,0 +DA:51,0 +DA:52,0 +DA:54,0 +DA:55,0 +DA:58,0 +DA:59,0 +DA:60,0 +DA:62,0 +LF:25 +LH:0 +end_of_record +SF:lib/features/vocabulary/cubit/vocabulary_cubit.dart +DA:10,0 +DA:13,0 +DA:14,0 +DA:18,0 +DA:19,0 +DA:22,0 +DA:24,0 +DA:27,0 +DA:29,0 +DA:30,0 +DA:38,0 +DA:43,0 +DA:46,0 +DA:47,0 +DA:49,0 +DA:54,0 +DA:65,0 +DA:66,0 +DA:70,0 +DA:71,0 +DA:75,0 +DA:76,0 +DA:77,0 +DA:78,0 +DA:81,0 +DA:83,0 +DA:87,0 +DA:89,0 +DA:93,0 +DA:94,0 +DA:98,0 +DA:102,0 +DA:104,0 +DA:105,0 +DA:106,0 +DA:107,0 +DA:115,0 +DA:116,0 +DA:117,0 +DA:119,0 +DA:122,0 +DA:125,0 +DA:129,0 +DA:130,0 +DA:131,0 +DA:135,0 +DA:136,0 +DA:137,0 +DA:138,0 +DA:139,0 +DA:140,0 +DA:141,0 +DA:142,0 +DA:150,0 +DA:153,0 +DA:154,0 +DA:155,0 +DA:156,0 +DA:163,0 +DA:164,0 +DA:165,0 +DA:167,0 +DA:169,0 +DA:171,0 +DA:173,0 +LF:65 +LH:0 +end_of_record +SF:lib/features/vocabulary/models/vocabulary_page_state.dart +DA:14,1 +DA:24,0 +DA:33,0 +DA:34,0 +DA:35,0 +DA:36,0 +DA:37,0 +DA:38,0 +DA:39,0 +DA:40,0 +DA:45,0 +DA:46,0 +DA:47,0 +DA:51,0 +DA:55,0 +DA:56,0 +DA:57,0 +DA:58,0 +DA:62,0 +DA:63,0 +DA:65,0 +DA:66,0 +DA:67,0 +DA:68,0 +DA:69,0 +DA:73,0 +DA:74,0 +DA:78,0 +DA:79,0 +DA:83,0 +DA:84,0 +DA:85,0 +DA:88,0 +DA:91,0 +DA:92,0 +DA:93,0 +DA:94,0 +DA:95,0 +DA:96,0 +DA:97,0 +DA:98,0 +DA:101,0 +DA:103,0 +DA:104,0 +DA:105,0 +DA:106,0 +DA:107,0 +DA:108,0 +DA:109,0 +LF:49 +LH:1 +end_of_record +SF:lib/features/vocabulary/models/vocabulary_word.dart +DA:13,0 +DA:21,0 +DA:24,0 +DA:27,0 +DA:30,0 +DA:33,0 +DA:36,0 +DA:37,0 +DA:38,0 +DA:39,0 +DA:43,0 +DA:44,0 +DA:47,0 +DA:48,0 +DA:52,0 +DA:53,0 +DA:54,0 +DA:58,0 +DA:61,0 +DA:63,0 +DA:69,0 +DA:70,0 +DA:71,0 +DA:72,0 +DA:73,0 +DA:78,0 +DA:79,0 +DA:82,0 +DA:85,0 +DA:86,0 +DA:87,0 +DA:88,0 +DA:91,0 +DA:93,0 +LF:34 +LH:0 +end_of_record +SF:lib/features/vocabulary/models/vocabulary_category.dart +DA:13,0 +DA:22,0 +DA:30,0 +DA:31,0 +DA:32,0 +DA:33,0 +DA:34,0 +DA:35,0 +DA:36,0 +DA:41,0 +DA:42,0 +DA:45,0 +DA:46,0 +DA:47,0 +DA:51,0 +DA:52,0 +DA:53,0 +DA:54,0 +DA:57,0 +DA:59,0 +DA:62,0 +DA:65,0 +DA:66,0 +DA:67,0 +DA:68,0 +DA:69,0 +DA:72,0 +DA:74,0 +DA:75,0 +DA:76,0 +DA:77,0 +LF:31 +LH:0 +end_of_record +SF:lib/features/vocabulary/models/word_difficulty.dart +DA:10,0 +DA:12,0 +DA:14,0 +DA:16,0 +DA:21,0 +DA:23,0 +DA:25,0 +DA:27,0 +DA:34,0 +DA:35,0 +DA:37,0 +LF:11 +LH:0 +end_of_record +SF:lib/features/vocabulary/pages/vocabulary_page.dart +DA:16,0 +DA:18,0 +DA:19,0 +DA:27,0 +DA:29,0 +DA:30,0 +DA:31,0 +DA:32,0 +DA:33,0 +DA:34,0 +DA:37,0 +DA:40,0 +DA:42,0 +DA:43,0 +DA:44,0 +DA:47,0 +DA:48,0 +DA:49,0 +DA:50,0 +DA:51,0 +DA:55,0 +DA:57,0 +DA:58,0 +DA:59,0 +DA:60,0 +DA:62,0 +DA:63,0 +DA:64,0 +DA:65,0 +DA:66,0 +DA:67,0 +DA:69,0 +DA:70,0 +DA:76,0 +DA:77,0 +DA:78,0 +DA:82,0 +DA:83,0 +DA:84,0 +DA:86,0 +DA:87,0 +DA:88,0 +DA:89,0 +DA:91,0 +DA:92,0 +DA:96,0 +DA:97,0 +DA:98,0 +DA:100,0 +DA:101,0 +DA:102,0 +DA:105,0 +DA:106,0 +DA:107,0 +DA:115,0 +DA:116,0 +DA:117,0 +DA:118,0 +DA:119,0 +DA:121,0 +DA:122,0 +DA:123,0 +DA:124,0 +DA:126,0 +DA:127,0 +DA:128,0 +DA:129,0 +DA:131,0 +DA:132,0 +DA:133,0 +DA:134,0 +DA:135,0 +DA:137,0 +DA:138,0 +DA:139,0 +DA:140,0 +DA:141,0 +DA:143,0 +DA:144,0 +LF:79 +LH:0 +end_of_record +SF:lib/features/vocabulary/widgets/vocabulary_header.dart +DA:8,0 +DA:15,0 +DA:16,0 +DA:18,0 +DA:19,0 +DA:20,0 +DA:21,0 +DA:22,0 +DA:24,0 +DA:28,0 +DA:30,0 +DA:32,0 +DA:33,0 +DA:34,0 +DA:36,0 +DA:37,0 +DA:38,0 +DA:39,0 +LF:18 +LH:0 +end_of_record +SF:lib/features/vocabulary/widgets/vocabulary_search_bar.dart +DA:7,0 +DA:12,0 +DA:13,0 +DA:20,0 +DA:22,0 +DA:23,0 +DA:26,0 +DA:28,0 +DA:29,0 +DA:32,0 +DA:33,0 +DA:34,0 +DA:35,0 +DA:39,0 +DA:40,0 +DA:41,0 +DA:44,0 +DA:46,0 +DA:47,0 +DA:48,0 +DA:49,0 +DA:50,0 +DA:51,0 +DA:53,0 +DA:54,0 +DA:55,0 +DA:56,0 +DA:58,0 +DA:59,0 +DA:60,0 +DA:62,0 +DA:64,0 +DA:65,0 +DA:67,0 +DA:68,0 +DA:69,0 +DA:71,0 +DA:72,0 +DA:74,0 +DA:78,0 +DA:79,0 +DA:80,0 +DA:83,0 +DA:84,0 +LF:44 +LH:0 +end_of_record +SF:lib/features/vocabulary/widgets/vocabulary_categories.dart +DA:10,0 +DA:17,0 +DA:19,0 +DA:23,0 +DA:25,0 +DA:26,0 +DA:28,0 +DA:29,0 +DA:33,0 +DA:34,0 +DA:35,0 +DA:36,0 +DA:38,0 +DA:39,0 +DA:40,0 +DA:41,0 +DA:44,0 +DA:45,0 +DA:53,0 +DA:54,0 +DA:56,0 +DA:57,0 +DA:58,0 +DA:59,0 +DA:60,0 +DA:62,0 +DA:63,0 +DA:64,0 +DA:65,0 +DA:66,0 +DA:67,0 +DA:71,0 +DA:73,0 +DA:74,0 +DA:76,0 +DA:77,0 +DA:79,0 +DA:80,0 +DA:82,0 +DA:83,0 +DA:85,0 +DA:95,0 +DA:96,0 +DA:98,0 +DA:99,0 +DA:100,0 +DA:101,0 +DA:102,0 +DA:104,0 +DA:105,0 +DA:106,0 +DA:107,0 +DA:108,0 +DA:109,0 +DA:113,0 +DA:115,0 +DA:116,0 +DA:117,0 +DA:118,0 +DA:119,0 +DA:121,0 +DA:122,0 +DA:123,0 +DA:124,0 +DA:125,0 +DA:127,0 +DA:130,0 +DA:131,0 +DA:132,0 +DA:133,0 +DA:135,0 +DA:136,0 +DA:137,0 +DA:139,0 +DA:140,0 +DA:141,0 +DA:142,0 +DA:144,0 +LF:78 +LH:0 +end_of_record +SF:lib/features/vocabulary/widgets/vocabulary_progress.dart +DA:10,0 +DA:17,0 +DA:19,0 +DA:20,0 +DA:21,0 +DA:23,0 +DA:24,0 +DA:25,0 +DA:26,0 +DA:32,0 +DA:34,0 +DA:35,0 +DA:36,0 +DA:37,0 +DA:38,0 +DA:42,0 +DA:43,0 +DA:44,0 +DA:45,0 +DA:46,0 +DA:49,0 +LF:21 +LH:0 +end_of_record +SF:lib/features/vocabulary/widgets/vocabulary_words_list.dart +DA:9,0 +DA:14,0 +DA:16,0 +DA:17,0 +DA:18,0 +DA:20,0 +DA:21,0 +DA:23,0 +DA:24,0 +DA:26,0 +DA:27,0 +DA:30,0 +DA:31,0 +DA:32,0 +DA:35,0 +DA:36,0 +DA:39,0 +DA:40,0 +DA:41,0 +DA:49,0 +DA:51,0 +DA:52,0 +DA:53,0 +DA:54,0 +DA:55,0 +DA:59,0 +DA:60,0 +DA:63,0 +DA:64,0 +DA:65,0 +DA:66,0 +DA:67,0 +DA:69,0 +DA:70,0 +LF:34 +LH:0 +end_of_record +SF:lib/features/vocabulary/widgets/vocabulary_word_card.dart +DA:15,0 +DA:22,0 +DA:24,0 +DA:26,0 +DA:27,0 +DA:28,0 +DA:29,0 +DA:30,0 +DA:31,0 +DA:35,0 +DA:36,0 +DA:38,0 +DA:39,0 +DA:42,0 +DA:45,0 +DA:46,0 +DA:47,0 +DA:48,0 +DA:55,0 +DA:56,0 +DA:57,0 +DA:58,0 +DA:59,0 +DA:60,0 +DA:61,0 +DA:64,0 +DA:65,0 +DA:69,0 +DA:70,0 +DA:72,0 +DA:74,0 +DA:75,0 +DA:76,0 +DA:77,0 +DA:78,0 +DA:79,0 +DA:81,0 +DA:82,0 +DA:89,0 +DA:93,0 +DA:94,0 +DA:95,0 +DA:98,0 +DA:101,0 +DA:102,0 +DA:103,0 +LF:46 +LH:0 +end_of_record +SF:lib/features/vocabulary/widgets/difficulty_chart.dart +DA:11,0 +DA:18,0 +DA:20,0 +DA:21,0 +DA:22,0 +DA:23,0 +DA:24,0 +DA:33,0 +DA:35,0 +DA:37,0 +DA:38,0 +DA:39,0 +DA:40,0 +DA:41,0 +DA:43,0 +DA:46,0 +DA:47,0 +DA:48,0 +DA:50,0 +DA:51,0 +DA:53,0 +DA:54,0 +DA:58,0 +DA:61,0 +DA:63,0 +DA:64,0 +DA:66,0 +DA:68,0 +DA:69,0 +DA:70,0 +DA:71,0 +DA:73,0 +DA:78,0 +DA:80,0 +DA:81,0 +DA:83,0 +DA:85,0 +DA:86,0 +DA:87,0 +DA:88,0 +DA:90,0 +DA:95,0 +DA:97,0 +DA:98,0 +DA:100,0 +DA:102,0 +DA:103,0 +DA:104,0 +DA:105,0 +DA:107,0 +DA:112,0 +DA:114,0 +DA:115,0 +LF:53 +LH:0 +end_of_record +SF:lib/features/yandex_ads/yandex_ads.dart +DA:13,0 +DA:19,0 +DA:22,0 +DA:23,0 +DA:24,0 +DA:27,0 +DA:28,0 +DA:29,0 +DA:31,0 +DA:35,0 +DA:38,0 +DA:41,0 +DA:44,0 +LF:13 +LH:0 +end_of_record +SF:lib/firebase_options.dart +DA:18,0 +DA:22,0 +DA:23,0 +DA:25,0 +DA:27,0 +DA:29,0 +DA:30,0 +DA:34,0 +DA:35,0 +DA:40,0 +LF:10 +LH:0 +end_of_record +SF:lib/managers/repository/firebase_config_repository.dart +DA:5,0 +DA:9,0 +DA:14,0 +DA:15,0 +DA:16,0 +DA:17,0 +DA:18,0 +DA:19,0 +DA:20,0 +DA:27,0 +LF:10 +LH:0 +end_of_record +SF:lib/managers/remote_config_manager.dart +DA:6,0 +DA:8,0 +DA:10,0 +DA:18,0 +DA:20,0 +DA:21,0 +DA:23,0 +DA:26,0 +DA:27,0 +DA:34,0 +DA:35,0 +DA:40,0 +DA:41,0 +DA:42,0 +DA:45,0 +DA:46,0 +DA:50,0 +DA:53,0 +DA:57,0 +DA:58,0 +DA:59,0 +DA:64,0 +DA:65,0 +DA:68,0 +DA:69,0 +DA:73,0 +DA:78,0 +DA:80,0 +DA:81,0 +DA:82,0 +DA:85,0 +DA:87,0 +LF:32 +LH:0 +end_of_record +SF:lib/managers/repository/dio_throttler.dart +DA:25,0 +DA:27,0 +DA:29,0 +DA:30,0 +DA:34,0 +DA:35,0 +DA:36,0 +DA:38,0 +DA:40,0 +DA:44,0 +DA:47,0 +DA:49,0 +DA:50,0 +DA:51,0 +DA:52,0 +DA:55,0 +LF:16 +LH:0 +end_of_record +SF:lib/widgets/shared_pref_button.dart +DA:16,0 +DA:24,0 +DA:32,0 +DA:33,0 +DA:34,0 +DA:35,0 +DA:36,0 +DA:37,0 +DA:38,0 +DA:39,0 +LF:10 +LH:0 +end_of_record +SF:lib/widgets/packs_menu_widget.dart +DA:22,0 +DA:29,0 +DA:30,0 +DA:34,0 +DA:36,0 +DA:38,0 +DA:39,0 +DA:40,0 +DA:41,0 +DA:42,0 +DA:46,0 +DA:48,0 +DA:53,0 +DA:54,0 +DA:55,0 +DA:56,0 +DA:57,0 +DA:58,0 +DA:59,0 +DA:60,0 +DA:61,0 +DA:63,0 +DA:64,0 +DA:65,0 +DA:67,0 +DA:68,0 +DA:70,0 +DA:71,0 +DA:78,0 +DA:82,0 +DA:83,0 +DA:85,0 +DA:88,0 +DA:89,0 +DA:90,0 +DA:95,0 +DA:106,0 +DA:107,0 +DA:108,0 +DA:110,0 +DA:112,0 +DA:113,0 +DA:114,0 +DA:115,0 +DA:117,0 +DA:118,0 +DA:120,0 +DA:121,0 +DA:122,0 +DA:125,0 +DA:131,0 +DA:135,0 +DA:136,0 +LF:53 +LH:0 +end_of_record +SF:lib/widgets/buy_subscription_widget.dart +DA:10,0 +DA:12,0 +DA:13,0 +DA:14,0 +DA:18,1 +LF:5 +LH:1 +end_of_record +SF:lib/widgets/enter_promo_code_widget.dart +DA:8,0 +DA:10,0 +DA:13,0 +DA:14,0 +DA:15,0 +DA:18,1 +LF:6 +LH:1 +end_of_record +SF:lib/widgets/card_game/card_game_main.dart +DA:20,0 +DA:29,0 +DA:31,0 +DA:34,0 +DA:35,0 +DA:37,0 +DA:39,0 +DA:41,0 +DA:44,0 +DA:46,0 +DA:47,0 +DA:50,0 +DA:51,0 +DA:52,0 +DA:53,0 +DA:55,0 +DA:56,0 +DA:57,0 +DA:58,0 +DA:59,0 +DA:60,0 +DA:61,0 +DA:62,0 +DA:63,0 +DA:64,0 +DA:65,0 +DA:67,0 +DA:68,0 +DA:69,0 +DA:73,0 +DA:75,0 +DA:76,0 +DA:77,0 +DA:78,0 +DA:79,0 +DA:80,0 +DA:84,0 +DA:92,0 +DA:105,0 +DA:107,0 +DA:109,0 +LF:41 +LH:0 +end_of_record +SF:lib/widgets/card_pack/available_pack.dart +DA:25,0 +DA:26,0 +DA:33,0 +DA:35,0 +DA:37,0 +DA:38,0 +DA:39,0 +DA:40,0 +DA:41,0 +DA:42,0 +DA:43,0 +DA:45,0 +DA:46,0 +DA:47,0 +DA:48,0 +DA:49,0 +DA:50,0 +DA:51,0 +DA:55,0 +DA:56,0 +DA:57,0 +DA:60,0 +DA:62,0 +DA:63,0 +DA:65,0 +DA:66,0 +DA:68,0 +DA:69,0 +DA:70,0 +DA:72,0 +DA:74,0 +DA:75,0 +DA:76,0 +DA:77,0 +DA:78,0 +DA:79,0 +DA:80,0 +DA:81,0 +DA:82,0 +DA:83,0 +DA:84,0 +DA:88,0 +DA:90,0 +DA:91,0 +DA:92,0 +DA:93,0 +DA:95,0 +DA:102,0 +DA:105,0 +DA:106,0 +DA:107,0 +DA:108,0 +DA:109,0 +DA:110,0 +DA:111,0 +DA:112,0 +DA:113,0 +DA:114,0 +DA:115,0 +DA:116,0 +DA:118,0 +DA:120,0 +DA:121,0 +DA:130,0 +DA:131,0 +DA:132,0 +DA:133,0 +DA:134,0 +DA:137,0 +DA:138,0 +DA:139,0 +DA:140,0 +DA:152,0 +DA:153,0 +DA:155,0 +DA:156,0 +DA:160,0 +DA:162,0 +DA:164,0 +DA:175,0 +DA:177,0 +DA:179,0 +DA:180,0 +DA:181,0 +DA:182,0 +DA:183,0 +DA:185,0 +DA:187,0 +DA:188,0 +DA:189,0 +DA:190,0 +DA:194,0 +DA:195,0 +DA:196,0 +DA:197,0 +DA:198,0 +DA:199,0 +DA:202,0 +DA:203,0 +DA:204,0 +DA:206,0 +DA:207,0 +DA:208,0 +DA:209,0 +DA:210,0 +DA:211,0 +DA:212,0 +DA:213,0 +DA:214,0 +DA:215,0 +DA:218,0 +DA:219,0 +DA:220,0 +DA:221,0 +DA:223,0 +DA:225,0 +DA:226,0 +DA:228,0 +DA:229,0 +DA:230,0 +DA:231,0 +DA:232,0 +DA:236,0 +DA:237,0 +DA:238,0 +DA:240,0 +DA:241,0 +DA:242,0 +DA:244,0 +DA:245,0 +DA:246,0 +DA:247,0 +DA:248,0 +DA:249,0 +DA:250,0 +DA:252,0 +DA:253,0 +DA:255,0 +DA:256,0 +DA:257,0 +DA:258,0 +DA:259,0 +DA:260,0 +DA:261,0 +DA:262,0 +DA:277,0 +DA:281,0 +DA:283,0 +DA:284,0 +DA:285,0 +DA:286,0 +DA:287,0 +DA:288,0 +DA:291,0 +DA:292,0 +DA:293,0 +DA:294,0 +DA:295,0 +DA:297,0 +DA:298,0 +DA:299,0 +DA:302,0 +DA:304,0 +DA:305,0 +DA:317,0 +DA:319,0 +DA:321,0 +DA:322,0 +DA:323,0 +DA:324,0 +DA:325,0 +DA:326,0 +DA:327,0 +DA:328,0 +DA:329,0 +DA:332,0 +DA:333,0 +DA:334,0 +DA:335,0 +DA:348,0 +DA:350,0 +DA:352,0 +DA:353,0 +DA:354,0 +DA:355,0 +DA:356,0 +DA:357,0 +DA:358,0 +DA:359,0 +DA:360,0 +DA:363,0 +DA:364,0 +DA:365,0 +DA:366,0 +DA:368,0 +DA:369,0 +DA:388,0 +DA:398,0 +DA:400,0 +DA:401,0 +DA:402,0 +DA:403,0 +DA:405,0 +DA:406,0 +DA:407,0 +DA:408,0 +DA:410,0 +DA:411,0 +DA:412,0 +DA:413,0 +DA:414,0 +DA:416,0 +DA:417,0 +DA:418,0 +DA:419,0 +DA:422,0 +DA:423,0 +DA:424,0 +DA:425,0 +DA:426,0 +DA:431,0 +DA:432,0 +DA:434,0 +DA:435,0 +DA:436,0 +DA:437,0 +DA:443,0 +DA:444,0 +DA:445,0 +DA:447,0 +DA:448,0 +DA:449,0 +DA:450,0 +DA:451,0 +DA:452,0 +DA:453,0 +DA:454,0 +DA:463,0 +DA:464,0 +DA:465,0 +DA:467,0 +DA:468,0 +DA:469,0 +DA:470,0 +DA:471,0 +DA:472,0 +DA:476,0 +DA:477,0 +DA:478,0 +DA:479,0 +DA:480,0 +LF:251 +LH:0 +end_of_record +SF:lib/widgets/card_pack/card_pack_header.dart +DA:12,0 +DA:14,0 +DA:15,0 +DA:16,0 +DA:17,0 +DA:19,0 +DA:21,0 +DA:22,0 +DA:23,0 +DA:24,0 +DA:25,0 +DA:30,0 +DA:32,0 +DA:34,0 +DA:35,0 +LF:15 +LH:0 +end_of_record +SF:lib/widgets/card_pack/cards_view.dart +DA:24,0 +DA:32,0 +DA:33,0 +DA:38,0 +DA:40,0 +DA:54,0 +DA:55,0 +DA:58,0 +DA:59,0 +DA:60,0 +DA:61,0 +DA:62,0 +DA:64,0 +DA:65,0 +DA:66,0 +DA:68,0 +DA:72,0 +DA:74,0 +DA:81,0 +DA:83,0 +DA:84,0 +DA:85,0 +DA:86,0 +DA:89,0 +DA:91,0 +DA:92,0 +DA:93,0 +DA:94,0 +DA:96,0 +DA:98,0 +DA:99,0 +DA:100,0 +DA:103,0 +DA:105,0 +DA:106,0 +DA:107,0 +DA:110,0 +DA:111,0 +DA:112,0 +DA:114,0 +DA:115,0 +DA:117,0 +DA:119,0 +DA:120,0 +DA:137,0 +DA:139,0 +DA:140,0 +DA:143,0 +DA:144,0 +DA:145,0 +DA:146,0 +DA:147,0 +DA:149,0 +DA:151,0 +DA:152,0 +DA:153,0 +DA:154,0 +DA:158,0 +DA:159,0 +DA:160,0 +DA:162,0 +DA:163,0 +DA:164,0 +DA:166,0 +DA:167,0 +DA:168,0 +DA:170,0 +DA:172,0 +DA:173,0 +DA:174,0 +DA:175,0 +DA:176,0 +DA:181,0 +DA:182,0 +DA:183,0 +DA:184,0 +DA:185,0 +DA:198,0 +DA:203,0 +DA:205,0 +DA:206,0 +DA:208,0 +DA:209,0 +DA:210,0 +DA:211,0 +LF:85 +LH:0 +end_of_record +SF:lib/widgets/card_pack/cards_view_controller.dart +DA:19,0 +DA:26,0 +DA:31,0 +DA:32,0 +DA:34,0 +DA:36,0 +DA:38,0 +DA:39,0 +DA:40,0 +DA:41,0 +DA:43,0 +DA:44,0 +DA:45,0 +DA:46,0 +DA:49,0 +DA:50,0 +DA:51,0 +DA:52,0 +DA:53,0 +DA:55,0 +DA:57,0 +DA:58,0 +DA:59,0 +DA:60,0 +DA:64,0 +DA:65,0 +DA:66,0 +DA:67,0 +DA:68,0 +DA:71,0 +DA:72,0 +DA:73,0 +DA:78,0 +DA:79,0 +DA:80,0 +DA:81,0 +DA:83,0 +DA:84,0 +DA:85,0 +DA:86,0 +DA:87,0 +DA:89,0 +DA:90,0 +DA:91,0 +DA:92,0 +DA:94,0 +DA:95,0 +DA:99,0 +DA:100,0 +DA:101,0 +DA:103,0 +DA:105,0 +DA:106,0 +DA:109,0 +DA:110,0 +DA:111,0 +DA:113,0 +DA:115,0 +DA:116,0 +DA:119,0 +DA:120,0 +DA:121,0 +DA:122,0 +DA:125,0 +DA:126,0 +DA:129,0 +DA:131,0 +DA:133,0 +DA:135,0 +DA:136,0 +DA:137,0 +DA:138,0 +DA:139,0 +DA:142,0 +DA:143,0 +DA:144,0 +DA:145,0 +DA:146,0 +DA:147,0 +DA:148,0 +DA:149,0 +DA:150,0 +DA:151,0 +DA:153,0 +DA:155,0 +DA:158,0 +DA:160,0 +DA:161,0 +DA:162,0 +DA:163,0 +DA:164,0 +DA:169,0 +DA:170,0 +DA:171,0 +DA:181,0 +DA:187,0 +DA:188,0 +DA:190,0 +DA:192,0 +DA:193,0 +DA:194,0 +DA:195,0 +DA:196,0 +LF:103 +LH:0 +end_of_record +SF:lib/widgets/card_pack/buy_pack_page.dart +DA:20,0 +DA:22,0 +DA:25,0 +DA:26,0 +DA:28,0 +DA:30,0 +DA:32,0 +DA:34,0 +DA:35,0 +DA:36,0 +DA:37,0 +DA:40,0 +DA:41,0 +DA:42,0 +DA:43,0 +DA:44,0 +DA:45,0 +DA:46,0 +DA:47,0 +DA:48,0 +DA:49,0 +DA:51,0 +DA:53,0 +DA:54,0 +DA:55,0 +DA:56,0 +DA:59,0 +DA:60,0 +DA:63,0 +DA:64,0 +DA:65,0 +DA:66,0 +DA:70,0 +DA:73,0 +DA:79,0 +DA:80,0 +DA:82,0 +DA:92,0 +DA:93,0 +DA:105,0 +DA:107,0 +DA:109,0 +DA:110,0 +DA:111,0 +DA:112,0 +DA:113,0 +DA:114,0 +DA:115,0 +DA:117,0 +DA:119,0 +DA:121,0 +DA:126,0 +DA:140,0 +DA:142,0 +DA:144,0 +DA:145,0 +DA:146,0 +DA:148,0 +DA:151,0 +DA:152,0 +DA:153,0 +DA:155,0 +DA:157,0 +DA:158,0 +DA:159,0 +DA:160,0 +DA:161,0 +DA:168,0 +DA:171,0 +DA:173,0 +DA:180,0 +DA:181,0 +DA:182,0 +DA:183,0 +DA:184,0 +DA:185,0 +DA:186,0 +DA:189,0 +DA:192,0 +DA:194,0 +DA:195,0 +DA:197,0 +DA:198,0 +DA:203,0 +DA:205,0 +DA:206,0 +DA:211,0 +DA:212,0 +DA:214,0 +DA:215,0 +DA:216,0 +DA:217,0 +DA:218,0 +DA:225,0 +LF:94 +LH:0 +end_of_record +SF:lib/widgets/card_pack/error_loading_pack.dart +DA:16,0 +DA:18,0 +DA:20,0 +DA:22,0 +DA:23,0 +DA:24,0 +DA:25,0 +DA:26,0 +DA:27,0 +DA:29,0 +DA:30,0 +DA:31,0 +DA:33,0 +DA:35,0 +DA:36,0 +DA:37,0 +DA:40,0 +DA:45,0 +DA:46,0 +DA:48,0 +DA:50,0 +DA:55,0 +LF:22 +LH:0 +end_of_record +SF:lib/widgets/card_pack/loading_pack.dart +DA:15,0 +DA:17,0 +DA:19,0 +DA:21,0 +DA:23,0 +DA:24,0 +DA:25,0 +DA:26,0 +DA:27,0 +DA:28,0 +DA:29,0 +DA:30,0 +DA:32,0 +DA:33,0 +DA:34,0 +DA:36,0 +DA:38,0 +DA:39,0 +DA:40,0 +DA:43,0 +DA:48,0 +DA:49,0 +DA:51,0 +DA:53,0 +DA:54,0 +DA:56,0 +DA:57,0 +DA:58,0 +DA:59,0 +DA:61,0 +DA:62,0 +DA:73,0 +DA:74,0 +DA:75,0 +DA:76,0 +DA:77,0 +DA:78,0 +DA:79,0 +DA:81,0 +DA:82,0 +DA:84,0 +DA:86,0 +DA:87,0 +DA:89,0 +DA:90,0 +DA:91,0 +LF:46 +LH:0 +end_of_record +SF:lib/widgets/card_pack/cards_list.dart +DA:24,0 +DA:36,0 +DA:38,0 +DA:40,0 +DA:41,0 +DA:43,0 +DA:44,0 +DA:45,0 +DA:47,0 +DA:48,0 +DA:49,0 +DA:50,0 +DA:51,0 +DA:60,0 +DA:62,0 +DA:63,0 +DA:65,0 +DA:67,0 +DA:68,0 +DA:69,0 +DA:70,0 +DA:72,0 +DA:86,0 +DA:97,0 +DA:99,0 +DA:100,0 +DA:101,0 +DA:103,0 +DA:104,0 +DA:105,0 +DA:106,0 +DA:107,0 +DA:108,0 +DA:109,0 +DA:122,0 +DA:129,0 +DA:131,0 +DA:132,0 +DA:133,0 +DA:134,0 +DA:135,0 +DA:136,0 +DA:137,0 +DA:139,0 +DA:140,0 +DA:141,0 +DA:142,0 +DA:146,0 +DA:147,0 +DA:148,0 +DA:150,0 +DA:152,0 +DA:153,0 +DA:154,0 +DA:155,0 +DA:157,0 +DA:158,0 +LF:57 +LH:0 +end_of_record +SF:lib/widgets/pack_button.dart +DA:21,0 +DA:26,0 +DA:28,0 +DA:30,0 +DA:31,0 +DA:32,0 +DA:33,0 +DA:34,0 +DA:36,0 +DA:37,0 +DA:38,0 +DA:39,0 +DA:40,0 +DA:41,0 +DA:44,0 +DA:47,0 +DA:49,0 +DA:50,0 +DA:51,0 +DA:52,0 +DA:54,0 +DA:55,0 +DA:56,0 +DA:58,0 +DA:60,0 +DA:61,0 +DA:63,0 +DA:64,0 +DA:65,0 +DA:67,0 +DA:69,0 +DA:70,0 +DA:72,0 +DA:73,0 +DA:74,0 +DA:76,0 +DA:81,0 +DA:82,0 +DA:84,0 +DA:85,0 +DA:86,0 +DA:88,0 +DA:92,0 +DA:93,0 +DA:95,0 +DA:96,0 +DA:97,0 +DA:98,0 +DA:99,0 +DA:100,0 +DA:101,0 +DA:103,0 +DA:106,0 +DA:108,0 +DA:109,0 +DA:110,0 +DA:115,0 +DA:116,0 +DA:117,0 +DA:119,0 +DA:126,0 +DA:127,0 +DA:128,0 +DA:129,0 +DA:130,0 +DA:131,0 +DA:132,0 +DA:134,0 +DA:135,0 +DA:136,0 +DA:137,0 +DA:146,0 +DA:147,0 +DA:149,0 +DA:150,0 +DA:159,0 +DA:161,0 +DA:163,0 +DA:164,0 +DA:166,0 +DA:167,0 +DA:168,0 +DA:170,0 +DA:174,0 +DA:176,0 +DA:180,0 +DA:181,0 +DA:182,0 +DA:183,0 +DA:184,0 +DA:185,0 +DA:187,0 +DA:190,0 +DA:191,0 +DA:194,0 +DA:195,0 +DA:196,0 +DA:197,0 +DA:201,0 +DA:203,0 +DA:204,0 +DA:205,0 +DA:221,0 +DA:248,0 +DA:250,0 +DA:251,0 +DA:252,0 +DA:254,0 +DA:256,0 +DA:257,0 +DA:258,0 +DA:260,0 +DA:262,0 +LF:113 +LH:0 +end_of_record diff --git a/test_ci_locally.sh b/test_ci_locally.sh new file mode 120000 index 0000000..d410b27 --- /dev/null +++ b/test_ci_locally.sh @@ -0,0 +1 @@ +tools/scripts/test_ci_locally.sh \ No newline at end of file diff --git a/tools/.gitignore b/tools/.gitignore new file mode 100644 index 0000000..6f4bf17 --- /dev/null +++ b/tools/.gitignore @@ -0,0 +1,30 @@ +# Build artifacts +*.exe +*.so +*.dylib +build/ +.dart_tool/ + +# Logs +*.log +logs/ + +# Temporary files +*.tmp +*.bak +*.swp + +# OS files +.DS_Store +Thumbs.db + +# IDE files +.vscode/ +.idea/ +*.iml + +# SSH keys (never commit!) +*.pem +*.key +id_* +ssh-* diff --git a/tools/README.md b/tools/README.md new file mode 100644 index 0000000..0e2e346 --- /dev/null +++ b/tools/README.md @@ -0,0 +1,78 @@ +# tools - Development & Deployment Tools + +Инструменты для разработки, тестирования и развертывания проекта Mnemo Cards. + +## Структура + +``` +tools/ +├── ci/ # CI/CD workflows для Forgejo Actions +│ ├── ci-main.yml # Главный pipeline +│ ├── ci-backend.yml # Backend CI +│ ├── ci-web.yml # Web app CI +│ ├── ci-mobile.yml # Mobile app CI +│ ├── cd-deploy.yml # Deployment +│ ├── code-quality.yml # Quality checks +│ ├── release.yml # Auto releases +│ └── agent.yml # AI agent +├── deploy/ # Deployment scripts +│ ├── backend-build_app.sh # Backend build & deploy +│ └── web-app/ # Web app deployment +│ ├── config.sh # Configuration +│ ├── deploy.sh # Main deploy script +│ └── nginx.conf # Nginx config +├── docs/ # Documentation +│ └── CI_CD_SETUP.md # CI/CD setup guide +└── scripts/ # Utility scripts + ├── check_deploy_ready.sh # Pre-deploy checks + └── test_ci_locally.sh # Local CI/CD testing +``` + +## Быстрый старт + +### Проверка готовности к деплою + +```bash +./scripts/check_deploy_ready.sh +``` + +### Локальное тестирование CI/CD + +```bash +./scripts/test_ci_locally.sh +``` + +### Настройка CI/CD + +См. [CI/CD Setup Guide](docs/CI_CD_SETUP.md) + +## CI/CD Workflow + +1. **Code Quality** - линтинг, тесты, безопасность +2. **Build** - параллельная сборка всех компонентов +3. **Deploy** - автоматическое развертывание на сервера + +### Компоненты + +- **Backend** (Dart) → `api.memo-cards.online` +- **Web App** (Flutter) → `memo-cards.online` +- **Mobile App** (Flutter) → GitHub releases + +## Требования + +### Локальная разработка +- Flutter SDK +- Dart SDK +- Git + +### Деплой +- SSH доступ к серверу `147.45.152.129` +- DNS: `memo-cards.online`, `api.memo-cards.online` +- Forgejo с настроенными secrets + +## Документация + +- [CI/CD Setup](docs/CI_CD_SETUP.md) - полное руководство по настройке +- [Deploy Scripts](deploy/README.md) - скрипты деплоя +- [CI Workflows](ci/README.md) - CI/CD pipelines +- [Scripts](scripts/README.md) - вспомогательные скрипты diff --git a/tools/ci/README.md b/tools/ci/README.md new file mode 100644 index 0000000..8191f70 --- /dev/null +++ b/tools/ci/README.md @@ -0,0 +1,76 @@ +# CI/CD Workflows + +Forgejo Actions workflows для автоматической сборки, тестирования и развертывания проекта. + +## Быстрый старт + +1. **Проверьте готовность:** + ```bash + ../../scripts/check_deploy_ready.sh + ``` + +2. **Настройте секреты в Forgejo:** + ``` + DEPLOY_SSH_PRIVATE_KEY # SSH ключ для деплоя + ``` + +3. **Протестируйте локально:** + ```bash + ../../scripts/test_ci_locally.sh + ``` + +4. **Запустите деплой:** + ```bash + git push origin main + ``` + +## Workflows + +- `ci-main.yml` - Главный pipeline (координирует все остальные) +- `ci-backend.yml` - CI для backend (Dart) +- `ci-web.yml` - CI для веб приложения (Flutter Web) +- `ci-mobile.yml` - CI для мобильного приложения (Flutter) +- `cd-deploy.yml` - CD для развертывания на сервер +- `code-quality.yml` - Контроль качества кода +- `release.yml` - Автоматические релизы +- `agent.yml` - AI-агент для автоматической генерации кода + +## Процесс CI/CD + +### 1. Code Quality Gate +- Проверка линтинга для всех проектов +- Запуск тестов с покрытием +- Сканирование на наличие секретов +- Проверка зависимостей на уязвимости + +### 2. Сборка компонентов +- **Backend**: Компиляция в нативный бинарный файл +- **Web App**: Сборка Flutter web приложения +- **Mobile App**: Сборка APK для Android и app для iOS + +### 3. Развертывание +- **Backend**: Автоматическое обновление сервиса на `api.memo-cards.online` +- **Web App**: Rsync на веб сервер `memo-cards.online` + перезагрузка Nginx +- **Mobile App**: Создание GitHub релиза с APK + +## Секреты Forgejo + +```bash +DEPLOY_SSH_PRIVATE_KEY # SSH ключ для доступа к серверу 147.45.152.129 +``` + +## Ручной запуск + +### Backend деплой +```bash +../../deploy/backend-build_app.sh +``` + +### Web app деплой +```bash +../../deploy/web-app/deploy.sh +``` + +## Troubleshooting + +См. [CI_CD_SETUP.md](../../docs/CI_CD_SETUP.md) для подробной диагностики проблем. diff --git a/.forgejo/workflows/agent.yml b/tools/ci/agent.yml similarity index 100% rename from .forgejo/workflows/agent.yml rename to tools/ci/agent.yml diff --git a/.forgejo/workflows/cd-deploy.yml b/tools/ci/cd-deploy.yml similarity index 100% rename from .forgejo/workflows/cd-deploy.yml rename to tools/ci/cd-deploy.yml diff --git a/.forgejo/workflows/ci-backend.yml b/tools/ci/ci-backend.yml similarity index 100% rename from .forgejo/workflows/ci-backend.yml rename to tools/ci/ci-backend.yml diff --git a/.forgejo/workflows/ci-main.yml b/tools/ci/ci-main.yml similarity index 62% rename from .forgejo/workflows/ci-main.yml rename to tools/ci/ci-main.yml index c6faba6..dcd1d81 100644 --- a/.forgejo/workflows/ci-main.yml +++ b/tools/ci/ci-main.yml @@ -8,21 +8,21 @@ on: jobs: code-quality: - uses: ./.forgejo/workflows/code-quality.yml + uses: ./code-quality.yml backend-ci: needs: code-quality - uses: ./.forgejo/workflows/ci-backend.yml + uses: ./ci-backend.yml web-ci: needs: code-quality - uses: ./.forgejo/workflows/ci-web.yml + uses: ./ci-web.yml mobile-ci: needs: code-quality - uses: ./.forgejo/workflows/ci-mobile.yml + uses: ./ci-mobile.yml deploy: needs: [backend-ci, web-ci, mobile-ci] if: github.ref == 'refs/heads/main' || github.ref == 'refs/heads/master' - uses: ./.forgejo/workflows/cd-deploy.yml + uses: ./cd-deploy.yml diff --git a/.forgejo/workflows/ci-mobile.yml b/tools/ci/ci-mobile.yml similarity index 100% rename from .forgejo/workflows/ci-mobile.yml rename to tools/ci/ci-mobile.yml diff --git a/.forgejo/workflows/ci-web.yml b/tools/ci/ci-web.yml similarity index 100% rename from .forgejo/workflows/ci-web.yml rename to tools/ci/ci-web.yml diff --git a/.forgejo/workflows/code-quality.yml b/tools/ci/code-quality.yml similarity index 100% rename from .forgejo/workflows/code-quality.yml rename to tools/ci/code-quality.yml diff --git a/.forgejo/workflows/release.yml b/tools/ci/release.yml similarity index 100% rename from .forgejo/workflows/release.yml rename to tools/ci/release.yml diff --git a/tools/deploy/README.md b/tools/deploy/README.md new file mode 100644 index 0000000..bfe72be --- /dev/null +++ b/tools/deploy/README.md @@ -0,0 +1,79 @@ +# Deploy Scripts + +Скрипты для развертывания компонентов проекта на сервера. + +## Структура + +``` +deploy/ +├── backend-build_app.sh # Сборка и деплой backend +└── web-app/ # Скрипты деплоя веб приложения + ├── config.sh # Конфигурация деплоя + ├── deploy.sh # Основной скрипт деплоя + ├── nginx.conf # Nginx конфигурация + └── setup-*.sh # Дополнительные setup скрипты +``` + +## Использование + +### Backend + +```bash +# Сборка и деплой backend на сервер +./backend-build_app.sh +``` + +### Web App + +```bash +# Переход в директорию web-app +cd web-app + +# Деплой веб приложения +./deploy.sh +``` + +## Конфигурация + +### Переменные окружения + +Основные настройки в `web-app/config.sh`: + +- `SERVER_IP` - IP сервера (147.45.152.129) +- `DOMAIN` - домен веб приложения (memo-cards.online) +- `API_BASE_URL` - URL API (https://api.memo-cards.online:8081) + +### SSH доступ + +Необходим SSH ключ для доступа к серверу. Ключ должен быть добавлен: + +1. В Forgejo secrets: `DEPLOY_SSH_PRIVATE_KEY` +2. На сервере в `~/.ssh/authorized_keys` + +## Процесс деплоя + +### Backend +1. Компиляция Dart кода в бинарный файл +2. Копирование на сервер +3. Обновление systemd сервиса +4. Перезапуск сервиса +5. Получение SSL сертификата (Let's Encrypt) + +### Web App +1. Сборка Flutter Web приложения +2. Копирование файлов на сервер (rsync) +3. Обновление Nginx конфигурации +4. Перезапуск Nginx +5. Получение SSL сертификата (Let's Encrypt) + +## SSL сертификаты + +Автоматически получаются сертификаты Let's Encrypt для: +- `memo-cards.online` (web app) +- `api.memo-cards.online` (backend API) + +## Безопасность + +- Используется SSH ключ для аутентификации +- Nginx конфигурация включает security headers +- CORS правильно настроен между доменами diff --git a/mnemo_cards_backend/build_app.sh b/tools/deploy/backend-build_app.sh similarity index 100% rename from mnemo_cards_backend/build_app.sh rename to tools/deploy/backend-build_app.sh diff --git a/mnemo_cards_web_v2/deploy/README.md b/tools/deploy/web-app/README.md similarity index 100% rename from mnemo_cards_web_v2/deploy/README.md rename to tools/deploy/web-app/README.md diff --git a/tools/deploy/web-app/VSCODE_README.md b/tools/deploy/web-app/VSCODE_README.md new file mode 100644 index 0000000..b3562b3 --- /dev/null +++ b/tools/deploy/web-app/VSCODE_README.md @@ -0,0 +1,70 @@ +# VSCode Server Setup + +VSCode (code-server) успешно установлен на сервере и доступен по адресу: + +**URL:** https://vscode.mnemo-cards.online + +## Учетные данные для входа + +- **Username:** vscode +- **Password:** AGktOidxrah1KVC0 + +## Доступ + +- ✅ Доступен только по домену vscode.mnemo-cards.online +- ❌ Заблокирован доступ по IP адресу сервера +- 🔒 Защищен SSL сертификатом от Let's Encrypt + +## Служба + +Code-server запущен как systemd сервис и автоматически запускается при перезагрузке сервера. + +```bash +# Проверить статус +sudo systemctl status code-server + +# Перезапустить +sudo systemctl restart code-server + +# Остановить +sudo systemctl stop code-server +``` + +## Конфигурация + +- Порт: 8080 (локально, проксируется через nginx) +- Пользователь: vscode +- Конфигурационный файл: `/home/vscode/.config/code-server/config.yaml` + +## Рабочая директория + +- **Домашняя директория:** `/home/vscode` +- **Репозиторий:** `/home/vscode/cards` (символическая ссылка: `/root/cards`) +- **Файлы конфигурации:** `/home/vscode/.config/code-server/` + +## Безопасность + +- 🔐 **Аутентификация:** Сильный пароль (16 символов) +- 🔒 **SSL/TLS:** Полностью шифрованное HTTPS соединение с сертификатом Let's Encrypt +- 🚫 **Доступ по IP:** Заблокирован - только по домену vscode.mnemo-cards.online +- 🛡️ **Rate Limiting:** + - Логин: максимум 5 попыток в минуту + - Общие запросы: максимум 30 запросов в минуту с burst до 10 +- 🔨 **Fail2Ban:** Автоматическая блокировка IP при подозрительной активности + - 3 неудачные попытки логина → бан на 1 час + - DDoS защита: 100 запросов в минуту → бан на 10 минут +- 👤 **Пользователь:** Отдельный пользователь vscode без sudo прав +- 📁 **Файловая система:** Полный доступ к своему репозиторию +- 🔄 **Автообновление:** SSL сертификаты обновляются автоматически + +## Обновление сертификатов + +SSL сертификаты автоматически обновляются через cron job certbot. + +## Устранение неполадок + +Если возникли проблемы с доступом: + +1. Проверьте статус code-server: `sudo systemctl status code-server` +2. Проверьте nginx конфигурацию: `sudo nginx -t` +3. Проверьте логи: `sudo journalctl -u code-server -f` diff --git a/mnemo_cards_web_v2/deploy/config.sh b/tools/deploy/web-app/config.sh similarity index 100% rename from mnemo_cards_web_v2/deploy/config.sh rename to tools/deploy/web-app/config.sh diff --git a/mnemo_cards_web_v2/deploy/deploy.sh b/tools/deploy/web-app/deploy.sh similarity index 100% rename from mnemo_cards_web_v2/deploy/deploy.sh rename to tools/deploy/web-app/deploy.sh diff --git a/mnemo_cards_web_v2/deploy/fix-forgejo-config.sh b/tools/deploy/web-app/fix-forgejo-config.sh similarity index 100% rename from mnemo_cards_web_v2/deploy/fix-forgejo-config.sh rename to tools/deploy/web-app/fix-forgejo-config.sh diff --git a/mnemo_cards_web_v2/deploy/forgejo-nginx.conf b/tools/deploy/web-app/forgejo-nginx.conf similarity index 100% rename from mnemo_cards_web_v2/deploy/forgejo-nginx.conf rename to tools/deploy/web-app/forgejo-nginx.conf diff --git a/mnemo_cards_web_v2/deploy/nginx.conf b/tools/deploy/web-app/nginx.conf similarity index 100% rename from mnemo_cards_web_v2/deploy/nginx.conf rename to tools/deploy/web-app/nginx.conf diff --git a/mnemo_cards_web_v2/deploy/setup-forgejo-domain.sh b/tools/deploy/web-app/setup-forgejo-domain.sh similarity index 100% rename from mnemo_cards_web_v2/deploy/setup-forgejo-domain.sh rename to tools/deploy/web-app/setup-forgejo-domain.sh diff --git a/tools/deploy/web-app/setup-vscode-domain.sh b/tools/deploy/web-app/setup-vscode-domain.sh new file mode 100755 index 0000000..09db83d --- /dev/null +++ b/tools/deploy/web-app/setup-vscode-domain.sh @@ -0,0 +1,185 @@ +#!/bin/bash + +# Setup script for VSCode (code-server) domain (vscode.mnemo-cards.online) +# Usage: ./setup-vscode-domain.sh + +set -e + +# Load configuration +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +source "$SCRIPT_DIR/config.sh" + +echo "🚀 Setting up VSCode (code-server) domain: vscode.mnemo-cards.online..." + +# Colors for output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' # No Color + +print_status() { + echo -e "${GREEN}[INFO]${NC} $1" +} + +print_warning() { + echo -e "${YELLOW}[WARNING]${NC} $1" +} + +print_error() { + echo -e "${RED}[ERROR]${NC} $1" +} + +print_success() { + echo -e "${GREEN}[SUCCESS]${NC} $1" +} + +print_info() { + echo -e "${BLUE}[INFO]${NC} $1" +} + +# Upload nginx config for VSCode +print_status "Uploading VSCode nginx configuration..." +scp "$SCRIPT_DIR/vscode-nginx.conf" "$SERVER_USER@$SERVER_IP:/tmp/vscode-nginx.conf" + +print_status "Setting up VSCode domain on server..." +# Execute setup commands on server +ssh "$SERVER_USER@$SERVER_IP" << EOF + set -e + + echo "Setting up VSCode (code-server) domain configuration..." + + # Install code-server if not already installed + if ! command -v code-server &> /dev/null; then + echo "Installing code-server..." + + # Update package list + apt update + + # Install required dependencies + apt install -y curl wget gnupg2 software-properties-common apt-transport-https ca-certificates + + # Add code-server repository + curl -fsSL https://code-server.dev/install.sh | sh + + echo "✅ code-server installed successfully" + else + echo "✅ code-server is already installed" + fi + + # Create code-server user if it doesn't exist + if ! id -u vscode &>/dev/null; then + echo "Creating vscode user..." + useradd -m -s /bin/bash vscode + echo "vscode:vscode123!" | chpasswd + usermod -aG sudo vscode + fi + + # Create code-server configuration directory + mkdir -p /home/vscode/.config/code-server + + # Create code-server config file + cat > /home/vscode/.config/code-server/config.yaml << 'CODE_SERVER_CONFIG_EOF' +bind-addr: 127.0.0.1:8080 +auth: password +password: vscode123! +cert: false +CODE_SERVER_CONFIG_EOF + + # Set proper ownership + chown -R vscode:vscode /home/vscode/.config + + # Create systemd service for code-server + cat > /etc/systemd/system/code-server.service << 'SYSTEMD_EOF' +[Unit] +Description=code-server +After=network.target + +[Service] +Type=simple +User=vscode +WorkingDirectory=/home/vscode +ExecStart=/usr/bin/code-server --config /home/vscode/.config/code-server/config.yaml +Restart=always +RestartSec=10 + +[Install] +WantedBy=multi-user.target +SYSTEMD_EOF + + # Enable and start code-server service + systemctl daemon-reload + systemctl enable code-server + systemctl start code-server + + # Wait a moment for service to start + sleep 5 + + # Check if service is running + if systemctl is-active --quiet code-server; then + echo "✅ code-server service started successfully" + else + echo "❌ Failed to start code-server service" + systemctl status code-server + exit 1 + fi + + # Install SSL certificate for vscode.mnemo-cards.online + if [ ! -d "/etc/letsencrypt/live/vscode.mnemo-cards.online" ]; then + echo "🔐 Getting Let's Encrypt SSL certificate for vscode.mnemo-cards.online..." + + # Stop nginx temporarily for certificate issuance + systemctl stop nginx 2>/dev/null || true + + if certbot certonly --standalone -d vscode.mnemo-cards.online --non-interactive --agree-tos --email admin@memo-cards.online; then + echo "✅ Let's Encrypt certificate obtained successfully for vscode.mnemo-cards.online!" + else + echo "❌ Failed to get Let's Encrypt certificate. Generating self-signed certificate..." + if [ ! -f "/etc/ssl/certs/nginx-selfsigned-vscode.crt" ]; then + openssl req -x509 -nodes -days 365 -newkey rsa:2048 \ + -keyout /etc/ssl/private/nginx-selfsigned-vscode.key \ + -out /etc/ssl/certs/nginx-selfsigned-vscode.crt \ + -subj "/C=RU/ST=Moscow/L=Moscow/O=MnemoCards/OU=IT/CN=vscode.mnemo-cards.online" + fi + fi + + # Start nginx again + systemctl start nginx 2>/dev/null || true + else + echo "✅ Let's Encrypt certificate already exists for vscode.mnemo-cards.online" + fi + + # Configure nginx for VSCode + echo "Configuring nginx for VSCode..." + + # Copy VSCode nginx configuration + cp /tmp/vscode-nginx.conf /etc/nginx/sites-available/vscode + + # Enable VSCode site + ln -sf /etc/nginx/sites-available/vscode /etc/nginx/sites-enabled/vscode + + # Test nginx configuration + nginx -t + + # Restart nginx + systemctl restart nginx + systemctl enable nginx + + # Setup cron for certificate renewal (if not already configured) + if ! crontab -l | grep -q "vscode.mnemo-cards.online"; then + echo "Setting up cron job for VSCode certificate renewal..." + (crontab -l ; echo "0 12 * * * certbot renew --quiet --cert-name vscode.mnemo-cards.online") | crontab - + fi + + echo "VSCode domain setup completed successfully!" + echo "VSCode is now available at: https://vscode.mnemo-cards.online" + echo "Username: vscode" + echo "Password: vscode123!" + echo "Access by IP address is blocked" +EOF + +print_success "VSCode domain setup completed successfully! 🎉" +print_success "VSCode is now available at: https://vscode.mnemo-cards.online" +print_info "Username: vscode" +print_info "Password: vscode123!" +print_info "Make sure DNS is configured: vscode.mnemo-cards.online -> $SERVER_IP" diff --git a/mnemo_cards_web_v2/deploy/setup_ssh_webroot.sh b/tools/deploy/web-app/setup_ssh_webroot.sh similarity index 100% rename from mnemo_cards_web_v2/deploy/setup_ssh_webroot.sh rename to tools/deploy/web-app/setup_ssh_webroot.sh diff --git a/mnemo_cards_web_v2/deploy/test-forgejo-domain.sh b/tools/deploy/web-app/test-forgejo-domain.sh similarity index 100% rename from mnemo_cards_web_v2/deploy/test-forgejo-domain.sh rename to tools/deploy/web-app/test-forgejo-domain.sh diff --git a/tools/deploy/web-app/vscode-nginx.conf b/tools/deploy/web-app/vscode-nginx.conf new file mode 100644 index 0000000..eafaabd --- /dev/null +++ b/tools/deploy/web-app/vscode-nginx.conf @@ -0,0 +1,99 @@ +# Note: Default server blocks are defined in forgejo configuration +# This configuration only handles vscode.mnemo-cards.online domain + +server { + listen 80; + server_name vscode.mnemo-cards.online; + + # Redirect HTTP to HTTPS + return 301 https://$server_name$request_uri; +} + +server { + listen 443 ssl http2; + server_name vscode.mnemo-cards.online; + + # SSL configuration - Let's Encrypt + ssl_certificate /etc/letsencrypt/live/vscode.mnemo-cards.online/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/vscode.mnemo-cards.online/privkey.pem; + + # Fallback to self-signed certificates if Let's Encrypt fails + # ssl_certificate /etc/ssl/certs/nginx-selfsigned-vscode.crt; + # ssl_certificate_key /etc/ssl/private/nginx-selfsigned-vscode.key; + ssl_protocols TLSv1.2 TLSv1.3; + ssl_ciphers ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384; + ssl_prefer_server_ciphers off; + + # Security headers + add_header X-Frame-Options "SAMEORIGIN" always; + add_header X-XSS-Protection "1; mode=block" always; + add_header X-Content-Type-Options "nosniff" always; + add_header Referrer-Policy "no-referrer-when-downgrade" always; + add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always; + + # Special rate limiting for login attempts + location /login { + # Strict rate limiting for login + limit_req zone=vscode_login burst=2 nodelay; + limit_req_status 429; + + proxy_pass http://localhost:8080; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + + # WebSocket support for VSCode + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + + # Timeout settings + proxy_connect_timeout 60s; + proxy_send_timeout 60s; + proxy_read_timeout 60s; + + # Buffer settings + proxy_buffering off; + proxy_request_buffering off; + } + + # Proxy to code-server running on port 8080 + location / { + # Apply rate limiting + limit_req zone=vscode_general burst=10 nodelay; + limit_req_status 429; + + proxy_pass http://localhost:8080; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + + # WebSocket support for VSCode + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + + # Timeout settings + proxy_connect_timeout 60s; + proxy_send_timeout 60s; + proxy_read_timeout 60s; + + # Buffer settings + proxy_buffering off; + proxy_request_buffering off; + } + + # Gzip compression + gzip on; + gzip_vary on; + gzip_min_length 1024; + gzip_proxied expired no-cache no-store private auth; + gzip_types text/plain text/css text/xml text/javascript application/x-javascript application/xml+rss application/javascript; + + # Security - deny access to hidden files + location ~ /\. { + deny all; + } +} diff --git a/tools/docs/CI_CD_SETUP.md b/tools/docs/CI_CD_SETUP.md new file mode 100644 index 0000000..91fbd57 --- /dev/null +++ b/tools/docs/CI_CD_SETUP.md @@ -0,0 +1,307 @@ +# Настройка CI/CD для проекта Mnemo Cards + +Этот документ описывает настройку автоматической сборки, тестирования и развертывания проекта в Forgejo. + +## Архитектура CI/CD + +Проект использует многоуровневую архитектуру CI/CD с разделением на отдельные компоненты: + +- **Backend** (Dart) - серверная часть +- **Web App** (Flutter Web) - веб версия приложения +- **Mobile App** (Flutter) - мобильное приложение для Android/iOS +- **Common Libraries** - общие пакеты + +## Структура Workflow + +``` +tools/ci/ +├── ci-main.yml # Главный координирующий workflow +├── ci-backend.yml # CI для backend +├── ci-web.yml # CI для веб приложения +├── ci-mobile.yml # CI для мобильного приложения +├── cd-deploy.yml # CD для развертывания +├── code-quality.yml # Контроль качества кода +├── release.yml # Автоматические релизы +└── agent.yml # AI-агент для автоматической генерации кода +``` + +## Требуемые Secrets + +Для работы CI/CD необходимо настроить следующие секреты в Forgejo: + +### SSH доступ для развертывания +``` +DEPLOY_SSH_PRIVATE_KEY # Приватный SSH ключ для доступа к серверу 147.45.152.129 +``` + +### API ключи (опционально) +``` +OPENAI_API_KEY # Для AI-агента +``` + +## Настройка серверов + +### Единый сервер (147.45.152.129) +- **API Backend** (api.memo-cards.online): Dart SDK, systemd сервис `mnemo_cards_server.service` +- **Web App** (memo-cards.online): Nginx, Flutter Web приложение +- **SSL**: Let's Encrypt сертификаты для обоих доменов +- **CORS**: Правильно настроен между доменами, COEP/COOP headers отключены для совместимости +- Доступ по SSH для деплоя + +## Процесс CI/CD + +### 1. Code Quality Gate +- Проверка линтинга для всех проектов +- Запуск тестов с покрытием +- Сканирование на наличие секретов +- Проверка зависимостей на уязвимости + +### 2. Сборка компонентов +- **Backend**: Компиляция в нативный бинарный файл +- **Web App**: Сборка Flutter web приложения +- **Mobile App**: Сборка APK для Android и app для iOS + +### 3. Развертывание +- **Backend**: Автоматическое обновление сервиса +- **Web App**: Rsync на веб сервер + перезагрузка Nginx +- **Mobile App**: Создание GitHub релиза с APK + +## 🚀 Быстрый старт деплоя + +### ✅ Чек-лист готовности + +- [ ] **SSH ключ сгенерирован и добавлен на сервер** +- [ ] **DNS домены настроены** (`memo-cards.online`, `api.memo-cards.online`, `code.memo-cards.online`) +- [ ] **Forgejo secrets настроены** (`DEPLOY_SSH_PRIVATE_KEY`) +- [ ] **Код готов к деплою** (все тесты проходят) + +### 🎯 Запуск в 3 шага + +1. **Подготовка:** + ```bash + # Генерация и настройка SSH ключа + ssh-keygen -t ed25519 -C "forgejo-deploy@memo-cards.online" -f ~/.ssh/forgejo_deploy + ssh-copy-id -i ~/.ssh/forgejo_deploy.pub root@147.45.152.129 + ``` + +2. **Настройка Forgejo:** + - Перейти в Settings → Secrets + - Добавить `DEPLOY_SSH_PRIVATE_KEY` с содержимым `~/.ssh/forgejo_deploy` + +3. **Запуск:** + ```bash + git push origin main # Автоматический запуск CI/CD + ``` + +## Запуск CI/CD + +### 🔧 Предварительная настройка + +#### 1. Настройка SSH доступа +```bash +# Генерация SSH ключа (если нет) +ssh-keygen -t ed25519 -C "forgejo-deploy@mnemo-cards.online" -f ~/.ssh/forgejo_deploy + +# Копирование публичного ключа на сервер +ssh-copy-id -i ~/.ssh/forgejo_deploy.pub root@147.45.152.129 + +# Добавление приватного ключа в Forgejo secrets +# Settings → Secrets → DEPLOY_SSH_PRIVATE_KEY +cat ~/.ssh/forgejo_deploy +``` + +#### 2. Настройка DNS доменов +Убедитесь, что DNS записи настроены: +- `memo-cards.online` → `147.45.152.129` +- `api.memo-cards.online` → `147.45.152.129` +- `code.memo-cards.online` → `147.45.152.129` (для Forgejo) + +#### 3. Проверка доступа к серверу +```bash +# Тест SSH подключения +ssh -i ~/.ssh/forgejo_deploy root@147.45.152.129 "echo 'SSH works!'" + +# Проверка что Dart установлен +ssh root@147.45.152.129 "dart --version" + +# Проверка что Nginx установлен +ssh root@147.45.152.129 "nginx -v" +``` + +### 🚀 Запуск деплоя + +#### Автоматический запуск +CI/CD запускается автоматически при: +- Push в ветки `main`/`master` +- Создании Pull Request +- Создании тега релиза (`v*.*.*`) + +#### Ручной запуск +1. Перейдите в раздел **Actions** в Forgejo +2. Выберите workflow **"Main CI Pipeline"** +3. Нажмите **"Run workflow"** + +#### Ручной деплой (альтернатива) +```bash +# Деплой backend +tools/deploy/backend-build_app.sh + +# Деплой web app +cd mnemo_cards_web_v2 +tools/deploy/web-app/deploy.sh +``` + +## Мониторинг и логи + +### Просмотр результатов +- Результаты тестов: `coverage/lcov.info` +- Логи сборки: В разделе Actions каждого workflow +- Артефакты сборки: Скачиваются из Actions + +### Уведомления +При успешном/неуспешном завершении можно настроить уведомления через: +- Email +- Webhooks +- Forgejo notifications + +## Создание релиза + +### Автоматический релиз +1. Создайте git tag: `git tag v1.2.3 && git push origin v1.2.3` +2. Workflow автоматически: + - Создаст GitHub release + - Обновит версии в pubspec.yaml файлах + - Опубликует APK и другие артефакты + +### Ручной релиз +Используйте существующие скрипты: +```bash +./mnemo_cards_backend/build_app.sh # Деплой backend +./mnemo_cards_web_v2/deploy/deploy.sh # Деплой web app +``` + +## Troubleshooting + +### 🚨 Проблемы с деплоем + +#### SSH подключение не работает +```bash +# Проверка SSH ключа локально +ssh -i ~/.ssh/forgejo_deploy root@147.45.152.129 "echo 'Connection OK'" + +# Проверка что ключ добавлен в known_hosts +ssh-keyscan -H 147.45.152.129 >> ~/.ssh/known_hosts + +# В Forgejo secrets должен быть полный приватный ключ +cat ~/.ssh/forgejo_deploy +``` + +#### Backend деплой падает +```bash +# Проверка что Dart установлен на сервере +ssh root@147.45.152.129 "which dart && dart --version" + +# Ручной запуск build скрипта +tools/deploy/backend-build_app.sh + +# Проверка статуса сервиса +ssh root@147.45.152.129 "systemctl status mnemo_cards_server" +``` + +#### Web app деплой падает +```bash +# Проверка что Nginx установлен +ssh root@147.45.152.129 "which nginx && nginx -v" + +# Ручной запуск deploy скрипта +cd mnemo_cards_web_v2 +tools/deploy/web-app/deploy.sh + +# Проверка Nginx конфигурации +ssh root@147.45.152.129 "nginx -t" +``` + +#### SSL сертификаты не работают +```bash +# Проверка Let's Encrypt сертификатов +ssh root@147.45.152.129 "ls -la /etc/letsencrypt/live/" + +# Ручное получение сертификатов +ssh root@147.45.152.129 "certbot certonly --standalone -d memo-cards.online -d api.memo-cards.online --email admin@memo-cards.online" +``` + +#### DNS проблемы +```bash +# Проверка DNS разрешения +nslookup memo-cards.online +nslookup api.memo-cards.online +nslookup code.memo-cards.online + +# Проверка доступности портов +telnet 147.45.152.129 80 +telnet 147.45.152.129 443 +telnet 147.45.152.129 8080 +telnet 147.45.152.129 8081 +``` + +### Проблемы с зависимостями +```bash +# Очистка кэша +flutter clean +flutter pub cache repair +``` + +### Проблемы с SSH +```bash +# Проверка SSH ключа +ssh -T git@code.memo-cards.online + +# Проверка доступа к серверам +ssh -i ~/.ssh/forgejo_deploy root@147.45.152.129 +``` + +### Проблемы с тестами +```bash +# Запуск тестов локально +cd mnemo_cards_web_v2 +flutter test --coverage + +# Просмотр покрытия +genhtml coverage/lcov.info -o coverage/html +open coverage/html/index.html +``` + +## Безопасность + +### Защита секретов +- Никогда не коммитьте реальные ключи в код +- Используйте отдельные ключи для каждого окружения +- Регулярно ротируйте SSH ключи + +### Code Quality Gates +- Минимальное покрытие тестами: 80% +- Обязательный проход линтера +- Сканирование на уязвимости в зависимостях + +## Расширение CI/CD + +### Добавление нового компонента +1. Создайте новый workflow файл в `.forgejo/workflows/` +2. Добавьте ссылку в `ci-main.yml` +3. Настройте необходимые секреты + +### Кастомные проверки +Добавьте в `code-quality.yml`: +```yaml +- name: Custom check + run: | + # Ваша логика проверки +``` + +## Контакты + +При проблемах с CI/CD: +1. Проверьте логи в Actions +2. Убедитесь, что все секреты настроены +3. Проверьте доступ к серверам +4. Создайте issue в репозитории diff --git a/tools/scripts/README.md b/tools/scripts/README.md new file mode 100644 index 0000000..4bfd5a1 --- /dev/null +++ b/tools/scripts/README.md @@ -0,0 +1,61 @@ +# Development Scripts + +Вспомогательные скрипты для разработки и тестирования. + +## Скрипты + +### `check_deploy_ready.sh` + +Проверяет готовность проекта к деплою: + +- Наличие SSH ключей +- Доступность сервера +- Установленное ПО (Dart, Nginx) +- DNS разрешение доменов +- Локальные CI/CD тесты + +```bash +./check_deploy_ready.sh +``` + +### `test_ci_locally.sh` + +Запускает локальное тестирование CI/CD pipeline: + +- Проверка зависимостей +- Линтинг кода +- Запуск тестов +- Проверка CORS конфигурации +- Валидация workflow файлов + +```bash +./test_ci_locally.sh +``` + +## Использование + +### Перед деплоем + +```bash +# Всегда проверяйте готовность перед деплоем +./check_deploy_ready.sh + +# И тестируйте CI/CD локально +./test_ci_locally.sh +``` + +### В CI/CD pipeline + +Эти скрипты автоматически запускаются в Forgejo Actions, но могут быть запущены и локально для отладки. + +## Выходные коды + +- `0` - Успешное выполнение +- `1` - Ошибка выполнения + +## Логи + +Скрипты выводят цветные логи: +- 🟢 `[OK]` - успешные проверки +- 🟡 `[WARN]` - предупреждения +- 🔴 `[ERROR]` - ошибки diff --git a/tools/scripts/check_deploy_ready.sh b/tools/scripts/check_deploy_ready.sh new file mode 100755 index 0000000..4d66c94 --- /dev/null +++ b/tools/scripts/check_deploy_ready.sh @@ -0,0 +1,109 @@ +#!/bin/bash + +# Script to check if deployment is ready +# Run this before attempting deployment + +set -e + +# Change to project root +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +PROJECT_ROOT="$(cd "$SCRIPT_DIR/../../.." && pwd)" +cd "$PROJECT_ROOT" + +echo "🔍 Checking deployment readiness..." + +# Colors +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' + +SERVER_IP="147.45.152.129" +SSH_KEY="${SSH_DEPLOY_KEY:-$HOME/.ssh/forgejo_deploy}" + +print_status() { + echo -e "${GREEN}[OK]${NC} $1" +} + +print_warning() { + echo -e "${YELLOW}[WARN]${NC} $1" +} + +print_error() { + echo -e "${RED}[ERROR]${NC} $1" +} + +print_info() { + echo -e "${BLUE}[INFO]${NC} $1" +} + +# Check 1: SSH key exists +echo "1. Checking SSH key..." +if [ -f "$SSH_KEY" ]; then + print_status "SSH private key found at $SSH_KEY" +else + print_error "SSH private key not found at $SSH_KEY" + echo " Generate with: ssh-keygen -t ed25519 -C 'forgejo-deploy@memo-cards.online' -f $SSH_KEY" + exit 1 +fi + +# Check 2: SSH connection +echo "2. Checking SSH connection..." +if ssh -o ConnectTimeout=10 -o BatchMode=yes -i "$SSH_KEY" root@$SERVER_IP "echo 'SSH OK'" 2>/dev/null; then + print_status "SSH connection to server successful" +else + print_error "Cannot connect to server via SSH" + echo " Make sure the public key is added to root@$SERVER_IP:~/.ssh/authorized_keys" + echo " Run: ssh-copy-id -i $SSH_KEY.pub root@$SERVER_IP" + exit 1 +fi + +# Check 3: Required software on server +echo "3. Checking server software..." +if ssh -i "$SSH_KEY" root@$SERVER_IP "which dart nginx" >/dev/null 2>&1; then + print_status "Dart and Nginx are installed on server" +else + print_error "Dart or Nginx not found on server" + echo " Install with: apt update && apt install -y dart nginx" + exit 1 +fi + +# Check 4: DNS resolution +echo "4. Checking DNS resolution..." +for domain in "memo-cards.online" "api.memo-cards.online" "code.memo-cards.online"; do + if nslookup "$domain" 2>/dev/null | grep -q "$SERVER_IP"; then + print_status "DNS for $domain resolves to $SERVER_IP" + else + print_warning "DNS for $domain may not be configured correctly" + echo " Expected: $domain -> $SERVER_IP" + fi +done + +# Check 5: Network connectivity +echo "5. Checking network connectivity..." +for port in 22 80 443 8080 8081; do + if nc -z -w5 $SERVER_IP $port 2>/dev/null; then + print_status "Port $port is accessible" + else + print_warning "Port $port is not accessible" + fi +done + +# Check 6: Local tests +echo "6. Running local CI/CD tests..." +if ./test_ci_locally.sh 2>&1 | grep -q "SUCCESS.*CORS configuration check completed"; then + print_status "Local CI/CD tests passed" +else + print_warning "Local CI/CD tests failed - check output above" +fi + +# Summary +echo "" +print_info "=== DEPLOYMENT READINESS SUMMARY ===" +print_info "Server IP: $SERVER_IP" +print_info "SSH Key: $SSH_KEY" +print_info "" +print_info "If all checks passed, you can proceed with deployment!" +print_info "Run: git push origin main" +echo "" diff --git a/tools/scripts/test_ci_locally.sh b/tools/scripts/test_ci_locally.sh new file mode 100755 index 0000000..4302087 --- /dev/null +++ b/tools/scripts/test_ci_locally.sh @@ -0,0 +1,214 @@ +#!/bin/bash + +# Script for local testing of CI/CD pipeline +# Run this before pushing to ensure everything works + +set -e + +# Change to project root +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +PROJECT_ROOT="$(cd "$SCRIPT_DIR/../../.." && pwd)" +cd "$PROJECT_ROOT" + +echo "🚀 Testing CI/CD pipeline locally..." + +# Colors for output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' # No Color + +print_status() { + echo -e "${GREEN}[INFO]${NC} $1" +} + +print_warning() { + echo -e "${YELLOW}[WARNING]${NC} $1" +} + +print_error() { + echo -e "${RED}[ERROR]${NC} $1" +} + +print_success() { + echo -e "${GREEN}[SUCCESS]${NC} $1" +} + +# Function to check if command exists +command_exists() { + command -v "$1" >/dev/null 2>&1 +} + +# Check prerequisites +print_status "Checking prerequisites..." + +if ! command_exists flutter; then + print_error "Flutter not found. Please install Flutter SDK." + exit 1 +fi + +if ! command_exists dart; then + print_error "Dart not found. Please install Dart SDK." + exit 1 +fi + +print_success "Prerequisites check passed" + +# Test backend +print_status "Testing backend..." +cd mnemo_cards_backend + +if [ -f "pubspec.yaml" ]; then + print_status "Installing backend dependencies..." + dart pub get + + print_status "Running backend code generation..." + dart run build_runner build --delete-conflicting-outputs || true + + print_status "Running backend lints..." + dart analyze lib/ || print_warning "Backend linting failed" + dart format --set-exit-if-changed lib/ || print_warning "Backend formatting check failed" + + print_status "Running backend tests..." + dart test --coverage || print_warning "Backend tests failed" + + print_success "Backend tests completed" +else + print_warning "Backend pubspec.yaml not found, skipping..." +fi + +cd .. + +# Test web app +print_status "Testing web app..." +cd mnemo_cards_web_v2 + +if [ -f "pubspec.yaml" ]; then + print_status "Installing web app dependencies..." + flutter pub get + + print_status "Running web app code generation..." + flutter pub run build_runner build --delete-conflicting-outputs || true + + print_status "Running web app lints..." + flutter analyze lib/ || print_warning "Web app linting failed" + flutter format --set-exit-if-changed lib/ || print_warning "Web app formatting check failed" + + print_status "Running web app tests..." + flutter test --coverage || print_warning "Web app tests failed" + + print_success "Web app tests completed" +else + print_warning "Web app pubspec.yaml not found, skipping..." +fi + +cd .. + +# # Test mobile app +# print_status "Testing mobile app..." +# cd mnemo_cards + +# if [ -f "pubspec.yaml" ]; then +# print_status "Installing mobile app dependencies..." +# flutter pub get + +# print_status "Running mobile app code generation..." +# flutter pub run build_runner build --delete-conflicting-outputs || true + +# print_status "Running mobile app lints..." +# flutter analyze lib/ || print_warning "Mobile app linting failed" +# flutter format --set-exit-if-changed lib/ || print_warning "Mobile app formatting check failed" + +# print_status "Running mobile app tests..." +# flutter test --coverage || print_warning "Mobile app tests failed" + +# print_success "Mobile app tests completed" +# else +# print_warning "Mobile app pubspec.yaml not found, skipping..." +# fi + +# cd .. + +# Test common packages +print_status "Testing common packages..." + +common_projects=("mnemo_cards_common" "mnemo_cards_common_backend" "mnemo_cards_frontend_common") + +for project in "${common_projects[@]}"; do + if [ -d "$project" ]; then + print_status "Testing $project..." + cd $project + + if [ -f "pubspec.yaml" ]; then + flutter pub get || dart pub get || print_warning "Failed to get dependencies for $project" + flutter analyze lib/ 2>/dev/null || dart analyze lib/ 2>/dev/null || print_warning "Linting failed for $project" + fi + + cd .. + fi +done + +print_success "Common packages tests completed" + +# Test CORS configuration +print_status "Testing CORS configuration..." + +# Check backend CORS config +if [ -f "mnemo_cards_backend/lib/api/mnemo_shelf.dart" ]; then + if grep -q "Access-Control-Allow-Origin.*\*" "mnemo_cards_backend/lib/api/mnemo_shelf.dart"; then + print_success "Backend CORS configured correctly (allows all origins)" + else + print_warning "Backend CORS configuration may be too restrictive" + fi +fi + +# Check web app nginx config for conflicting headers +if [ -f "mnemo_cards_web_v2/deploy/nginx.conf" ]; then + if grep -q "^[[:space:]]*add_header Cross-Origin-Embedder-Policy.*require-corp" "mnemo_cards_web_v2/deploy/nginx.conf" || grep -q "^[[:space:]]*add_header Cross-Origin-Opener-Policy.*same-origin" "mnemo_cards_web_v2/deploy/nginx.conf"; then + print_warning "Web app nginx has active COEP/COOP headers that may conflict with CORS" + else + print_success "Web app nginx CORS configuration looks good (COEP/COOP headers disabled)" + fi +fi + +print_success "CORS configuration check completed" + +# Check for uncommitted changes +print_status "Checking for uncommitted changes..." +if [ -n "$(git status --porcelain)" ]; then + print_warning "You have uncommitted changes:" + git status --short + print_warning "Please commit or stash them before pushing" +else + print_success "No uncommitted changes" +fi + +# Check workflow files +print_status "Validating workflow files..." +if [ -d ".forgejo/workflows" ]; then + for workflow in .forgejo/workflows/*.yml; do + if [ -f "$workflow" ]; then + print_status "Validating $workflow..." + # Basic YAML syntax check + if command_exists yamllint; then + yamllint "$workflow" || print_warning "YAML syntax issue in $workflow" + else + python3 -c "import yaml; yaml.safe_load(open('$workflow'))" || print_warning "YAML syntax issue in $workflow" + fi + fi + done + print_success "Workflow validation completed" +else + print_warning "No .forgejo/workflows directory found" +fi + +# Summary +print_success "Local CI/CD testing completed!" +print_status "If all tests passed, you can safely push your changes." +print_status "Don't forget to:" +echo " 1. Set up secrets in Forgejo if not done yet" +echo " 2. Test deployment scripts locally if possible" +echo " 3. Check that all required servers are accessible" + +exit 0