Steemnova: Market - offer extension

in #utopian-io3 years ago (edited)

Offer visibility

This feature is connected to market place. Which is the place where players can add trade offers. Previously it was impossible to add same limits to the offer, so everyone could accept our offer - even enemy. When the alliances have begun the wars the market could come back to the chats because of unwanted enemy support.

When we add the new offer we can see new select box with 3 options:
1.png

  • All except enemies means if your alliance is in war with a different one (war pact is needed) the enemies cannot buy your offer
  • Allies and trading partners means that your offer will be buyable for people from your alliance and for each alliance which has pact better or equal "trading partner". It also helps the game to create better usecase for trade partner pact - before there was not any gain.
  • All - everyone can buy

Still all offers are visible on the market, but instead of "buy" button there is a message. Like on the picture:
2.png

Implementation

SQL table

I had to change the schema of the database. A new table was needed. I could try to add new columns it doesn't make sense because fleet table contains all fleets and only a few are the trading fleets.

How the new table looks you can see in the migration file:

 21 install/migrations/migration_7.sql
@@ -0,0 +1,21 @@
+CREATE TABLE `%PREFIX%trades` (
+  `seller_fleet_id`  bigint(11) unsigned NOT NULL DEFAULT 0,
+  `buyer_fleet_id`  bigint(11) unsigned DEFAULT NULL,
+        `buy_time` datetime,
+        `transaction_type` tinyint(1) unsigned NOT NULL DEFAULT 0,
+        `filter_visibility` tinyint(1) unsigned NOT NULL DEFAULT 0,
+        `filter_flighttime` mediumint unsigned NOT NULL DEFAULT 0,
+        `ex_resource_type` tinyint(1) unsigned NOT NULL DEFAULT 0,
+        `ex_resource_amount` double(50,0) unsigned NOT NULL DEFAULT '0',
+        PRIMARY KEY (`seller_fleet_id`)
+) ENGINE=MyISAM  DEFAULT CHARSET=utf8;
+
+INSERT INTO `%PREFIX%trades` (`seller_fleet_id`, `ex_resource_type`,`ex_resource_amount`)
+SELECT fleet_id, fleet_wanted_resource, fleet_wanted_resource_amount
+FROM %PREFIX%fleets
+WHERE `fleet_mission` = 16;
+
+ALTER TABLE %PREFIX%fleets DROP COLUMN `fleet_wanted_resource`;
+ALTER TABLE %PREFIX%fleets DROP COLUMN `fleet_wanted_resource_amount`;
+ALTER TABLE %PREFIX%log_fleets DROP COLUMN `fleet_wanted_resource`;
+ALTER TABLE %PREFIX%log_fleets DROP COLUMN `fleet_wanted_resource_amount`;

I've used foreign key from the FLEETS table as seller_fleet_id. It is also unque key because one offer = one fleet.

buyer_fleet_id and buy_time are needed only for history of the transactions and it gives us possibility to create some statistics.

transaction_type is right now always 0. But it will be possible to sell fleet in the future. So to avoid the next migrations I've added this field extra

filter_visibility contains information about offer visibility

filter_flighttime is not used yet. But when will be more users -> more galaxies the transaction time can be too long. It will give possibility to limit the flight time to the customer and back.

ex_resource_type and ex_resource_amount are the old columns in the fleet table used for the exchange value.

Creating offer

Changes in the template part are very small. Only the new select with options and translations.

+               <tr class="no-border">
+                   <td>
+                       {$LNG.fl_visibility}
+                   </td>
+                   <td>
+                       <select name="visibility">
+                           <option value="2" selected>{$LNG.fl_visibility_no_enemies}</option>
+                           <option value="1">{$LNG.fl_visibility_alliance}</option>
+                           <option value="0">{$LNG.fl_visibility_all}</option>
+                       </select>
+                   </td>
+               </tr>

When you click the "continue" button the last step of the sending fleet is doing the job and new record to the trading table is added.

@@ -38,6 +38,9 @@ public function show()
        $TransportDeuterium     = max(0, round(HTTP::_GP('deuterium', 0.0)));
        $WantedResourceType     = HTTP::_GP('resEx', 0);
        $WantedResourceAmount       = max(0, round(HTTP::_GP('exchange', 0.0)));
+
+       $visibility     = HTTP::_GP('visibility', 0);
        $stayTime               = HTTP::_GP('staytime', 0);
        $token                  = HTTP::_GP('token', '');
 
@@ -116,9 +119,9 @@ public function show()
 
        $ACSTime = 0;
 
