<?php

use Core\ArraySorter;
use Core\ComparsionHelper;
use Core\Config;
use Core\Db;
use FightRequest\FRHelper;
use Tournament\Tournament;
use Tournament\TournamentModel;
use User\Effects;

class FightRequest
{
    private bool $backTest = false; // Для проверок хаотических поединков.
    private static bool $bcktst;
    private User $u;
    public string $error = '';
    public const BATTLE_RAZDEL_GROUP = 4;
    public const BATTLE_RAZDEL_CHAOTIC = 5;
    public const BATTLE_RAZDEL_CURRENT = 6;
    public const BATTLE_RAZDEL_ENDED = 7;
    public const BATTLE_RAZDEL_TOURNAMENTS = 10;
    private const BATTLE_TYPE_MELEE = 1;
    private const BATTLE_TYPE_NO_EKR_ITEMS = 51;
    private const CHAOTIC_TYPE_PRIZED = 33;

    /**
     * Заявки на бой.
     */
    public function __construct()
    {
        $this->u = User::start();
        unset($_POST['kingfight'], $_POST['nobot'], $_POST['mut_clever']);

        $this->u->info['no_zv_key'] = true;
        if (!empty($_GET['del_z_time'])) {
            $zay = Db::getValue(
                'select count(*) from zayvki where id = ? and creator = ? and start = 0 and cancel = 0 and btl_id = 0 and priz = 0',
                [$this->u->info['zv'], $this->u->info['id']]
            );
            if ($zay) {
                $cols = $this->countUsersAll($this->u->info['zv']);
                if ($cols === 1) {
                    Db::sql('update stats set zv = 0 where id = ?', [$this->u->info['id']]);
                    Db::sql('delete from zayvki where id = ?', [$this->u->info['zv']]);
                }
            }
        }
        $this->test(); //проверяем заявки
    }

    /** Считаем количество людей в конкретной заявке.
     * @param int $frId id заявки
     * @return int
     */
    private function countUsersAll(int $frId): int
    {
        return Db::getValue('select count(*) from stats where zv = ?', [$frId]);
    }

    /** Считаем количество людей в конкретной заявке во второй команде.
     * @param int $frId id заявки
     * @return int
     */
    private function countUsersInTeam2(int $frId): int
    {
        return Db::getValue('select count(*) from stats where zv = ? and team = 2', [$frId]);
    }

    private function testTravm()
    {
        $tr = Db::getValue(
            'select v1 from eff_users where id_eff = 4 and `delete` = 0 and uid = ? order by v1 desc limit 1',
            [$this->u->info['id']]
        );
        return $tr ? $tr - 1 : 0;
    }

    private function testGroupAndChaotic()
    {
        //Проверяем хаотичные и групповые бои [в этом городе ?]
        $sp = Db::getRows(
            'select * from zayvki where btl_id = 0 and cancel = 0 and start = 0 and razdel in (4,5) order by id desc limit 22'
        );
        foreach ($sp as $pl) {
            $uz = Db::getRow(
                'select users.id, * from users left join stats on users.id = stats.id where zv = ?',
                [$pl['id']]
            );
            $i = [];
            $toChat = '';
            $toWhere = '';
            foreach ($uz as $t) {
                ${'tm' . $t['team']} ??= [];
                $i[$t['team']] ??= 0;
                ${'tm' . $t['team']}[$i[$t['team']]] = $t;
                $toChat .= '' . $t['login'] . ',';
                $toWhere .= 'OR `id` = "' . $t['id'] . '" ';
                $i[$t['team']]++;
            }

            if ($pl['razdel'] == self::BATTLE_RAZDEL_CHAOTIC) {
                $cols = $this->countUsersAll($pl['id']);
                if ($cols >= $pl['maxplayers']) {
                    $pl['time_start'] = time() - $pl['time'] - 1;
                }
            }

            if (
                $pl['time_start'] >= time() - $pl['time'] &&
                ($pl['razdel'] != self::BATTLE_RAZDEL_GROUP || $i[1] < $pl['tm1max'] || $i[2] < $pl['tm2max'])
            ) {
                continue;
            }

            $toChat = rtrim($toChat, ',');
            $toWhere = ltrim($toWhere, 'OR ');
            if ($pl['razdel'] == self::BATTLE_RAZDEL_GROUP) {
                $this->testGroup($i, $pl, $toChat, $toWhere);
            } else {
                $this->testCronChaotic($pl, $toChat, $toWhere);
            }
        }
    }

    /** Проверяем заявки
     * @return void
     */
    private function test()
    {
        if ($this->u->info['zv'] > 0) {
            $z = Db::getValue(
                'select count(*) from zayvki where id = ? and (cancel > 0 or btl_id >0 or time < unix_timestamp() - 3600)',
                [$this->u->info['zv']]
            );
            if ($z > 0) {
                $this->u->info['zv'] = 0;
                Db::sql('update stats set zv = 0 where id = ?', [$this->u->info['id']]);
            }
        }
        $this->testGroupAndChaotic();
    }

    private function testGroup($groups, $zayavka, $toChat, $toWhere)
    {
        if ($zayavka['razdel'] != 4) {
            return;
        }
        if (
            empty($groups[1]) ||
            empty($groups[2]) ||
            (
                empty($groups[3]) &&
                $zayavka['teams'] == 3
            )
        ) {
            //группа не набрана
            $this->cancelGroup($zayavka, $toChat);
        } else {
            //Начинаем поединок
            $this->startBattle($zayavka['id'], $toChat . '|-|' . $toWhere);
        }
    }

    private function testCronChaotic($zayavka, $toChat, $toWhere)
    {
        $chat = new Chat();
        $levelToExp = [
            0 => 0,
            1 => 110,
            2 => 420,
            3 => 1300,
            4 => 2500,
            5 => 5000,
            6 => 12500,
            7 => 30000,
            8 => 300000,
            9 => 3000000,
            10 => 10000000,
            11 => 52000000,
            12 => 63000000,
            13 => 182000000,
            14 => 212000000,
            15 => 352000000,
            16 => 504000000,
            17 => 1187000000,
            18 => 2455000000,
            19 => 4387000000,
            20 => 6355000000,
            21 => 15500000000,
            22 => 755500000000,
        ];
        $botUsers = [];
        define('FAST_FIGHT_REQUIRED_FIGHTERS_COUNT', 2);
        define('FIGHT_REQUIRED_FIGHTERS_COUNT', 6);

        $requiredFightersToStartBattle = FIGHT_REQUIRED_FIGHTERS_COUNT;
        if ($zayavka['fastfight'] > 0) {
            $requiredFightersToStartBattle = FAST_FIGHT_REQUIRED_FIGHTERS_COUNT;
        }

        $pendingFightersCount = $this->countUsersAll($zayavka['id']);
        if ($pendingFightersCount < $requiredFightersToStartBattle) {
            //группа не набрана
            //Добавляем недостающих игроков
            if (!$zayavka['nobot']) { // Если нет запрета на ботов.
                //$getRealPlayersQuery = 'select * from stats left join users on stats.id = users.id where exp >= ? and exp < ? and bot = 0 order by btl_cof desc limit 50';
                $getBotsQuery = 'select * from stats left join users on stats.id = users.id where bot = 2 and exp >= ? and exp < ?';
                $botUsers = Db::getRows(
                    $getBotsQuery,
                    [$levelToExp[$zayavka['min_lvl_1']], $levelToExp[$zayavka['max_lvl_1'] + 1]]
                );
            }

            if (empty($botUsers)) {
                $text = ' Не удалось начать поединок по причине: Группа не набрана. (' . $zayavka['id'] . ': 0 ' . $levelToExp[$zayavka['min_lvl_1']] . '-' . $levelToExp[$zayavka['max_lvl_1'] + 1] . ')';
                $chat->sendsys($text, 'Merlin');
                $this->cancelGroup($zayavka, $toChat, ' Боты проспали.');
            } else {
                $pendingBotsCount = 0;
                for ($i = 0; $i < $requiredFightersToStartBattle - $pendingFightersCount; $i++) {
                    shuffle($botUsers);
                    $botInfo = array_shift($botUsers);
                    $botData = [
                        'id' => $botInfo['id'],
                        'login' => $botInfo['login'],
                        'level' => $botInfo['level'],
                        'city' => $botInfo['city'],
                        'cityreg' => $botInfo['city'],
                        'name' => $botInfo['login'],
                        'sex' => $botInfo['sex'],
                        'hobby' => '',
                        'time_reg' => time(),
                        'obraz' => $botInfo['obraz'],
                        'stats' => $botInfo['stats'],
                        'upLevel' => $botInfo['upLevel'],
                        'priems' => $botInfo['priems'],
                        'loclon' => true,
                    ];
                    $bot = $this->u->addNewbot(1, null, $botData, null, true);
                    if (!$bot) {
                        continue;
                    }
                    Db::sql(
                        'update stats set btl_cof = ?, zv = ?, hpNow = 1000000, mpNow = 1000000 where id = ?',
                        [$botInfo['btl_cof'], $zayavka['id'], $bot]
                    );
                    Db::sql('update users set room = 303, battle = 0 where id = ?', [$bot]);
                    $pendingBotsCount++;
                }
                unset($botUsers, $botInfo, $botData, $bot);

                if ($pendingBotsCount + $pendingFightersCount >= $requiredFightersToStartBattle) {
                    $this->backTest = true;
                    self::$bcktst = true;
                }
            }
        } else {
            //Начинаем поединок
            $this->startBattle($zayavka['id'], $toChat . '|-|' . $toWhere);
        }
    }

