Перейти к публикации
Дизайн и модификация IPS Community IPBSkinsBETA
Поиск в
  • Дополнительно...
Искать результаты, содержащие...
Искать результаты в...
TemKa_SD

Помогите создать tasks

Рекомендованные сообщения

Здравствуйте. Я не знаком с программированием, только на уровне чтения ну и основ. Мне нужно реализовать следующее:

 

В таблице 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 запрос правильный.

Поделиться сообщением


Ссылка на сообщение

Если "игрок" (stats_gameplayers.gameid, stats_gameplayers.name, stats_gameplayers.spoofedrealm)

Где здесь игрок?

Наверное, должно быть поле для хранения ID игрока, которое равно id из таблицы stats_forum_connections

Поделиться сообщением


Ссылка на сообщение
08/13/18 07:49 (изменено)

Да, только не ID а логин + сервер (stats_gameplayers.name, stats_gameplayers.spoofedrealm) а в таблице с играми, чтобы дату вывести сравниваются поля stats_gameplayers.gameid и stats_games.id. Вы структуру запроса примерно напишите плиз, я дальше сам поля подставлю.

Изменено пользователем TemKa_SD

Поделиться сообщением


Ссылка на сообщение

только не 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)));

  • Upvote 1

Поделиться сообщением


Ссылка на сообщение

Так, не могу разобраться. Составил 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). Только, может через модуль наверно переменные лучше поставить, ну это потом уже, сначала с этим помогите плиз ))

post-60255-0-04576400-1534152806_thumb.png

post-60255-0-84306900-1534152980_thumb.png

Поделиться сообщением


Ссылка на сообщение

Покажите все 3 таблицы (как на 2 скрине).

Поделиться сообщением


Ссылка на сообщение

А, стоп. В этой функции же мне просто нужно получить результат true или false (были ли игры за последние 30 дней). А сравнение с пользователем в функции выше должно быть, где записывает active. Правильно?

Поделиться сообщением


Ссылка на сообщение

Обвел поля, которые нужны для выборки и сравнения.

post-60255-0-44755100-1534153630_thumb.png

post-60255-0-90561000-1534153635_thumb.png

post-60255-0-34481600-1534153641_thumb.png

Поделиться сообщением


Ссылка на сообщение

Зачем Вам столько полей получать, если по факту Вы их нигде не используете

 

К тому же делаете одинаковую работу, но разными способами

 

        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=1

if (count($names))
{
   \IPS\Db::i()->update('stats_forum_connections', array('active' => 1), \IPS\Db::i()->in('name', $names));    
}

  • Upvote 1

Поделиться сообщением


Ссылка на сообщение

Огромное спасибо, всё работает как надо.

Поделиться сообщением


Ссылка на сообщение

Пожалуйста, добавьте еще сервер к нику, а то я что-то не разберусь со структурой.

$names = iterator_to_array($db::i('stats')->select(
	    'stats_gameplayers.name, stats_gameplayers.spoofedrealm',

post-60255-0-27284300-1534158714_thumb.png

Поделиться сообщением


Ссылка на сообщение

Что этот "сервер" делает в запросе?

Поделиться сообщением


Ссылка на сообщение

Тоже самое что и ник, идет сравнение по нему ник + сервер. Просто может играть такой же ник но с другого сервера.

Поделиться сообщением


Ссылка на сообщение

Как Вы тогда определяете, к какому аккаунту принадлежит игрок?

Поделиться сообщением


Ссылка на сообщение
08/13/18 11:33 (изменено)

Это уже реализовано в компоненте, мне таск просто нужен, который обновляет active с 0 на 1. И наоборот, если игрок играл а потом перестал.

post-60255-0-85865400-1534160077_thumb.png

Изменено пользователем TemKa_SD

Поделиться сообщением


Ссылка на сообщение

Создайте аккаунт или войдите в него для комментирования

Вы должны быть пользователем, чтобы оставить комментарий

Создать аккаунт

Зарегистрируйтесь для получения аккаунта. Это просто!

Зарегистрировать аккаунт

Войти

Уже зарегистрированы? Войдите здесь.

Войти сейчас

  • Сейчас на странице   0 пользователей

    Нет пользователей, просматривающих эту страницу.

×
×
  • Создать...