-        $db = Database::get();
+       $db = Database::get();
 
-        if(!empty($fleetGroup))
+       if(!empty($fleetGroup))
        {
             $sql = "SELECT ankunft FROM %%USERS_ACS%% INNER JOIN %%AKS%% ON id = acsID
            WHERE acsID = :acsID AND :maxFleets > (SELECT COUNT(*) FROM %%FLEETS%% WHERE fleet_group = :acsID);";
@@ -408,10 +411,28 @@ public function show()
        $fleetStayTime      = $fleetStartTime + $StayDuration;
        $fleetEndTime       = $fleetStayTime + $duration;
 
-       FleetFunctions::sendFleet($fleetArray, $targetMission, $USER['id'], $PLANET['id'], $PLANET['galaxy'],
+       $fleet_id = FleetFunctions::sendFleet($fleetArray, $targetMission, $USER['id'], $PLANET['id'], $PLANET['galaxy'],
            $PLANET['system'], $PLANET['planet'], $PLANET['planet_type'], $targetPlanetData['id_owner'],
            $targetPlanetData['id'], $targetGalaxy, $targetSystem, $targetPlanet, $targetType, $fleetResource,
-           $fleetStartTime, $fleetStayTime, $fleetEndTime, $fleetGroup, 0, $WantedResourceType,$WantedResourceAmount);
+           $fleetStartTime, $fleetStayTime, $fleetEndTime, $fleetGroup, 0);
+
+
+       if($targetMission == 16) {
+           $sql    = 'INSERT INTO %%TRADES%% SET
+               seller_fleet_id             = :sellerFleet,
+               filter_visibility           = :visibility,
+               filter_flighttime           = :flightTime,
+               ex_resource_type            = :resType,
+               ex_resource_amount      = :resAmount;';
+
+               $db->insert($sql, array(
+                   ':sellerFleet'          => $fleet_id,
+                   ':resType'                  => $WantedResourceType,
+                   ':resAmount'                => $WantedResourceAmount,
+                   ':flightTime'               => $maxFlightTime * 3600,
+                   ':visibility'               => $visibility
+               ));
+       }

List

Function show() is rendering preparing data for template.

In the first part I had to change the sql because of the new schema and the new filter. New LEFT JOIN with the union of the 2 queries gives us information about "pact" level with the seller It is needed to analyze the visibility of the offer.

@@ -231,8 +272,18 @@ public function show()
            $message = $this->doBuy();
        }
 
-       $sql = "SELECT * FROM %%FLEETS%%, %%USERS%% WHERE fleet_mission = 16 AND fleet_mess = 2 AND fleet_owner = %%USERS%%.id ORDER BY fleet_end_time ASC;";
+       $sql = 'SELECT *
+           FROM %%FLEETS%%
+           JOIN %%USERS%% ON fleet_owner = id
+           JOIN %%TRADES%% ON fleet_id = seller_fleet_id
+           LEFT JOIN (
+               SELECT owner_2 as al ,level, accept  FROM %%DIPLO%% WHERE owner_1 = :al
+               UNION
+               SELECT owner_1 as al,level, accept  FROM %%DIPLO%% WHERE owner_2 = :al) as packts
+           ON al = ally_id
+           WHERE fleet_mission = 16 AND fleet_mess = 2 ORDER BY fleet_end_time ASC;';
        $fleetResult = $db->select($sql, array(
+           ':al' => $USER['ally_id']
        ));
 
        $activeFleetSlots   = $db->rowCount();