    /** Проверяем хаотичные и групповые бои [в этом городе ?] */
    private function testCronGroupAndChaotic(): void
    {
        $zv1k = Db::getRows(
            'select * from zayvki where btl_id = 0 and cancel = 0 and start = 0 and razdel in (4, 5) order by id desc'
        );
        foreach ($zv1k as $zv) {
            $i = [];
            $toChat = $toWhere = '';
            $users = Db::getRows(
                'select * from stats left join users on stats.id = users.id where zv = ?',
                [$zv['id']]
            );
            foreach ($users as $user) {
                ${'tm' . $user['team']} ??= [];
                $i[$user['team']] ??= 0;
                ${'tm' . $user['team']}[$i[$user['team']]] = $user;
                $toChat .= $user['login'] . ',';
                $toWhere .= 'OR id = ' . $user['id'] . ' ';
                $i[$user['team']]++;
            }
            if (
                $zv['time_start'] > time() - $zv['time'] &&
                ($zv['razdel'] != self::BATTLE_RAZDEL_GROUP || $i[1] < $zv['tm1max'] || $i[2] < $zv['tm2max'])
            ) {
                continue;
            }
            $toChat = rtrim($toChat, ',');
            $toWhere = ltrim($toWhere, 'OR ');

            if ($zv['razdel'] == self::BATTLE_RAZDEL_GROUP) {
                $this->testGroup($i, $zv, $toChat, $toWhere);
            } else {
                $this->testCronChaotic($zv, $toChat, $toWhere);
            }
        }
    }

    public function testCronZv()
    {
        $this->testCronGroupAndChaotic();

        if ($this->backTest || self::$bcktst) {
            self::$bcktst = false;
            $this->testCronZv();
        }

    }

    private function cancelGroup($zv, $uids, $debug = null)
    {
        Db::sql('update stats set zv = default where zv = ?', [$zv['id']]);
        Db::sql('update zayvki set cancel = unix_timestamp() where id = ?', [$zv['id']]);
        if (empty($uids)) {
            return;
        }
        $text = ' Не удалось начать поединок по причине: Группа не набрана!';
        if ($zv['priz'] > 0) {
            $pg = $this->cancelPrizedChaotic($zv);
            if (!empty($pg[0])) {
                $uids = $pg[0];
            }
            $text .= $pg[1];
        }
        $chat = new Chat();
        $chat->sendsys($text . $debug, $uids);
    }

    private function cancelPrizedChaotic(array $zv): array
    {
        $stmt = Db::getRows('select id from stats where zv = ?', [$zv['id']]);
        foreach ($stmt as $user) {
            if ($zv['type'] === self::CHAOTIC_TYPE_PRIZED) {
                $stmt2 = Db::getValue('select id from users where inUser = ?', [$user['id']]);
                if (!empty($stmt2)) {
                    Db::sql('update users set inUser = 0 where id = ?', [$stmt2]);
                    Db::sql('delete from users where id = ?', [$user['id']]);
                    Db::sql('delete from stats where id = ?', [$user['id']]);
                    Db::sql('delete from items_users where uid = ?', [$user['id']]);
                    Db::sql('delete from eff_users where uid = ?', [$user['id']]);
                    $this->u->addItem(4754, $user['id']);
                }
            } else {
                $this->u->addItem(4754, $user['id']);
            }
        }
        return [
            $stmt2 ?? 0,
            ' Вы получаете Призовой Жетон (х1)',
        ];
    }

    private function addGroupRequest()
    {

    }

