Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Создание схемы базы и моделей #20

Closed
vtm9 opened this issue Jul 24, 2017 · 29 comments
Closed

Создание схемы базы и моделей #20

vtm9 opened this issue Jul 24, 2017 · 29 comments

Comments

@vtm9
Copy link
Contributor

vtm9 commented Jul 24, 2017

Предлагаю коллективно продумать основные модели и их связи. Если кто-то знает бесплатный инструмент для совместного проектирования, будет круто. А так можно просто в обсуждении.

Как вариант:
модели: User, Game, Battle, Language

связи:
у battle два user-a и один game.
many_to_many user и battle
battle has_one game
many_to_many game languages

@krigar1184
Copy link
Contributor

Battle пишется через a :) Но мне непонятно, зачем нужны две сущности для игры.
Я бы ввёл сущности User, Game и Language. User и Game связаны как многие-ко-многим, в таблице-связке присутствует ссылка на Language.

@vtm9
Copy link
Contributor Author

vtm9 commented Jul 24, 2017

По идее battle это сам процесс батла, со своим стейтом(конечный автомат), а игра хранит параметры игры, типо задание, знает как её сгенерить и прогнать тесты и т.д.
PS: спасибо за a

@krigar1184
Copy link
Contributor

Точно, задание же тоже надо хранить. Тогда дополню свой вариант так: вводим сущность Task - задача, и связываем их с Game как один ко многим (в Game должна храниться ссылка на Task). Т.е., грубо, имеем следующую структуру БД:

Task(id, description)
Game(id, task_id)
User(id)
User2Game(user_id, game_id, language_id)
Language(id)

В итоге процесс получается примерно такой:

  • игра начинается с создания пользователем игры (создаётся сущность Game) и вступления пользователя в игру как минимум двух пользователей (создаются соответствующие связи в User2Game);
  • игра заканчивается при выходе из игры обоих пользователей. Пользователь выходит из игры либо когда он выиграл, либо когда он, образно говоря, сдался (закрыл браузер и т.д.).

@vtm9
Copy link
Contributor Author

vtm9 commented Jul 24, 2017

в твоем случае получается два конечных автомата, как я понял создается две сущности User2Game. Интересно это хорошо или плохо, я думаю как минимум сложнее.

@egorsmth
Copy link
Contributor

если вместо второго юзера будет бот?

@krigar1184
Copy link
Contributor

Получается конечный автомат с тремя состояниями: Idle (дефолтное, 0-1 игроков), Running (только из Idle, 2+ игроков) и Finished (из Running или Idle, 0 игроков). Возможно, этот вариант чуть сложнее твоего, но и гибче - позволяет подключаться к одной игре более чем 2-м игрокам, к примеру.

@vtm9
Copy link
Contributor Author

vtm9 commented Jul 24, 2017

@krigar1184, Не совсем понял, в какой сущности в твоем случае будет state_machine работать.
В моем варианте есть сущность battle, в которой есть state и событие add_user, которое добавляет пользователей в баттл, и их можно сколько угодно добавить.

@st0ck
Copy link

st0ck commented Jul 24, 2017

Согласен с @krigar1184. Battle и Game выглядят сущностями одного порядка.
@Matt182 если чего-то не упустил, то вроде как мысль была в том, что бот будет повторять лог игры одного из игроков (из предыдущих игр). Так что по сути это тот же User, под него надо будет просто отдельную запись создать.
Насколько я понял задумку, здесь нужна сущность для хранения хода игры.
Допусим Tactic. Указание на нее можно сделать в

User2Game(user_id, game_id, language_id, :tactic_id)

Tactic не знает ничего о пользователе и игре - по сути это просто лог. Его можно хранить одной записью в таблице потому как поиск по такому логу врядли понадобится.
Таким образом бот может воспользоваться тактикой любого игрока в новой игре без создания новых записей.

@vtm9 можно стейт хранить в Game(id, task_id, state)

@vtm9
Copy link
Contributor Author

vtm9 commented Jul 24, 2017

@st0ck, логично, согласен

@icu0755
Copy link

icu0755 commented Jul 25, 2017

Task(id, description)
Game(id, task_id, state)
User(id)

Должно быть достаточно для начала.
Language достаточно просто хранить строкой, пока не вижу никакой пользы от создания таблицы.
User2Game можно хранить где-нибудь в memcache, redis или просто в памяти. Зачем лишний раз обращаться к БД?

