battles/classes/Battles/Bank.php

237 lines
9.2 KiB
PHP
Raw 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;
class Bank
{
public $user_id;
private $money;
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' => 'Оплата стоимости регистрации клана.',
];
public function __construct($row)
{
$bank_row = \db::c()->query('SELECT user_id, money FROM bank WHERE user_id = ?i', $row)->fetch_assoc();
$this->user = \db::c()->query('SELECT money FROM users WHERE id = ?i', $row)->fetch_object();
foreach ($this as $key => $value) {
if (isset($bank_row[$key])) {
$this->$key = $bank_row[$key];
}
}
// Если ВДРУГ у человека нет счёта в банке - создаём.
if (empty($this->user_id)) {
\db::c()->query('INSERT INTO bank (user_id) VALUES (?i)', $row);
$this->user_id = $row;
}
}
/**
* Комиссия: процент от переводимой суммы, но не менее 1 кр. Задаётся в config.php.
*
* @param int $amount сумма.
*
* @return int
*/
private function bankCommission(int $amount): int
{
$bankCommission = round($amount * \Config::$bank_commission);
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
* @throws \Krugozor\Database\Mysql\Exception
*/
private function bankLogs(int $receiverId, int $amount, string $operationType, int $senderId = 0): void
{
if (!$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);
}
\db::c()->query('INSERT INTO `bank_logs` (sender_id, receiver_id, amount_result, type, text)
VALUES (?i, ?i, ?i, "?s", "?s")', $senderId, $receiverId, $amount, $operationType, $text);
}
/**
* Перевод денег между банковскими счетами игроков с банковской комиссией.
*
* @param int $receiver ID получателя.
* @param int $amount сумма.
*
* @return int
* @throws \Krugozor\Database\Mysql\Exception
*/
public function sendMoney(int $receiver, int $amount): int
{
$receiverWallet = \db::c()->query('SELECT money FROM bank WHERE user_id = ?i', $receiver)->fetch_object();
if ($amount <= 0) {
throw new \Exceptions\GameException(self::ERROR_WRONG_AMOUNT);
}
if (!$receiverWallet) {
throw new \Exceptions\GameException(self::ERROR_NO_BANK_ACCOUNT);
}
$amountWithComission = $amount + $this->bankCommission($amount);
if ($amountWithComission > $this->money) {
throw new \Exceptions\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 \Krugozor\Database\Mysql\Exception
*/
public function depositMoney(int $amount): array
{
if ($amount <= 0) {
throw new \Exceptions\GameException(self::ERROR_WRONG_AMOUNT);
}
$wallet = \db::c()->query('SELECT money FROM users WHERE id = ?i', $this->user_id)->fetch_object();
if ($wallet->money < $amount) {
throw new \Exceptions\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 \Krugozor\Database\Mysql\Exception
*/
public function withdrawMoney(int $amount):array
{
if ($amount <= 0) {
throw new \Exceptions\GameException(self::ERROR_WRONG_AMOUNT);
}
$amountWithComission = $amount + $this->bankCommission($amount);
if ($this->money < $amountWithComission) {
throw new \Exceptions\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
* @throws \Krugozor\Database\Mysql\Exception
*/
public static function setBankMoney(int $amount, int $user_id, string $operationType = ''): void
{
try {
\db::c()->query('UPDATE bank SET money = ?i WHERE user_id = ?i', $amount, $user_id);
if ($operationType) {
(new Bank($user_id))->bankLogs(0, $amount, $operationType);
}
} catch (\Throwable $e) {
echo "Не отработал запрос в БД в файле {$e->getFile()}({$e->getLine()})";
}
}
/**
* Установить количество денег на руках.
*
* @param int $amount сумма.
* @param int $user_id ID пользователя.
*
* @return void
* @throws \Krugozor\Database\Mysql\Exception
*/
public static function setWalletMoney(int $amount, int $user_id): void
{
try {
\db::c()->query('UPDATE users SET money = ?i WHERE `id` = ?i', $amount, $user_id);
} catch (\Throwable $e) {
echo "Не отработал запрос в БД в файле {$e->getFile()}({$e->getLine()})";
}
}
public function getMoney()
{
return $this->money;
}
public function setMoney($amount)
{
$this->money = $amount;
}
}