    public function addGroupOrChaoticRequest(int $r)
    {
        if (!in_array($r, [self::BATTLE_RAZDEL_GROUP, self::BATTLE_RAZDEL_CHAOTIC])) {
            return;
        }
        $k = (int)$_POST['k'];
        $az = 1;

        if ($this->testTravm() == 1 && $k !== 1) {
            $this->error = 'Вы травмированы. С такими увечьями доступны кулачные бои.';
            $az = 0;
        } elseif ($this->testTravm() == 2) {
            $this->error = 'Вы травмированы. С такими увечьями невозможно сражаться.';
            $az = 0;
        } elseif ($this->u->isWeakened()) {
            $this->error = 'Вы еще слишком ослаблены чтобы начать новый бой';
            $az = 0;
        }
        if ($this->u->info['zv'] > 0) {
            $this->error = 'Вы уже находитесь в заявке.';
            $az = 0;
        }
        if ($az === 0) {
            return;
        }

        $timeout = (int)$_POST['timeout'];

        $nz = [];
        $nz['travmaChance'] = 0;
        $nz['time_start'] = 0;
        $nz['tm1max'] = 0;
        $nz['tm2max'] = 0;
        $nz['invise'] = 0;
        $nz['tm1'] = 0;
        $nz['tm2'] = 0;
        $nz['otmorozok'] = 0;
        $nz['fastfight'] = 0;
        $nz['noinc'] = 0;
        $nz['type'] = 0;

        if ($k === 1) {
            $nz['type'] = 1;
        }
        if ($k === 2) {
            $nz['type'] = 6;
            $nz['travmaChance'] = 100;
        }

        if (!in_array($timeout, [1, 2, 3, 4, 5])) {
            $timeout = 3;
        }

        $nz['timeout'] = $timeout * 60;
        $nz['razdel'] = $r;

        $nz['comment'] = substr($_POST['cmt'], 0, 40);
        $nz['comment'] = str_replace('"', '&quot;', $nz['comment']);

        $gad = 1;

        if ($r == self::BATTLE_RAZDEL_CHAOTIC) {
            //хаотичный бой
            if ($_POST['startime2']) {
                $nz['time_start'] = (int)$_POST['startime2'];

                if (!in_array($nz['time_start'], [60, 180, 300])) {
                    $nz['time_start'] = 600;
                }

                if (isset($_POST['mut_hidden'])) {
                    $nz['invise'] = 1;
                }
                if (isset($_POST['noinc'])) {
                    $nz['noinc'] = 1;
                }
                if (isset($_POST['fastfight'])) {
                    $nz['fastfight'] = 1;
                }
                if (isset($_POST['otmorozok'])) {
                    $nz['otmorozok'] = 1;
                }
                if (isset($_POST['nobot'])) {
                    $nz['nobot'] = 1;
                }
                if (isset($_POST['kingfight'])) {
                    $nz['kingfight'] = 1;
                }
                if (isset($_POST['arand'])) {
                    $nz['arand'] = 1;
                }
                if (isset($_POST['travma'])) {
                    $nz['travmaChance'] = 100;
                }
                if (isset($_POST['noatack'])) {
                    $nz['noatack'] = 1;
                }
                if (isset($_POST['noeff'])) {
                    $nz['noeff'] = 1;
                }
                if (isset($_POST['smert'])) {
                    $nz['smert'] = 1;
                }
                if (isset($_POST['noart'])) {
                    $nz['noart'] = 1;
                }
                if ($nz['kingfight'] == 1 && $nz['fastfight'] == 1) {
                    $nz['kingfight'] = 0;
                }

                //Генерируем уровни
                $levels = FRHelper::getChaoticTeammatesLevel($_POST['levellogin1'], $this->u->info['level']);
                $nz['min_lvl_1'] = $levels->min;
                $nz['max_lvl_1'] = $levels->max;
                $nz['min_lvl_2'] = $levels->min;
                $nz['max_lvl_2'] = $levels->max;

                $nz['tm1'] = $this->u->stats['reting'];

                if (
                    !$this->u->info['no_zv_key'] &&
                    (
                        $_POST['code21'] == 0 ||
                        $_POST['code21'] != $_SESSION['code2'] ||
                        $_SESSION['code2'] == 0 ||
                        !isset($_SESSION['code2'])
                    )
                ) {
                    $this->error = 'Неправильный код подтверждения';
                    $gad = 0;
                }
            } else {
                $gad = 0;
                $this->error = 'Что-то не так...<br>';
            }
        } elseif ($r == self::BATTLE_RAZDEL_GROUP) {
            //групповой бой
            //здесь заносим и проверяем данные на гурпповой бой
            if ($_POST['startime']) {
                $nz['time_start'] = (int)$_POST['startime'];
                if (!in_array($nz['time_start'], [300, 600, 900, 1200, 1800])) {
                    $nz['time_start'] = 600;
                }

                $nz['tm1max'] = ComparsionHelper::minimax((int)$_POST['nlogin1'], 1, 99);
                $nz['tm2max'] = ComparsionHelper::minimax((int)$_POST['nlogin2'], 1, 99);

                //Генерируем уровни союзника
                $levels = FRHelper::getTeammatesLevel($_POST['levellogin1'], $this->u->info['level']);
                $nz['min_lvl_1'] = $levels->min;
                $nz['max_lvl_1'] = $levels->max;

                //Генерируем уровни противника
                $levels = FRHelper::getTeammatesLevel($_POST['levellogin2'], $this->u->info['level']);
                $nz['min_lvl_2'] = $levels->min;
                $nz['max_lvl_2'] = $levels->max;

            } else {
                $gad = 0;
                $this->error = 'Что-то не так...<br>';
            }
        }

        $bt2 = (int)$_POST['bots2'];
        if ($bt2 != 0 && $r == self::BATTLE_RAZDEL_GROUP) {
            $bt2 = 1;
            $nz['min_lvl_2'] = $this->u->info['level'];
            $nz['max_lvl_2'] = $this->u->info['level'];
            $nz['min_lvl_1'] = $this->u->info['level'];
            $nz['max_lvl_1'] = $this->u->info['level'];
        } else {
            $bt2 = 0;
        }

        if ($gad == 1) {
            if ($nz['razdel'] == self::BATTLE_RAZDEL_CHAOTIC) {
                $nz['maxplayers'] = (int)$_POST['players'];
            }

            $dbvalues = [
                $nz['maxplayers'],
                $nz['otmorozok'],
                $nz['smert'],
                $nz['noart'],
                $nz['noeff'],
                $nz['noatack'],
                $nz['arand'],
                $nz['kingfight'],
                $nz['nobot'],
                $nz['fastfight'],
                $nz['noinc'],
                $bt2,
                strtotime(date('d.m.Y H:i:00')),
                $this->u->info['city'],
                $this->u->info['id'],
                $nz['type'],
                $nz['time_start'],
                $nz['timeout'],
                $nz['min_lvl_1'],
                $nz['min_lvl_2'],
                $nz['max_lvl_1'],
                $nz['max_lvl_2'],
                $nz['tm1max'],
                $nz['tm2max'],
                $nz['travmaChance'],
                $nz['invise'],
                $nz['razdel'],
                $nz['comment'],
                $nz['tm1'],
                $nz['tm2'],
            ];
            $dbquery = 'insert into zayvki (`maxplayers`,`otmorozok`,`smert`,`noart`,`noeff`,`noatack`,`arand`,`kingfight`,`nobot`,`fastfight`,`noinc`,`bot2`,`time`,`city`,`creator`,`type`,`time_start`,`timeout`,`min_lvl_1`,`min_lvl_2`,`max_lvl_1`,`max_lvl_2`,`tm1max`,`tm2max`,`travmaChance`,`invise`,`razdel`,`comment`,`tm1`,`tm2`) values (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)';
            Db::run($dbquery, $dbvalues);
            $zid = Db::lastInsertId();
            if ($zid) {
                Db::sql('update stats set zv = ?, team = 1 where id = ?', [$zid, $this->u->info['id']]);
                $this->u->info['zv'] = $zid;
                $this->error = 'Заявка на бой подана';
            } else {
                $this->error = 'Ошибка: Заявка не подана!';
            }
        }
    }

    /**
     * Звуковой пинг в чат?
     * @return void
     * @todo убрать колхоз с условиями когда станет ясно как оно работает.
     */
    private function sendSysChatSound(string $to = '', int $room = 0)
    {
        $cmsg = new ChatMessage();
        if (empty($to)) {
            $cmsg->setTo($this->u->info['login']);
        } else {
            $cmsg->setTo($to);
        }
        if (empty($room)) {
            $cmsg->setRoom($this->u->info['room']);
        } else {
            $cmsg->setRoom($room);
        }
        $cmsg->setCity($this->u->info['city']);
        $cmsg->setType(11);
        $cmsg->setSound(117);
        (new Chat())->sendMsg($cmsg);
    }

