battles/classes/Battles/Bank.php

204 lines
6.9 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;
use Battles\Database\Db;
class Bank
{
private int $userId = 0;
private int $money = 0;
private string $error = '';
private string $status = '';
private int $comission = 0;
private const ERROR_NO_MONEY_IN_WALLET = "Ошибка! Нет денег в кошельке!";
private const ERROR_NO_BANK_ACCOUNT = "Ошибка! Счёта не существует!";
private const ERROR_NO_MONEY_IN_BANK_ACCOUNT = "Ошибка! Нет денег на счету!";
private const ERROR_WRONG_AMOUNT = "Ошибка! Сумма должна быть положительной!";
private const ERROR_WRONG_ID = 'Неверный ID!';
private const LOG = [
'sendMoney' => 'Банк: Перевод средств на другой счёт.',
'receiveMoney' => 'Банк: Получение средств.',
'depositMoney' => 'Пополнение счёта.',
'withdrawMoney' => 'Снятие денег со счёта.',
'clanRegister' => 'Оплата стоимости регистрации клана.',
'sellShop' => 'Продажа товара в магазине.'
];
public function __construct(int $userId = null)
{
if (empty($userId)) {
$userId = User::getInstance()->getId();
}
$bankRow = Db::getInstance()->fetch('SELECT user_id, money FROM bank WHERE user_id = ?', $userId);
foreach ($this as $key => $value) {
if (isset($bankRow[$key])) {
$this->$key = $bankRow[$key];
}
}
}
/**
* Комиссия: процент от переводимой суммы, но не менее 1 кр. Задаётся в config.php.
*
* @param int $amount сумма.
*
* @return int
*/
private function commission(int $amount): int
{
$bankCommission = round($amount * GameConfigs::BANK_COMISSION);
$this->comission = max(1, (int)$bankCommission);
return $this->comission;
}
/**
* Пишем банковское событие в лог в БД
*
* @param int $receiverId ID получателя.
* @param int $amount сумма.
* @param string $operationType тип банковской операции.
* @param ?int $senderId ID отправителя (ID игрока, если не указано иное).
*
* @return void
*/
private function addLog(int $receiverId, int $amount, string $operationType, ?int $senderId = null): void
{
if (is_null($senderId)) {
$senderId = $this->userId;
}
if ($operationType === 'depositMoney' || $operationType === 'withdrawMoney') {
$receiverId = $this->userId;
}
$commText = $this->comission ? ' Комиссия: ' . $this->comission : '';
$text = self::LOG[$operationType] . $commText;
$this->status = $text;
GameLogs::addBankLog($senderId, $receiverId, $amount, $operationType, $text);
}
/**
* Перевод денег между банковскими счетами игроков с банковской комиссией.
*
* @param mixed $receiver ID получателя.
* @param mixed $amount Cумма.
*/
public function sendMoney($receiver, $amount)
{
if (!is_numeric($receiver)) {
$this->error = self::ERROR_WRONG_ID;
return;
}
$rec = new self($receiver);
if (!is_numeric($amount) || $amount <= 0) {
$this->error = self::ERROR_WRONG_AMOUNT;
}
if (!$rec->userId) {
$this->error = self::ERROR_NO_BANK_ACCOUNT;
}
$amountWithComission = $amount + $this->commission($amount);
if ($amountWithComission > $this->money) {
$this->error = self::ERROR_NO_MONEY_IN_BANK_ACCOUNT;
}
if ($this->error) {
return;
}
// Снимаем сумму с комиссией у отправителя
$this->modify(-$amountWithComission);
$this->addLog($rec->userId, $this->money, 'sendMoney', $this->userId);
// Отдаём сумму на счёт получателю
$rec->modify($amount);
$rec->addLog($rec->userId, $rec->money, 'receiveMoney', $this->userId);
}
/**
* Пополнение банковского счёта игрока
*
* @param int $amount сумма.
*
*/
public function depositMoney(int $amount)
{
if ($amount <= 0) {
$this->error = self::ERROR_WRONG_AMOUNT;
}
// Забираем деньги из кошелька получателя
if (!User::getInstance($this->userId)->money()->spend($amount)) {
$this->error = self::ERROR_NO_MONEY_IN_WALLET;
}
if ($this->error) {
return;
}
// Отдаём сумму на счёт получателю
$this->modify($amount);
$this->addLog(0, $this->money, 'depositMoney');
}
/**
* Снятие денег с банковского счёта игрока с банковской комиссией.
*
* @param int $amount сумма.
*
*/
public function withdrawMoney(int $amount)
{
if ($amount <= 0) {
$this->error = self::ERROR_WRONG_AMOUNT;
}
$amountWithComission = $amount + $this->commission($amount);
if ($this->money < $amountWithComission) {
$this->error = self::ERROR_NO_MONEY_IN_BANK_ACCOUNT;
}
if ($this->error) {
return;
}
// Снимаем сумму с комиссией у отправителя
$this->modify(-$amountWithComission);
$this->addLog(0, $this->money, 'withdrawMoney');
// Отдаём сумму в кошелёк получателя
User::getInstance($this->userId)->money()->earn($amount);
}
private function save()
{
Db::getInstance()->execute('UPDATE bank SET money = ? WHERE user_id = ?', [$this->money, $this->userId]);
}
public function getMoney(): int
{
return $this->money;
}
public function modify(int $amount, string $logType = '')
{
if ($amount > 0) {
// add_money
$this->money += $amount;
$this->save();
} elseif ($amount < 0) {
// remove_money
if ($this->money < $amount) {
return;
}
$this->money -= $amount;
$this->save();
}
if ($logType && $amount !== 0) {
$this->addLog(0, $this->money, $logType);
}
}
public function getStatus(): string
{
if (!$this->error) {
return $this->status;
}
return $this->error;
}
}