Українська
Завдання
Відповідно до номера свого варіанта виконайте завдання обраного рівня складності.
Варіанти
Варіант 1. Резервне копіювання тек
1. Початковий рівень. Створити консольну програму, яка запитує в користувача шлях до вихідної теки та шлях до теки резервної копії, асинхронно копіює всі файли верхнього рівня (FileStream.CopyToAsync) і після кожного файла виводить його назву та розмір. Наприкінці програма виводить кількість скопійованих файлів і загальний обсяг у мегабайтах.
2. Базовий рівень. Створити консольну програму, яка асинхронно копіює теку з усіма підтеками до іншої теки (шляхи вводяться з клавіатури). Програма перевіряє існування вихідної теки, виводить прогрес через IProgress<T> (відсоток скопійованих байтів після кожного файла) і дозволяє скасувати копіювання клавішею Esc; після скасування виводиться, скільки файлів і байтів скопійовано, а недокопійований файл вилучається.
3. Високий рівень. Створити консольний застосунок backup, який приймає аргументи source і target та опції --parallel N (кількість одночасних копіювань, типово 4), --timeout сек, --only-newer (копіювати лише файли, новіші за наявні в копії) і --help. Копіювання обмежується SemaphoreSlim, кожен файл копіюється в окремій задачі, прогрес виводиться одним рядком. Помилки окремих файлів (доступ заборонено, файл зайнятий) не зупиняють роботу: після завершення програма виводить таблицю «файл – розмір – результат – час, мс», підсумки та всі помилки з AggregateException у потік помилок. Для тестової теки з 200 файлів виміряти час для --parallel 1, 2, 4, 8 і вивести таблицю прискорень. Коди завершення: 0 – успіх, 1 – часткові помилки, 2 – скасовано, 3 – некоректні аргументи.
Варіант 2. Хешування файлів дистрибутива
1. Початковий рівень. Створити консольну програму, яка для всіх файлів теки, шлях до якої вводить користувач, обчислює хеші SHA-256 за допомогою SHA256.HashDataAsync і виводить таблицю «файл – розмір – хеш». Файли обробляються послідовно з await.
2. Базовий рівень. Створити консольну програму, яка перевіряє контрольні суми дистрибутива. Програма читає файл SHA256SUMS.txt (рядки у форматі «хеш назва файла»), одночасно обчислює хеші файлів з обмеженням до 4 задач (SemaphoreSlim) і виводить для кожного файла «OK», «НЕ ЗБІГАЄТЬСЯ» або «ВІДСУТНІЙ». Наприкінці виводяться кількість файлів кожної категорії та загальний час; відсутній або некоректний файл сум спричиняє повідомлення.
3. Високий рівень. Створити консольний застосунок hashcheck з командами create тека (створити файл сум) і verify тека та опціями --algorithm sha256|sha512, --parallel N, --help. Хешування виконується в задачах з обмеженням паралелізму, прогрес виводиться через IProgress<T>, клавіша Esc скасовує роботу з повідомленням про кількість оброблених файлів. Програма генерує тестову теку з 100 файлів по 20 МБ (якщо її немає), вимірює час для 1, 2, 4, 8 і 16 одночасних задач і виводить таблицю «задачі – час, с – прискорення – ефективність»; результати всіх запусків мають збігатися з послідовним варіантом. Помилки читання виводяться в потік помилок, код завершення 1, якщо є розбіжності сум.
Варіант 3. Курси валют із кількох джерел
1. Початковий рівень. Створити консольну програму, яка імітує три джерела курсу долара (асинхронні методи з різними затримками Task.Delay від 200 до 1500 мс і фіксованими курсами), запускає запити одночасно, за допомогою Task.WhenAny виводить перший отриманий курс, назву джерела та час очікування.
2. Базовий рівень. Створити консольну програму, яка запитує в користувача код валюти (USD, EUR, PLN) і одночасно звертається до трьох імітованих джерел курсу з випадковими затримками та ймовірністю відмови 30 %. Програма використовує першу успішну відповідь (WhenAny у циклі, задачі з помилками пропускаються), обмежує загальне очікування 1 с (WaitAsync) і в разі таймауту або відмови всіх джерел використовує резервний курс з локального файла JSON з позначкою «резервне джерело».
3. Високий рівень. Створити консольний застосунок rates, який приймає коди валют аргументами та опції --timeout мс, --sources N (кількість імітованих джерел), --strategy first|median і --help. Стратегія first бере першу успішну відповідь і скасовує решту запитів токеном; median чекає всі відповіді до таймауту й обчислює медіану. Імітовані джерела мають затримки та відмови, задані у файлі sources.json. Програма виводить таблицю «валюта – курс – джерело (джерела) – час, мс – стан», підсумок кількості скасованих, невдалих і прострочених запитів; винятки всіх джерел виводяться в потік помилок, а якщо жоден курс не отримано, код завершення – 1.
Варіант 4. Обробка фотографій туристів
1. Початковий рівень. Створити консольну програму, яка імітує обробку 10 фотографій: для кожної запускається задача Task.Run, що «зменшує» фото (затримка 100–500 мс) і повертає новий розмір файла. Після Task.WhenAll програма виводить таблицю «фото – розмір до – розмір після» і загальну економію місця.
2. Базовий рівень. Створити консольну програму, яка для кількості фотографій, введеної користувачем, будує граф задач: «зменшити» → «додати водяний знак» → «зберегти» за допомогою продовжень. Для 10 % фотографій (вибір визначає Random зі сталим зерном) зменшення кидає виняток; продовження з OnlyOnRanToCompletion пропускають такі фото, а продовження з OnlyOnFaulted записує помилку. Програма виводить стани всіх задач і звіт про оброблені та пошкоджені фото.
3. Високий рівень. Створити консольний застосунок photos, який приймає шлях до файла CSV зі списком фото (назва, розмір, мегапікселі) та опції --steps resize,watermark,compress, --parallel N, --fail-rate відсоток, --help. Для кожного фото будується ланцюжок етапів (тривалість пропорційна мегапікселям), кількість одночасно оброблюваних фото обмежується. Помилки будь-якого етапу збираються через AggregateException і не зупиняють інші фото. Програма виводить таблицю «фото – етапи – стан – час, мс», звіт про помилки з назвою етапу та час обробки для --parallel 1, 4 і 16 з прискоренням. Некоректні рядки CSV виводяться в потік помилок.
Варіант 5. Опитування метеостанцій
1. Початковий рівень. Створити консольну програму з асинхронним генератором IAsyncEnumerable<double>, який кожні 500 мс (PeriodicTimer) повертає температуру імітованої метеостанції. Програма перебирає 10 показників циклом await foreach і виводить номер, час і температуру.
2. Базовий рівень. Створити консольну програму, яка одночасно опитує три імітовані метеостанції (асинхронні генератори з різними періодами) і виводить показники в міру надходження. Для кожної станції обчислюються мінімум, максимум і середнє. Опитування зупиняється через кількість секунд, введену користувачем (CancelAfter), або клавішею Esc; після зупинки виводиться таблиця статистики станцій.
3. Високий рівень. Створити консольний застосунок weather, який читає конфігурацію станцій з файла JSON (назва, період, базова температура, ймовірність збою) і приймає опції --duration сек, --window N (ковзне вікно), --alert градуси, --csv файл, --help. Кожна станція – асинхронний генератор з [EnumeratorCancellation]; збій станції не зупиняє інші, а повторна спроба виконується через 1 с. Програма виводить ковзні середні, попередження про перевищення порогу, записує всі показники у CSV через await using і після завершення виводить таблицю «станція – показників – збоїв – мін – макс – середнє». Некоректна конфігурація спричиняє код завершення 2.
Варіант 6. Перевірка посилань у документах
1. Початковий рівень. Створити консольну програму, яка запускає в собі локальний тестовий сервер HttpListener зі сторінками /ok, /missing (404) і /slow (затримка 3 с), за допомогою HttpClient перевіряє три посилання послідовно з await і виводить для кожного код відповіді та час запиту.
2. Базовий рівень. Створити консольну програму, яка читає текстовий файл, знаходить у ньому всі посилання на локальний тестовий сервер (http://localhost:порт/..., сервер запускається в тій самій програмі) і перевіряє їх одночасно, не більше 5 запитів водночас (SemaphoreSlim), з таймаутом 2 с на запит. Програма виводить таблицю «посилання – результат – час, мс» і кількість робочих, битих і прострочених посилань.
3. Високий рівень. Створити консольний застосунок linkcheck, який приймає файли Markdown або HTML аргументами та опції --parallel N, --timeout мс, --retries K, --report файл і --help. Посилання перевіряються через HttpClient на локальному тестовому сервері, що імітує затримки, коди 200, 301, 404, 500 і розриви з’єднання; повторні спроби виконуються лише для помилок 5xx і таймаутів. Програма виводить таблицю «файл – рядок – посилання – результат – спроб – час» із підсумками, записує звіт у CSV, порівнює загальний час для --parallel 1, 5 і 20 і повертає код 1, якщо знайдено биті посилання.
Варіант 7. Імпорт замовлень із CSV
1. Початковий рівень. Створити консольну програму, яка асинхронно читає файл orders.csv (номер, клієнт, сума) методом File.ReadAllLinesAsync, перетворює рядки на записи та виводить кількість замовлень і загальну суму.
2. Базовий рівень. Створити консольну програму, яка одночасно імпортує замовлення з кількох файлів CSV (імена вводяться через пробіл) у задачах Task.Run. Під час розбору некоректний рядок спричиняє FormatException з номером рядка та назвою файла. Після Task.WhenAll програма виводить усі помилки з AggregateException.InnerExceptions, а також кількість успішно імпортованих замовлень і суму за кожним файлом.
3. Високий рівень. Створити консольний застосунок import, який приймає файли CSV або теку та опції --strict (будь-яка помилка скасовує весь імпорт), --parallel N, --out файл і --help. Рядки файлів читаються асинхронним генератором IAsyncEnumerable<string>, валідуються (дата, сума, email) і збираються в загальний список без дублікатів номерів. У режимі --strict перша помилка скасовує решту задач через спільний токен, інакше помилки накопичуються. Програма виводить таблицю «файл – рядків – імпортовано – помилок – час», перші 10 помилок, записує результат у CSV і повертає код 0, 1 (часткові помилки) або 2 (імпорт скасовано).
Варіант 8. Розрахунок заробітної плати
1. Початковий рівень. Створити консольну програму, у якій задано списки працівників трьох відділів (оклад, премія у відсотках). Для кожного відділу запускається задача Task<decimal>, що обчислює фонд оплати праці; після Task.WhenAll виводиться фонд кожного відділу та загальна сума.
2. Базовий рівень. Створити консольну програму, яка читає файл CSV з працівниками (відділ, ПІБ, оклад, відпрацьовані дні, премія) і обчислює зарплату з утриманням податків (18 % ПДФО, 5 % військовий збір) окремою задачею для кожного відділу. Некоректні дані відділу переводять його задачу в стан Faulted, але інші відділи обробляються. Програма виводить відомість за відділами із підсумками та список відділів з помилками.
3. Високий рівень. Створити консольний застосунок payroll, який приймає файл працівників, місяць (--month 2026-09) і опції --departments список, --parallel, --out теку, --help. Для кожного відділу будується ланцюжок «розрахунок → перевірка лімітів → запис відомості у файл» з асинхронним записом. Програма генерує тестові дані на 100 000 працівників, порівнює час послідовного й паралельного розрахунку (таблиця «варіант – час – прискорення») і перевіряє, що загальні суми збігаються до копійки. Помилки відділів виводяться в потік помилок, підсумкова відомість – вирівняною таблицею з рядком «Разом».
Варіант 9. Трансляція спортивних подій
1. Початковий рівень. Створити консольну програму, яка імітує три матчі: для кожного асинхронний метод кожні 300–800 мс генерує подію («гол», «кутовий», «картка») і виводить її з назвою матчу. Програма запускає матчі одночасно й чекає їх завершення через Task.WhenAll.
2. Базовий рівень. Створити консольну програму, у якій імітовані матчі передають події в Channel<MatchEvent>, а кілька асинхронних обробників (табло, статистика, журнал) обробляють їх. Обробка кожної події обмежена таймаутом 200 мс (WaitAsync), а прострочена обробка фіксується як попередження. Тривалість трансляції вводить користувач; наприкінці виводиться рахунок і статистика подій за типами.
3. Високий рівень. Створити консольний застосунок broadcast, який читає розклад матчів з файла JSON і приймає опції --speed множник, --handlers табло,журнал,статистика, --handler-timeout мс і --help. Події матчів надходять у канал, кожен обробник працює у власній задачі; повільний або аварійний обробник не затримує інших, а його винятки збираються. Клавіша Esc коректно зупиняє трансляцію з дочитуванням каналу. Після завершення виводиться таблиця «матч – рахунок – подій» та таблиця «обробник – оброблено – прострочено – помилок – середній час, мс»; журнал подій записується у файл асинхронно.
Варіант 10. Архіватор журналів
1. Початковий рівень. Створити консольну програму, яка асинхронно стискає файл журналу, шлях до якого вводить користувач, у формат GZip (GZipStream, CopyToAsync) і виводить розміри до та після стиснення та коефіцієнт стиснення.
2. Базовий рівень. Створити консольну програму, яка стискає всі файли *.log заданої теки в GZip одночасно (не більше 4 файлів водночас), виводить прогрес через IProgress<T> (кількість оброблених файлів і байтів) і дозволяє скасувати архівацію клавішею Esc; частково записані архіви при скасуванні вилучаються. Наприкінці виводиться таблиця файлів із коефіцієнтами стиснення.
3. Високий рівень. Створити консольний застосунок logzip, який приймає теку та опції --older-than днів, --level fastest|optimal|smallest, --parallel N, --delete-source, --timeout сек, --help. Програма генерує тестові журнали (200 файлів), стискає їх з обмеженим паралелізмом, перевіряє кожен архів розпакуванням у пам’ять і лише тоді вилучає вихідний файл. Виводиться таблиця «рівень – паралелізм – час – прискорення – сумарний коефіцієнт» для рівнів стиснення та 1, 2, 4, 8 задач. Помилки доступу до файлів виводяться в потік помилок; код завершення 2 при скасуванні.
Варіант 11. Пошук у бібліотеці книг
1. Початковий рівень. Створити консольну програму, яка запитує в користувача слово та асинхронно читає всі текстові файли теки books, виводячи назви книг, що містять це слово, і кількість входжень у кожній.
2. Базовий рівень. Створити консольну програму, яка шукає фразу, введену користувачем, у всіх книгах теки одночасно (окрема задача на книгу) і за допомогою Task.WhenAny виводить першу знайдену книгу та номер рядка. Після першого результату інші задачі скасовуються спільним токеном; програма виводить, скільки задач завершилося, скасувалося та скільки часу минуло до першого результату.
3. Високий рівень. Створити консольний застосунок booksearch, який приймає теку і фразу та опції --mode first|all, --ignore-case, --parallel N, --timeout мс, --help. У режимі first повертається перший збіг зі скасуванням решти задач, у режимі all – усі збіги в порядку готовності (Task.WhenEach) з виведенням «книга – рядок – фрагмент». Програма генерує тестову бібліотеку з 500 книг, вимірює час обох режимів для --parallel 1, 4, 16 і перевіряє, що режим all знаходить стільки ж збігів, скільки послідовний пошук. Помилки читання файлів виводяться в потік помилок.
Варіант 12. Бронювання авіаквитків
1. Початковий рівень. Створити консольну програму з імітованим сервісом бронювання: асинхронний метод BookAsync з імовірністю 50 % кидає TimeoutException. Програма повторює спробу до 5 разів із затримкою 300 мс між спробами та виводить номер кожної спроби й результат.
2. Базовий рівень. Створити консольну програму, яка бронює квитки на рейс, номер якого вводить користувач, через імітований сервіс з випадковими відмовами. Повтори виконуються з експоненційною затримкою (200, 400, 800 мс…) з випадковим відхиленням до 20 %, лише для тимчасових помилок (TimeoutException, HttpRequestException); помилка «місць немає» не повторюється. Загальний час обмежено 5 с токеном скасування; програма виводить журнал спроб і результат.
3. Високий рівень. Створити консольний застосунок booking, який читає список запитів на бронювання з файла CSV (пасажир, рейс, клас) і приймає опції --max-retries, --base-delay мс, --timeout сек, --parallel N, --seed, --help. Метод повторних спроб реалізується як узагальнена функція вищого порядку RetryAsync<T> з токеном скасування. Бронювання виконуються одночасно з обмеженням, сервіс імітує перевантаження (більше помилок, якщо одночасних запитів понад 5). Програма виводить таблицю «пасажир – рейс – результат – спроб – час», статистику спроб і порівняння кількості успіхів для --parallel 2, 5, 10.
Варіант 13. Музичний плейліст
1. Початковий рівень. Створити консольну програму з класом-імітатором програвача, який через заданий час генерує подію TrackFinished. За допомогою TaskCompletionSource програма перетворює подію на задачу й послідовно «відтворює» три треки, виводячи назви й момент завершення кожного.
2. Базовий рівень. Створити консольну програму, яка читає плейліст з файла (назва, тривалість у секундах) і відтворює його на імітаторі програвача з подіями TrackFinished та PlaybackError. Метод PlayAsync повертає задачу через TaskCompletionSource (RunContinuationsAsynchronously), помилка переводить задачу в стан Faulted, а клавіша S (пропустити) скасовує поточний трек. Програма виводить журнал відтворення та загальний час.
3. Високий рівень. Створити консольний застосунок player, який приймає файл плейлиста та опції --shuffle, --repeat N, --speed множник, --crossfade мс і --help. Імітатор програвача має події початку, завершення, помилки та буферизації; кожна подія перетворюється на задачу з таймаутом (WaitAsync), тому «завислий» трек пропускається. Клавіші N, P і Esc (наступний, пауза, стоп) обробляються в окремій задачі. Після завершення виводиться таблиця «трек – заплановано – фактично – результат» і сумарна статистика; невідомі опції та відсутні файли спричиняють повідомлення в потік помилок і код завершення 1.
Варіант 14. Обчислення числа π кількома методами
1. Початковий рівень. Створити консольну програму, яка одночасно запускає дві задачі обчислення числа π: ряд Лейбніца (100 мільйонів членів) і метод Монте-Карло (100 мільйонів точок). Програма виводить значення, похибку та час кожної задачі.
2. Базовий рівень. Створити консольну програму, яка запитує в користувача потрібну точність (кількість знаків після коми, 3–9) і запускає «змагання» трьох методів обчислення π (ряд Лейбніца, формула Валліса, Монте-Карло), які періодично перевіряють досягнення точності й токен скасування. Перший метод, що досяг точності, визначається через Task.WhenAny, решта скасовується; програма виводить переможця, стани всіх задач і кількість виконаних ітерацій.
3. Високий рівень. Створити консольний застосунок pi-race, який приймає опції --digits N, --methods leibniz,wallis,montecarlo,nilakantha, --timeout сек, --parallel-mc N (кількість задач для методу Монте-Карло) і --help. Кожен метод повідомляє прогрес через IProgress<T>, Монте-Карло розбивається на N задач з незалежними генераторами. Програма виводить таблицю «метод – досягнута точність – ітерацій – час – стан», для Монте-Карло – таблицю «задачі – час – прискорення – ефективність» для 1, 2, 4, 8, 16 задач і перевіряє, що скасовані задачі мають стан Canceled, а не Faulted.
Варіант 15. Моніторинг сайтів
1. Початковий рівень. Створити консольну програму, яка запускає локальний тестовий сервер HttpListener з трьома сторінками з різними затримками і за допомогою PeriodicTimer кожні 2 с перевіряє доступність сторінок HttpClient, виводячи час перевірки, код відповіді і час відповіді. Програма виконує 5 циклів перевірки.
2. Базовий рівень. Створити консольну програму, яка періодично (інтервал вводить користувач) одночасно перевіряє сторінки локального тестового сервера, що випадково сповільнюється або повертає 503. Кожен запит має таймаут 1 с; для кожної сторінки програма накопичує кількість перевірок, відмов, мінімальний, середній і максимальний час відповіді. Моніторинг зупиняється клавішею Esc, після чого виводиться таблиця статистики.
3. Високий рівень. Створити консольний застосунок monitor, який читає список перевірок з файла JSON (адреса на локальному тестовому сервері, інтервал, таймаут, очікуваний код) і приймає опції --duration хв, --alert-after N (відмов поспіль), --log файл, --help. Кожна перевірка працює у власному циклі PeriodicTimer, результати записуються в журнал асинхронно; після N відмов поспіль виводиться попередження, а після відновлення – повідомлення з тривалістю простою. Наприкінці виводиться таблиця «сайт – доступність, % – відмов – p50, мс – p95, мс – максимум, мс». Помилки конфігурації спричиняють код завершення 2.
Варіант 16. Конвертер субтитрів
1. Початковий рівень. Створити консольну програму, яка асинхронно читає файл субтитрів SRT, зсуває час усіх субтитрів на кількість секунд, введену користувачем (може бути від’ємною), і асинхронно записує результат у новий файл.
2. Базовий рівень. Створити консольну програму, яка перетворює субтитри з формату SRT у формат WebVTT асинхронним конвеєром з трьох етапів: читання блоків (IAsyncEnumerable<string>), перетворення, запис. Некоректні блоки пропускаються з повідомленням, що містить номер блока. Програма виводить кількість перетворених і пропущених блоків і дозволяє скасувати перетворення великого файла клавішею Esc.
3. Високий рівень. Створити консольний застосунок subconv, який приймає файли або теку та опції --to srt|vtt, --shift мс, --fps-from, --fps-to (перерахунок частоти кадрів), --parallel N, --help. Кожен файл обробляється асинхронним конвеєром «читання → розбір → перетворення → запис», файли обробляються одночасно з обмеженням. Помилки окремих файлів збираються й виводяться в потік помилок, а решта файлів обробляється. Програма генерує 100 тестових файлів, виводить таблицю «файл – блоків – пропущено – час» та порівняння часу для 1, 4 і 16 одночасних файлів.
Варіант 17. Шкільний розклад
1. Початковий рівень. Створити консольну програму, яка запускає 4 задачі Task.Run, кожна з яких генерує випадковий розклад уроків на тиждень для одного класу (зі своїм зерном Random) і обчислює кількість «вікон». Програма виводить розклад з найменшою кількістю вікон.
2. Базовий рівень. Створити консольну програму, яка генерує варіанти шкільного розкладу для кількох класів з обмеженнями (не більше 7 уроків на день, у вчителя не два уроки одночасно) у кількох задачах одночасно. Час пошуку обмежено кількістю секунд, введеною користувачем (CancelAfter); після таймауту кожна задача повертає найкращий знайдений варіант, а програма виводить найкращий розклад і кількість перевірених варіантів кожною задачею.
3. Високий рівень. Створити консольний застосунок timetable, який читає вчителів, класи та навчальне навантаження з файла JSON і приймає опції --tasks N, --time сек, --seed, --out файл, --help. Кожна задача виконує випадковий пошук із локальним покращенням, періодично повідомляє найкращу оцінку через IProgress<T> і перевіряє токен. Клавіша Esc або таймаут зупиняє пошук. Програма виводить розклад найкращого варіанта для кожного класу, таблицю «задачі – перевірено варіантів – найкраща оцінка» для 1, 2, 4, 8, 16 задач і записує розклад у файл CSV. Некоректні вхідні дані спричиняють код завершення 2.
Варіант 18. Складський облік
1. Початковий рівень. Створити консольну програму зі словником залишків 5 товарів, яка одночасно запускає 20 задач, що змінюють залишки (надходження та відвантаження), використовуючи ConcurrentDictionary.AddOrUpdate, і виводить кінцеві залишки та перевірку, що вони збігаються з послідовним розрахунком.
2. Базовий рівень. Створити консольну програму, яка обробляє файл операцій складу (товар, тип, кількість) пакетами одночасно. Операція відвантаження, що зробила б залишок від’ємним, кидає виняток; пакет з помилкою не застосовується (перевірка до зміни залишків), а інші пакети застосовуються. Програма виводить залишки, кількість застосованих і відхилених пакетів і всі помилки з AggregateException.
3. Високий рівень. Створити консольний застосунок warehouse, який приймає файли операцій кількох складів та опції --batch N, --parallel N, --on-error skip|stop, --help. Операції кожного складу обробляються в окремій задачі, пакети – атомарно (зміни застосовуються до копії й фіксуються лише після перевірки). Режим stop скасовує всі склади після першої помилки через спільний токен. Програма виводить таблицю «склад – операцій – застосовано – відхилено – стан задачі», підсумкові залишки з перевіркою відповідності послідовній обробці та звіт часткових відмов у потік помилок; код завершення 1, якщо є відхилені пакети.
Варіант 19. Лікарські взаємодії
1. Початковий рівень. Створити консольну програму, яка асинхронно завантажує локальну базу взаємодій ліків з файла JSON (JsonSerializer.DeserializeAsync), запитує в користувача назви двох препаратів і виводить опис їхньої взаємодії або повідомлення про її відсутність.
2. Базовий рівень. Створити консольну програму, яка перевіряє список препаратів, введений користувачем через кому, на попарні взаємодії. Кожен запит до «повільної» бази (затримка 300 мс) виконується асинхронно, а результати кешуються як задачі в ConcurrentDictionary<string, Task<Interaction?>>, тому однаковий запит не виконується двічі. Програма виводить таблицю знайдених взаємодій, кількість запитів до бази та кількість звернень до кешу.
3. Високий рівень. Створити консольний застосунок interactions, який приймає файл з рецептами (пацієнт, список препаратів) та опції --db файл, --parallel N, --cache-ttl сек, --severity minor|moderate|major, --help. Запити до бази імітують затримки та тимчасові збої; кеш задач зберігає лише успішні результати (невдала задача вилучається з кешу). Програма перевіряє рецепти одночасно, виводить для кожного пацієнта таблицю взаємодій заданої серйозності, підсумок «рецептів – запитів до бази – влучень у кеш – помилок» і порівняння часу з кешем і без нього.
Варіант 20. Пакетна розсилка сповіщень
1. Початковий рівень. Створити консольну програму, яка імітує надсилання 20 сповіщень асинхронним методом із затримкою 100 мс, надсилаючи одночасно не більше 5 (SemaphoreSlim), і виводить час відправлення кожного сповіщення та загальний час.
2. Базовий рівень. Створити консольну програму, яка читає список отримувачів з файла та надсилає сповіщення через імітований шлюз з обмеженням швидкості: не більше N повідомлень за секунду (N вводить користувач). Шлюз випадково відмовляє з імовірністю 10 %, невдалі повідомлення повторюються один раз. Програма виводить прогрес і звіт доставки: доставлено, повторно доставлено, не доставлено.
3. Високий рівень. Створити консольний застосунок notify, який приймає файл отримувачів і шаблон повідомлення та опції --rate N/с, --burst N, --channels email,sms,push, --retries K, --dry-run, --help. Для кожного каналу діє власне обмеження швидкості (реалізоване PeriodicTimer і SemaphoreSlim), канали працюють одночасно, Esc зупиняє розсилку з дочеканням поточних відправлень. Програма виводить звіт доставки «канал – надіслано – помилок – повторів – середня затримка», записує недоставлені повідомлення у файл для повторного запуску та перевіряє, що фактична швидкість не перевищила ліміт.
Варіант 21. Навігатор маршрутів
1. Початковий рівень. Створити консольну програму, яка одночасно запускає три задачі пошуку маршруту (імітація з різними затримками, кожна повертає довжину та час у дорозі) і після Task.WhenAll виводить усі маршрути та найкращий за часом.
2. Базовий рівень. Створити консольну програму, яка для графа доріг, заданого у файлі (місто, місто, відстань, середня швидкість), шукає маршрут між містами, введеними користувачем, кількома стратегіями в окремих задачах (найкоротша відстань, найменший час, найменше пересадок). Загальний пошук обмежено 2 с; задачі, що не встигли, скасовуються, а програма виводить найкращий зі знайдених маршрутів і стан кожної задачі.
3. Високий рівень. Створити консольний застосунок route, який приймає файл графа, пункти --from, --to, опції --via (проміжні пункти), --strategy, --timeout мс і --help. Альтернативні маршрути шукаються одночасно (алгоритм Дейкстри з різними вагами та варіант із забороною кожного ребра найкращого маршруту); кожна задача перевіряє токен. Програма виводить таблицю «маршрут – відстань – час – пересадок – задача – час пошуку», генерує граф на 10 000 вершин для вимірювання часу послідовного і паралельного пошуку альтернатив і повертає код 1, якщо маршрут не знайдено.
Варіант 22. Перевірка домашніх завдань
1. Початковий рівень. Створити консольну програму, яка імітує «компіляцію» 8 студентських робіт: кожна задача виконується випадковий час від 0,5 до 3 с, а через WaitAsync(TimeSpan) з таймаутом 2 с програма визначає, які роботи зібрано вчасно, і виводить таблицю результатів.
2. Базовий рівень. Створити консольну програму, яка перевіряє роботи студентів із теки (кожна робота – текстовий файл з «кодом»). Для кожної роботи імітується компіляція і запуск тестів у задачі з таймаутом, заданим користувачем; робота, що перевищила таймаут, скасовується токеном (а не лише перестає очікуватися). Програма виводить таблицю «студент – результат – тестів пройдено – час» і кількість робіт кожної категорії.
3. Високий рівень. Створити консольний застосунок grader, який приймає теку з роботами та файл тестів і опції --timeout сек, --parallel N, --attempts K, --report файл, --help. Перевірка кожної роботи – граф задач «компіляція → тести (паралельно) → оцінка», де невдала компіляція скасовує тести, а таймаут окремого тесту не зупиняє інші. Програма виводить таблицю оцінок з підсумками, звіт помилок компіляції, записує результати в CSV і порівнює загальний час перевірки для --parallel 1, 4, 8; некоректні аргументи спричиняють код завершення 2.
Варіант 23. Сканер портів локальної мережі
1. Початковий рівень. Створити консольну програму, яка перевіряє, чи відкриті порти 1–1024 на 127.0.0.1, асинхронно підключаючись методом TcpClient.ConnectAsync з таймаутом 200 мс, і виводить список відкритих портів. Для перевірки програма перед скануванням відкриває два порти TcpListener.
2. Базовий рівень. Створити консольну програму, яка сканує діапазон портів вузла localhost, введений користувачем, одночасно, не більше 100 підключень водночас, з таймаутом на підключення. Перед скануванням програма відкриває кілька тестових портів TcpListener. Програма виводить таблицю відкритих портів з часом відповіді, кількість закритих і прострочених портів і загальний час сканування.
3. Високий рівень. Створити консольний застосунок portscan, який приймає опції --host (лише localhost або адреси з 127.0.0.0/8), --ports 1-1024,8080, --parallel N, --timeout мс, --open-test 3 (кількість тестових слухачів) і --help. Сканування обмежує паралелізм, повідомляє прогрес через IProgress<T> і скасовується клавішею Esc. Програма виводить таблицю «порт – стан – час, мс – відома служба», порівняння часу сканування для --parallel 1, 10, 100, 500 і кількість потоків пулу до і після сканування (ThreadPool.ThreadCount). Заборонена адреса або некоректний діапазон спричиняє код завершення 2.
Варіант 24. Генерація PDF-звітів
1. Початковий рівень. Створити консольну програму, яка імітує генерацію 8 звітів (синхронне обчислення тривалістю близько 1 с кожне) у задачах Task.Run і виводить загальний час та кількість потоків пулу (ThreadPool.ThreadCount) під час роботи.
2. Базовий рівень. Створити консольну програму, яка генерує N звітів (N вводить користувач), імітуючи блокувальну операцію Thread.Sleep(2000), двома способами: задачами пулу Task.Run і задачами з TaskCreationOptions.LongRunning. Для кожного способу програма виводить загальний час, максимальну кількість потоків пулу та кількість окремих потоків (Process.GetCurrentProcess().Threads.Count) і пояснювальний висновок.
3. Високий рівень. Створити консольний застосунок reports, який приймає опції --count N, --mode pool|longrunning|async, --work мс, --compare, --help. Режим async замінює блокування на Task.Delay. Під час роботи окрема задача кожні 100 мс фіксує кількість потоків пулу та процесу. Опція --compare запускає всі режими для N = 10, 50, 200 і виводить таблицю «режим – N – час, с – макс. потоків пулу – макс. потоків процесу» та затримку старту останнього звіту, що показує голодування пулу. Звіти записуються у файли асинхронно; некоректні опції виводяться в потік помилок.
Варіант 25. Лабораторні вимірювання
1. Початковий рівень. Створити консольну програму з асинхронним генератором IAsyncEnumerable<double>, який імітує прилад: кожні 100 мс повертає вимір напруги з шумом. Програма перебирає 50 вимірів і виводить кожен десятий, а наприкінці – середнє і стандартне відхилення.
2. Базовий рівень. Створити консольну програму, яка читає асинхронний потік вимірів імітованого приладу і обчислює ковзну статистику у вікні розміром, введеним користувачем (середнє, мінімум, максимум, відхилення). Виміри, що відрізняються від ковзного середнього більше ніж на 3 стандартні відхилення, позначаються як викиди. Вимірювання зупиняється через задану кількість секунд (WithCancellation), після чого виводиться кількість вимірів і викидів.
3. Високий рівень. Створити консольний застосунок lab-meter, який приймає опції --channels N (кількість приладів), --rate Гц, --window N, --duration сек, --csv файл, --replay файл і --help. У режимі --replay виміри читаються з раніше записаного CSV зі збереженням інтервалів, інакше імітуються. Канали об’єднуються в один асинхронний потік, статистика кожного каналу оновлюється щосекунди одним рядком, усі виміри записуються у CSV через await using. Після завершення виводиться таблиця «канал – вимірів – середнє – σ – викидів – пропущено» і перевіряється, що фактична частота відповідає заданій з похибкою до 5 %.
Варіант 26. Ігрові сервери
1. Початковий рівень. Створити консольну програму, яка імітує «пінг» 5 ігрових серверів асинхронними методами з випадковими затримками (зерно Random задане), одночасно чекає всі відповіді й виводить сервери, відсортовані за затримкою.
2. Базовий рівень. Створити консольну програму, яка читає список серверів з файла (назва, регіон, базова затримка) і виконує по 5 імітованих пінгів кожного сервера, одночасно для всіх серверів. Пінг, довший за 500 мс, вважається втраченим (таймаут через токен). Програма виводить таблицю «сервер – регіон – середня затримка – втрати, %», відсортовану за середньою затримкою, і рекомендований сервер.
3. Високий рівень. Створити консольний застосунок ping-servers, який приймає файл серверів і опції --count N, --interval мс, --timeout мс, --region, --watch (безперервний режим з PeriodicTimer і зупинкою клавішею Esc) та --help. Для кожного сервера обчислюються мінімум, медіана, p95, джитер і втрати; результати в міру надходження виводяться через Task.WhenEach. Для порівняння справжнього мережевого виклику програма запускає локальний TCP-сервер і вимірює час TcpClient.ConnectAsync. Таблиця сортується за медіаною, сервери з втратами понад 20 % позначаються.
Варіант 27. Завантаження карт тайлами
1. Початковий рівень. Створити консольну програму, яка імітує завантаження 16 тайлів карти (сітка 4×4) асинхронними методами з випадковою затримкою, одночасно, і виводить сітку з часом завантаження кожного тайла та загальний час.
2. Базовий рівень. Створити консольну програму, яка завантажує тайли для масштабу, введеного користувачем (кількість тайлів 4^масштаб), з локального тестового сервера або імітованого джерела, не більше 8 одночасно, з повторенням невдалих завантажень до 3 разів. Тайли зберігаються у файли z/x/y.png, прогрес виводиться у відсотках, а наприкінці – кількість успішних, повторених і невдалих тайлів.
3. Високий рівень. Створити консольний застосунок tiles, який приймає опції --zoom від-до, --bbox x1,y1,x2,y2, --parallel N, --retries K, --cache тека, --timeout мс і --help. Уже збережені тайли не завантажуються повторно, джерело імітує затримки, помилки 429 (занадто багато запитів) і 500; після 429 застосовується затримка, вказана джерелом. Esc скасовує завантаження з видаленням неповних файлів. Програма виводить таблицю «масштаб – тайлів – з кешу – завантажено – повторів – помилок – час» і порівняння часу для --parallel 1, 4, 16, 64.
Варіант 28. Податкові декларації
1. Початковий рівень. Створити консольну програму, яка для декларації (дохід, витрати, пільги задані в програмі) послідовно виконує три перевірки як ланцюжок продовжень ContinueWith: обов’язкові поля, арифметика, ліміти пільг, і виводить результат кожної перевірки.
2. Базовий рівень. Створити консольну програму, яка читає декларації з файла JSON і для кожної будує ланцюжок перевірок продовженнями з умовними гілками: після успішної перевірки полів виконуються одночасно перевірки арифметики і пільг, після них – розрахунок податку; невдала перевірка через OnlyOnFaulted формує повідомлення про відхилення. Програма виводить для кожної декларації статус і суму податку або причини відхилення.
3. Високий рівень. Створити консольний застосунок tax-check, який приймає файл декларацій і опції --rules файл (ліміти та ставки), --year, --parallel N, --out теку, --help. Для кожної декларації будується граф задач з умовними продовженнями і таймаутом на перевірку в «зовнішньому реєстрі» (імітація із затримками та збоями). Винятки всіх перевірок збираються з AggregateException.Flatten(). Програма виводить таблицю «декларант – статус – податок – помилок – час», записує квитанції для прийнятих і повідомлення для відхилених декларацій у файли та повертає код 1, якщо є відхилені.
Варіант 29. Електронна черга в ЦНАП
1. Початковий рівень. Створити консольну програму, яка імітує видачу талонів у черзі: PeriodicTimer кожні 500 мс видає новий талон, а асинхронний метод оператора обслуговує талон 1–2 с. Програма працює 10 с і виводить журнал видачі й обслуговування.
2. Базовий рівень. Створити консольну програму, яка імітує електронну чергу з кількома віконцями (кількість вводить користувач): генератор відвідувачів на PeriodicTimer, віконця – асинхронні задачі, що забирають талони з черги. Робота зупиняється клавішею Esc; після зупинки нові талони не видаються, але черга дообслуговується. Журнал подій записується у файл асинхронно, а на екран виводяться середній час очікування та кількість обслугованих.
3. Високий рівень. Створити консольний застосунок queue, який приймає файл послуг (назва, середній час обслуговування, частка відвідувачів) і опції --windows N, --hours H, --speed множник, --break-every хв, --log файл, --help. Віконця мають перерви, послуги – пріоритети, робочий день завершується за таймером, а незавершені обслуговування коректно скасовуються. Журнал пишеться асинхронно без блокування віконець. Програма виводить таблицю «послуга – відвідувачів – середнє очікування – максимальне очікування – не обслуговано» та підбирає мінімальну кількість віконець, за якої середнє очікування не перевищує 15 хв.
Варіант 30. Порівняння async і потоків
1. Початковий рівень. Створити консольну програму, яка запускає 1 000 задач, кожна з яких виконує await Task.Delay(1000), і виводить загальний час, кількість потоків процесу та використану пам’ять (GC.GetTotalMemory).
2. Базовий рівень. Створити консольну програму, яка для кількості очікувань, введеної користувачем, виконує їх двома способами: окремими потоками Thread з Thread.Sleep(1000) і задачами з await Task.Delay(1000). Для кожного способу програма виводить загальний час, максимальну кількість потоків процесу та приріст робочого набору пам’яті (Process.WorkingSet64) у вигляді таблиці.
3. Високий рівень. Створити консольний застосунок wait-bench, який приймає опції --counts 100,1000,10000, --modes thread,pool-sleep,async, --delay мс, --csv файл, --help. Режим pool-sleep виконує Thread.Sleep у задачах пулу. Окрема задача фіксує кількість потоків процесу та пулу і робочий набір кожні 50 мс. Програма виводить таблицю «режим – кількість – час, с – макс. потоків – пам’ять, МБ – затримка старту останнього очікування, мс», записує результати у CSV, пропускає режим thread для 10 000 з попередженням, якщо потрібна пам’ять перевищує доступну, і формулює висновок про масштабованість кожного режиму.
Порядок виконання та захисту роботи
- Опрацювати теоретичні відомості та приклади розв’язання завдань.
- Визначити для свого варіанта, які операції є обчислювальними, а які – операціями вводу-виводу; скласти граф задач і вказати точки скасування, таймаути та звіт про прогрес.
- Створити в JetBrains Rider консольний проєкт .NET 10; для імітації повільних джерел використовувати
Task.Delayз токеном скасування, файли створювати в тимчасовій теці. - Реалізувати завдання обраного рівня складності без блокувальних викликів
Wait()іResultдля незавершених задач та безasync void(крім обробників подій). - Перевірити сценарії успіху, помилки однієї з задач, таймауту та скасування; час вимірювати в конфігурації Release (медіана кількох запусків), задачі переглянути у вкладках Parallel Stacks і Tasks налагоджувача.
- Продемонструвати роботу програми викладачеві, пояснити програмний код і відповісти на контрольні питання.