ch.sahits.game.openpatrician.engine.player.PlayerEngine Maven / Gradle / Ivy
package ch.sahits.game.openpatrician.engine.player;
import ch.sahits.game.event.data.ClockTickDayChange;
import ch.sahits.game.openpatrician.engine.AbstractEngine;
import ch.sahits.game.openpatrician.engine.land.city.ReputationCalculator;
import ch.sahits.game.openpatrician.event.data.ShipArrivesAtDestinationEvent;
import ch.sahits.game.openpatrician.model.IBalanceSheet;
import ch.sahits.game.openpatrician.model.ICompany;
import ch.sahits.game.openpatrician.model.IHumanPlayer;
import ch.sahits.game.openpatrician.model.IPlayer;
import ch.sahits.game.openpatrician.model.PlayerList;
import ch.sahits.game.openpatrician.model.building.IBuilding;
import ch.sahits.game.openpatrician.model.building.ISteward;
import ch.sahits.game.openpatrician.model.building.IStorage;
import ch.sahits.game.openpatrician.model.building.ITownHouse;
import ch.sahits.game.openpatrician.model.building.ITradingOffice;
import ch.sahits.game.openpatrician.model.building.IWorkShop;
import ch.sahits.game.openpatrician.model.city.ICity;
import ch.sahits.game.openpatrician.model.map.IMap;
import ch.sahits.game.openpatrician.model.personal.IReputation;
import ch.sahits.game.openpatrician.model.product.AmountablePrice;
import ch.sahits.game.openpatrician.model.product.EWare;
import ch.sahits.game.openpatrician.model.product.IWare;
import ch.sahits.game.openpatrician.model.sea.TravellingVessels;
import ch.sahits.game.openpatrician.model.ship.INavigableVessel;
import ch.sahits.game.openpatrician.model.ship.IShip;
import ch.sahits.game.openpatrician.utilities.annotation.ClassCategory;
import ch.sahits.game.openpatrician.utilities.annotation.EClassCategory;
import ch.sahits.game.openpatrician.utilities.annotation.LazySingleton;
import ch.sahits.game.openpatrician.utilities.spring.DependentPropertyInitializer;
import ch.sahits.game.openpatrician.utilities.spring.DependentValue;
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 org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
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;
import java.util.Optional;
import java.util.Set;
/**
* Base engine representing a player. If the player is AI the correseponding
* engine will be a subclass of this engine.
* @author Andi Hotz, (c) Sahits GmbH, 2015
* Created on Jun 16, 2015
*/
@LazySingleton
@ClassCategory(EClassCategory.SINGLETON_BEAN)
public class PlayerEngine extends AbstractEngine {
private final Logger logger = LogManager.getLogger(getClass());
@SuppressWarnings("FieldCanBeLocal")
@DependentValue("sailor.cost.per.day")
private double dailySailorCost = 0.5;
@Autowired
private PlayerList players;
@Autowired
private HumanPlayerEngine humanPlayerEngine;
@Autowired
private IMap map;
@Autowired
private ReputationCalculator repCalc;
@Autowired
private TravellingVessels vessels;
@Autowired
@Qualifier("serverClientEventBus")
private AsyncEventBus clientServerEventBus;
@Autowired
@Qualifier("timerEventBus")
private AsyncEventBus timerEventBus;
@Autowired
private DependentPropertyInitializer propertyInitializer;
@PostConstruct
private void init() {
try {
propertyInitializer.initializeAnnotatedFields(this);
} catch (IllegalAccessException e) {
logger.warn("Failed to initialize DependentValue annotated fields");
}
clientServerEventBus.register(this);
timerEventBus.register(this);
}
@PreDestroy
private void unregister() {
clientServerEventBus.unregister(this);
timerEventBus.unregister(this);
}
@Subscribe
public void handleDailyUpdate(ClockTickDayChange event){
dailyUpdateBalanceSheet();
updateCompanyValue();
}
/**
* Handling the daily update events.
* @param event day change update
*/
@Subscribe
public void handleWeeklyUpdate(ClockTickDayChange event) {
for (IPlayer player : players) {
for (ICity city : map.getCities()) {
try {
IReputation reputation = city.getReputation(player);
int wareReputation = repCalc.calculateWareReputation(city, player);
reputation.addWareReputation(wareReputation);
} catch (RuntimeException e) {
logger.error("Failed to update reputation for "+player.getName()+" "+player.getLastName()+" in "+city.getName(), e);
}
}
}
}
@VisibleForTesting
void updateCompanyValue() {
for (IPlayer player : players) {
ICompany company = player.getCompany();
long newCompanyValue = company.getCash();
// Add value of all ships
List ships = player.getFleet();
for (IShip ship : ships) {
newCompanyValue += ship.getValue();
Set loaded = ship.getLoadedWares();
for (IWare ware : loaded) {
AmountablePrice ap = ship.getWare(ware);
newCompanyValue+=ap.getAVGPrice()*ap.getAmount();
}
}
// Add value of all buildings
for (ICity city : map.getCities()) {
List buildings = player.findBuildings(city);
for (IBuilding building : buildings) {
newCompanyValue += building.getValue();
if (building instanceof ITradingOffice){
ITradingOffice office = (ITradingOffice) building;
for (IWare ware : EWare.values()) {
AmountablePrice ap = office.getWare(ware);
newCompanyValue+=ap.getAVGPrice()*ap.getAmount();
}
}
}
}
company.setCompanyValue(newCompanyValue);
}
}
@Override
public List getChildren() {
ArrayList engines = new ArrayList<>();
engines.add(humanPlayerEngine);
return engines;
}
private void dailyUpdateBalanceSheet() {
// property taxes are handled by the city hall engine
// office trading is handled in the AutomaticTradingEngine
List cities = map.getCities();
for (IPlayer player : players) {
long sum = 0;
int stewardCosts = 0;
int rentalIncome = 0;
int wageCosts = 0;
int otherCosts = 0;
for (ICity city : cities) {
// steward costs
Optional optOffice = player.findTradingOffice(city);
if (optOffice.isPresent()) {
ITradingOffice office = optOffice.get();
Optional steward = office.getSteward();
if (steward.isPresent()) {
stewardCosts -= (int) Math.rint(steward.get().getSalary() / 7.0);
sum += stewardCosts;
}
// rentalIncome
List townHouses = player.findBuildings(city, ITownHouse.class);
for (IBuilding building : townHouses) {
rentalIncome += ((ITownHouse) building).computeRentalIncome();
sum += rentalIncome;
}
// wages
List workshops = player.findBuildings(city, IWorkShop.class);
IStorage storage = office.getStorage();
for (IBuilding building : workshops) {
int workers = ((IWorkShop) building).getWorkers();
int salaryPerWorker = ((IWorkShop) building).getSalaryPerWorker();
wageCosts -= (int) Math.rint(salaryPerWorker * workers / 7.0);
}
wageCosts -= storage.guardCostsPerDayBinding().get();
List fleet = player.getFleet();
for (IShip ship : fleet) {
double sailorSalary = ship.getNumberOfSailors() * dailySailorCost;
wageCosts -= sailorSalary;
if (ship.getCaptian().isPresent()) {
wageCosts -= ship.getCaptian().get().getSalary();
} else if (sailorSalary > 0) {
wageCosts -= dailySailorCost;
}
}
sum += wageCosts;
// other costs
otherCosts -= storage.costsPerDayBinding().get();
sum += otherCosts;
// all other exceptional costs are deduced where they occur.
if (player instanceof IHumanPlayer) {
player.getCompany().updateCash(sum);
Optional optMainOffice = player.findTradingOffice(player.getHometown());
Preconditions.checkArgument(optMainOffice.isPresent(), "There must be a trading office in the hometown.");
IBalanceSheet balanceSheet = optMainOffice.get().getCurrentWeek();
balanceSheet.updateRentalIncome(rentalIncome);
balanceSheet.updateStewardCosts(stewardCosts);
balanceSheet.updateSalaries(wageCosts);
balanceSheet.updateOtherExpensesRegular(otherCosts);
} else {
player.getCompany().updateCashDirectly(sum);
}
}
}
}
}
@Subscribe
public void handleShipReachesDestination(ShipArrivesAtDestinationEvent event) {
INavigableVessel vessel = event.getShip();
vessels.remove(vessel);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy