Сводный текст домашних заданий
План
Доделать задачу и опубликовать её по стандартным правилам
- При публикации следовать рекомендациям оформления commit message
План
Для решения задач заводите виртуальные окружения с помощью pipenv в каждом отдельном каталоге с решениями (1, 2 и т п.)
Задача_1: напишите программу, реализующую простейший multi-user dungeon (по ходу практикума MUD будет усложняться)
- имеется поле 10х10 клеток; рисовать поле и его наполнение - не нужно
- по каждой оси нумерация с 0 по 9
- первая координата задает координату по горизонтали, вторая - по вертикали
- клетка (0, 0) находится в левом верхнем углу поля (важно для навигации)
- в каждой клетке может либо быть пусто, либо находиться один монстр
- по полю ходит игрок; когда он попадает на клетку с монстром, случается "происшествие" (encounter)
- в начале игры игрок появляется в клетке (0, 0)
- настройка поля и игровой процесс организованы при помощи командной строки
должен поддерживаться не только интерактивный режим (с консольным вводом), но и режим с получением команд из текстового файла (перенаправление ввода при помощи "<") - это нужно для автотестирования
- начальная версия командного языка:
up, down, left, right
- перемещение по полю на одну клетку в выбранном направлении
если игрок переходит через границу поля, он появляется у противоположной границы (например, left в позиции (0, 5) переводит в позицию (9, 5))
при выполнении команды выводится: "Moved to (<x>, <y>)", где <x>, <y> - координаты клетки, куда попал игрок
- если игрок попал в клетку с монстром, случается "происшествие", логика которого описана ниже
addmon <x> <y> <hello>
добавление в клетку (x, y) монстра, при встрече говорящего слово-приветствие, заданное в <hello> (достаточно поддерживать слова без пробелов)
- если в этой клетке уже есть монстр, новый монстр его заменяет (пока это сводится к замене слова-приветствия)
- если в этой клетке находится игрок, происшествие при добавлении монстра не случается
при выполнении команды выводится: "Added monster to (<x>, <y>) saying <hello>"; если монстр заменяется, также выводится, с новой строки, "Replaced the old monster"
- при вводе неверной команды должно выводиться "Invalid command"
- при вводе команды с неверными аргументами должно выводиться "Invalid arguments", фанатично проверять корректность аргументов НЕ нужно
- отработка происшествия (т.е. попадания игрока на клетку с монстром):
происшествие должно отрабатываться в функции encounter(x,y), вызываемой после вывода "Moved to ..."
- вывести текстового монстра, произносящего слово-приветствие
для формирования монстра, говорящего текст, используется функция cowsay(text) из модуля python-cowsay
этот модуль нужно поставить в окружение с помощью pipenv install
- для начала все монстры будут выглядеть как default'ная корова из cowsay
- имеется поле 10х10 клеток; рисовать поле и его наполнение - не нужно
Задача_2: заведите ветку named_monsters в репозитории Д/З и на ней добавьте в MUD (на параллельной ветке в git) поддержку именованных монстров, при этом пользуйтесь редактированием истории на ветке. Решение это задачи надо делать на ветку named_monsters.
Скопируйте решение Задачи_1.
- новая функциональность (её нужно разбить на коммиты, как сказано ниже!):
поддержка команды addmon <name> <x> <y> <hello> , где <name> это имя монстра (строка без пробелов)
- старый (без имени) формат команды больше не должен поддерживаться
- для клетки (x, y) должно запоминаться имя монстра, в дополнение к строке-приветствию
строка, выводимая при успешном добавлении монстра, должна выглядеть так: "Added monster <name> to (<x>, <y>) saying <hello>"
когда игрок попадает на клетку с монстром, в функции encounter() должно выводиться существо из коллекции модуля python-cowsay, произносящее приветствие (использовать функцию cowsay(message, cow=name))
при выполнении команды addmon должно проверяться, что <name> это имя одного из "штатных" существ, доступных в python-cowsay (список имен см. list_cows). Если проверка неуспешна, добавление монстра не выполняется, и выводится "Cannot add unknown monster".
занесите новую функциональность на ветку named_monsters (создание ветки: git checkout -b) в виде следующих коммитов, именно в таком порядке:
а) доработка разбора и обработки команды addmon <x> <y> <name> <hello>, кроме проверки того, что <name> - имя "штатного" существа
- порядок аргументов перепутан специально, чтобы потом редактировать историю
б) добавление передачи имени монстра в вызов cowsay() из функции encounter()
в) добавление в обработку команды addmon проверки того, что <name> - имя "штатного" существа
каждый коммит нужно выполнять после отладки соответствующей функциональности, удалив отладочный код; разработали+отладили а) => занесли а), потом переходим к б), и т.п.
отредактируйте историю (git rebase -i) на ветке named_monsters:
в коммите а) замените в разборе addmon порядок аргументов команды на правильный (опция edit)
- переставьте местами коммиты б) и в)
содержание коммитов в истории удобно контролировать при помощи команды git log --patch
ещё раз отредактируйте историю на ветке named_monsters:
- объедините коммиты а) и в)
План
Задача_1: работа с ветками в git при разработке программы
В решении Задачи_2 с предыдущего занятия сделайте merge ветки named_monsters на ветку work
Скопируйте решение Задачи_2 с предыдущего занятия. Сделайте коммит. Далее этот коммит будет обозначаться как
Продолжите историю на ветке work:
Реализуйте вывод, при старте программы, строки-приветствия "<<< Welcome to Python-MUD 0.1 >>>"
- Сохраните вывод строки-приветствия в виде одного коммита
Создайте ветку shlex_parse на базе коммита и переключитесь на неё (проверьте!)
Реализуйте на ветке shlex_parse:
разбор команд MUD при помощи shlex вместо ранее реализованного разбора
поддержку команды addmon с синтаксисом (взамен прежнего синтаксиса): addmon <monster_name> hello <hello_string> hp <hitpoints> coords <x> <y>, где:
hello, hp, coords - имена параметров команды, все параметры обязательные
<hello_string> - строка приветствия, которую "произносит" монстр при встрече; может быть строкой с пробелами, заключенной в кавычки
<hitpoints> - положительное целое, задающее количество очков здоровья монстра (должно запоминаться вместе с именем монстра и строкой приветствия)
<x>, <y> - координаты монстра
порядок следования именованных параметров произвольный, например: addmon dragon hp 999 coords 6 9 hello "Who goes there?"
- разбиение на коммиты - на ваше усмотрение, но коммитов на ветке должно быть не менее двух
Посмотрите структуру веток в qgit
Сделайте merge ветки shlex_parse на ветку work
Посмотрите структуру веток в qgit; обратите внимание на merge-коммит и на порядок следования коммитов в "суммарной" истории до merge-коммита
Создайте ветку custom_monster на базе коммита и переключитесь на неё (проверьте!)
Реализуйте на ветке custom_monster поддержку нового монстра
монстр выглядит так: (пожалуйста, не удаляйте инициалы jgs - это условие использования, заданное автором Joan G. Stark)
,_ _, ) '-._ ,_ _, _.-' ( ) _.-'.|\\--//|.'-._ ( )' .'\/o\/o\/'. `( ) .' . \====/ . '. ( ) / << >> \ ( '-._/`` ``\_.-' jgs __\\'--'//__ (((""` `"")))
поддержка монстра реализуется при помощи read_dot_cow(), см. пример на https://pypi.org/project/python-cowsay/
имя монстра "jgsbat"
должна быть реализована поддержка добавления этого монстра на игровое поле по команде addmon, с указанием имени монстра (наравне со "стандартными" персонажами python-cowsay)
Сделайте rebase ветки work (где к этому шагу будет merge-коммит) на ветку custom_monster
Внимание! в результате именно ветка work должна вобрать в себя все коммиты (т.е. команда должна быть git rebase custom_monster work)
посмотрите структуру веток в qgit
План
Задача_1: переход на cmd, разработка на ветке с конфликтом объединения
Скопируйте решение Задачи_1 с предыдущего занятия. Сделайте коммит.
Продолжите историю на ветке work:
Реорганизуйте уже имеющиеся команды с помощью cmd и do_команда()
- При этом "из коробки" приедет автодополнение частично введенного имени команды по нажатию TAB
- Решение оформить в виде серии коммитов
ВНИМАНИЕ: поскольку в дальнейшем нужно будет реализовать в MUD поддержку пакетного режима выполнения команд со считыванием их из командного файла (*.mood), разделяйте в коде работу с командной строкой (т.е. ввод команд) и разбор/выполнение команд. Так чтобы без существенной переделки кода можно было добавить альтернативный источник команд - файл, а не командную строку.
Реализуйте поддержку базовой команды attack (без параметров). Обработка команды:
Если в позиции, где находится игрок, нет монстра, вывести "No monster here" и завершить обработку команды
- Атака наносит урон монстру в 10 очков здоровья, если у монстра не менее 10 о.з., в противном случае урон равен количеству о.з. монстра
Вывести: "Attacked <имя монстра>, damage <урон> hp", где <имя монстра> - имя монстра в одной позиции с игроком (таких монстров ровно один), <урон> - число списанных о.з.
- После корректировки здоровья монстра (как принято говорить, "отрицательного выздоровления") вывести:
если о.з. монстра равны 0: "<имя монстра> died"
в противном случае: "<имя монстра> now has <очки здоровья>", где <очки здоровья> - количество оставшихся о.з. у монстра
- Если у монстра 0 о.з., удалить монстра с позиции
Далее последний коммит в реализации базовой команды attack обозначен как
Создайте ветку weapon_name на базе коммита и переключитесь на неё (проверьте!)
Реализуйте на ветке weapon_name атаку разными видами оружия, с указанием оружия в параметре with команды attack
синтаксис команды: attack with <имя оружия>
варианты для <имя оружия>: sword, spear, axe; наносимый урон, соответственно: 10, 15, 20
при указании неизвестного оружия выводить: "Unknown weapon", и завершать обработку команды
параметр with необязательный, значение по умолчанию: sword
для имени оружия должно работать автодополнение имен через TAB (используйте complete_команда())
если имя оружия указано правильно, продолжать обработку как для базовой команды attack, но с соответствующим оружию значением урона
Создайте ветку attack_by_name на базе коммита и переключитесь на неё (проверьте!)
Реализуйте на ветке attack_by_name атаку с обязательным указанием имени монстра
синтаксис команды: attack <имя монстра>
если монстра с данным именем нет в позиции, где находится игрок, вывести "No <имя монстра> here" и завершить обработку команды
в противном случае (т.е. монстр с данным именем есть), продолжить обработку как для базовой команды attack
для имени монстра должно работать автодополнение, а также пролистывание имен через TAB (используйте complete_команда()); пролистываться должны имена ДОСТУПНЫХ В ИГРЕ монстров, т.е. тех, которые могут быть добавлены через команду addmon
сделайте merge ветки weapon_name на ветку work, он будет бесконфликтным (т.к. на work история не продвинулась дальше )
сделайте merge ветки attack_by_name на ветку work, при этом разрешите конфликты из-за разных доработок команды attack
в результате должна появиться поддержка команды с синтаксисом "attack <имя монстра> with <имя оружия>", с поддержкой автодополнения и пролистывания как по имени монстра, так и по имени оружия
План
Задача_1. MUD в формате клиент-сервер (однопользовательский), оформление изменений в виде патчсета.
Скопируйте решение Задачи_1 с предыдущего занятия. Сделайте коммит. Далее этот коммит будет обозначаться
Продолжите историю на ветке work
- Переведите монолитную реализацию MUD на схему "клиент+сервер" (однопользовательскую)
- клиент отвечает за:
- получение команд от пользователя, их разбор, проверку корректности (включая вывод сообщений о некорректных командах)
- вывод информации, полученной от сервера
- т.е. по сути клиент не имеет состояния
сервер работает по принципу echo-сервера, воспринимающего строки вида команда параметры
- сервер отвечает за хранение и модификацию состояния игры, включая:
- позицию игрока
- расположение монстров, их типы и количество очков здоровья (о.з.)
организация протокола клиент->сервер:
по протоколу передаются только команды с гарантированно корректными параметрами; сервер не занимается их перепроверкой (в жизни - не так )
- набор команд протокола следует сделать более простым, чем набор пользовательских команд:
- не нужны опциональные параметры; если пользователь опустил опциональный параметр, клиентом в команду для сервера подставляется значение по умолчанию
- можно все параметры сделать позиционными
однотипные команды можно объединять в одну, с различением по параметрам: например, единственная команда перемещения с указанием приращения по каждой координате (вместо up: move 0 -1, вместо right: move 1 0)
- в целом, клиент выполняет "частичное переваривание" пользовательского ввода и передает серверу упрощенный и гарантированно корректный результат
организация протокола сервер->клиент:
- сервер возвращает только те данные, которые нужны клиенту для вывода
- сервер отвечает на каждую команду клиента без каких-либо задержек
- клиент вправе ждать ответа сервера на отправленную команду, и возвращаться к приёму пользовательских команд только после получения ответа
- по сути, параллелизма в работе клиента и сервера НЕТ
- важные частные случаи:
"энкаунтер" (т.е. перемещение игрока в позицию с монстром): на сервер поступает команда перемещения, в ответ сервер шлёт имя монстра и его приветственный текст; рендерингом с помощью cowsay занимается клиент
- атака: на сервер шлётся имя монстра и количество о.з., соответствующее выбранному оружию; сервер отвечает - либо что монстра с таким именем в позиции нет; либо (если монстр есть), то количеством списанных о.з. и количеством оставшихся о.з. (если второе равно 0, значит монстр убит)
- ДИСКЛЕЙМЕР: вышесказанное - не готовый проект протокола, а намёки на то, как его имеет смысл построить!
- клиент отвечает за:
оформите реализацию в виде набора коммитов на ветке work, желательно не менее 3 коммитов
- сформируйте по этому набору коммитов патчсет:
создайте подкаталог patchdir
при помощи команды git format-patch с ключом --output-directory создайте в подкаталоге patchdir патчсет, включающий все коммиты, реализующие клиент-серверную схему
- закоммитьте файлы патчсета
- примените патчсет:
скопируйте каталог patchdir в место, находящееся вне git-репозитория (далее путь к этому месту обозначен как path_to_patchdir)
создайте ветку apply_patch от коммита , переключитесь на неё (проверьте!)
при помощи команды git am path_to_patchdir/patchdir/* примените патчсет
проверка: посмотрите структуру веток при помощи gitk; на ветках work и apply_patch должны быть одинаковые наборы коммитов
План
Задача_1. Многопользовательский MUD (multiuser multiuser dungeon)
Скопируйте решение Задачи_1 с предыдущего занятия. Сделайте коммит. Работайте на ветке work.
- Сделайте (наконец-то!) MUD многопользовательским. Подробности ниже.
- Многосессионность (поддержку работы с одним сервером одновременно нескольких клиентов) реализуйте по схеме "коровьего чата" из лекций.
- Именованные сеансы:
При подключении клиента к серверу, клиент передаёт серверу имя пользователя (строка без пробелов, поступает клиенту при запуске - python mymud.py username).
- Сервер проверяет, что подключенного пользователя с таким именем ещё нет; если есть - отказывает в подключении; если нет, то создает подключение (сообщая об этом клиенту) и запоминает имя пользователя.
- Асинхронность работы клиента с сервером:
- после отправки сообщения серверу, клиент НЕ ждёт ответа от сервера
- все сообщения от сервера клиенту _после_ успешного подключения - "асинхронные", т.е. принимаются параллельно работе пользователя с командной строкой
- все сообщения от сервера клиенту предназначены ДЛЯ ВЫВОДА "as is", никакого разбора в духе "набор параметров от сервера к клиенту" теперь не нужно; т.е. клиент отправляет команды на сервер без ожидания ответа и без "понимания", что сообщения от сервера приходят в ответ на конкретные команды
схема параллельного ожидания сообщений и обработки пользовательского ввода - см. лекцию (раздел "Cmd и асинхронные сообщения")
- важно: после получения от сервера (и вывода) сообщения, клиент должен показать командную строку с набранным (но не введённым) пользователем текстом, чтобы результат ввода не исчезал (опять см. лекцию)
- Частичная неделимость обработки пользовательской команды на сервере (для ограничения гонок):
- помним, что сервер последовательный
- получив команду от клиента, сервер обрабатывает её сразу (а не планирует обработку через async)
- отправку сообщения клиенту (клиентам) сервер осуществляет асинхронно
- Широковещательные сообщения от сервера клиентам:
- сообщения о "знаковых событиях" сервер рассылает всем клиентам, в духе коровьего чата (где он транслирует всем клиентам полученное от клиента сообщение)
- знаковые события:
- атака на монстра (сообщать: кто атаковал (имя пользователя), чем, какого монстра, сколько очков здоровья снёс, сколько о.з. осталось; если монстр убит, то сообщить об этом [чтобы клиентам не пришлось выпарсивать число о.з.]) сколько включая результат)
- установка монстра (кто поставил, имя монстра, кол-во о.з.)
- заход пользователя (в т.ч. сообщить имя) в MUD
- прекращения сеанса пользователя в MUD (тоже с указанием имени)
- есть и не-широковещательные сообщения, например приветствие от встреченного монстра поступает одному конкретному пользователю
- Прямого взаимодействия между пользователями нет
- Возможны логические гонки: например, два пользователя более-менее одновременно отправили команду атаки на одного и того же монстра, "первый" убил монстра, а второму пришло индивидуальное сообщение о том, что монстра нет. Это терпимо.
План
Задача_1: MUD messaging
Скопируйте решение Задачи_1 с предыдущего занятия. Сделайте коммит. Работайте на ветке work.
- Задайтесь вопросом: если MUD теперь многопользовательский, как пользователи (приключенцы) будут кооперироваться, чтобы вынести особо крутого монстра?
- Спойлер: нужен чат
- Реализуйте команду для передачи сообщения всем игрокам
Синтаксис: sayall <строка>, где <строка> - либо одно слово (без пробельных символов), либо строка в кавычках
- Примеры:
sayall PREVED
sayall "Let's attack dragon at 5 9"
Сервер транслирует строку всем с указанием имени пользователя-источника. Пример: kobold702: Let's attack dragon at 5 9
Задача_2: MUDуляризация, применение flake8 и pydocstyle
Скопируйте решение Задачи_1. Сделайте коммит. Работайте на ветке work.
Оформите MUD в виде пакета с минимум двумя подпакетами: клиент (client), сервер (server); возможно, понадобится ещё третий: библиотека общих классов/констант/функций (common). Вот предположительная структура всего пакета:
mood ├── client │ ├── … │ └── __main__.py ├── common │ ├── __init__.py │ └── … └── server ├── … └── __main__.py
- В силу cowsay-ориентированности, наш MUD обрёл официальное название - MOOD
Запуск для каждого подпакета — в __main__.py
Добейтесь полного отсутствия претензий со стороны flake8 и pydocstyle к содержимому пакетов
- Разрешается настраивать ☺
План
Задача_1. Бродячие монстры и Сфинкс
Скопировать решение Задачи_2 (где выделяются два модуля) с предыдущего занятия. Сделать коммит. Работать на ветке work.
Добавить sphinx в pipenv
- Добавить на сервере MUD поддержку бродячих монстров:
- один раз в 30 секунд выбирается случайный монстр, и он перемещается на одну клетку в случайно выбранном направлении (вправо/влево/вверх/вниз; помним, что поле "закольцовано")
- если в результате перемещения монстр попал бы на клетку, где уже есть монстр, то перемещение НЕ ПРОИСХОДИТ, и проводится повторный выбор монстра и направления; и так пока не будет выполнено успешное перемещение монстра
при перемещении сервер выдаёт всем игрокам сообщение "<имя_монстра> moved one cell <направление>", где <направление> это right, left, up, down. Например: "manticore moved one cell right"
- если монстр попадает на клетку, где есть игрок (или игроки), происходит "энкаунтер" - как если бы игрок(и) сам зашел(ли) на клетку с монстром
- в т.ч. монстр отрисовывается у столкнувшихся с ним игроков, с произнесением приветственной фразы
- Для модуля-сервера задокументировать все функции, классы и модуль в формате autodoc
- Добиться выгонки технической документации по этим классам/функциям/модулю
Следить за тем, чтобы генераты (html-документация) не хранились в git (.gitignore), а настойки shpinx — хранились
- Оформить титульный лист документации (как минимум, скопипастить туда формулировку задачи)
- Сделать в титульном листе ссылку на техническую документацию
Задача_2. MUD-скриптование.
Скопировать решение Задачи_1. Сделать коммит. Работать на ветке work.
реализовать (см. последнее упражнение) получение команд из командного файла, если при запуске передан параметр "--file <имя_файла>"
- командные файлы рекомендуется снабжать расширением ".mood"
при получении команд из файла, ввод команд через cmd не должен работать
- чтобы не "зафлудить" сервер, интервал между последовательными отправками команд с клиента на сервер должен быть не менее 1 секунды
- примечание: скриптование нацелено на автоматическое тестирование MUD-ов, но при таком тестировании (когда дело до него дойдёт) "бродячих монстров" будет необходимо отключать
План
Задача_0. Доделать упражнения по русификации, т.к. они будут использоваться в упражнениях на занятии по автоматизации.
Задача_1. Реализовать для MUD-а поддержку команды включения/выключения режима бродячих монстров
Скопировать решение Задачи_1 с предыдущего занятия. Сделать коммит. Работать на ветке work.
- реализовать команду:
- формат: "movemonsters on" / "movemonsters off" (включить / выключить режим бродячих монстров)
состояние сервера по умолчанию: режим бродячих монстров включен
- сообщение от сервера в ответ на команду: "Moving monsters: on" / "Moving monsters: off"
выключение режима Б.М. нужно для автоматического тестирования через скрипты. Сложно тестировать атаку на монстра, если нет уверенности, что он всё ещё там, куда его поставили...
Задача_2. Локализация сообщений на стороне сервера.
- Почему на стороне сервера?
- на сервере формируются сообщения, включающие числовые значения и соответствующие им слова в множественном числе
протокол от сервера к клиенту строится на сообщениях, не подлежащих интерпретации клиентом (т.е. они только выводятся клиентом в терминал), а значит числовые значения как отдельные параметры в нём передать невозможно
поскольку вариантов множественного числа в русском языке больше, чем в английском, полноценная русификация множественного числа на клиенте без знания числового значения тоже невозможна (нельзя просто взять и перевести "points" как "очков", потому что "два очка")
Скопировать решение Задачи_1. Сделать коммит. Работать на ветке work.
добавить в клиент поддержку команды locale <имя_локали> (просто распознавание и передача на сервер)
- добавить в сервер поддержку работы с локалями:
запоминание, для каждого клиента в отдельности, заданной клиентом локали
поддержка через babel перевода сообщений для единственной (у нас учебная задача) локали ru_RU.UTF8
- отправка на клиент локализованных сообщений: если для установленной этим клиентом локали есть перевод, то отправляем переведенные сообщения, иначе - исходные сообщения: "Поскольку для каждого клиента отдельная корутина, локаль клиента — это просто переменная в ней. Надо просто не забывать каждый раз при отправки сообщеньки выставлять эту локаль" (с)
большинство сообщений от сервера клиенту - широковещательные (т.е. ко всем клиентам), и каждому клиенту это сообщение нужно отправлять с учетом выставленной этим клиентом локали.
- какие сообщения сервера нужно локализовывать:
реакция сервера на установку локали (сообщение только тому клиенту, который подал команду locale):
исходное: "Set up locale: <имя_локали>"
рус. локаль: "Установлена локаль: <имя_локали>"
- сообщения о знаковых событиях: атака на монстра, установка монстра, заход пользователя, прекращение сеанса пользователя
подробности о знаковых событиях см. ../06_SocialProject
- количество очков здоровья у монстра (имеющихся при установке, снятых при атаке, оставшихся после атаки) должно локализовываться с правильным применением множественного числа (1 очко / 2 очка / ... 5 очков / ... 21 очко и т.п.), то есть в файле локализации нужно задействовать формулу выбора множественного числа.
добавьте файлы локализации сервера в его модуль, проверьте что после установки модуля локализация "подхватывается" (при выставлении клиентом локали ru_RU.UTF8 этому клиенту выдаются русифицированные сообщения)
План
Задача_1. Тестирование отработки сервером команд от клиента (проверяется связка клиент+сервер)
Скопировать решение Задачи_1 с предыдущего занятия. Сделать коммит. Работать на ветке work.
модифицировать архитектуру проекта таким образом, чтобы в нём была отдельная функция для запуска сервера
- написать набор тестов для отработки сервером команд от клиента, организованный следующим образом:
setup:
- запуск сервера на локальном хосте
пример запуска: proc = multiprocessing.Process(target=функция_для_запуска_сервера([её, параметры]))
- подключение к этому серверу
- запуск сервера на локальном хосте
teardown: закрытие соединения и прерывание работы сервера (proc.terminate())
каждый тест запускается на клиенте и имеет вид: <отправка команды; ожидание и проверка ответа>; команда - фиксированное сообщение в формате протокола клиент->сервер
- проверяются команды:
- установка монстра (недалеко от начального положения игрока)
- подход к монстру; ожидаемый ответ: "появление" монстра и произнесение им приветствия
- атака на монстра
Задача_2. Тестирование клиента с использованем мокеров
Скопировать решение Задачи_1 с предыдущего занятия (не с этого; не будем смешивать два формата тестирования). Сделать коммит. Работать на ветке work.
написать набор тестов для преобразования клиентом команд из формата пользовательского ввода в формат протокола клиент->сервер
- сервер не запускается, работает только клиент
- для пользовательского ввода и для отправки сообщений к серверу используются мокеры (так можно протестировать всю цепочку действий от ввода до отправки)
- мокер пользовательского ввода при последовательных обращениях возвращает заданную последовательность пользовательских команд
выбрать две команды, у каждой из которых формат пользовательского ввода НЕ совпадает с форматом протокола клиент->сервер
для каждой из этих команд протестировать преобразование правильной команды в формат протокола клиент->сервер (для двух разных значений параметров команды; если команда - движение, то для двух разных направлений)
- хотя бы для одной команды протестировать обработку неправильно заданных параметров
План
Задача_1. Автоматизация сборки для MUD.
Скопировать решение Задачи_1 с предыдущего занятия. Сделать коммит. Работать на ветке work.
реализовать цель i18n для полной генерации перевода
- реализовать цели-шаги генерации перевода, как в описанном выше упражнении
цель i18n должна зависеть от этих целей-шагов
реализовать цель html для генерации html-документации
реализовать цель test для прогона тестов связки клиент+сервер (зависит от цели i18n, потому что проверяет русифицированные ответы сервера)
для каждой цели реализовать удаление генератов (использовать атрибут clean и функцию clean_targets; для удаления каталога с документацией использовать функцию shutil.rmtree)
цель по умолчанию: html
План
Задача_1. Пакетирование для MUD (частично сделано в классе, но рекомендуется не торопиться и переделать аккуратно)
Скопировать решение Задачи_1 с предыдущего занятия. Сделать коммит. Работать на ветке work.
Реализовать в клиенте команду documentation с вызовом браузера посредством webbrowser.open(), которая показывает сгенерированную документацию
сделать pyproject.toml, содержащий описание общего пакета с клиентом и сервером
описание эксплуатационных зависимостей (cowsay-python и др. используемых пакетов)
- описание собственно содержимого пакета:
файл(ы) *.py
- скомпилированный перевод
txt-файл с дополнительным монстром
- сгенерированная документация
- если в состав конкретной реализации входят ещё какие-то файлы, нужные для запуска, то и они
- указание точек входа для генерации двух сценариев — запуск сервера и запуск клиента
Предусмотреть описание сборочных зависимостей (например, в секции [dev-packages] Pipfile-а или в requirements-dev.txt)
- проверить установку пакета и запуск клиента и сервера:
в двух отдельных pipenv-окружениях
в едином pipenv-окружении
- (в обоих случаях окружение создаётся заново)
План
ВЫЖИТЬ