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

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