@@ -243,7 +294,7 @@ public function show()
        {
            $resourceN = " ";
            //TODO TRANSLATION
-           switch($fleetsRow['fleet_wanted_resource']) {
+           switch($fleetsRow['ex_resource_type']) {
                case 1:
                    $resourceN = $LNG['tech'][901];
                    break;
@@ -257,6 +308,11 @@ public function show()
                    break;
            }
 
+           //Level of diplo
+           if($fleetsRow['accept'] == 0){
+               $fleetsRow['level'] = NULL;
+           }
+
            $SpeedFactor        = FleetFunctions::GetGameSpeedFactor();
            //FROM
            $FROM_fleet =  FleetFunctions::unserialize($fleetsRow['fleet_array']);
@@ -271,7 +327,9 @@ public function show()
            $TO_HC_SPEED        = FleetFunctions::GetFleetMaxSpeed(array(203 =>1), $USER);
            $TO_HC_DUR          = FleetFunctions::GetMissionDuration(10, $TO_HC_SPEED, $TO_Distance, $SpeedFactor, $USER);
 
-
+           //Level 5 - enemies
+           //Level 0 - 3 alliance
+           $buy = $this->checkBuyable($fleetsRow['filter_visibility'], $fleetsRow['level'], $fleetsRow['ally_id'], $USER['ally_id']);
 
            $FlyingFleetList[]  = array(
                'id'            => $fleetsRow['fleet_id'],
@@ -282,10 +340,12 @@ public function show()
                'fleet_resource_deuterium'          => $fleetsRow['fleet_resource_deuterium'],
 
                'total' => $fleetsRow['fleet_resource_metal'] + $fleetsRow['fleet_resource_crystal'] + $fleetsRow['fleet_resource_deuterium'],
-
+               'diplo' => $fleetsRow['level'],
+               'possible_to_buy' => $buy['buyable'],
+               'reason' => $buy['reason'],
                'fleet_wanted_resource' => $resourceN,
-               'fleet_wanted_resource_id' => $fleetsRow['fleet_wanted_resource'],
-               'fleet_wanted_resource_amount'  => $fleetsRow['fleet_wanted_resource_amount'],
+               'fleet_wanted_resource_id' => $fleetsRow['ex_resource_type'],
+               'fleet_wanted_resource_amount'  => $fleetsRow['ex_resource_amount'],
 
                'end'   => $fleetsRow['fleet_end_stay'] - TIMESTAMP,

Like you see here is the checkBuyable function used. This functions returns error message if something is going wrong:

+   private function checkBuyable($visibility, $level, $seller_ally, $ally) {
+       global $LNG;
+       if($visibility == 2 && $level == 5 ) {
+           return array(
+               'buyable' => false,
+               'reason' => $LNG['market_buyable_no_enemies']
+           );
+       }
+
+       if($visibility == 1 && $ally != $seller_ally && ($level == NULL || $level >3)) {
+           return array(
+               'buyable' => false,
+               'reason' => $LNG['market_buyable_only_trade_partners']
+           );
+       }
+
+       return array("buyable" => true,
+           'reason' => '');
+   }

Also I've change the template to show error message and the state of the seller (by color - green = ally, red = enemy)

https://github.com/steemnova/steemnova/pull/69/files#diff-127a8cf4e4d0ceba23590e6053f6cf75

Buy action

Last part happens when you click the "buy" button. Then the doBuy() function is checking the offer and send fleets.
Changes contain:

  • adjustment to the new schema
  • visibility checking
  • Fix: cargo ships calculation when officer (extra capacity bonus) exists.
    private function doBuy() {
        global $USER, $PLANET, $reslist, $resource, $LNG, $pricelist;
        $FleetID            = HTTP::_GP('fleetID', 0);
@@ -40,7 +60,7 @@ private function doBuy() {
            return $checkResult['message'];
        }
        //Get trade fleet
-       $sql = "SELECT * FROM %%FLEETS%% WHERE fleet_id = :fleet_id AND fleet_mess = 2;";
+       $sql = "SELECT * FROM %%FLEETS%% JOIN %%TRADES%% ON fleet_id = seller_fleet_id JOIN %%USERS%% ON fleet_owner = id WHERE fleet_id = :fleet_id AND fleet_mess = 2;";
        $fleetResult = $db->select($sql, array(
            ':fleet_id' => $FleetID,
        ));
@@ -50,26 +70,40 @@ private function doBuy() {
            return $LNG['market_p_msg_not_found'];
        }
 
+       if($fleetResult[0]['filter_visibility'] != 0 && $USER['id'] != $fleetResult[0]['id']) {
+           //Check packts
+           $sql = "SELECT * FROM %%DIPLO%% WHERE (owner_1 = :ow AND owner_2 = :ow2) OR (owner_2 = :ow AND owner_1 = :ow2) AND accept = 1;";
+           $res = $db->select($sql, array(
+               ':ow' => $USER['ally_id'],
+               ':ow2' => $fleetResult[0]['ally_id'],
+           ));
+           $buy = $this->checkBuyable($fleetResult[0]['filter_visibility'], $res[0]['level'], $fleetResult[0]['ally_id'], $USER['ally_id']);
+           if(!$buy['buyable']) {
+               return $buy['reason'];
+           }
+       }
+
        //if not in range 1-3
-       if($fleetResult[0]['fleet_wanted_resource'] >= 4 ||
-           $fleetResult[0]['fleet_wanted_resource'] <= 0) {
+       if($fleetResult[0]['ex_resource_type'] >= 4 ||
+           $fleetResult[0]['ex_resource_type'] <= 0) {
                return $LNG['market_p_msg_wrong_resource_type'];
        }
+       $factor = 1 + $USER['factor']['ShipStorage'];
 
        //-------------FLEET SIZE CALCULATION---------------
        $fleetResult = $fleetResult[0];
-       $amount = $fleetResult['fleet_wanted_resource_amount'];
+       $amount = $fleetResult['ex_resource_amount'];
 
        $F1capacity = 0;
        $F1type = 0;
        //PRIO for LC
        if($shipType == 1) {
-           $F1capacity = $pricelist[202]['capacity'];
+           $F1capacity = $pricelist[202]['capacity'] * $factor;
            $F1type = 202;
        }
        // PRIO for HC
        else {
-           $F1capacity = $pricelist[203]['capacity'];
+           $F1capacity = $pricelist[203]['capacity'] * $factor;
            $F1type = 203;
        }
 
@@ -84,12 +118,12 @@ private function doBuy() {
        if ($amountTMP > 0) {
            //We need HC
            if($shipType == 1) {
-               $F2capacity = $pricelist[203]['capacity'];
+               $F2capacity = $pricelist[203]['capacity'] * $factor;
                $F2type = 203;
            }
            //We need LC
            else{
-               $F2capacity = $pricelist[202]['capacity'];
+               $F2capacity = $pricelist[202]['capacity'] * $factor;
                $F2type = 202;
            }
            $F2 = min($PLANET[$resource[$F2type]], ceil($amountTMP / $F2capacity));
@@ -118,11 +152,11 @@ private function doBuy() {
        $met = 0;
        $cry = 0;
        $deu = 0;
-       if ($fleetResult['fleet_wanted_resource'] == 1)
+       if ($fleetResult['ex_resource_type'] == 1)
            $met = $amount;
-       elseif ($fleetResult['fleet_wanted_resource'] == 2)
+       elseif ($fleetResult['ex_resource_type'] == 2)
            $cry = $amount;
-       elseif ($fleetResult['fleet_wanted_resource'] == 3)
+       elseif ($fleetResult['ex_resource_type'] == 3)
            $deu = $amount;
 
        $fleetResource  = array(
@@ -141,7 +175,7 @@ private function doBuy() {
        $PLANET[$resource[902]] -= $fleetResource[902];
        $PLANET[$resource[903]] -= $fleetResource[903] + $consumption;
 
-       FleetFunctions::sendFleet($fleetArray, 3/*Transport*/, $USER['id'], $PLANET['id'], $PLANET['galaxy'],
+       $buyerfleet = FleetFunctions::sendFleet($fleetArray, 3/*Transport*/, $USER['id'], $PLANET['id'], $PLANET['galaxy'],
            $PLANET['system'], $PLANET['planet'], $PLANET['planet_type'], $fleetResult['fleet_owner'], $fleetResult['fleet_start_id'],
            $fleetResult['fleet_start_galaxy'], $fleetResult['fleet_start_system'], $fleetResult['fleet_start_planet'], $fleetResult['fleet_start_type'],
            $fleetResource, $fleetStartTime, $fleetStayTime, $fleetEndTime,0,0,0,0,1);
@@ -189,6 +223,13 @@ private function doBuy() {
            ':fleetId'  => $FleetID,
            ':endTime'  => $fleetStartTime
        ));
+
+       $sql    = 'UPDATE %%TRADES%% SET  `buyer_fleet_id` = :buyerFleetId,`buy_time` = NOW() WHERE seller_fleet_id = :fleetId;';
+       $db->update($sql, array(
+           ':fleetId'  => $FleetID,
+           ':buyerFleetId' =>$buyerfleet
+       ));
+
        $LC = 0;
        $HC = 0;
        if(array_key_exists(202,$fleetArrayTMP))



Posted on Utopian.io - Rewarding Open Source Contributors

Sort:  

Thank you for the contribution. It has been approved.

You can contact us on Discord.
[utopian-moderator]

Thank you.

Hey @dotevo I am @utopian-io. I have just upvoted you!

Achievements

  • You have less than 500 followers. Just gave you a gift to help you succeed!
  • Seems like you contribute quite often. AMAZING!

Community-Driven Witness!

I am the first and only Steem Community-Driven Witness. Participate on Discord. Lets GROW TOGETHER!

mooncryption-utopian-witness-gif

Up-vote this comment to grow my power and help Open Source contributions like this one. Want to chat? Join me on Discord https://discord.gg/Pc8HG9x