TemKa_SD 9 08/11/18 22:16 Здравствуйте. Я не знаком с программированием, только на уровне чтения ну и основ. Мне нужно реализовать следующее: В таблице 1 содержатся данные игрового аккаунта, в котором есть полу active и оно принимает значения 0 или 1. Эта активность берется с двух других таблиц, где сравниваются ИГРОКИ и ИГРЫ, там где ИГРЫ есть дата игры, по ней и будет проходить сравнение, если игрок играл за последний месяц, то должно передаваться значение 1. Я уже написал основу, разобрался немного, мне осталось составить SQL запрос для сравнения игрока и игр. Т.е запрос примерно такой: Если "игрок" (stats_gameplayers.gameid, stats_gameplayers.name, stats_gameplayers.spoofedrealm) есть в "играх" за последний месяц (stats_games.id) то условие выполняется, true. /** * memberActive Task */ class _memberActive extends \IPS\Task { /** * Execute * * If ran successfully, should return anything worth logging. Only log something * worth mentioning (don't log "task ran successfully"). Return NULL (actual NULL, not '' or 0) to not log (which will be most cases). * If an error occurs which means the task could not finish running, throw an \IPS\Task\Exception - do not log an error as a normal log. * Tasks should execute within the time of a normal HTTP request. * * @return mixed Message to log or NULL * @throws \IPS\Task\Exception */ public function execute() { $db = \IPS\sharedstats\DB::get(); $accounts = []; foreach($db::i('stats')->select('id, status, name, active, server, created', 'stats_forum_connections') as $acc) { $accounts[$acc['id']] = [ 'status' => $acc['status'], 'name' => $acc['name'], 'server' => $acc['server'], 'active' => $acc['active'] ]; } $this->updateAccounts($accounts); } /** * Cleanup * * If your task takes longer than 15 minutes to run, this method * will be called before execute(). Use it to clean up anything which * may not have been done * * @return void */ public function cleanup() { } /** * @param $accounts */ protected function updateAccounts($accounts) { foreach($accounts as $id => $acc) { $data = $this->fetchAccount($acc); $account = \IPS\sharedstats\Records\ForumConnection::load($id); if(!$data) { $account->active = '0'; } else { $account->active = '1'; } $account->save(); } } protected function fetchAccount($acc) { $result = true; if (FALSE === $result) { return false; } else { return json_decode($result, true); } } } Это готовый таск, он рабочий, данные изменяются где надо. Нужно вместо $result = true; вставить SQL запрос правильный. Поделиться сообщением Ссылка на сообщение
newbie 1723 08/13/18 05:30 Если "игрок" (stats_gameplayers.gameid, stats_gameplayers.name, stats_gameplayers.spoofedrealm)Где здесь игрок?Наверное, должно быть поле для хранения ID игрока, которое равно id из таблицы stats_forum_connections Поделиться сообщением Ссылка на сообщение
TemKa_SD 9 08/13/18 07:49 (изменено) Да, только не ID а логин + сервер (stats_gameplayers.name, stats_gameplayers.spoofedrealm) а в таблице с играми, чтобы дату вывести сравниваются поля stats_gameplayers.gameid и stats_games.id. Вы структуру запроса примерно напишите плиз, я дальше сам поля подставлю. Изменено 13 августа 2018 пользователем TemKa_SD Поделиться сообщением Ссылка на сообщение
newbie 1723 08/13/18 08:32 только не ID а логин + сервер (stats_gameplayers.name, stats_gameplayers.spoofedrealm)А где связь между игроком и данными игрового аккаунта в таблицах stats_gameplayers и stats_forum_connections? Вот Вам пример с юзерами и темами $data = \IPS\Db::i()->select( 'core_members.member_id', 'core_members', array( 'start_date>?', \IPS\DateTime::create()->sub(new \DateInterval('P1D'))->getTimestamp()), null, null, 'member_id' )->join( 'core_pfields_content', 'core_pfields_content.member_id=core_members.member_id' )->join( 'forums_topics', 'forums_topics.starter_id=core_pfields_content.member_id' ); Получить список ID'шников юзеров, которые создали тему(ы) за последние 24 часа. По сути можно устанавливать active=0 для всех записей, а после устанавливать active=1 для записей, полученных в результате запроса. Опять же пример.Сперва устанавливаем всем юзерам стиль с ID 1 \IPS\Db::i()->update('core_members', array('skin' => 1)); После устанавливаем стиль с ID 10 юзерам, которые создали тему(ы) за последние 24 часа. $data2 = \IPS\Db::i()->select( 'core_pfields_content.member_id', 'core_pfields_content', array( 'forums_topics.start_date>?', \IPS\DateTime::create()->sub(new \DateInterval('P1D'))->getTimestamp()), null, null, 'core_pfields_content.member_id' )->join( 'forums_topics', 'forums_topics.starter_id=core_pfields_content.member_id' ); \IPS\Db::i()->update('core_members', array('skin' => 10), \IPS\Db::i()->in('member_id', iterator_to_array($data2))); 1 Поделиться сообщением Ссылка на сообщение
TemKa_SD 9 08/13/18 09:37 Так, не могу разобраться. Составил SQL запрос нужный, попробуем так. SELECT gp.gameid, gp.name, gp.spoofedrealm FROM stats_gameplayers gp INNER JOIN stats_games g ON gp.gameid = g.id AND g.datetime='2018-06-30 13:27:56' Осталось изменить следующее: Вместо даты нужно указать за последние 30 дней. Добавить сравнение игрока и сервера из таблицы stats_forum_connections (поля в первом сообщении, member_id - id пользователя IPS). Только, может через модуль наверно переменные лучше поставить, ну это потом уже, сначала с этим помогите плиз )) Поделиться сообщением Ссылка на сообщение
newbie 1723 08/13/18 09:42 Покажите все 3 таблицы (как на 2 скрине). Поделиться сообщением Ссылка на сообщение
TemKa_SD 9 08/13/18 09:44 А, стоп. В этой функции же мне просто нужно получить результат true или false (были ли игры за последние 30 дней). А сравнение с пользователем в функции выше должно быть, где записывает active. Правильно? Поделиться сообщением Ссылка на сообщение
TemKa_SD 9 08/13/18 09:47 Обвел поля, которые нужны для выборки и сравнения. Поделиться сообщением Ссылка на сообщение
newbie 1723 08/13/18 10:41 Зачем Вам столько полей получать, если по факту Вы их нигде не используете К тому же делаете одинаковую работу, но разными способами foreach($db::i('stats')->select('id, status, name, active, server, created', 'stats_forum_connections') as $acc) { $accounts[$acc['id']] = [ 'status' => $acc['status'], 'name' => $acc['name'], 'server' => $acc['server'], 'active' => $acc['active'] ]; }Здесь Вы получаете аккаунты с 4-мя полями А дальше снова загружаете аккаунты foreach($accounts as $id => $acc) { $account = \IPS\sharedstats\Records\ForumConnection::load($id); Сделайте так1. Сбросим все значения active на 0\IPS\Db::i()->update('stats_forum_connections', array('active' => 0)); 2. Получим имена игроков, которые играли за последние 30 дней$names = iterator_to_array(\IPS\Db::i()->select( 'stats_gameplayers.name', 'stats_gameplayers', array( 'UNIX_TIMESTAMP(stats_games.datetime)>?', \IPS\DateTime::create()->sub(new \DateInterval('P30D'))->getTimestamp()), null, null, 'stats_gameplayers.name' )->join( 'stats_games', 'stats_games.id=stats_gameplayers.gameid' )); 3. Установим active=1if (count($names)) { \IPS\Db::i()->update('stats_forum_connections', array('active' => 1), \IPS\Db::i()->in('name', $names)); } 1 Поделиться сообщением Ссылка на сообщение
TemKa_SD 9 08/13/18 11:00 Огромное спасибо, всё работает как надо. Поделиться сообщением Ссылка на сообщение
TemKa_SD 9 08/13/18 11:11 Пожалуйста, добавьте еще сервер к нику, а то я что-то не разберусь со структурой.$names = iterator_to_array($db::i('stats')->select( 'stats_gameplayers.name, stats_gameplayers.spoofedrealm', Поделиться сообщением Ссылка на сообщение
newbie 1723 08/13/18 11:19 Что этот "сервер" делает в запросе? Поделиться сообщением Ссылка на сообщение
TemKa_SD 9 08/13/18 11:22 Тоже самое что и ник, идет сравнение по нему ник + сервер. Просто может играть такой же ник но с другого сервера. Поделиться сообщением Ссылка на сообщение
newbie 1723 08/13/18 11:29 Как Вы тогда определяете, к какому аккаунту принадлежит игрок? Поделиться сообщением Ссылка на сообщение
TemKa_SD 9 08/13/18 11:33 (изменено) Это уже реализовано в компоненте, мне таск просто нужен, который обновляет active с 0 на 1. И наоборот, если игрок играл а потом перестал. Изменено 13 августа 2018 пользователем TemKa_SD Поделиться сообщением Ссылка на сообщение