@st0ck
Copy link

st0ck commented Jul 25, 2017

@icu0755
а как статистику хранить? Если User2Game не будет, то и от хранения Game в базе тоже нет никакого смысла.
Кроме того наличие User2Game в базе не мешает кэшировать эту информацию в редисе и писать в базу только 1 раз - по завершению игры.

@icu0755
Copy link

icu0755 commented Jul 25, 2017

Тогда это GameResult или GameStats, куда нужно записать результат игры. Тактику или Игровой лог можно писать в отдельную табличке, не привязанную к игроку или даже к игре (game_id в примере можно заменить просто на id).

GameResult(user_id, game_id, language: string, result: <won, lost>)
GameLog(game_id, task_id, log)

@vtm9
Copy link
Contributor Author

vtm9 commented Jul 25, 2017

@icu0755 по мне так один/пару запросов в базу в таблицу UserGame мало что изменят, по крайней мере на начальном этапе.

GameResult(user_id, game_id, language) выглядит как UserGame

На счет language в табличке, польза есть - у нас будет в базе реестр языков, а параметры со временем могут появиться. Хотя можно его и в коде приложения хранить. Тут на любителя.

GameLog странная модель, так как у Game и Task связь один к одному. Я бы лог хранил в UserGame.

По поводу кеша и тд, я бы пробовал оптимизировать позже, и поскольку у нас Erlang можно mnesia попробовать.

@st0ck
Copy link

st0ck commented Jul 25, 2017

@icu0755 я не видел что из себя представляла реализация игры и поэтому, возможно, чего-то не понимаю. Там нельзя было зайти в уже прошедшую игру и посмотреть что происходило?
Если отвязывать Log от Game, то будет нельзя.
Если я все правильно понимаю, то бот будет воспроизводить некоторую стратегию по решению конкретной задачи.
Тут как минимум два пути: сложный и простой. Сложный - мы делаем систему обучения бота на основе множества решений на одном языке. Тогда нам нужно уметь связывать язык и лог/тактику. Простой - бот просто воспроизводит решение одного из победителей. Тут информация о языке тоже не лишняя.

Возможно я не очень понимаю, что конкретно имеется в виду под GameResult. Можешь пояснить?

У User2Game была совершенно простая мысль - указать какие пользователи участвовали в конкретной игре. Язык и тактика - это то, что привязано к составному ключу (user_id, game_id) как 1-к-1 и было внесено в эту же таблицу просто чтобы не плодить сущности.
User2Game не является названием таблицы, если это было причиной избавиться от нее. Можно ее переименовать в Connection, GameParticipant, GameTroop, GameUnit или как-нибудь получше :)

На мой взгляд хранить в GameLog ход решения всех участников нецелесообразно. Гораздо проще будет обрабатывать информацию по каждому пользователю отдельно (с привязкой к задаче, игроку и, возможно, игре).

@icu0755
Copy link

icu0755 commented Jul 25, 2017

@vtm9 @st0ck из переписки я понял, что User2Game планировалась для хранения текущих сессий, что, мне кажется, является неверным решением, поэтому я предложил от нее "избавиться". Если в ней хранится только результат, то да, она фактически копия GameResult(user_id, game_id, language: string, result: <won, lost>)

По GameLog ваша правда, конечно же, надо разделить лог по языкам. Иначе этим логом невозможно будет пользоваться для создания бота. Если стоит задача хранить историю игры для повторного просмотра имеет смысл разбить на game_id, user_id. Пока такой задачи не стоит, судя по трекеру.

@vtm9 в GameLog нам нужен по сути только уникальный id, табличка может выглядеть так
GameLog(id, task_id, language, log), просто game_id тоже уникален поэтому до появления language мы могли его использовать в качестве primary key.

@tuykin
Copy link

tuykin commented Jul 26, 2017

Ребят, возвращаясь к теме ботов, нет ли смысла разделить понятие Player и User, чтобы не мешать логику авторизации и логику игры?

@vtm9
Copy link
Contributor Author

vtm9 commented Jul 26, 2017

@kinley Если bot это созданный нами User c Id = 1. То тогда смысла особо нет. Скорее получится путаница, так как часть логики в User а часть в Player. Как ты предлагаешь реализовать ботов?

@tuykin
Copy link

tuykin commented Jul 26, 2017

