battles/classes/Battles/Bank.php
Igor Barkov (iwork) 3502904656 Рефакторинг, очистка, работа над ошибками, связанными с базой, отказ от глобальной переменной $user во многих файлах.
Singleton в некоторых местах вместо решения #42.
Новые шаги для решения #16 и #52.
Closes #42.
Closes #32.
Closes #31.
2022-01-27 01:15:33 +02:00

229 lines
8.5 KiB
PHP
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
/**
* Author: lopiu
* Date: 03.07.2020
* Time: 07:24
*/
namespace Battles;
use Exceptions\GameException;
use Battles\Database\Db;
use Throwable;
class Bank
{
public int $user_id = 0;
private int $money = 0;
private $user;
const ERROR_NO_MONEY_IN_WALLET = "Ошибка! Нет денег в кошельке!";
const ERROR_NO_BANK_ACCOUNT = "Ошибка! Счёта не существует!";
const ERROR_NO_MONEY_IN_BANK_ACCOUNT = "Ошибка! Нет денег на счету!";
const ERROR_WRONG_AMOUNT = "Ошибка! Сумма должна быть положительной!";
const LOG = [
'sendMoney' => 'Банк: Перевод средств на другой счёт.',
'receiveMoney' => 'Банк: Получение средств.',
'depositMoney' => 'Пополнение счёта.',
'withdrawMoney' => 'Снятие денег со счёта.',
'clanRegister' => 'Оплата стоимости регистрации клана.',
'sellShop' => 'Продажа товара в магазине.'
];
public function __construct(int $user_id)
{
$bank_row = Db::getInstance()->fetch('SELECT user_id, money FROM bank WHERE user_id = ?', $user_id);
$this->user = Db::getInstance()->fetch('SELECT money FROM users WHERE id = ?', $user_id);
foreach ($this as $key => $value) {
if (isset($bank_row[$key])) {
$this->$key = $bank_row[$key];
}
}
}
/**
* Комиссия: процент от переводимой суммы, но не менее 1 кр. Задаётся в config.php.
*
* @param int $amount сумма.
*
* @return int
*/
private function bankCommission(int $amount): int
{
$bankCommission = round($amount * GameConfigs::BANK_COMISSION);
if ($bankCommission < 1) {
return 1;
} else {
return (int)$bankCommission;
}
}
/**
* Пишем банковское событие в лог в БД
*
* @param int $receiverId ID получателя.
* @param int $amount сумма.
* @param string $operationType тип банковской операции.
* @param int $senderId ID отправителя (ID игрока, если не указано иное).
*
* @return void
*/
private function bankLogs(int $receiverId, int $amount, string $operationType, int $senderId = null): void
{
if (is_null($senderId)) {
$senderId = $this->user_id;
}
$text = self::LOG[$operationType];
if ($operationType == "sendMoney") {
$text .= " Комиссия: " . $this->bankCommission($amount);
} elseif ($operationType == "depositMoney") {
$receiverId = $this->user_id;
} elseif ($operationType == "withdrawMoney") {
$receiverId = $this->user_id;
$text .= " Комиссия: " . $this->bankCommission($amount);
}
GameLogs::addBankLog($senderId,$receiverId,$amount,$operationType,$text);
}
/**
* Перевод денег между банковскими счетами игроков с банковской комиссией.
*
* @param int $receiver ID получателя.
* @param int $amount сумма.
*
* @return int
* @throws GameException
*/
public function sendMoney(int $receiver, int $amount): int
{
$receiverWallet = Db::getInstance()->ofetch('SELECT money FROM bank WHERE user_id = ?', $receiver);
if ($amount <= 0) {
throw new GameException(self::ERROR_WRONG_AMOUNT);
}
if (!$receiverWallet) {
throw new GameException(self::ERROR_NO_BANK_ACCOUNT);
}
$amountWithComission = $amount + $this->bankCommission($amount);
if ($amountWithComission > $this->money) {
throw new GameException(self::ERROR_NO_MONEY_IN_BANK_ACCOUNT);
}
// Снимаем сумму с комиссией у отправителя
$this->money -= $amountWithComission;
self::setBankMoney($this->money, $this->user_id);
$this->bankLogs($receiver, $this->money, "sendMoney");
// Отдаём сумму на счёт получателю
$receiverWallet->money += $amount;
self::setBankMoney($receiverWallet->money, $receiver);
$this->bankLogs($receiver, $receiverWallet->money, "receiveMoney");
// Возвращаем изменившиеся значения
return $this->money;
}
/**
* Пополнение банковского счёта игрока
*
* @param int $amount сумма.
*
* @return array
* @throws GameException
*/
public function depositMoney(int $amount): array
{
if ($amount <= 0) {
throw new GameException(self::ERROR_WRONG_AMOUNT);
}
$walletMoney = Db::getInstance()->fetchColumn('SELECT money FROM users WHERE id = ?', $this->user_id);
if ($walletMoney < $amount) {
throw new GameException(self::ERROR_NO_MONEY_IN_WALLET);
}
// Забираем деньги из кошелька получателя
$this->user->money -= $amount;
self::setWalletMoney($this->user->money, $this->user_id);
// Отдаём сумму на счёт получателю
$this->money += $amount;
self::setBankMoney($this->money, $this->user_id);
$this->bankLogs(0, $this->money, "depositMoney");
// Возвращаем изменившиеся значения
return [
'walletMoney' => $this->user->money,
'bankMoney' => $this->money
];
}
/**
* Снятие денег с банковского счёта игрока с банковской комиссией.
*
* @param int $amount сумма.
*
* @return array
* @throws GameException
*/
public function withdrawMoney(int $amount): array
{
if ($amount <= 0) {
throw new GameException(self::ERROR_WRONG_AMOUNT);
}
$amountWithComission = $amount + $this->bankCommission($amount);
if ($this->money < $amountWithComission) {
throw new GameException(self::ERROR_NO_MONEY_IN_BANK_ACCOUNT);
}
// Снимаем сумму с комиссией у отправителя
$this->money -= $amountWithComission;
self::setBankMoney($this->money, $this->user_id);
$this->bankLogs(0, $this->money, "withdrawMoney");
// Отдаём сумму в кошелёк получателя
$this->user['money'] += $amount;
self::setWalletMoney($this->user['money'], $this->user_id);
// Возвращаем изменившиеся значения
return [
'walletMoney' => $this->user['money'],
'bankMoney' => $this->money
];
}
/**
* Установить количество денег на банковском счету.
*
* @param int $amount сумма.
* @param int $user_id ID пользователя.
* @param string $operationType Тип операции. По умолчанию пусто. Если ввести, система запишет событие в банковский лог.
*
* @return void
*/
public static function setBankMoney(int $amount, int $user_id, string $operationType = ''): void
{
try {
Db::getInstance()->execute('UPDATE bank SET money = ? WHERE user_id = ?', [$amount, $user_id]);
if ($operationType) {
GameLogs::addBankLog(0, 0, $amount, $operationType, self::LOG[$operationType]);
}
} catch (Throwable $e) {
echo "Не отработал запрос в БД в файле {$e->getFile()}({$e->getLine()})";
}
}
/**
* Установить количество денег на руках.
*
* @param int $amount сумма.
* @param int $user_id ID пользователя.
*
* @return void
*/
public static function setWalletMoney(int $amount, int $user_id): void
{
User::getInstance($user_id)->setMoney($amount);
User::getInstance($user_id)->saveMoney();
}
public function getMoney(): int
{
return $this->money;
}
public function setMoney($amount)
{
$this->money = $amount;
}
}