From 9a7eb9ddf747feb56cd7e2511e6c60e9c193bc84 Mon Sep 17 00:00:00 2001
From: Peter Alexander <>
Date: Tue, 25 Jan 2022 16:12:41 +0000
Subject: [PATCH] Demand fraction for oilcrops and cereals to change with price

---
 src/ac/ed/lurg/ModelConfig.java               |  4 +-
 src/ac/ed/lurg/ModelMain.java                 | 17 +++--
 src/ac/ed/lurg/Timestep.java                  |  4 +-
 .../ed/lurg/country/AbstractCountryAgent.java | 69 +++++++++++--------
 src/ac/ed/lurg/country/CountryAgent.java      | 17 +++--
 .../ed/lurg/country/CountryAgentManager.java  |  7 +-
 src/ac/ed/lurg/country/CountryPrice.java      | 51 ++++++++------
 src/ac/ed/lurg/country/GlobalPrice.java       | 30 +++++---
 .../country/crafty/CraftyCountryAgent.java    |  6 +-
 9 files changed, 115 insertions(+), 90 deletions(-)

diff --git a/src/ac/ed/lurg/ModelConfig.java b/src/ac/ed/lurg/ModelConfig.java
index 1fb85b6a..444305f0 100755
--- a/src/ac/ed/lurg/ModelConfig.java
+++ b/src/ac/ed/lurg/ModelConfig.java
@@ -300,10 +300,8 @@ public class ModelConfig {
 	public static final String SSP_SCENARIO = getProperty("SSP_SCENARIO", "SSP1_v9_130325");
 	public static final ModelFitType DEMAND_ANIMAL_PROD_FIT = ModelFitType.findByName(getProperty("DEMAND_ANIMAL_PROD_FIT", "loglinear"));
 	public static final ModelFitType DEMAND_NON_ANIMAL_PROD_FIT = ModelFitType.findByName(getProperty("DEMAND_NON_ANIMAL_PROD_FIT", "loglinear"));
-	public static final double TOTAL_MAX_DEMAND_FRACT_CHANGE = getDoubleProperty("TOTAL_MAX_DEMAND_FRACT_CHANGE", 0.5);
-	public static final double ANNUAL_MAX_DEMAND_FRACT_CHANGE = getDoubleProperty("ANNUAL_MAX_DEMAND_FRACT_CHANGE", 0.0);
 	public static final boolean LIMIT_DEMAND_FRACTION = getBooleanProperty("LIMIT_DEMAND_FRACTION", true);
-	public static final int DEMAND_FRACT_CHANGE_START_STEP = getIntProperty("DEMAND_FRACT_CHANGE_START_STEP", 0);
+	public static final boolean DEMAND_FRACT_BY_COST = getBooleanProperty("DEMAND_FRACT_BY_COST", false);;
 	public static final double MAX_INCOME_PROPORTION_FOOD_SPEND = getDoubleProperty("MAX_INCOME_PROPORTION_FOOD_SPEND", 0.7);
 
 	public static final double PASTURE_HARVEST_FRACTION = getDoubleProperty("PASTURE_HARVEST_FRACTION", 0.5);
diff --git a/src/ac/ed/lurg/ModelMain.java b/src/ac/ed/lurg/ModelMain.java
index 5a3096e0..0ef9cab2 100644
--- a/src/ac/ed/lurg/ModelMain.java
+++ b/src/ac/ed/lurg/ModelMain.java
@@ -144,11 +144,15 @@ public class ModelMain {
 		
 		// output results
 		outputTimestepResults(timestep);
-		
 		checkAndSaveCheckpoint(timestep);
 	}
 
 	private void checkAndSaveCheckpoint(Timestep timestep) {
+		if (ModelConfig.IS_CALIBRATION_RUN || shouldSaveCheckpoint(timestep)) 
+			serializeCheckpoint();
+	}
+	
+	private boolean shouldSaveCheckpoint(Timestep timestep) {
 		if (ModelConfig.CHECKPOINT_YEARS != null) {
 			LogWriter.println("Looking to see if checkpoint year reached " + ModelConfig.CHECKPOINT_YEARS);
 
@@ -156,12 +160,11 @@ public class ModelMain {
 			for(int i=0; i<yearStr.length; i++) {
 				LogWriter.println("Got a checkpoint yearStr " + yearStr[i]);
 				int year = Integer.parseInt(yearStr[i]);
-				if (timestep.getYear() == year) {
-					LogWriter.println("Saving checkpoint");
-					serializeCheckpoint();
-				}
+				if (timestep.getYear() == year)
+					return true;
 			}
 		}
+		return false;
 	}
 
 	private void writeLandCoverFile(Timestep timestep, RasterSet<LandUseItem> landUseRaster) {
@@ -443,10 +446,6 @@ public class ModelMain {
 			outputWaterAvailablity(timestep, currentIrrigationData);  // uses the year directory structure created above
 		}
 
-		if (ModelConfig.IS_CALIBRATION_RUN) {
-			serializeCheckpoint();
-		}
-
 		if (timestep.isInitialTimestep() && ModelConfig.GENERATE_NEW_YIELD_CLUSTERS)
 			outputClusters(clusterIdRaster);
 
diff --git a/src/ac/ed/lurg/Timestep.java b/src/ac/ed/lurg/Timestep.java
index f2ffcdfe..eee35941 100644
--- a/src/ac/ed/lurg/Timestep.java
+++ b/src/ac/ed/lurg/Timestep.java
@@ -1,12 +1,14 @@
 package ac.ed.lurg;
 
 import java.io.File;
+import java.io.Serializable;
 import java.util.ArrayList;
 import java.util.Collection;
 
 
-public class Timestep {
+public class Timestep implements Serializable {
 
+	private static final long serialVersionUID = 718573167735145325L;
 	private int timestep;
 	
 	public Timestep(int timestep) {
diff --git a/src/ac/ed/lurg/country/AbstractCountryAgent.java b/src/ac/ed/lurg/country/AbstractCountryAgent.java
index 6b5a68fc..20b55b74 100644
--- a/src/ac/ed/lurg/country/AbstractCountryAgent.java
+++ b/src/ac/ed/lurg/country/AbstractCountryAgent.java
@@ -17,11 +17,11 @@ public abstract class AbstractCountryAgent {
 	protected CompositeCountry country;
 	protected Map<CropType, Double> tradeBarriers;
 	protected Map<CommodityType, Double> currentProjectedDemand;
+	private Map<CropType, GlobalPrice> currentWorldPrices;
 	protected Map<CropType, CountryPrice> currentCountryPrices;
 	private Map<CropType, CountryPrice> previousCountryPrices;
-	protected Map<CommodityType, Map<CropType, Double>> baseDemandFact;
 	protected Timestep currentTimestep;
-	protected Map<CommodityType, Map<CropType, Double>> currentMinDemandFract;
+	protected Map<CommodityType, Map<CropType, Double>> currentDemandFract;
 	protected double currentGen2EcDemand;
 	protected double exportTaxRate;
 	
@@ -30,7 +30,6 @@ public abstract class AbstractCountryAgent {
 		this.demandManager = demandManager;
 		this.country = country;
 		this.tradeBarriers = tradeBarriers;
-		baseDemandFact = demandManager.getBaseDemandFracts(country);
 	}
 
 	public CompositeCountry getCountry() {
@@ -39,16 +38,14 @@ public abstract class AbstractCountryAgent {
 	
 	protected void setCurrentTimestep(Timestep timestep) {
 		currentTimestep = timestep;
-		currentMinDemandFract = getMinDemandFraction();
 	}
 
-	private void calculateCountryPrices(Map<CropType, GlobalPrice> worldPrices){
+	private void calculateCountryPrices(){
 		Map<CropType, CountryPrice> countryPrices = new HashMap <CropType, CountryPrice>();
 
 		for (CropType c : CropType.getImportedTypes()) {
-			GlobalPrice worldPrice = worldPrices.get(c);
-			Double tb = tradeBarriers.get(c);
-			CountryPrice prices = createCountryPrices(c, worldPrice.getCountryImportPrice(tb==null ? 0 : tb, currentTimestep), worldPrice.getExportPrice());
+			GlobalPrice worldPrice = currentWorldPrices.get(c);
+			CountryPrice prices = createCountryPrices(c, worldPrice);
 			countryPrices.put(c, prices);
 		}
 				
@@ -80,18 +77,17 @@ public abstract class AbstractCountryAgent {
 		LogWriter.println(String.format("calculateExportTax %s: exportTax is now %s", country, exportTaxRate));
 	}
 	
-	abstract protected CountryPrice createCountryPrices(CropType crop, double importPrice, double exportPrice);
-
-	private void calculateDemand(boolean outputGamsDemand) {
-		Map<CommodityType, Double> producerPrices = getProducerCommodityPrices();
-		currentProjectedDemand = demandManager.getDemand(country, currentTimestep.getYear(), producerPrices, outputGamsDemand);
-		currentGen2EcDemand = demandManager.getSecondGenBioenergyDemand(country, currentTimestep.getYear());
-	}
+	abstract protected CountryPrice createCountryPrices(CropType crop, GlobalPrice worldPrice);
 	
 	protected void calculateCountryPricesAndDemand(Map<CropType, GlobalPrice> worldPrices, boolean outputGamsDemand) {
 		LogWriter.println("\ncalculateCountryPricesAndDemand for " + country + " "+ currentTimestep.getTimestep());
-		calculateCountryPrices(worldPrices);
-		calculateDemand(outputGamsDemand);
+		currentWorldPrices = worldPrices;
+		currentDemandFract = getDemandFraction();
+		calculateCountryPrices();
+		
+		Map<CommodityType, Double> producerPrices = getProducerCommodityPrices();
+		currentProjectedDemand = demandManager.getDemand(country, currentTimestep.getYear(), producerPrices, outputGamsDemand);
+		currentGen2EcDemand = demandManager.getSecondGenBioenergyDemand(country, currentTimestep.getYear());
 	}
 	
 	private Map<CommodityType, Double> getProducerCommodityPrices() {
@@ -118,25 +114,38 @@ public abstract class AbstractCountryAgent {
 	public Map<CropType, CountryPrice> getCurrentCountryPrices() {
 		return currentCountryPrices;
 	}
-	
-	private Map<CommodityType, Map<CropType, Double>> getMinDemandFraction() {
-		Map<CommodityType, Map<CropType, Double>> minDemandFraction = new HashMap<CommodityType, Map<CropType, Double>>();
 
-		int yearsOfChange = ModelConfig.IS_CALIBRATION_RUN ? 0
-				: (currentTimestep.getTimestep() - ModelConfig.DEMAND_FRACT_CHANGE_START_STEP) * ModelConfig.TIMESTEP_SIZE;
+	private Map<CommodityType, Map<CropType, Double>> getDemandFraction() {
+		Map<CommodityType, Map<CropType, Double>> baseDemandFact = demandManager.getBaseDemandFracts(country);
+		Map<CommodityType, Map<CropType, Double>> demandFraction = new HashMap<CommodityType, Map<CropType, Double>>();
+
+		for (Map.Entry<CommodityType, Map<CropType, Double>> entry : baseDemandFact.entrySet()) {
+			CommodityType comm = entry.getKey();
+			Map<CropType, Double> baseFracts = entry.getValue();
+			
+			if (ModelConfig.IS_CALIBRATION_RUN || !ModelConfig.DEMAND_FRACT_BY_COST || (comm != CommodityType.CEREALS && comm != CommodityType.OILCROPSPULSES))
+				demandFraction.put(comm, baseFracts);
+			
+			else {
+				Map<CropType, Double> newFracts = new HashMap<CropType, Double>();
+				double totalAdjQuantities = 0;
+
+				for (Map.Entry<CropType, Double> cropEntry : baseFracts.entrySet()) {
+					GlobalPrice worldPrice = currentWorldPrices.get(cropEntry.getKey());
+					double adjFract = worldPrice.getReferencePrice() / worldPrice.getExportPrice() * cropEntry.getValue(); // adjust by price ratio
+					newFracts.put(cropEntry.getKey(), adjFract);
+					totalAdjQuantities += adjFract;
+				}
 
-		for (CommodityType comm : baseDemandFact.keySet()) {
-			if (comm == CommodityType.CEREALS || comm == CommodityType.OILCROPSPULSES) {
 				Map<CropType, Double> cropFracts = new HashMap<CropType, Double>();
-				for (Map.Entry<CropType, Double> crop : baseDemandFact.get(comm).entrySet()) {
-					cropFracts.put(crop.getKey(), crop.getValue() * Math.max(ModelConfig.TOTAL_MAX_DEMAND_FRACT_CHANGE,
-							(1 - ModelConfig.ANNUAL_MAX_DEMAND_FRACT_CHANGE * yearsOfChange)));
-				}
-				minDemandFraction.put(comm, cropFracts);
+				for (Map.Entry<CropType, Double> cropEntry : newFracts.entrySet())
+					cropFracts.put(cropEntry.getKey(), cropEntry.getValue()/totalAdjQuantities);  //rebase to 1 by dividing by totalAdjQuantities
+				
+				demandFraction.put(comm, cropFracts);
 			}
 		}
 
-		return minDemandFraction;
+		return demandFraction;
 	}
 
 	protected void updateNetImportsFromProdAndDemand(Map<CommodityType, Double> demands, Map<CommodityType, Map<CropType, Double>>  minDemandFracts, Map<CropType, CropUsageData> cropUsages) {
diff --git a/src/ac/ed/lurg/country/CountryAgent.java b/src/ac/ed/lurg/country/CountryAgent.java
index f4b5aefb..c5adfc45 100644
--- a/src/ac/ed/lurg/country/CountryAgent.java
+++ b/src/ac/ed/lurg/country/CountryAgent.java
@@ -144,8 +144,10 @@ public class CountryAgent extends AbstractCountryAgent {
 		throw new RuntimeException("Skipping optimisation of country " + country);
 	}
 	
-	public void updateNetImportsFromProdAndDemand() {
-		updateNetImportsFromProdAndDemand(currentProjectedDemand, currentMinDemandFract, previousGamsRasterOutput.getCropUsageData());
+	public void recalculateDemandAndNetImports(Map<CropType, GlobalPrice> worldPrices) {
+		shockGDP();
+		calculateCountryPricesAndDemand(worldPrices, true);
+		updateNetImportsFromProdAndDemand(currentProjectedDemand, currentDemandFract, previousGamsRasterOutput.getCropUsageData());
 	}
 	
 	private void saveGDXFile(String ext) {
@@ -196,7 +198,7 @@ public class CountryAgent extends AbstractCountryAgent {
 		}
 
 		GamsCountryInput countryLevelInputs = new GamsCountryInput(country, currentProjectedDemand, currentCountryPrices, importConstraints, 
-				previousGamsRasterOutput.getCropUsageData(), currentMinDemandFract, subsidyRates, currentGen2EcDemand);	
+				previousGamsRasterOutput.getCropUsageData(), currentDemandFract, subsidyRates, currentGen2EcDemand);	
 		GamsRasterInput input = new GamsRasterInput(currentTimestep, countryYieldSurfaces, previousGamsRasterOutput.getLandUses(), irrigData, countryLevelInputs);
 
 		return input;
@@ -205,7 +207,7 @@ public class CountryAgent extends AbstractCountryAgent {
 	@Override
 	protected double getCommPriceFromCropPrice(CommodityType commodity) {
 		double commPricePlum = 0;
-		Map<CropType, Double> demandFract = baseDemandFact.get(commodity);
+		Map<CropType, Double> demandFract = currentDemandFract.get(commodity);
 		
 		for (CropType crop : commodity.getCropTypes()) {
 			double consumerCropPrice = currentCountryPrices.get(crop).getConsumerPrice();
@@ -216,14 +218,15 @@ public class CountryAgent extends AbstractCountryAgent {
 	}
 	
 	@Override
-	protected CountryPrice createCountryPrices(CropType crop, double importPrice, double exportPrice) {
+	protected CountryPrice createCountryPrices(CropType crop, GlobalPrice worldPrice) {
 		Map<CropType, CropUsageData> cropUsageMap = previousGamsRasterOutput.getCropUsageData();
 		CropUsageData cropUsageData = cropUsageMap.get(crop);
 
 		double weighting = Math.max(0, cropUsageData.getShockedNetImports()/(cropUsageData.getProductionExpected()+cropUsageData.getShockedNetImports()));
 		double prodCost = cropUsageData.getProdCostRate();
-		CountryPrice cp = new CountryPrice(crop, importPrice, exportPrice, prodCost, weighting, exportTaxRate);
-		LogWriter.println("Created " + cp);
+		Double tb = tradeBarriers.get(crop);
+		double tradeBarrier = tb==null ? 0 : tb;
+		CountryPrice cp = new CountryPrice(crop, worldPrice, tradeBarrier, prodCost, weighting, exportTaxRate);
 		return cp;
 	}
 
diff --git a/src/ac/ed/lurg/country/CountryAgentManager.java b/src/ac/ed/lurg/country/CountryAgentManager.java
index 3d413b3c..eb3685e4 100644
--- a/src/ac/ed/lurg/country/CountryAgentManager.java
+++ b/src/ac/ed/lurg/country/CountryAgentManager.java
@@ -130,11 +130,8 @@ public class CountryAgentManager {
 	}
 
 	public void recalculateDemandAndNetImportsForAll() {
-		for (CountryAgent ca : gamsCountryAgents) {
-			ca.shockGDP();
-			ca.calculateCountryPricesAndDemand(internationalMarket.getWorldPrices(), true);
-			ca.updateNetImportsFromProdAndDemand();
-		}
+		for (CountryAgent ca : gamsCountryAgents)
+			ca.recalculateDemandAndNetImports(internationalMarket.getWorldPrices());
 	}
 	
 	public void updateProtectedAreasForAll(RasterSet<LandUseItem> newProtectedAreas) {
diff --git a/src/ac/ed/lurg/country/CountryPrice.java b/src/ac/ed/lurg/country/CountryPrice.java
index 38531248..a9af5ff7 100644
--- a/src/ac/ed/lurg/country/CountryPrice.java
+++ b/src/ac/ed/lurg/country/CountryPrice.java
@@ -8,18 +8,16 @@ public class CountryPrice {
 
 	private CropType crop;
 	private double importPrice;
-	private double exportPrice;
-	private double exportTaxRate;
-	private double prodCost;
-	private double consumerPriceweighting;
+	private double grossExportPrice;
+	private double consumerPrice;
+	private double netExportPrice;
 
-	public CountryPrice(CropType crop, double importPrice, double exportPrice, double prodCost, double weighting, double exportTaxRate){
+	public CountryPrice(CropType crop, GlobalPrice worldPrice, double tradeBarrier, double prodCost, double importWeighting, double exportTaxRate){
 		this.crop = crop;
-		this.importPrice = importPrice;
-		this.exportPrice = exportPrice;
-		this.prodCost = prodCost;
-		this.consumerPriceweighting = weighting;
-		this.exportTaxRate = exportTaxRate;
+		this.importPrice = worldPrice.getCountryImportPrice(tradeBarrier);
+		this.grossExportPrice = worldPrice.getExportPrice();
+		this.consumerPrice = calcConsumerPrice(prodCost, importWeighting);
+		this.netExportPrice = calcProducerNetExportPrice(exportTaxRate);
 	}
 
 	public double getImportPrice() {
@@ -27,22 +25,31 @@ public class CountryPrice {
 	}
 	
 	public double getExportPrice() {
-		return exportPrice;
+		return grossExportPrice;
 	}
 	
 	public double getConsumerPrice() {
-		double exportOrProdCost = Double.isNaN(prodCost) || prodCost <= 0.0 ? exportPrice : prodCost;
+		return consumerPrice;
+	}
+	
+	public double getProducerNetExportPrice() {
+		return netExportPrice;
+	}
+	
+	private double calcConsumerPrice(double prodCost, double importWeighting) {
+		double exportOrProdCost = Double.isNaN(prodCost) || prodCost <= 0.0 ? getExportPrice() : prodCost;
 		double consumerPrice;
+		double importPrice = getImportPrice();
 
 		switch (ModelConfig.PRICE_CALCULATION) {
 			case IMPORTONLY:
 				consumerPrice = importPrice;
 				break;
 			case WEIGHTEDIMPEXP:
-				consumerPrice = importPrice*consumerPriceweighting + exportPrice*(1-consumerPriceweighting);
+				consumerPrice = importPrice*importWeighting + getExportPrice()*(1-importWeighting);
 				break;
 			case WEIGHTEDINCLPRODCOSTS:
-				consumerPrice = importPrice*consumerPriceweighting + exportOrProdCost*(1-consumerPriceweighting);
+				consumerPrice = importPrice*importWeighting + exportOrProdCost*(1-importWeighting);
 				break;
 			default:
 				consumerPrice = importPrice;
@@ -50,21 +57,21 @@ public class CountryPrice {
 				break;
 		}
 		
-		LogWriter.println(String.format("   Crop %s: import %.4f, export %.4f, prodcost %.4f, newCropPrice %.4f", crop, importPrice, exportPrice, prodCost, consumerPrice));
-
+		LogWriter.println(String.format("CountryPrice:   Crop %s: import %.4f, export %.4f, prodcost %.4f, importWeighting %.4f, newCropPrice %.4f", 
+				crop, importPrice, getExportPrice(), prodCost, importWeighting, consumerPrice));
 		return consumerPrice;
 	}
 	
-	public double getProducerNetExportPrice() {
+	private double calcProducerNetExportPrice(double exportTaxRate) {
 		if (ModelConfig.APPLY_EXPORT_TAXES)
-			return exportPrice / (1 + exportTaxRate);
+			return getExportPrice() / (1 + exportTaxRate);
 		else
-			return exportPrice;
+			return getExportPrice();
 	}
 	
 	@Override
 	public String toString() {
-		return "CountryPrice [crop=" + crop + ", importPrice=" + importPrice + ", exportPrice=" + exportPrice + 
-				", exportTaxRate=" + exportTaxRate + ", prodCost=" + prodCost + ", consumerPriceweighting="+ consumerPriceweighting + "]";
+		return "CountryPrice [crop=" + crop + ", importPrice=" + importPrice + ", grossExportPrice=" + grossExportPrice
+				+ ", consumerPrice=" + consumerPrice + ", netExportPrice=" + netExportPrice + "]";
 	}
-}
+}
\ No newline at end of file
diff --git a/src/ac/ed/lurg/country/GlobalPrice.java b/src/ac/ed/lurg/country/GlobalPrice.java
index 919802ab..fa0fc1a3 100644
--- a/src/ac/ed/lurg/country/GlobalPrice.java
+++ b/src/ac/ed/lurg/country/GlobalPrice.java
@@ -10,24 +10,27 @@ public class GlobalPrice implements Serializable {
 
 	private static final long serialVersionUID = 2477952576838887039L;
 	
-	private int timestepId;
+	private Timestep timestep;
 	private double exportPrice;
 	private double importAmount;
 	private double exportAmountBeforeLoss;
 	private double transportLosses;
 	private double stockLevel;
+	private double referencePrice;
 
-	private GlobalPrice(int timestepId, double exportPrice, double stockLevel, double importAmount, double exportAmountBeforeLoss, double transportLosses) {
-		this.timestepId = timestepId;
+	private GlobalPrice(Timestep timestep, double exportPrice, double stockLevel, double importAmount, double exportAmountBeforeLoss, double transportLosses, double referencePrice) {
+		this.timestep = timestep;
 		this.exportPrice = exportPrice;
 		this.stockLevel = stockLevel;
 		this.importAmount = importAmount;
 		this.exportAmountBeforeLoss = exportAmountBeforeLoss;
 		this.transportLosses = transportLosses;
+		this.referencePrice = referencePrice;
+		LogWriter.println("Created " + this);
 	}
 	
 	public static GlobalPrice createInitial(double exportPrice, double intitalStock) {
-		return new GlobalPrice(ModelConfig.START_TIMESTEP-1, exportPrice, intitalStock, Double.NaN, Double.NaN, Double.NaN);
+		return new GlobalPrice(new Timestep(ModelConfig.START_TIMESTEP-1), exportPrice, intitalStock, Double.NaN, Double.NaN, Double.NaN, Double.NaN);
 	}
 	
 	public double getExportPrice(){
@@ -38,7 +41,7 @@ public class GlobalPrice implements Serializable {
 		return stockLevel;
 	}
 	
-	public double getCountryImportPrice(double countryTradeBarrier, Timestep timestep) {
+	public double getCountryImportPrice(double countryTradeBarrier) {
 
 		int currentYear = timestep.getYear();
 		double tradeBarrierMultiplier = ModelConfig.updateParameterForShocks(currentYear, "TRADE_BARRIER_MULTIPLIER");
@@ -68,7 +71,7 @@ public class GlobalPrice implements Serializable {
 	public GlobalPrice createWithUpdatedMarketPrices(double newImports, double newExportAmountBeforeLoss, Timestep timestep, double production) {
 
 		if (newImports > 0 || newExportAmountBeforeLoss > 0) {
-			double oldDiff = timestep.getTimestep() != timestepId ? 0.0 : exportAmountBeforeLoss - transportLosses - importAmount; // if recomputing for same year need to back our previous adjustment
+			double oldDiff = !timestep.equals(timestep) ? 0.0 : exportAmountBeforeLoss - transportLosses - importAmount; // if recomputing for same year need to back our previous adjustment
 			double transportLossRate = ModelConfig.updateParameterForShocks(timestep.getYear(), "TRANSPORT_LOSSES");
 			double newTransportLosses = newExportAmountBeforeLoss * transportLossRate;
 			double stockChange = newExportAmountBeforeLoss - newTransportLosses - newImports - oldDiff;
@@ -112,7 +115,9 @@ public class GlobalPrice implements Serializable {
 			LogWriter.println(String.format(", after limit %.4f", adjustment));
 
 			double newPrice = exportPrice * adjustment;
-			return new GlobalPrice(timestep.getTimestep(), newPrice, updatedStock, newImports, newExportAmountBeforeLoss, newTransportLosses);			
+			double refPrice = ModelConfig.IS_CALIBRATION_RUN ? exportPrice : referencePrice;  // during calibration reference price isn't fixed, but it is after that
+			
+			return new GlobalPrice(timestep, newPrice, updatedStock, newImports, newExportAmountBeforeLoss, newTransportLosses, refPrice);			
 		}
 		else {
 			LogWriter.printlnError(String.format("Price for not updated (still %s), as no imports and no exports for it", exportPrice));
@@ -122,14 +127,19 @@ public class GlobalPrice implements Serializable {
 
 	@Override
 	public String toString() {
-		return String.format("exportPrice=%.6f", exportPrice);
+		return "GlobalPrice [timestep=" + timestep.getTimestep() + ", exportPrice=" + exportPrice + ", importAmount=" + importAmount
+				+ ", stockLevel=" + stockLevel + ", referencePrice=" + referencePrice + "]";
 	}
 
+	public double getReferencePrice() {
+		return referencePrice;
+	}
+	
 	public double getStockChange() {
 		return exportAmountBeforeLoss - transportLosses - importAmount;
 	}
-
+	
 	public GlobalPrice createPriceAdjustedByFactor(double factor) {
-		return new GlobalPrice(timestepId, exportPrice * factor, stockLevel, importAmount, exportAmountBeforeLoss, transportLosses);			
+		return new GlobalPrice(timestep, exportPrice * factor, stockLevel, importAmount, exportAmountBeforeLoss, transportLosses, referencePrice);			
 	}
 }
\ No newline at end of file
diff --git a/src/ac/ed/lurg/country/crafty/CraftyCountryAgent.java b/src/ac/ed/lurg/country/crafty/CraftyCountryAgent.java
index fbc10bb0..0117c8e2 100644
--- a/src/ac/ed/lurg/country/crafty/CraftyCountryAgent.java
+++ b/src/ac/ed/lurg/country/crafty/CraftyCountryAgent.java
@@ -30,13 +30,13 @@ public class CraftyCountryAgent extends AbstractCountryAgent {
 	public void updateProduction(Map<CropType, CropUsageData> cropUsageMap, Map<CropType, GlobalPrice> worldPrices) {
 		this.cropUsageData = cropUsageMap;
 		calculateCountryPricesAndDemand(worldPrices, false);
-		updateNetImportsFromProdAndDemand(currentProjectedDemand, currentMinDemandFract, cropUsageMap);
+		updateNetImportsFromProdAndDemand(currentProjectedDemand, currentDemandFract, cropUsageMap);
 	}
 
 	@Override
  	protected double getCommPriceFromCropPrice(CommodityType commodity) {
  		double commPricePlum = 0;
- 		Map<CropType, Double> demandFract = baseDemandFact.get(commodity);
+ 		Map<CropType, Double> demandFract = currentDemandFract.get(commodity);
  
  		for (CropType crop : commodity.getCropTypes()) {
  			commPricePlum += currentCountryPrices.get(crop).getImportPrice() * demandFract.get(crop);  // weight price by base demand of each cereal crop
@@ -45,7 +45,7 @@ public class CraftyCountryAgent extends AbstractCountryAgent {
  	}
 
 	@Override
-	protected CountryPrice createCountryPrices(CropType crop, double importPrice, double exportPrice) {
+	protected CountryPrice createCountryPrices(CropType crop, GlobalPrice worldPrice) {
 		// TODO Auto-generated method stub
 		return null;
 	}
-- 
GitLab