
ch.sahits.game.openpatrician.engine.land.city.AutomaticTradingEngine Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of OpenPatricianEngine Show documentation
Show all versions of OpenPatricianEngine Show documentation
Engine part driving the models and the game
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 extends ISteward> 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