2019-01-11 20:26:10 +00:00
< ? php
2021-03-12 16:26:15 +00:00
2020-10-28 20:21:08 +00:00
namespace Battles ;
2021-03-12 16:26:15 +00:00
2021-01-28 21:05:34 +00:00
use Battles\Database\DBPDO ;
2021-08-20 17:40:06 +00:00
use Exceptions\GameException ;
2021-01-28 21:05:34 +00:00
2019-01-11 20:26:10 +00:00
class ShopItem extends Item
{
2021-08-20 17:40:06 +00:00
private const NO_ITEMS_IN_STOCK = " Товара нет в наличии! " ;
private const NO_MONEY = " У вас нет денег!" ;
2021-08-30 16:30:56 +00:00
private const NO_BARTER_ITEMS = 'У вас нет требуемых предметов!' ;
2021-08-20 17:40:06 +00:00
private const BUTTON = [
'setmarket' => 'Сдать в магазин' ,
'unsetmarket' => 'Снять с продажи' ,
'buymarket' => 'Совершить обмен' ,
'sellshop' => 'Продать' ,
'buyshop' => 'Купить' ,
];
2021-08-23 18:51:34 +00:00
private const BUY_QUERY = <<< SQL
insert into inventory (
owner_id , name , item_type , durability ,
need_strength , need_dexterity , need_intuition , need_endurance , need_intelligence , need_wisdom ,
add_strength , add_dexterity , add_intuition , add_endurance , add_intelligence , add_wisdom ,
add_accuracy , add_evasion , add_criticals , add_min_physical_damage , add_max_physical_damage ,
image , weight , price )
select
? , name , item_type , durability ,
need_strength , need_dexterity , need_intuition , need_endurance , need_intelligence , need_wisdom ,
add_strength , add_dexterity , add_intuition , add_endurance , add_intelligence , add_wisdom ,
add_accuracy , add_evasion , add_criticals , add_min_physical_damage , add_max_physical_damage ,
image , weight , greatest (
(
( add_strength + add_dexterity + add_intuition + add_endurance + add_intelligence + add_wisdom ) *
( 5 + floor (( add_strength + add_dexterity + add_intuition + add_endurance + add_intelligence + add_wisdom ) / 10 ))
) +
(
( add_accuracy + add_criticals + add_evasion ) *
( 2 + floor (( add_accuracy + add_criticals + add_evasion ) / 50 ))
) +
(
( add_min_physical_damage + add_max_physical_damage ) *
( 1 + floor (( add_min_physical_damage + add_max_physical_damage ) / 100 ))
)
, 1 )
from items where id = ?
SQL ;
2021-08-20 17:40:06 +00:00
// Тип операции в магазине. Для отображения разных блоков в разных случаях.
private $optype ;
private ? int $shop_item_quantity ;
private ? int $price ;
2021-08-29 22:34:50 +00:00
public static string $status = '' ;
2021-08-30 16:30:56 +00:00
private ? string $jsonBarterList ;
private int $offerId ;
2021-08-20 17:40:06 +00:00
public function __construct ( $row , $operationType = null )
{
parent :: __construct ( $row );
if ( $operationType ) {
$this -> optype = $operationType ;
}
$this -> price = $row -> price ? ? null ;
$this -> shop_item_quantity = $row -> shop_item_quantity ? ? null ;
$this -> item_id = $row -> item_id ? ? $row -> id ;
2021-08-30 16:30:56 +00:00
$this -> jsonBarterList = $row -> barter_items_list_json ;
$this -> offerId = $row -> offer_id ; // Ид позиции в магазине.
2021-08-20 17:40:06 +00:00
}
2021-08-29 22:34:50 +00:00
public function printInfo () : string
2019-01-11 20:26:10 +00:00
{
2021-08-29 22:34:50 +00:00
$str = $this -> getAllInfo ();
2021-08-30 16:30:56 +00:00
if ( $this -> optype === 'buyshop' ) {
$str .= $this -> getLowItemQuantityNote ();
$str .= $this -> getBarterList ();
2021-08-20 17:40:06 +00:00
}
if ( $this -> optype === 'sellshop' ) {
2021-08-30 16:30:56 +00:00
$str .= $this -> getTextBasedOnPrice ();
}
return $str ;
}
private function getBarterList () : string
{
if ( ! $this -> jsonBarterList ) {
return '' ;
}
$str = '<div><br>Помимо денег требуются следующие товары:' ;
foreach ( json_decode ( $this -> jsonBarterList ) as $item ) {
$str .= '<br>↣ ' . Item :: getItemById ( $item -> item_id ) -> name . ', ' . $item -> quantity . ' шт.' ;
2021-08-20 17:40:06 +00:00
}
2021-08-30 16:30:56 +00:00
$str .= '</div>' ;
2021-08-29 22:34:50 +00:00
return $str ;
2021-08-20 17:40:06 +00:00
}
2021-08-30 16:30:56 +00:00
private function getLowItemQuantityNote () : string
{
if ( $this -> shop_item_quantity < 1 || $this -> shop_item_quantity > 19 ) {
return '' ;
}
return " <div style='margin-top: 9px; font-style: italic;'>Н а складе осталось $this->shop_item_quantity единиц товара!</div> " ;
}
private function getTextBasedOnPrice () : string
{
if ( $this -> getSellPriceMean () < 50 ) {
$goods = 'этот хлам' ;
} elseif ( $this -> getSellPriceMean () < 100 ) {
$goods = 'этот посредственный товар' ;
} elseif ( $this -> getSellPriceMean () < 500 ) {
$goods = 'этот неплохой предмет' ;
} elseif ( $this -> getSellPriceMean () < 1000 ) {
$goods = 'эту отличную штуку' ;
} else {
$goods = 'это превосходное изделие' ;
}
return " <div style='margin-top: 9px; font-style: italic;'>В среднем за $goods можно выручить <span class='success'> { $this -> getSellPriceMean () } </span> кр.</div> " ;
}
2021-08-29 22:34:50 +00:00
public function printImage () : string
2021-08-20 17:40:06 +00:00
{
if ( ! $this -> image ) {
$this -> image = 'noitem.png' ;
}
2021-08-29 22:34:50 +00:00
return " <img src='/i/sh/ $this->image ' class='item-wrap-normal' alt=''> " ;
2019-01-11 20:26:10 +00:00
}
2021-08-29 22:34:50 +00:00
public static function buyItem ( $id , User $buyer )
2019-01-15 15:56:15 +00:00
{
2021-08-30 16:30:56 +00:00
$check = DBPDO :: $db -> ofetch ( " select * from trade_offers where shop_item_id = ? " , $id );
$item = new Item ( DBPDO :: $db -> fetch ( 'select * from items where id = ?' , $id ));
$price = $item -> calculateItemCost ();
2021-08-20 17:40:06 +00:00
2021-08-30 16:30:56 +00:00
if (
! self :: checkAndRemoveBarteredItems ( $check -> barter_item_list_json , $buyer -> getId ()) ||
! self :: checkAndPayTheBills ( $price , $buyer ) ||
! self :: checkAndChangeRemainingItems ( $check -> shop_item_quantity , $check -> shop_item_id )
) {
return ;
2021-08-20 17:40:06 +00:00
}
2021-08-30 16:30:56 +00:00
DBPDO :: $db -> execute ( self :: BUY_QUERY , [ $buyer -> getId (), $check -> shop_item_id ]);
$deloText = $buyer -> getLogin () . " купил товар « " . Item :: getItemById ( $item -> item_id ) -> name . " » id:( " . $item -> item_id . " ) в магазине за " . $price . " . " ;
GameLogs :: addUserLog ( $buyer -> getId (), $deloText );
self :: $status = " Предмет " . $item -> name . " куплен за " . $price . " . " ;
}
private static function checkAndRemoveBarteredItems ( string $json_list , int $user_id ) : bool
{
if ( empty ( $json_list )) {
return true ;
}
$allowItemRemove = true ;
foreach ( json_decode ( $json_list ) as $item ) {
$row = DBPDO :: $db -> ofetch ( 'select sum(1) as s from inventory where name = ? and owner_id = ?' , [ Item :: getItemById ( $item -> item_id ) -> name , $user_id ]);
if ( $row -> s < $item -> quantity ) {
$allowItemRemove = false ;
2021-08-20 17:40:06 +00:00
}
}
2021-08-30 16:30:56 +00:00
if ( ! $allowItemRemove ) {
self :: $status = self :: NO_BARTER_ITEMS ;
return false ;
}
foreach ( json_decode ( $json_list ) as $item ) {
DBPDO :: $db -> execute ( 'delete from inventory where name = ? and owner_id = ? limit ?' , [ Item :: getItemById ( $item -> item_id ) -> name , $user_id , $item -> quantity ]);
}
return true ;
2021-08-20 17:40:06 +00:00
2021-08-30 16:30:56 +00:00
}
private static function checkAndPayTheBills ( int $price , User $user ) : bool
{
if ( $user -> getMoney () > $price ) {
$user -> setMoney ( $user -> getMoney () - $price );
$user -> saveMoney ();
return true ;
}
try {
$bank = new Bank ( $user -> getId ());
$bank -> withdrawMoney ( $price );
return true ;
} catch ( GameException $e ) {
self :: $status = 'Банковская ошибка! ' . self :: NO_MONEY ;
return false ;
2021-08-20 17:40:06 +00:00
}
2021-08-30 16:30:56 +00:00
}
2021-08-20 17:40:06 +00:00
2021-08-30 16:30:56 +00:00
private static function checkAndChangeRemainingItems ( int $current_quantity , $item_id ) : bool
{
if ( empty ( $current_quantity )) {
self :: $status = self :: NO_ITEMS_IN_STOCK ;
return false ;
}
if ( $current_quantity === - 1 ) {
return true ;
}
DBPDO :: $db -> execute ( " update trade_offers set shop_item_quantity = shop_item_quantity -1 where shop_item_quantity != -1 and shop_item_id = ? " , $item_id );
return true ;
2021-03-12 16:26:15 +00:00
}
2021-08-29 22:34:50 +00:00
public static function sellItem ( $id , User $seller , $bankTrade = 0 )
2021-03-12 16:26:15 +00:00
{
$db = new DBPDO ();
$item = $db -> ofetch ( 'select * from inventory where item_id = ?' , $id );
2021-08-20 17:40:06 +00:00
$sellingItemName = $item -> name ;
2021-03-12 16:26:15 +00:00
// Продажа за цену от нуля до половины стоимости.
2021-08-22 21:50:47 +00:00
$sellingPrice = $item -> price > 1 ? mt_rand ( 0 , $item -> price / 2 ) : mt_rand ( 0 , 1 );
2021-03-12 16:26:15 +00:00
$db -> execute ( 'delete from inventory where item_id = ?' , $id );
if ( $bankTrade ) {
$bank = new Bank ( $seller -> getId ());
2021-08-20 17:40:06 +00:00
$bank -> setMoney ( $bank -> getMoney () + $sellingPrice );
2021-08-22 18:51:00 +00:00
Bank :: setBankMoney ( $bank -> getMoney (), $seller -> getId (), 'sellShop' );
2021-03-12 16:26:15 +00:00
} else {
$db -> execute ( 'update users set money = money - ? where id = ?' , [ $sellingPrice , $_SESSION [ 'uid' ]]);
}
2021-08-20 17:40:06 +00:00
$deloText = " { $seller -> getLogin () } продал товар « { $sellingItemName } » id:( $id ) в магазине за $sellingPrice кр. " ;
2021-03-12 16:26:15 +00:00
GameLogs :: addUserLog ( $seller -> getId (), $deloText );
if ( $sellingPrice == 0 ) {
2021-08-29 22:34:50 +00:00
self :: $status = " После длительных и изнурительных торгов вы плюнули на всё и просто подарили ваш « { $sellingItemName } » торговцу. " ;
2021-03-12 16:26:15 +00:00
} else {
2021-08-29 22:34:50 +00:00
self :: $status = " Вы продали « { $sellingItemName } » за $sellingPrice кр. " ;
2019-01-15 15:56:15 +00:00
}
}
2021-08-20 17:40:06 +00:00
/** Подчсчёт средней суммы продажи .
* @ return int
*/
private function getSellPriceMean () : ? int
{
2021-08-22 21:50:47 +00:00
if ( $this -> price > 1 ) {
2021-08-20 17:40:06 +00:00
$arr = range ( 0 , $this -> price / 2 );
2021-08-22 18:51:00 +00:00
return array_sum ( $arr ) / count ( $arr );
2021-08-22 21:50:47 +00:00
} else {
return $this -> price == 1 ? 1 : null ;
2021-08-20 17:40:06 +00:00
}
}
2019-01-11 20:26:10 +00:00
/**
2021-01-28 21:05:34 +00:00
* Для кнопок управления под картинкой предмета в зависимости от ситуации .
2019-01-11 20:26:10 +00:00
*/
2021-08-29 22:34:50 +00:00
public function printControls () : string
2019-01-11 20:26:10 +00:00
{
2021-08-29 22:34:50 +00:00
if ( ! in_array ( $this -> optype , [ 'setmarket' , 'unsetmarket' , 'buymarket' , 'sellshop' , 'buyshop' ,])) {
return '' ;
}
$str = $this -> optype == 'setmarket' ? '<input placeholder=" ' . $this -> price . ' " name="cost">' : '' ;
$button_name = self :: BUTTON [ $this -> optype ];
return <<< FORM
2021-08-20 17:40:06 +00:00
< form method = " post " > $str
2021-08-30 16:30:56 +00:00
< input type = " hidden " name = " itemId " value = " $this->offerId " >
2021-08-20 17:40:06 +00:00
< br >< input type = " submit " name = " $this->optype " value = " $button_name " >
2019-02-15 15:00:01 +00:00
</ form >
2021-08-20 17:40:06 +00:00
FORM ;
2019-01-11 20:26:10 +00:00
}
2021-08-20 17:40:06 +00:00
/**
2021-08-22 20:43:42 +00:00
* @ return int
2021-08-20 17:40:06 +00:00
*/
2021-08-22 20:43:42 +00:00
public function getItemType () : int
2021-08-20 17:40:06 +00:00
{
return $this -> item_type ;
}
2021-08-27 15:55:18 +00:00
/** Выдача магазинных предметов по запросу .
* Ввелась чтобы перебить takeshopitem () в functions с идентичным функционалом .
* @ param int $item_id ИД предмета .
* @ param int $to ИД пперсонажа - получателя .
*/
public static function giveNewItem ( int $item_id , int $to ) : array
{
$check = DBPDO :: $db -> ofetch ( 'select 1 from items where id = ?' , $item_id );
if ( ! $check ) {
return [];
}
DBPDO :: $db -> execute ( self :: BUY_QUERY , [ $to , $item_id ]);
$return = DBPDO :: $db -> ofetch ( 'select image, name from inventory where item_id = ?' , DBPDO :: $db -> lastInsertId ());
return [
'img' => $return -> image ,
'name' => $return -> name ,
'id' => $item_id ,
];
}
2019-01-11 20:26:10 +00:00
}