package org.freerealm.settlement;
import org.freerealm.settlement.workforce.WorkForce;
import java.util.Iterator;
import java.util.Map.Entry;
import java.util.TreeMap;
import java.util.Vector;
import org.freerealm.map.Coordinate;
import org.freerealm.map.MapItem;
import org.freerealm.Realm;
import org.freerealm.ResourceStorageManager;
import org.freerealm.resource.Resource;
import org.freerealm.resource.ResourceStorer;
import org.freerealm.tile.Tile;
import org.freerealm.Utility;
import org.freerealm.settlement.improvement.SettlementImprovement;
import org.freerealm.settlement.improvement.SettlementImprovementType;
/**
*
* @author Deniz ARIKAN
*/
public class Settlement extends MapItem implements ResourceStorer {
private Realm realm;
private String name;
private int population;
private Vector<SettlementBuildable> productionQueue;
private int productionPoints;
private ResourceStorageManager storageManager;
private WorkForceManager workForceManager;
private boolean contiuousProduction;
private Vector<SettlementImprovement> improvements;
public Settlement(Realm realm) {
super(realm);
setRealm(realm);
productionPoints = 0;
contiuousProduction = false;
productionQueue = new Vector<SettlementBuildable>();
workForceManager = new WorkForceManager();
storageManager = new ResourceStorageManager(realm);
improvements = new Vector<SettlementImprovement>();
}
@Override
public String toString() {
return getName();
}
// <editor-fold defaultstate="collapsed" desc="City improvement methods">
public boolean hasImprovementType(SettlementImprovementType improvementType) {
Iterator<SettlementImprovement> improvementsIterator = getImprovementsIterator();
while (improvementsIterator.hasNext()) {
SettlementImprovementType checkImprovementType = improvementsIterator.next().getType();
if (checkImprovementType.equals(improvementType)) {
return true;
}
}
return false;
}
public void addImprovement(SettlementImprovement improvement) {
getImprovements().add(improvement);
}
public void removeImprovement(SettlementImprovement improvement) {
getImprovements().remove(improvement);
}
public void clearImprovements() {
getImprovements().clear();
}
public Iterator<SettlementImprovement> getImprovementsIterator() {
return getImprovements().iterator();
}
public int getImprovementUpkeep() {
int upkeep = 0;
Iterator<SettlementImprovement> improvementsIterator = getImprovementsIterator();
while (improvementsIterator.hasNext()) {
SettlementImprovementType improvement = improvementsIterator.next().getType();
upkeep = upkeep + improvement.getUpkeepCost();
}
return upkeep;
}
private Vector<SettlementImprovement> getImprovements() {
return improvements;
}
public Iterator<SettlementImprovementType> getBuildableImprovements() {
Vector<SettlementImprovementType> buildableImprovements = new Vector<SettlementImprovementType>();
Iterator<SettlementImprovementType> iterator = realm.getCityImprovementManager().getImprovementsIterator();
while (iterator.hasNext()) {
SettlementImprovementType cityImprovement = iterator.next();
if (canBuild(cityImprovement)) {
buildableImprovements.add(cityImprovement);
}
}
return buildableImprovements.iterator();
}
public boolean canBuild(SettlementBuildable buildable) {
if (!arePrerequisitesSatisfied(buildable)) {
return false;
} else {
if (buildable instanceof SettlementImprovementType) {
if (hasImprovementType((SettlementImprovementType) buildable)) {
return false;
} else {
return true;
}
} else {
return true;
}
}
}
private boolean arePrerequisitesSatisfied(SettlementBuildable settlementBuildable) {
Iterator<SettlementBuildablePrerequisite> prerequisitesIterator = settlementBuildable.getPrerequisitesIterator();
while (prerequisitesIterator.hasNext()) {
SettlementBuildablePrerequisite prerequisite = prerequisitesIterator.next();
prerequisite.setSettlement(this);
if (!prerequisite.isSatisfied()) {
return false;
}
}
return true;
}
// </editor-fold>
private int getTotalResourceProduction(Resource resource) {
int totalProduction = 0;
Iterator workforceIterator = getWorkForceManager().getWorkforce().entrySet().iterator();
while (workforceIterator.hasNext()) {
Entry entry = (Entry) workforceIterator.next();
WorkForce workForce = (WorkForce) entry.getValue();
Resource workForceResource = workForce.getResource();
if (resource.equals(workForceResource)) {
Coordinate coordinate = (Coordinate) entry.getKey();
Tile tile = getRealm().getTile(coordinate);
int producedQuantity = tile.getProduction(resource) * workForce.getNumberOfWorkers();
totalProduction = totalProduction + producedQuantity;
}
}
return totalProduction;
}
public int getResourceProduction(Resource resource) {
int totalProduction = getTotalResourceProduction(resource);
int actualProduction = Utility.increaseByPercent(totalProduction, getResourceModifier(resource));
return applyEfficiency(actualProduction);
}
private void manageWorkforce() {
if (getProductionWorkforce() < 0) {
int populationDecrease = -1 * getProductionWorkforce();
Iterator<WorkForce> workforceIterator = getWorkForceManager().getWorkForceIterator();
while (workforceIterator.hasNext()) {
WorkForce workForce = (WorkForce) workforceIterator.next();
if (workForce.getNumberOfWorkers() > populationDecrease) {
workForce.setNumberOfWorkers(workForce.getNumberOfWorkers() - populationDecrease);
return;
} else {
populationDecrease = populationDecrease - workForce.getNumberOfWorkers();
workForce.setNumberOfWorkers(0);
}
}
}
}
public int getFoodProduction() {
return getResourceProduction(realm.getResourceManager().getResource(Resource.FOOD));
}
public int getFoodNeeded() {
return getPopulation() * Integer.parseInt(getRealm().getProperty("food_needed_per_citizen"));
}
public int getWealthCollectedByTax() {
int wealthCollectedByTax = (getProductionWorkforce() * getPlayer().getTaxRate()) / 100;
wealthCollectedByTax = wealthCollectedByTax * (100 + getTaxIncomeModifier()) / 100;
return wealthCollectedByTax;
}
public int getWealthCollectedByTaxIf(int tax) {
int wealthCollectedByTax = (getProductionWorkforce() * tax) / 100;
wealthCollectedByTax = wealthCollectedByTax * (100 + getTaxIncomeModifier()) / 100;
return wealthCollectedByTax;
}
public SettlementBuildable getCurrentProduction() {
if (productionQueue.size() > 0) {
return productionQueue.get(0);
} else {
return null;
}
}
public void addToProductionQueue(SettlementBuildable buildable) {
productionQueue.add(buildable);
}
public void removeFromProductionQueue(int index) {
productionQueue.remove(index);
}
public Iterator<SettlementBuildable> getProductionQueueIterator() {
return productionQueue.iterator();
}
public int getProductionWorkforce() {
return getPopulation() - getWorkForceManager().getTotalWorkers() - getSettlementImprovementWorkerCount();
}
public int getProductionPointsPerTurn() {
int productionPointsPerTurn = (getProductionWorkforce() * (100 - getPlayer().getTaxRate())) / 100;
productionPointsPerTurn = Utility.increaseByPercent(productionPointsPerTurn, getProductionModifier());
return applyEfficiency(productionPointsPerTurn);
}
public int getMaxWorkersPerTile() {
int maxWorkersPerTile = Integer.parseInt(getRealm().getProperty("max_workers_per_tile"));
maxWorkersPerTile = Utility.increaseByPercent(maxWorkersPerTile, getMaximumWorkersModifier());
return maxWorkersPerTile;
}
/**
* This method will return all valid coordinates that can be assigned a
* workforce by the settlement. Resulting Vector will not only contain empty
* coordinates around the settlement, but also the coordinates that are already
* assigned a workforce and those that are being used by a nearby settlement.
* @return Vector<Coordinate>
*/
public Vector<Coordinate> getValidWorkForceCoordinates() {
Vector<Coordinate> availableCoordinatesForWorkForce = new Vector<Coordinate>();
availableCoordinatesForWorkForce.add(getCoordinate());
availableCoordinatesForWorkForce.addAll(Utility.getCircleCoordinates(getCoordinate(), realm, 1));
return realm.normalizeCoordinates(availableCoordinatesForWorkForce);
}
private int getBasePopulationIncrease() {
if (getPopulation() < 300) {
return 3;
} else if (getPopulation() < 600) {
return 2;
} else if (getPopulation() < 900) {
return 1;
}
return 1;
}
public int getPopulationIncreasePercent() {
//int defaultPopulationChangePercent = Integer.parseInt(getRealm().getProperty("default_population_change"));
int defaultPopulationIncrease = getBasePopulationIncrease();
return defaultPopulationIncrease;
}
public int getTotalCapacity(Resource resource) {
int capacity = Integer.parseInt(realm.getProperty("default_storage"));
capacity = capacity + getCapacityModifier(resource);
return capacity;
}
// <editor-fold defaultstate="collapsed" desc="Getters & setters">
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getPopulation() {
return population;
}
public void setPopulation(int population) {
this.population = population;
manageWorkforce();
}
public int getProductionPoints() {
return productionPoints;
}
public void setProductionPoints(int productionPoints) {
this.productionPoints = productionPoints;
}
public ResourceStorageManager getStorageManager() {
return storageManager;
}
public void setStorageManager(ResourceStorageManager resourceStorageManager) {
this.storageManager = resourceStorageManager;
}
public WorkForceManager getWorkForceManager() {
return workForceManager;
}
public boolean isContiuousProduction() {
return contiuousProduction;
}
public void setContiuousProduction(boolean contiuousProduction) {
this.contiuousProduction = contiuousProduction;
}
public int getResourceQuantity(Resource resource) {
return getStorageManager().getResourceQuantity(resource);
}
public void setResourceQuantity(Resource resource, int quantity) {
getStorageManager().setResourceQuantity(resource, quantity);
}
public int getRemainingCapacity(Resource resource) {
return getTotalCapacity(resource) - getResourceQuantity(resource);
}
public TreeMap<Resource, Integer> getResources() {
return getStorageManager().getResources();
}
public Iterator<Resource> getStorableResourcesIterator() {
return realm.getResourceManager().getResourcesIterator();
}
public Iterator<Resource> getContainedResourcesIterator() {
return realm.getResourceManager().getResourcesIterator();
}
public boolean isStoringResource(Resource resource) {
return true;
}
private Realm getRealm() {
return realm;
}
private void setRealm(Realm realm) {
this.realm = realm;
}
private int getBaseEfficiency() {
if (getPopulation() < 1000) {
return 100;
} else if (getPopulation() < 1500) {
return 95;
} else if (getPopulation() < 3500) {
return 90;
}
return 80;
}
public int getEfficiency() {
return getBaseEfficiency() + getEfficiencyModifier();
}
private int applyEfficiency(int value) {
return Utility.calculatePercent(value, getEfficiency());
}
// </editor-fold>
private int getSettlementImprovementWorkerCount() {
int settlementImprovementWorkerCount = 0;
Iterator<SettlementImprovement> iterator = getImprovementsIterator();
while (iterator.hasNext()) {
SettlementImprovement cityImprovement = iterator.next();
settlementImprovementWorkerCount = settlementImprovementWorkerCount + cityImprovement.getNumberOfWorkers();
}
return settlementImprovementWorkerCount;
}
// <editor-fold defaultstate="collapsed" desc="Modifiers">
public int getResourceModifier(Resource resource) {
int modifier = 0;
for (SettlementImprovement improvement : getImprovements()) {
if (improvement.isEnabled()) {
modifier = modifier + improvement.getType().getResourceModifier(resource, true);
}
}
return modifier;
}
public int getDefenceModifier() {
int modifier = 0;
for (SettlementImprovement improvement : getImprovements()) {
if (improvement.isEnabled()) {
modifier = modifier + improvement.getType().getDefenceModifier();
}
}
return modifier;
}
private int getTaxIncomeModifier() {
int modifier = 0;
for (SettlementImprovement improvement : getImprovements()) {
if (improvement.isEnabled()) {
modifier = modifier + improvement.getType().getTaxModifier();
}
}
return modifier;
}
private int getProductionModifier() {
int modifier = 0;
for (SettlementImprovement improvement : getImprovements()) {
if (improvement.isEnabled()) {
modifier = modifier + improvement.getType().getProductionModifier();
}
}
return modifier;
}
private int getMaximumWorkersModifier() {
int modifier = 0;
for (SettlementImprovement improvement : getImprovements()) {
if (improvement.isEnabled()) {
modifier = modifier + improvement.getType().getMaximumTileWorkersModifier();
}
}
return modifier;
}
private int getEfficiencyModifier() {
int modifier = 0;
for (SettlementImprovement improvement : getImprovements()) {
if (improvement.isEnabled()) {
modifier = modifier + improvement.getType().getEfficiencyModifier();
}
}
return modifier;
}
private int getCapacityModifier(Resource resource) {
int modifier = 0;
for (SettlementImprovement improvement : getImprovements()) {
if (improvement.isEnabled()) {
modifier = modifier + improvement.getType().getCapacityModifier(resource);
}
}
return modifier;
}
public Tile getTile() {
return realm.getTile(getCoordinate());
}
// </editor-fold>
}