    public function startBattle($id, $vars = null)
    {
        // что это?
        $z = Db::getRow(
            'select * from zayvki where id = ? and start = 0 and cancel = 0 and (time > unix_timestamp() - 60*60*2 or razdel > 3)',
            [$id]
        );
        if (!isset($z['id'])) {
            return;
        }

        $vars = explode('|-|', $vars);
        if ($z['razdel'] == self::BATTLE_RAZDEL_GROUP || $z['razdel'] == self::BATTLE_RAZDEL_CHAOTIC) {
            if ($z['razdel'] == self::BATTLE_RAZDEL_CHAOTIC) {
                $sp = Db::getRows(
                    'select id, team, upLevel, btl_cof, exp from stats where zv = ? order by btl_cof desc', [$z['id']]
                );

                // Разбивка на команды раньше зависела от равной суммы btl_cof в командах, но как это должно было
                // работать никто не знал. Теперь просто пул игроков мешается и бьётся пополам. Ins.

                $pld2 = [];
                $team1IdsArr = [];
                $team2IdsArr = [];
                foreach ($sp as $pl) {
                    $pld2[] = $pl;
                }
                shuffle($pld2);
                $pieces = array_chunk($pld2, ceil(count($pld2) / 2));
                foreach ($pieces[0] as $team1) {
                    $team1IdsArr[] = $team1['id'];
                }
                foreach ($pieces[1] as $team2) {
                    $team2IdsArr[] = $team2['id'];
                }
                $team1Ids = implode($team1IdsArr);
                $team2Ids = implode($team2IdsArr);
                Db::sql('update stats set team = 1 where id in (?)', [$team1Ids]);
                Db::sql('update stats set team = 2 where id in (?)', [$team2Ids]);
            }
            $args = [
                $z['otmorozok'],
                $z['priz'],
                $z['smert'],
                $z['noart'],
                $z['noeff'],
                $z['noatack'],
                $z['arand'],
                $z['kingfight'],
                $z['nobot'],
                $z['fastfight'],
                $z['razdel'],
                $z['city'],
                $z['timeout'],
                $z['type'],
                $z['invise'],
                $z['travmChance'],
                $z['exp'],
            ];
            $q = 'insert into battle (
                    otmorozok,
                    priz,
                    smert,
                    noart,
                    noeff,
                    noatack,
                    arand,
                    kingfight,
                    nobot,
                    fastfight,
                    razdel,
                    city,
                    time_start,
                    timeout,
                    type,
                    invis,
                    travmChance,
                    addExp
                    ) values (?,?,?,?,?,?,?,?,?,?,?,?,unix_timestamp(),?,?,?,?,?)';
            //ТУТ старт боя
            Db::sql($q, $args);
            unset($q, $args);
            $btl_id = Db::lastInsertId();
            if ($btl_id) {
                if ($z['type'] == self::BATTLE_TYPE_MELEE) {
                    Db::sql(
                        'update items_users set inOdet = 0 where uid in (select id from stats where zv = ?)', [$z['id']]
                    );
                } elseif ($z['type'] == self::BATTLE_TYPE_NO_EKR_ITEMS) {
                    Db::sql(
                        'update items_users set inOdet = 0 where uid in (select id from stats where zv = ?) and 2price > 0',
                        [$z['id']]
                    );
                }
                //обновляем данные о поединке
                Db::sql('update stats set zv = 0 where zv = ?', [$z['id']]);
                $q = 'update users set battle = ' . $btl_id . ' where ' . $vars[1];
                Db::sql($q);
                unset($q);

                //обновляем заявку, что бой начался
                Db::sql('update zayvki set start = unix_timestamp(), btl_id = ? where id = ?', [$btl_id, $z['id']]);
                $this->u->info['battle'] = $btl_id;
                //Отправляем сообщение в чат всем бойцам
                $this->sendSysChatSound($vars[0], -1);
            }
        } elseif ($z['razdel'] >= 1 && $z['razdel'] <= 3) {
            //начало PvP
            if ($this->u->info['team'] != 1 || $this->u->info['zv'] != $z['id']) {
                $this->error = 'Вы не можете начать поединок.';
            } else {
                $enemyId = Db::getValue('select id from stats where zv = ? and team = 2 limit 1', [$z['id']]);
                if (!$enemyId) {
                    $this->error = 'Вы не можете начать поединок, вашу заявку никто не принял.';
                } else {
                    $enemy = Db::getRow('select login, money from users where id = ?', [$enemyId]);
                    //создаем поединок
                    if (
                        $enemy['money'] < $z['money'] ||
                        $this->u->info['money'] < $z['money']
                    ) {
                        $z['money'] = 0.00;
                    }

                    $args = [
                        $z['otmorozok'],
                        $z['smert'],
                        $z['noart'],
                        $z['noeff'],
                        $z['noatack'],
                        $z['arand'],
                        $z['kingfight'],
                        $z['nobot'],
                        $z['fastfight'],
                        $this->u->info['city'],
                        $z['timeout'],
                        $z['type'],
                        $z['travmChance'],
                        $z['money'],
                    ];
                    $q = 'insert into battle (
                    otmorozok,
                    smert,
                    noart,
                    noeff,
                    noatack,
                    arand,
                    kingfight,
                    nobot,
                    fastfight,
                    city,
                    time_start,
                    timeout,
                    type,
                    travmChance,
                    money
                    ) values (?,?,?,?,?,?,?,?,?,?,unix_timestamp(),?,?,?,?)';
                    Db::sql($q, $args);
                    $btl_id = Db::lastInsertId();
                    unset($q, $args);
                    if (!$btl_id) {
                        $this->error = 'Ошибка создания битвы.';
                    } else {
                        //обновляем данные о поединке
                        Db::sql('update stats set zv = 0 where zv = ?', [$z['id']]);
                        Db::sql(
                            'update users set battle = ? where id = ? or id = ?',
                            [$btl_id, $this->u->info['id'], $enemyId]
                        );

                        //Если бой кулачный, то снимаем вещи
                        if ($z['type'] == self::BATTLE_TYPE_MELEE) {
                            Db::sql(
                                'update items_users set inOdet = 0 where uid in (?,?) ',
                                [$this->u->info['id'], $enemyId]
                            );
                        }

                        //обновляем заявку, что бой начался
                        Db::sql(
                            'update zayvki set start = unix_timestamp(), btl_id = ? where id = ?', [$btl_id, $z['id']]
                        );
                        $this->u->info['battle'] = $btl_id;

                        //Отправляем сообщение в чат всем бойцам
                        $this->sendSysChatSound($enemy['login']);
                        die('<script>location="main.php?battle_id=' . $btl_id . '";</script>');
                    }
                }
            }
        }
    }

    public function getCurrentStatus(array $zi, int $r)
    {
        // нахуй статус
        // если у меня нет заявки
        // если я в бою
        // если я не в тех категориях

        if (
            !$this->u->info['zv'] || $this->u->info['battle'] > 0 ||
            !in_array($r, [self::BATTLE_RAZDEL_GROUP, self::BATTLE_RAZDEL_CHAOTIC, self::BATTLE_RAZDEL_TOURNAMENTS])
        ) {
            return;
        }
        $battleType = [
            self::BATTLE_RAZDEL_GROUP => 'группового',
            self::BATTLE_RAZDEL_CHAOTIC => 'хаотичного',
        ];
        $tm_start = floor(($zi['time'] + $zi['time_start'] - time()) / 6) / 10;
        $tm_start = $this->rzv($tm_start);
        echo '<b>Ожидаем начала ' . $battleType[$zi['razdel']] . ' боя</b>';
        echo '<br>Ваш бой начнется через ' . $tm_start . ' мин.';
    }

    public function getEndedBattlesList(string $slogin, int $dt)
    {
        $code = PassGen::intCode();
        $btl = '';
        $see = '';
        $usr = Db::getRow('select id, login, level, city from users where login = ? limit 1', [$slogin]);

        if (isset($usr['id'])) {
            $tms = $dt;
            $tmf = $dt + 86400;
            $sp = Db::getRows(
                'select * from battle_last where time >= ? and time < ? and uid = ? order by id desc ',
                [$tms, $tmf, $usr['id']]
            );
            $jk = 0;
            $btl_lst = [];
            foreach ($sp as $pl) {
                $b = Db::getRow('select * from battle_end where battle_id = ? limit 1', [$pl['battle_id']]);
                $tm = '';
                if (isset($b['id'])) {
                    $tms = [];
                    $ts = [];
                    $spi = Db::getRows('select * from battle_last where battle_id = ?', [$pl['battle_id']]);
                    foreach ($spi as $pli) {
                        if (!isset($tms[$pli['team']])) {
                            $ts[] = $pli['team'];
                        }
                        $tms[$pli['team']][count($tms[$pli['team']])] = $pli;
                    }
                    $k = 0;
                    while ($k < count($ts)) {
                        $g = $ts[$k];
                        $h = 0;
                        $tm2 = '';
                        while ($h < count($tms[$g])) {
                            if ($tms[$g][$h]['uid'] > 0) {
                                if ($tms[$g][$h]['align'] > 0) {
                                    $tm2 .= '<img src="//' . Config::get('img') . '/i/align/align' .
                                        $tms[$g][$h]['align'] . '.gif">';
                                }
                                $tm2 .= '<b>' . $tms[$g][$h]['login'] . '</b> [' . $tms[$g][$h]['lvl'] . ']
                                <a href="info/' . $tms[$g][$h]['uid'] . '" target="_blank">
                                <img src="//' . Config::get('img') . '/i/inf_capitalcity.gif" alt=""></a>, ';
                            }
                            $h++;
                        }
                        $tm2 = rtrim($tm2, ', ');
                        $btlg = Db::getValue('select id, team_win from battle where id = ?', [$pl['battle_id']]);
                        if (isset($btlg['id']) && $g == $btlg['team_win']) {
                            $tm2 .= ' <img width="20" height="20" src="//' . Config::get(
                                    'img'
                                ) . '/i/flag.gif" title="Победа"> ';
                        }
                        $tm .= $tm2;
                        if ($k + 1 < count($ts) && $tm2 != '' && $ts[$k + 1] > 0) {
                            $tm .= ' <b style="color: red">против</b> ';
                        }
                        $k++;
                    }
                }
                if (!isset($btl_lst[$b['id']])) {
                    $btl_lst[$b['id']] = true;
                    if ($tm == '') {
                        $tm = 'Данные поединка потеряны';
                    }
                    $jk++;
                    $btl .= $jk . '. <span class=date>' . date(
                            'd.m.y H:i', $pl['time']
                        ) . '</span> ' . $tm . ' <A HREF="logs.php?log=' . $pl['battle_id'] . '&rnd=' . $code . '" target=_blank>»»</A><br>';
                }
            }
        }
        $see .= empty($btl) ? '<div style="font-weight: bold;">В этот день не было боев, или же, летописец опять потерял свитки...</div><hr><br>' : $btl;
        echo $see;
    }

    public function getCurrentBattlesList(): void
    {
        $code = PassGen::intCode();
        $query = 'select
        login,
        users.id,
        team,
        battle,
        time_start,
        typeBattle from users
            left join stats on users.id = stats.id
            left join battle on users.battle = battle.id
                   where
                       battle in (select id from battle
                                            where type != 329 and
                                                  team_win = -1 and
                                                  time_over = 0 and
                                                  start1 > 0
                                            order by time_start)
                   order by battle desc';
        $currentBattles = Db::getRows($query);

        if (empty($currentBattles)) {
            echo '<div style="text-align: center;">К сожалению сейчас боев нет...</div>';
        } else {
            // Надеялся на вывод вида:
            // [battle -> [team -> [uid, uid, uid], team -> [uid, uid, uid],]],
            // [battle -> [team -> [uid, uid, uid], team -> [uid, uid, uid],]],
            // но глубоко наломался, где-то перемудрил с ArraySorter::groupBy()
            // и на выходе там сортировка, но с сохранением всех вложенностей,
            // что усложнило последющий вывод. Но вышло как вышло. Ins.
            $currentBattlesArray = ArraySorter::groupBy($currentBattles, 'battle');
            echo '<ol>';
            foreach ($currentBattlesArray as $battleId => $cb) {
                $players = '';
                $typeBattle = 0;
                $timeStart = 0;
                $teams = ArraySorter::groupBy($cb, 'team');
                foreach ($teams as $teamId => $team) {
                    foreach ($team as $key => $player) {
                        $players .= $this->u->microLogin($player['id']);
                        if ($key !== array_key_last($team)) {
                            $players .= ', ';
                        } else {
                            $typeBattle = $player['typeBattle'];
                            $timeStart = $player['time_start'];
                        }
                    }
                    if ($teamId !== array_key_first($teams)) {
                        continue;
                    }
                    $players .= '<strong style="color: red;"> против </strong>';
                }
                echo '<li><span class=date>' . date('d.m.y H:i', $timeStart) . '</span>';
                echo " $players ";
                echo '<img src="//' . Config::get('img') . '/i/fighttype' . $typeBattle . '.gif" alt="">';
                echo '<a href="//' . Config::get('host') . '/logs.php?log=' . $battleId .
                    '&rnd=' . $code . '">▶▶</a>';
            }
            echo '</ol>';
        }
    }

    public function getTournaments(): object
    {
        /** Турниры by Insallah*/
        # Защита от F5
        if (!isset($_SESSION['bypass'])) {
            $_SESSION['bypass'] = mt_rand();
        }
        if ($_SERVER['REQUEST_METHOD'] === 'POST' && $_POST['key'] == $_SESSION['bypass']) {
            unset($_SESSION['bypass']);
            if (array_key_exists('tournament_start', $_POST)) {
                (new Tournament())->join($this->u->info['id']);
            }
        }

        # Формируем список идущих турниров.
        $tournamentsList = Db::getRows('select * from tournaments');
        $tournaments = '<ul>';
        foreach ($tournamentsList as $tournament) {
            $time = $tournament['start_time'] === -1 ? 'Турнир уже начался!' : date(
                'G:i', $tournament['start_time']
            );
            $tournament_members_id = TournamentModel::getFreeFighters($tournament['tid']);
            $members = [];
            foreach ($tournament_members_id as $member) {
                $members[] = TournamentModel::uidToLogin($member);
            }
            $tournaments .= sprintf(
                "<li>Турнир для %d уровней.<br>Время подачи заявки: %s<br>Участники: %s</li>",
                $tournament['tid'], $time, implode(', ', $members)
            );
        }
        $tournaments .= '</ul>';

        return (object)[
            'hasTournaments' => !empty($tournamentsList),
            'listTournaments' => $tournaments,
        ];
        /** Конец турниров от Insallah. */
    }

    /** Дописывает значение после точки, если такового нет. 1 -> 1.0, 1.1 -> 1.1
     * @param string $str
     * @return string
     */
    public function rzv(string $str): string
    {
        $symbols = explode('.', $str);
        return isset($symbols[1]) ? $symbols[0] . '.' . $symbols[1] : $symbols[0] . '.0';
    }

    public function seeZv(array $zi, int $r)
    {
        $code = PassGen::intCode();
        if (!$r) {
            return;
        }
        if (!in_array($r, [self::BATTLE_RAZDEL_GROUP, self::BATTLE_RAZDEL_CHAOTIC])) {
            return;
        }//Список заявок
        $i = 0;
        $fightrequests = Db::getRows(
            'select * from zayvki where razdel = ? and start = 0 and cancel = 0 and time > unix_timestamp() - ? order by id desc',
            [$r, 2 * 60 * 60]
        );
        $zvb = '';
        foreach ($fightrequests as $pl) {
            $tmStart = floor(($pl['time'] + $pl['time_start'] - time()) / 6) / 10;
            $tmStart = $this->rzv($tmStart);

            if (!empty($pl['comment'])) {
                $dl = '';
                if ($this->u->isModerator() && $pl['dcom'] == 0) {
                    $dl .= ' (<a href="/main.php?zayvka=1&r=' . $pl['razdel'] . '&delcom=' . $pl['id'] . '&key=' . $this->u->info['nextAct'] . '&rnd=' . $code . '">удалить комментарий</a>)';
                    $pl['dcom'] = $this->deleteComment($pl['id']);
                }
                if ($pl['dcom'] > 0) {
                    $dl = ' <i style="color: grey">Комментарий удален модератором</i>';
                    if (!$this->u->isModerator()) {
                        $pl['comment'] = '';
                    }
                }
                $zv_comm = ' ' . $pl['comment'] . $dl . ' ';
            } else {
                $zv_comm = '';
            }

            $rad = '';

            if ($pl['razdel'] == self::BATTLE_RAZDEL_CHAOTIC) {
                $tm = '';

                $uids = Db::getColumn('select id from stats where zv = ?', [$pl['id']]);
                $cols = count($uids);
                foreach ($uids as $uid) {
                    $tm .= $this->u->microLogin($uid) . ', ';
                }

                $tm = rtrim($tm, ', ');
                if (!isset($zi['id']) && $this->u->room['zvsee'] == 0) {
                    $rad = '<input type="radio" name="btl_go" id="btl_go' . $pl['id'] . '" value="' . $pl['id'] . '"> ';
                }
                $n1tv = '';
                $unvs = '';
                if ($pl['invise'] == 1) {
                    $userslist = $this->u->isModerator() ? $tm : '';
                    $tm = '<span style="color:maroon">' . $this->u->microLogin($pl['creator']) . '</span>' .
                        $userslist . ' - <i>невидимый</i>';
                    $unvs = ' Участников: ' . $cols . ' чел. ';
                    $n1tv .= ' <img src="//' . Config::get('img') . '/i/fighttypehidden0.gif" title="Невидимый">';
                }
                if ($pl['kingfight'] == 1) {
                    $n1tv .= ' <img src="//' . Config::get('img') . '/king.gif" title="Призовой поединок">';
                }
                if ($pl['travmaChance'] == 100) {
                    $n1tv .= '<img src="//' . Config::get('img') . '/fighttype6.gif" title="Кровавый поединок">';
                }
                if ($pl['noatack'] == 1) {
                    $n1tv .= ' <img src="//' . Config::get('img') . '/i/fighttypehidden0.gif" title="Закрытый бой">';
                }
                if ($pl['nobot'] == 1) {
                    $n1tv .= ' <img src="//' . Config::get('img') . '/nobot.gif" title="В бой не вступают боты">';
                }
                if ($pl['fastfight'] == 1) {
                    $n1tv .= ' <img src="//' . Config::get(
                            'img'
                        ) . '/fastfight.gif" title="Для начала боя необходимо минимум 2 игрока">';
                }
                if ($pl['noeff'] == 1) {
                    $n1tv .= ' <img src="//' . Config::get(
                            'img'
                        ) . '/svitok4.png" width="20" height="20" title="Запрет на использование свитков восстановления НР и маны">';
                }
                if ($pl['arand'] == 1) {
                    $n1tv .= ' <img src="//' . Config::get(
                            'img'
                        ) . '/random.png" width="20" height="20" title="Распределение бойцов случайным образом">';
                }
                if ($pl['noart'] == 1) {
                    $n1tv .= ' <img src="//' . Config::get(
                            'img'
                        ) . '/noart.png" width="20" height="20" title="Бой без артефактов">';
                }
                if ($pl['otmorozok'] == 1) {
                    $n1tv .= ' <img src="//' . Config::get(
                            'img'
                        ) . '/snow.gif" width="20" height="20" title="В бой могут вмешаться Отморозки">';
                }

                if ($pl['priz'] == 1) {
                    $zv_comm = ' <a href="/n/567/" target="_blank"><span style="color:firebrick;" title="Участники получают жетоны, чем больше призовых хаотов за сутки, тем больше падает жетонов за победу "><b>(Героическое Сражение)</b></span></a>';
                }
                if ($r == 5 && ($pl['creator'] == $this->u->info['id']) && $cols < 2 && $pl['priz'] == 0) {
                    $del_q = '&nbsp;&nbsp;<a href="/main.php?zayvka=1&r=' . $pl['razdel'] . '&del_z_time=' . $pl['id'] . '&rnd=' . $code . '">
                    <img src="//' . Config::get('img') . '/i/clear.gif" title="Удалить заявку" alt=""></a>';
                } else {
                    $del_q = '';
                }
                $lvldt = '';
                if ($pl['min_lvl_1'] != $pl['max_lvl_2']) {
                    $lvldt .= '' . $pl['min_lvl_1'] . '-' . $pl['max_lvl_2'] . ' ур. ';
                } else {
                    $lvldt .= '' . $pl['min_lvl_1'] . ' ур. ';
                }
                $lvldt .= $cols . '/' . $pl['maxplayers'];
                $zvb .= $rad . '<span class="date">' . date('H:i', $pl['time']) . '</span>
                    <span style="color: green; font-weight: bold; font-style: italic;">(' . $lvldt . ')</span>
                    тип боя: <IMG SRC="//' . Config::get('img') . '/i/fighttype' . $pl['type'] . '.gif" WIDTH="20" HEIGHT="20" title="Хаотичный бой">
                    ' . $n1tv . ' (таймаут <b>' . ($pl['timeout'] / 60) . ' мин.</b>) <b>' . $zv_comm . '</b>
                    <span class="dsc" style="font-style: italic; color: green;">(' . $unvs . 'Бой начнется через <B>' . $tmStart . '</B> мин.)</span>
                    <i>Участники:</i> ' . $tm . ' ' . $del_q . '<br>';

            } elseif ($pl['razdel'] == self::BATTLE_RAZDEL_GROUP) {
                if ($pl['min_lvl_2'] < 2) {
                    $pl['min_lvl_2'] = 2;
                }
                if ($pl['max_lvl_2'] > 21) {
                    $pl['max_lvl_2'] = 21;
                }

                if ($pl['teams'] == 2) {
                    //Персонаж в заявке, подключаем ему противника
                    //Ищем бота для групповых
                    $xx2 = $this->countUsersInTeam2($pl['id']);
                    if ($pl['bot2'] > 0 && $xx2 < $pl['tm2max']) {
                        //Добавляем ботов за вторую команду
                        $spb = Db::getColumn(
                            'select users.id from users left join stats on users.id = stats.id where bot = 3 and level = ? and battle = 0 and zv = 0'
                        );
                        foreach ($spb as $botId) {
                            if ($xx2 >= $pl['tm2max'] || rand(0, 10000) >= 5000 || rand(0, 10000) <= 5000) {
                                continue;
                            }
                            $bt = $this->u->addNewbot(0, '', $botId);
                            if ($bt == 0) {
                                continue;
                            }
                            Db::sql('update stats set zv = ?, team = 2 where id = ?', [$pl['id'], $bt]);
                            $xx2++;
                        }
                    }
                    unset($xx2);
                }

                //генерируем команды
                $teams = [];
                $cols = [];
                $tmc = [];
                $users = Db::getRows('select team, id from stats where zv = ?', [$pl['id']]);
                foreach ($users as $user) {
                    ${'tm' . $user['team']} .= $this->u->microLogin($user['id']) . ', ';
                    $tmc[$user['team']]++;
                    $teams[$user['team']][] = $this->u->microLogin($user['id']);
                }

                foreach ($teams as $id => $members) {
                    $cols[$id] = count($members);
                    $teams[$id] = !empty($cols[$id]) ? implode(', ', $members) : 'группа пока не набрана';
                }

                if (!isset($zi['id']) && $this->u->room['zvsee'] == 0) {
                    $rad = '<input type="radio" name="groupClick" id="groupClick" value="' . $pl['id'] . '"> ';
                }

                $zvb .= $rad . '<span class="date">' . date('H:i', $pl['time']) . '</span> ';

                foreach ($teams as $id => $memberList) {
                    $zvb .= '(<span style="color: green;">' . $cols[$id] . '/<b>' . $pl['tm' . $id . 'max'] . '</b></span>) ';
                    $zvb .= $memberList;
                    $zvb .= '<span style="color: green; font-style: italic; font-weight: bold;"> (';
                    $zvb .= $pl['min_lvl_' . $id] == $pl['max_lvl_' . $id] ?
                        $pl['min_lvl_' . $id] : $pl['min_lvl_' . $id] . '-' . $pl['max_lvl_' . $id];
                    $zvb .= ' ур.)</span>';
                    if ($id !== array_key_last($teams)) {
                        $zvb .= ' <i>против</i> ';
                    }
                }

                $zvb .= ' тип боя: <IMG SRC="//' . Config::get(
                        'img'
                    ) . '/i/fighttype' . $pl['type'] . '.gif" WIDTH="20" HEIGHT="20" title="Групповой бой"> (таймаут: <b>' . ($pl['timeout'] / 60) . ' мин.</b>) ';
                $zvb .= ' <b>' . $zv_comm . '</b> ';
                $zvb .= ' <i style="color: green">(Бой начнется через <b>' . $tmStart . '</b>)</i><BR>';
            }
            $i++;
        }
        if ($i == 0) {
            //заявок нет
            if ($this->u->room['zvsee'] > 0) {
                echo '<div style="margin-top: 32px; text-align: center; font-weight: bold;">В данном разделе нет ни одной заявки</div>';
            }
        } else {
            if (!isset($zi['id']) && $this->u->room['zvsee'] == 0) {

                $html = <<<HTML
                <div style="float:left;">
                    <form method="post" style="margin:0;padding:0;" action="/main.php?zayvka=1&r=<?= $r ?>&rnd=<?= $code ?>"><br>
                        <input class="btn" type="submit" value="Принять вызов"><br><?= $zvb ?>
                        <input class="btn" style="margin-top:1px;" type="submit" value="Принять вызов">
                    </form>
                </div>
                HTML;

                if ($r === self::BATTLE_RAZDEL_CHAOTIC) {
                    if (!$this->u->info['no_zv_key']): ?>
                        <div style="float:left;">
                            <form method="post" style="margin:0px;padding:0px;"
                                  action="/main.php?zayvka=1&r=<?= $r ?>&rnd=<?= $code ?>"><br>
                                <img src="/show_reg_img/security2.php?id='<?= time() ?>" width="70" height="20">
                                Код подтверждения: <input style="width:40px;" type="text" name="code21">
                                <input class="btn" type="submit" value="Принять вызов"><br><?= $zvb ?>
                                <img src="/show_reg_img/security2.php?id=<?= time() ?>" width="70" height="20">
                                Код подтверждения: <input style="width:40px;" type="text" name="code22">
                                <input class="btn" style="margin-top:1px;" type="submit" value="Принять вызов">
                            </form>
                        </div>
                    <?php
                    else:
                        echo $html;
                    endif;
                } else {
                    if (empty($zvb) || $this->u->info['level'] <= Config::get('bot_level')) {
                        echo '<div style="float:left;">' . $zvb . '</div>';
                    } else {
                        echo $html;
                    }
                }
            } else {
                echo $zvb;
            }
        }
    }

    private function deleteComment($uid): int
    {
        if (
            !isset($_GET['delcom']) ||
            $_GET['delcom'] != $uid ||
            !$this->u->newAct($_GET['key'])
        ) {
            return 0;
        }
        Db::sql('update zayvki set dcom = ? where id = ?', [$this->u->info['id'], $uid]);
        return $this->u->info['id'];
    }

    /** Принять групповую заявку.
     * @param array $z заявка
     * @return void
     */
    private function joinGroup(array $z)
    {
        $tm = 0;
        if (isset($_GET['tm1'])) {
            $tm = 1;
        } elseif (isset($_GET['tm2'])) {
            $tm = 2;
        } else {
            $this->error = 'Что-то здесь не так';
        }
        if ($tm == 0) {
            return;
        }
        $t1 = $tm;
        $t2 = 1;
        $tmmax = 0;
        $cln = 0;
        if ($tm == 1) {
            $t2 = 2;
        }
        $clanTeamsCheck = Db::getRows(
            'select clan, team from users left join stats on users.id = stats.id where zv = ?', [$z['id']]
        );
        foreach ($clanTeamsCheck as $ctc) {
            if ($ctc['team'] == $t1) {
                $tmmax++;
            }
            if (
                !empty($this->u->info['clan']) &&
                $this->u->info['clan'] == $ctc['clan'] &&
                $ctc['team'] == $t2
            ) {
                $cln++;
            }
        }

        $error = null;
        if ($cln > 0) {
            $error = 'Вы не можете сражаться против сокланов';
        } elseif ($z['bot2'] == 1 && $t1 == 2) {
            $error = 'Вы не можете сражаться на стороне ботов';
        } elseif ($z['tm' . $t1 . 'max'] <= $tmmax) {
            $error = 'Группа уже набрана (' . ($z['tm' . $t1 . 'max'] - $tmmax) . ')';
        } elseif (
            $z['min_lvl_' . $t1] > $this->u->info['level'] ||
            $z['max_lvl_' . $t1] < $this->u->info['level']
        ) {
            $error = 'Вы не подходите по уровню, за эту команду могут зайти персонажи ' .
                $z['min_lvl_' . $t1] . ' - ' . $z['max_lvl_' . $t1] . ' уровня';
        } elseif ($this->u->isWeakened()) {
            $error = 'Вы слишком ослаблены, восстановитесь';
        }

        if ($error) {
            $this->error = $error;
            return;
        }
        Db::sql('update stats set zv = ?, team = ? where id = ?', [$z['id'], $t1, $this->u->info['id']]);
        $this->error = 'Вы приняли групповой бой...';
        $this->u->info['zv'] = $z['id'];
        $this->u->info['team'] = $t1;
    }

    /** Присоединиться к хаотической заявке.
     * @param array $z заявка
     * @return void
     */
    private function joinChaotic(array $z)
    {
        $error = null;
        $cols = $this->countUsersAll($z['id']);
        if ($cols >= $z['maxplayers']) {
            $error = 'Достигнут максимальный предел участников в этой заявке!';
        } elseif ($this->testTravm() == 1 && $z['k'] != 1) {
            $error = 'Вы травмированы. С такими увечьями доступны кулачные бои.';
        } elseif ($this->testTravm() == 2) {
            $error = 'Вы травмированы. С такими увечьями невозможно сражаться.';
        } elseif (
            !$this->u->info['no_zv_key'] &&
            (
                !isset($_SESSION['code2']) ||
                $_SESSION['code2'] < 1 ||
                (
                    $_POST['code21'] != $_SESSION['code2'] &&
                    $_POST['code22'] != $_SESSION['code2']
                )
            )
        ) {
            $error = 'Неправильный код подтверждения';
        } elseif (
            $z['min_lvl_1'] > $this->u->info['level'] ||
            $z['max_lvl_1'] < $this->u->info['level']
        ) {
            $error = 'Вы не подходите по уровню, за эту команду могут зайти персонажи ' .
                $z['min_lvl_1'] . ' - ' . $z['max_lvl_1'] . ' уровня';
        } elseif ($this->u->isWeakened()) {
            $error = 'Вы слишком ослаблены, восстановитесь';
        }

        if ($error) {
            $this->error = $error;
            return;
        }
        $t1 = 0;
        if ($z['type'] == self::CHAOTIC_TYPE_PRIZED) {
            $this->joinPrizedChaotic();
        }

        $this->u->info['login2'] = '';
        $blnc = $this->u->stats['reting'];
        $z['tm' . $t1] += $blnc;

        Db::run('update stats set zv = ?, team = ? where id = ?', [$z['id'], $t1, $this->u->info['id']]);
        Db::sql('update users set login2 = ? where id = ?', [$this->u->info['login2'], $this->u->info['id']]);
        Db::sql('update zayvki set tm1 = ?, tm2 = ? where id = ?', [$z['tm1'], $z['tm2'], $z['id']]);
        $this->u->info['zv'] = $z['id'];
        $this->u->info['team'] = $t1;
        $this->error = 'Вы приняли хаотичный бой...';

    }

    private function joinPrizedChaotic()
    {
        //============================================================================================= Призовые
        Db::sql(
            'insert into users (
                   name,
                   align,
                   `real`,
                   login,
                   host_reg,
                   pass,
                   ip,
                   ipreg,
                   room,
                   timereg,
                   mail,
                   sex,
                   fnq,
                   molch2,
                   level
                   ) values (?,?,1,?,0,?,?,?,422,unix_timestamp(),?,?,0,unix_timestamp() + 86400,8)',
            [
                $this->u->info['name'],
                $this->u->info['align'],
                $this->u->info['login'],
                $this->u->info['pass'],
                IP,
                IP,
                'haot@new-combats.com',
                $this->u->info['sex'],
            ]
        );

        $uidb = Db::lastInsertId();
        Db::sql('update users set inUser = ? where id = ?', [$uidb, $this->u->info['id']]);
        /** Классы:
         * 1 - Уворот
         * 2 - Крит
         * 3 - Танк
         * 4 - Топор
         * 5 - Маг земли
         * 6 - Маг воздуха
         */
        $sellclass = rand(1, 6);
        $stmt1 = Db::prepare('update items_users set inOdet = ? where id = ?');
        $stmt2 = Db::prepare(
            'update items_users set `1price` = (select price_1 from items_shop where sid = 1 and items_shop.item_id = ?) where id = ?'
        );
        $stmt3 = Db::prepare(
            'insert into stats (id, stats, ability, skills, exp, priems) values (?,?,-75,-9,100000,?)'
        );

        $classItems = [
            1 => [
                1 => 525,
                2 => 539,
                3 => 523,
                14 => 523,
                4 => 290,
                5 => 541,
                7 => 633,
                8 => 647,
                9 => 680,
                10 => 685,
                11 => 685,
                12 => 685,
                13 => 1151,
                16 => 707,
                17 => 712,
            ],
            2 => [
                1 => 527,
                2 => 537,
                3 => 567,
                14 => 723,
                4 => 291,
                5 => 544,
                7 => 626,
                8 => 651,
                9 => 683,
                10 => 686,
                11 => 686,
                12 => 686,
                13 => 706,
                16 => 708,
                17 => 717,
            ],
            3 => [
                1 => 533,
                2 => 536,
                3 => 558,
                14 => 722,
                4 => 291,
                5 => 545,
                7 => 628,
                8 => 654,
                9 => 684,
                10 => 689,
                11 => 689,
                12 => 689,
                13 => 700,
                16 => 710,
                17 => 718,
            ],
            4 => [
                1 => 528,
                2 => 538,
                3 => 552,
                14 => 552,
                4 => 291,
                5 => 543,
                7 => 627,
                8 => 653,
                9 => 681,
                10 => 687,
                11 => 687,
                12 => 687,
                13 => 320,
                16 => 709,
                17 => 716,
            ],
            5 => [
                1 => 531,
                2 => 534,
                3 => 1026,
                4 => 291,
                5 => 548,
                7 => 629,
                8 => 657,
                9 => 674,
                10 => 692,
                11 => 692,
                12 => 692,
                13 => 699,
                16 => 711,
                17 => 714,
            ],
            6 => [
                1 => 531,
                2 => 534,
                3 => 1026,
                4 => 291,
                5 => 548,
                7 => 629,
                8 => 658,
                9 => 675,
                10 => 693,
                11 => 693,
                12 => 693,
                13 => 699,
                16 => 711,
                17 => 714,
            ],
        ];

        $classStats = [
            1 => [
                's1=21|s2=31|s3=16|s4=30|rinv=40|m9=5|m6=10|s7=0|a1=10|a2=0|a3=0|a4=0|a5=0|mg1=0|mg2=0|mg3=0|mg4=0|mg5=0|mg6=0|mg7=0|s5=0|s6=0',
                '193|8|217|221|6|213|14|220|141|232|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0',
            ],
            2 => [
                's1=24|s2=20|s3=24|s4=30|rinv=40|m9=5|m6=10|s7=0|a1=0|a2=0|a3=0|a4=9|a5=0|mg1=0|mg2=0|mg3=0|mg4=0|mg5=0|mg6=0|mg7=0|s5=0|s6=0|a6=0|s8=0|s9=0|s10=0|s11=0|s12=0|s13=0|s14=0|s15=0',
                '193|204|221|138|9|188|240|215|147|232|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0',
            ],
            3 => [
                's1=42|s2=3|s3=3|s4=50|rinv=40|m9=5|m6=10|s7=0|a1=0|a2=0|a3=9|a4=0|a5=0|mg1=0|mg2=0|mg3=0|mg4=0|mg5=0|mg6=0|mg7=0|s5=0|s6=0|a6=0|s8=0|s9=0|s10=0|s11=0|s12=0|s13=0|s14=0|s15=0',
                '11|204|233|226|45|14|139|221|6|232|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0',
            ],
            4 => [
                's1=43|s2=15|s3=15|s4=25|rinv=40|m9=5|m6=10|s7=0|a1=0|a2=10|a3=0|a4=0|a5=0|mg1=0|mg2=0|mg3=0|mg4=0|mg5=0|mg6=0|mg7=0|s5=0|s6=0',
                '193|139|49|14|6|217|221|204|147|45|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0',
            ],
            5 => [
                's1=14|s2=3|s3=3|s4=25|rinv=40|m9=5|m6=10|s7=0|a1=0|a2=0|a3=0|a4=0|a5=3|mg1=0|mg2=0|mg3=0|mg4=6|mg5=0|mg6=0|mg7=0|s5=13|s6=40|a6=0|s8=0|s9=0|s10=0|s11=0|s12=0|s13=0|s14=0|s15=0',
                '208|117|170|44|113|128|122|249|246|147|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0',
            ],
            6 => [
                's1=14|s2=3|s3=3|s4=25|rinv=40|m9=5|m6=10|s7=0|a1=0|a2=0|a3=0|a4=0|a5=3|mg1=0|mg2=6|mg3=0|mg4=0|mg5=0|mg6=0|mg7=0|s5=13|s6=40|a6=0|s8=0|s9=0|s10=0|s11=0|s12=0|s13=0|s14=0|s15=0',
                '208|93|98|260|39|263|257|104|30|147|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0',
            ],
        ];

        /** @var array $classEffects
         * Эффекты:<br>
         * 1 - Сила;<br>
         * 7 - Интуиция;<br>
         * 8 - Ловкость;<br>
         * 9 - Интеллект;<br>
         * 20 - Сокрушение;<br>
         * 25 - Защита от оружия;<br>
         * 32 - Холодный разум;<br>
         * 37 - Нектар;<br>
         * 38 - Нектар отрицания;<br>
         * 53 - Магическое усиление воздуха;<br>
         * 54 - Магическое усиление земли;<br>
         * 283 - Бутерброд -Завтрак Рыцаря- толстый;<br>
         * 296 - Жажда Жизни +6;<br>
         * 439 - Магическое усиление общее;<br>
         */
        $classEffects = [
            1 => [8, 20, 25, 37, 38, 283, 296,],
            2 => [7, 20, 25, 37, 38, 283, 296,],
            3 => [1, 20, 25, 37, 38, 283, 296,],
            4 => [1, 20, 25, 37, 38, 283, 296,],
            5 => [9, 32, 54, 439, 25, 37, 38, 283, 296,],
            6 => [9, 32, 53, 439, 25, 37, 38, 283, 296,],
        ];

        foreach ($classEffects[$sellclass] as $classEffect) {
            Effects::addById($uidb, $classEffect);
        }
        $items = $classItems[$sellclass];

        foreach ($items as $slot => $itemId) {
            $re = $this->u->addItem($itemId, $uidb);
            $stmt1->execute([$slot, $re]);
            $stmt2->execute([$itemId, $re]);
        }
        $stmt3->execute([$uidb, $classStats[$sellclass][0], $classStats[$sellclass][1]]);

        Db::sql('update users set money = -3000, money2 = 0 where id = ?', [$uidb]);

        //Корекция хп в призовых
        Db::sql('update stats set hpNow = hpAll, mpNow = mpAll where id = ?', [$uidb]);
        $this->u->info['id'] = $uidb;
        //=============================================================================================
        $this->error = 'Вы вселены в клона 8го левела'; //ТУТ вселяем в клона призовые хаоты
        //echo '<script>location="/main.php?battle_id=' . $btl_id . '";</script>'; - и где, блять, брать $btl_id ???
        echo '<script>location="/main.php";</script>';
    }

    public function go(int $id)
    {
        global $zi;
        if (empty($id) || !empty($this->u->info['battle'])) {
            return;
        }
        if (isset($zi['id'])) {
            $this->error = 'Вы не можете принять бой. Сначала отзовите свою заявку.';
            return;
        }

        $z = Db::getRow(
            'select * from zayvki where id = ? and start = 0 and cancel = 0 and time > unix_timestamp() - 60*60*2',
            [$id]
        );
        if (!isset($z['id'])) {
            $this->error = 'Заявка на бой не найдена.';
            return;
        }
        if ($z['razdel'] == self::BATTLE_RAZDEL_GROUP) {
            $this->joinGroup($z);
        } elseif ($z['razdel'] == self::BATTLE_RAZDEL_CHAOTIC) {
            $this->joinChaotic($z);
        }
    }
}