All Downloads are FREE. Search and download functionalities are using the official Maven repository.

ch.sahits.game.openpatrician.engine.land.city.AutomaticTradingEngine Maven / Gradle / Ivy

There is a newer version: 1.0.1
Show newest version
package ch.sahits.game.openpatrician.engine.land.city;

import ch.sahits.game.event.data.PeriodicalDailyUpdate;
import ch.sahits.game.openpatrician.annotation.ClassCategory;
import ch.sahits.game.openpatrician.annotation.EClassCategory;
import ch.sahits.game.openpatrician.annotation.LazySingleton;
import ch.sahits.game.openpatrician.engine.AbstractEngine;
import ch.sahits.game.openpatrician.model.IPlayer;
import ch.sahits.game.openpatrician.model.building.ETradeType;
import ch.sahits.game.openpatrician.model.building.IAutomatedTrading;
import ch.sahits.game.openpatrician.model.building.ISteward;
import ch.sahits.game.openpatrician.model.building.ITradingOffice;
import ch.sahits.game.openpatrician.model.building.TradingOfficeList;
import ch.sahits.game.openpatrician.model.city.ICity;
import ch.sahits.game.openpatrician.model.event.BuildingFinished;
import ch.sahits.game.openpatrician.model.product.EWare;
import ch.sahits.game.openpatrician.model.product.WareAmountCalculator;
import ch.sahits.game.openpatrician.model.time.EUpdateIntervalRegistration;
import ch.sahits.game.openpatrician.model.time.IIndividualPeriodicalUpdater;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Preconditions;
import com.google.common.eventbus.AsyncEventBus;
import com.google.common.eventbus.Subscribe;
import javafx.beans.binding.IntegerBinding;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import java.util.ArrayList;
import java.util.List;

/**
 * @author Andi Hotz, (c) Sahits GmbH, 2014
 *         Created on Dec 23, 2014
 */
@LazySingleton
@ClassCategory(EClassCategory.SINGLETON_BEAN)
public class AutomaticTradingEngine extends AbstractEngine {
    @Autowired
    @Qualifier("serverClientEventBus")
    private AsyncEventBus clientServerEventBus;
    @Autowired
    private IIndividualPeriodicalUpdater updater;
    @Autowired
    private WareAmountCalculator calculator;
    @Autowired
    private TradingOfficeList offices;
    @PreDestroy
    private void unregister() {
        clientServerEventBus.unregister(this);
    }
    @PostConstruct
    private void initialize() {
        clientServerEventBus.register(this);
    }
    @Override
    public List getChildren() {
        return new ArrayList<>();
    }

    /**
     * When a traiding office is build add it.
     * @param event
     */
    @Subscribe
    public void handleTradingOfficeBuilt(BuildingFinished event) {
       if (event.getBuilding() instanceof  ITradingOffice) {
           final ITradingOffice tradingOffice = (ITradingOffice) event.getBuilding();
           offices.add(tradingOffice);
           Preconditions.checkState(tradingOffice.getSteward() == null, "Stewart must be null on building");
           final AutomaticTradingEngine engine = this;
           tradingOffice.stewardProperty().addListener(new ChangeListener() {
               @Override
               public void changed(ObservableValue observableValue, ISteward oldSteward, ISteward newSteward) {
                  if (newSteward == null) {
                      updater.unregister(tradingOffice);
                  } else {
                      updater.register(engine, tradingOffice, EUpdateIntervalRegistration.DAILY);
                  }
               }
           });
       }
    }

    /**
     * Check if the update message is addressed to this instance and find the targeted
     * Tradeing office. Execute the buy and sell action on the office.
     * @param event
     */
    @Subscribe
    public void handleDailyUpdates(PeriodicalDailyUpdate event) {
      if (event.isAddresse(this) && event.getTarget() instanceof ITradingOffice) {
          ITradingOffice target = (ITradingOffice) event.getTarget();
          for (ITradingOffice office : offices) {
              if (target.equals(office)) {
                  sellAndBuy(office);
                  break;
              }
          }
      }
    }

    /**
     * Execute the automatic buying and selling of the automated trading.
     * @param office
     */
    @VisibleForTesting
    void sellAndBuy(ITradingOffice office) {
      Preconditions.checkNotNull(office.getSteward(), "Steward may not be null");
        Preconditions.checkNotNull(office.getOfficeTrading(), "OfficeTrading may not be null");
        ISteward steward = office.getSteward();
        IAutomatedTrading automatedTrading = office.getOfficeTrading();
        // Iterate over all wares and figure out if they should be bought or sold
        for (EWare ware : EWare.values()) {
            if (automatedTrading.tradingTypeProperty(ware).get() == ETradeType.CITY_OFFICE) {
               // buy from the city for at max avgPrice
                final double discountFactor = steward.getDiscountFactor();
                int avgPrice = automatedTrading.getPrice(ware);
                final ICity city = office.getCity();
                final int amountToBuy = calculator.calculateBuyAmount(ware, city, avgPrice);
                int price = ware.buyPrice(new SimpleIntegerProperty(city.getWare(ware).getAmount()), new IntegerBinding() {
                    @Override
                    protected int computeValue() {
                        return amountToBuy;
                    }
                });
                final IPlayer owner = office.getOwner();
                int amountBought = city.move(ware, -amountToBuy, owner);
                office.move(ware, -amountBought, (int) (price * discountFactor));
                long totalPrice = (long) ((-amountBought * price) * discountFactor);
                owner.getCompany().updateCash(-totalPrice);
            }
            if (automatedTrading.tradingTypeProperty(ware).get() == ETradeType.OFFICE_CITY) {
                int withouldingAmount = automatedTrading.getAmount(ware);
                final int amountInOffice = office.getWare(ware).getAmount();
                if (amountInOffice >= withouldingAmount) { // only go into it if there is something to be sold
                    // sell to the city for at least avgPrice witholding a defined amount.
                    final int wareAvgPrice = office.getWare(ware).getAVGPrice();
                    final ICity city = office.getCity();
                    int avgPrice = automatedTrading.getPrice(ware);
                    int amountToSellProposed = calculator.calculateSellAmount(ware, city, avgPrice);
                    final int amountToSell = Math.min(amountToSellProposed, amountInOffice - withouldingAmount);
                    int price = ware.sellPrice(new SimpleIntegerProperty(city.getWare(ware).getAmount()), new IntegerBinding() {
                        @Override
                        protected int computeValue() {
                            return amountToSell;
                        }
                    });
                    final IPlayer owner = office.getOwner();
                    int amountSold = city.move(ware, -amountToSell, owner);
                    office.move(ware, amountSold);
                    long totalPrice = amountSold * price;
                    owner.getCompany().updateCash(totalPrice);
                    int profit = (int)(totalPrice - (amountSold * wareAvgPrice));
                    steward.updateProfit(profit);
                }

            }
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy