Задача построение дерева рефералов сетки партнера по следующим критериям:
посчитать суммарный объем volume * coeff_h * coeff_cr по всем уровням реферральной системы за период времени
посчитать прибыльность (сумма profit) за определенный период времени
посчитать количество прямых рефералов и количество всех рефералов клиента
<?php
namespace app\commands;
use app\models\Users;
use yii\console\Controller;
use \yii\helpers\BaseConsole;
use yii\helpers\Console;
/**
* Class ReferralController
* @package app\commands
*/
class ReferralController extends Controller
{
/**
* Метод для построения дерева и вывода общего количества рефералов
*/
public function actionTree(){
//Вводим uid полльзователя
$client_uid = BaseConsole::input("Введите uid пользователя: ");
$this->checkValidUid($client_uid);
//Получаем всех пользователей
$users = Users::find()
->select(['client_uid', 'partner_id'])
->asArray()
->all();
/**
* Функция прохода по всем пользователя и поиск рефералов (используется рекурсивный метод)
*
* @param $users //массив пользователей
* @param $client_uid //uid клиента
* @param int $level // уровень, то есть вложенность рефералов меняется если находим у реферала реферала
*/
function printBuildTree($users, $client_uid, $level = 0) {
foreach ($users as $arr) {
if ($arr['partner_id'] == $client_uid) {
if ($level == 0){
//Печать дерева
echo "|" . " |-- " . $arr['client_uid'] ."\n";
}
else{
//Печать дерева
echo "|" . str_repeat(" |-- ", $level + 1) . $arr['client_uid'] . "\n";
}
//Сама рекурсия, то есть находим реферала и для него ищем реферала
printBuildTree($users, $arr['client_uid'], $level + 1);
}
}
}
/**
* Функция подсчета прямых рефералов
*
* @param $users
* @param $client_uid
* @param int $level
* @param int $i
* @return int
*/
function getDirectReferral($users, $client_uid, $level = 0, $i = 0) {
foreach ($users as $arr) {
if ($arr['partner_id'] == $client_uid) {
if ($level == 0){
$i++;
$i += getDirectReferral($users, $arr['client_uid'], $level + 1);
}
}
}
return $i;
}
/**
* Функция подсчета всех рефералов
*
* @param $users
* @param $client_uid
* @param int $level
* @param int $i
* @return int
*/
function getAllReferral($users, $client_uid, $level = 0, $i = 0) {
foreach ($users as $arr) {
if ($arr['partner_id'] == $client_uid) {
$i++;
$i += getAllReferral($users, $arr['client_uid'], $level + 1);
}
}
return $i;
}
echo "|-- " . $client_uid . "\n";
$result = printBuildTree($users, $client_uid);
echo $result;
echo "Всего прямых рефералов: " . getDirectReferral($users, $client_uid) . "\n";
echo "Всего всех рефералов: " . getAllReferral($users, $client_uid) . "\n";
//82824897
}
/**
* Метод получения Прибыльности и Суммарного объема
*/
public function actionTotalVolume(){
//Вводим uid полльзователя
$client_uid = BaseConsole::input("Введите uid пользователя: ");
//Вводим дату ОТ
$date_from = BaseConsole::input("Введите дату ОТ в формате ГОД-Месяц-День ЧАСЫ:МИНУТЫ:СЕКУНДЫ ");
//Вводим дату ДО
$date_to = BaseConsole::input("Введите дату ДО в формате ГОД-Месяц-День ЧАСЫ:МИНУТЫ:СЕКУНДЫ ");
$this->checkValidUid($client_uid);
//Проверяем если ввели дату то делаем условие
if (!empty($date_from)){
$date_from_condition = ['>=', 't.close_time',
$date_from];
}
else{
$date_from_condition = [];
}
//Проверяем если ввели дату то делаем условие
if (!empty($date_to)){
$date_to_condition = ['<=', 't.close_time',
$date_to];
}
else{
$date_to_condition = [];
}
//Получаем всех пользователей
$users = (new \yii\db\Query())
->select(['volume', 'coeff_h', 'coeff_cr', 'a.client_uid', 'profit', 'partner_id'])
->from(['u' => 'users'])
->leftJoin(['a' => 'accounts'], 'a.client_uid = u.client_uid')
->leftJoin(['t' => 'trades'], 't.login = a.login')
->where(['u.client_uid' => $client_uid])
->andWhere($date_from_condition)
->andWhere($date_to_condition)
->all();
$total_volume = 0;
$sum_profit = 0;
foreach ($users as $arr) {
$total_volume += $arr['volume'] * $arr['coeff_h'] * $arr['coeff_cr'];
$sum_profit += $arr['profit'];
}
echo "Прибыльность: " . $sum_profit . "\n";
echo "Суммарный объем: " . $total_volume . "\n";
}
/**
* Функция проверки на пустоту и валидность uid
*
* @param $client_uid
*/
protected function checkValidUid($client_uid){
if (empty($client_uid) || !is_numeric($client_uid)){
$this->stdout("uid не может быть пустым и должен содержать число \n", Console::FG_RED);
exit();
}
}
}