@vtm9 Если bot - это User, то получается, что

  • у него будет рейтинг, нужно будет его исключать из списков (решается разными ролями пользователей)
  • у bot'а будет понятие "старегия игры" - тот самый Tactic, о котором говори @st0ck. Так вот, боты с различными стратегиями - это разные игроки?
  • у User есть email-password и прочие поля, не актуальные для bot'а.

Это некоторые моменты, которыми будет отличаться bot от обычных пользователей. Не создаст ли это много дополнительных ветвлений логики из-за того, что мы приравняем эти два понятия?

В общем, есть подозрение, что я усложняю. Саму реализацию бота еще не думал. Важно - хранить все логи игр. Тогда изначально можно просто копировать ходы лучшего/среднего игрока. А в дальнейшем можно добавить машинное обучение или прочие приблуды и экспериментировать с AI бота.

@vtm9
Copy link
Contributor Author

vtm9 commented Jul 26, 2017

@kinley. По идее Player - это сущность, которая будет в, но её не надо специально где-то хранить. Game, и для игры без разницы это пользователь или бот. Вопрос в том, как хранить это в базе. Можно сделать так, что бот это пользователь с id = null. Тогда при старте игры пользователем, мы ищем соперника в течении 5 секунд, иначе кидаем его на бота, причем сама игра ничего не знает про бота. А бот будет отдельный процесс, который потом запишется в базу в табличку UserGame как user_id = null. И не надо будет рейтинг ему вести.

Про логику игры ботов можно отдельное обсуждение сделать.

@tuykin
Copy link

tuykin commented Jul 26, 2017

@vtm9 такой вариант кажется лучше!

Ребят, а есть где-то расписанные что-то вроде User Stories / Use Cases, чтобы было понятно, какие кейсы покрыты текущей структурой, а какие не очень на нее ложатся?
И вообще есть ли смысл в том, чтобы их расписывать?

@vtm9
Copy link
Contributor Author

vtm9 commented Jul 26, 2017

Думаю, что пока надо отталкиваться от одной итории. Есть игры, есть пользователи с гитхаба. пользователь может выбирать игры и играть, а там либо другой игрок, либо бот

@krigar1184
Copy link
Contributor

Поддерживаю идею разделить пользователя и игрока, например AuthUser и Player - в будущем будет проще реализовать логику для ботов.

@vtm9
Copy link
Contributor Author

vtm9 commented Jul 26, 2017

@krigar1184, а можешь по подробнее, например как их хранить в базе

@krigar1184
Copy link
Contributor

@vtm9, простая связь один к одному. Когда пользователь логинится первый раз, создаётся AuthUser (наверняка во Фениксе это есть из коробки), здесь будут храниться данные, относящиеся к аутентификации/авторизации. Модель Player создаётся при вступлении пользователя в игру первый раз, и она же используется для последующих игр. Соответственно, тут храним данные, относящиеся непосредственно к играм: количество проведённых игр, побед и т.п.

@vtm9
Copy link
Contributor Author

vtm9 commented Jul 26, 2017

@krigar1184, пока не очень понятно, зачем Pleyer как модель с данными в базе. И как хранить игры ботов?

@krigar1184
Copy link
Contributor

Бот может быть Player без AuthUser, например. Для этого Player и нужен - для отделения логики аутентификации (которая ботам не нужна) от логики игры.

@vtm9
Copy link
Contributor Author

vtm9 commented Jul 26, 2017

Бота можно порождать как отдельный процесс, который шлет данный в игру, по заданному алгоритму, а потом помечать, что играл бот. Тогда Player вообще не нужен.

@icu0755
Copy link

icu0755 commented Jul 26, 2017

Бот - это по сути тоже Player, т.е мы переместим с этим связанные проблемы (рейтинг, количество проведенных побед и т.д.) из таблицы User в таблицу Player. Для аутентификации по OAuth используются токены, которые скорее всего записываются в отдельную таблицу, а для бота естественно никакого токена не будет. Т.е. логика аутентификации уже будет вынесена в другую таблицу.

@vtm9
Copy link
Contributor Author

vtm9 commented Jul 26, 2017

Кстати на счет ботов, можно сделать такую штуку, как в strava. Типо там ты можешь пробежать маршрут, он его запишет со всеми подробностями, а потом твои друзья увидят твои результаты и могут соревноваться по этому же маршруту. То есть ты можешь играть на скорость с записями треков других пользователей, например если они твои друзья.

@vtm9 vtm9 closed this as completed Nov 30, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants