From 79911adc00e05f151b48e70e118b2e50a1414a48 Mon Sep 17 00:00:00 2001
From: Peter Alexander <peter@blackhillock.co.uk>
Date: Tue, 28 Jan 2020 21:22:00 +0000
Subject: [PATCH] Price shocks

---
 debug_config.properties                       |  4 +-
 src/ac/ed/lurg/InternationalMarket.java       | 18 ++++++-
 src/ac/ed/lurg/ModelConfig.java               |  2 +-
 src/ac/ed/lurg/ModelMain.java                 |  3 +-
 src/ac/ed/lurg/country/GlobalPrice.java       |  4 ++
 src/ac/ed/lurg/shock/PriceShockManager.java   | 46 ++++++++++++++++
 .../ed/lurg/shock/ProductionShockManager.java | 53 -------------------
 src/ac/ed/lurg/shock/YieldShockManager.java   |  2 +-
 8 files changed, 72 insertions(+), 60 deletions(-)
 create mode 100644 src/ac/ed/lurg/shock/PriceShockManager.java
 delete mode 100644 src/ac/ed/lurg/shock/ProductionShockManager.java

diff --git a/debug_config.properties b/debug_config.properties
index 34fd146f..717dffaf 100644
--- a/debug_config.properties
+++ b/debug_config.properties
@@ -6,11 +6,11 @@ YIELD_FILENAME=yield.out
 DEBUG_LIMIT_COUNTRIES=false
 DEBUG_COUNTRY_NAME=Mongolia
 
-IS_CALIBRATION_RUN = false
+IS_CALIBRATION_RUN = true
 GENERATE_NEW_YIELD_CLUSTERS = false
 NUM_YIELD_CLUSTERS=8000
 
-END_TIMESTEP=1
+END_TIMESTEP=0
 TIMESTEP_SIZE=10
 
 INTERPOLATE_OUTPUT_YEARS = false
diff --git a/src/ac/ed/lurg/InternationalMarket.java b/src/ac/ed/lurg/InternationalMarket.java
index 5ebe200e..5f3d517f 100644
--- a/src/ac/ed/lurg/InternationalMarket.java
+++ b/src/ac/ed/lurg/InternationalMarket.java
@@ -15,6 +15,7 @@ import ac.ed.lurg.country.AbstractCountryAgent;
 import ac.ed.lurg.country.GlobalPrice;
 import ac.ed.lurg.country.StockReader;
 import ac.ed.lurg.landuse.CropUsageData;
+import ac.ed.lurg.shock.PriceShockManager;
 import ac.ed.lurg.types.CropToDoubleMap;
 import ac.ed.lurg.types.CropType;
 import ac.ed.lurg.utils.LogWriter;
@@ -22,7 +23,8 @@ import ac.ed.lurg.utils.LogWriter;
 public class InternationalMarket {
 
 	private Map<CropType, GlobalPrice> worldPrices;
-
+	private PriceShockManager priceShockManager;
+	
 	public InternationalMarket() {
 		if(ModelConfig.IS_CALIBRATION_RUN) {
 			worldPrices = new HashMap<CropType, GlobalPrice>();
@@ -38,7 +40,7 @@ public class InternationalMarket {
 		else {
 			worldPrices = deserializeGlobalPrice();
 		}
-
+		priceShockManager = new PriceShockManager();
 	}
 
 	public  Map<CropType, GlobalPrice> getWorldPrices() {
@@ -141,6 +143,18 @@ public class InternationalMarket {
 		}
 	}
 
+	public void applyPriceShocks(Timestep timestep) {
+		Map<CropType, Double> shocks = priceShockManager.getShocks(timestep);
+		for (Map.Entry<CropType, Double> entry : shocks.entrySet()) {
+			CropType crop = entry.getKey();
+			GlobalPrice preShock = worldPrices.get(crop);
+			double factor = 1.0 + entry.getValue();
+			GlobalPrice adjustedPrice = preShock.createPriceAdjustedByFactor(factor);
+			LogWriter.println(String.format("applyPriceShocks: %s adjusting price by %.4f to export price %.2f", crop.getFaoName(), factor, adjustedPrice.getExportPrice()));
+			worldPrices.put(crop, adjustedPrice);
+		}
+	}
+
 	/*	public double findMaxPriceDiff(Map<CropType, Double> previousExportPrices) {
 		if (previousExportPrices == null)
 			return Double.MAX_VALUE;
diff --git a/src/ac/ed/lurg/ModelConfig.java b/src/ac/ed/lurg/ModelConfig.java
index 748f3673..77e3ec18 100755
--- a/src/ac/ed/lurg/ModelConfig.java
+++ b/src/ac/ed/lurg/ModelConfig.java
@@ -177,7 +177,6 @@ public class ModelConfig {
 	public static final String SUBSIDY_RATE_FILE = getProperty("SUBSIDY_RATE_FILE", DATA_DIR + File.separator + SUBSIDY_RATE_FILENAME);
 	public static final String ANIMAL_RATES_FILE = DATA_DIR + File.separator + "animal_numbers.csv";;
 	public static final String INITIAL_CONSUMER_PRICE_FILE = DATA_DIR + File.separator + "consumerprices.csv";;
-	public static final String PRODUCTIONSHOCKS_PARAMETER_FILE = getProperty("PRODUCTIONSHOCKS_PARAMETER_FILE", OUTPUT_DIR + File.separator+ "productionShocks.csv");
 	public static final String GDP_FRACTIONS_FILE = DATA_DIR + File.separator + "agriculturalGdpFraction.csv";
 
 	// yield data
@@ -241,6 +240,7 @@ public class ModelConfig {
 	public static final String HIGH_SLOPE_AREAS_FILE = SPATIAL_DATA_DIR + File.separator + "maxcropfrac2.txt";
 	public static final String YIELDSHOCK_MAP_DIR = SPATIAL_DATA_DIR + File.separator + "yieldshockmaps";
 	public static final String YIELDSHOCKS_PARAMETER_FILE = getProperty("YIELDSHOCKS_PARAMETER_FILE", OUTPUT_DIR + File.separator+ "yieldshocks.csv");
+	public static final String PRICESHOCKS_PARAMETER_FILE = getProperty("PRICESHOCKS_PARAMETER_FILE", OUTPUT_DIR + File.separator+ "priceshocks.csv");
 
 	// Output
 	public static final String LAND_COVER_OUTPUT_FILE = OUTPUT_DIR + File.separator + "lc.txt";
diff --git a/src/ac/ed/lurg/ModelMain.java b/src/ac/ed/lurg/ModelMain.java
index 5e598999..903986b8 100644
--- a/src/ac/ed/lurg/ModelMain.java
+++ b/src/ac/ed/lurg/ModelMain.java
@@ -146,7 +146,8 @@ public class ModelMain {
 			countryAgents.updateNetImportsForAll(); // calculate imports and exports
 			internationalMarket.determineInternationalTrade(countryAgents.getAll(), gen2EcDDemand, timestep); // calculate prices
 		}
-
+		internationalMarket.applyPriceShocks(timestep);
+		
 		// output results
 		outputTimestepResults(timestep, globalLandUseRaster);
 	}
diff --git a/src/ac/ed/lurg/country/GlobalPrice.java b/src/ac/ed/lurg/country/GlobalPrice.java
index 0e9dc478..bf0ac898 100644
--- a/src/ac/ed/lurg/country/GlobalPrice.java
+++ b/src/ac/ed/lurg/country/GlobalPrice.java
@@ -123,4 +123,8 @@ public class GlobalPrice implements Serializable {
 	public double getStockChange() {
 		return exportAmountBeforeLoss - transportLosses - importAmount;
 	}
+
+	public GlobalPrice createPriceAdjustedByFactor(double factor) {
+		return new GlobalPrice(timestepId, exportPrice * factor, stockLevel, importAmount, exportAmountBeforeLoss, transportLosses);			
+	}
 }
\ No newline at end of file
diff --git a/src/ac/ed/lurg/shock/PriceShockManager.java b/src/ac/ed/lurg/shock/PriceShockManager.java
new file mode 100644
index 00000000..f00e99f5
--- /dev/null
+++ b/src/ac/ed/lurg/shock/PriceShockManager.java
@@ -0,0 +1,46 @@
+package ac.ed.lurg.shock;
+
+import java.io.File;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import ac.ed.lurg.ModelConfig;
+import ac.ed.lurg.Timestep;
+import ac.ed.lurg.types.CropType;
+import ac.ed.lurg.utils.LogWriter;
+import ac.ed.lurg.utils.StringTabularReader;
+
+public class PriceShockManager {
+	private StringTabularReader priceShockReader;
+
+	public PriceShockManager() {
+
+		String shockFile = ModelConfig.PRICESHOCKS_PARAMETER_FILE;
+		priceShockReader = new StringTabularReader(",", new String[]{"year", "crop", "shockFactor"});
+
+		if (new File(shockFile).isFile()) 
+			priceShockReader.read(shockFile);
+		else
+			LogWriter.println("Can't find a price shock file (" +shockFile + "), so will not shock prices");
+	}
+	
+	public Map<CropType, Double> getShocks(Timestep timestep) {
+		Map<CropType, Double> shocks = new HashMap<CropType, Double>();
+
+		Map<String, String> queryMap = new HashMap<String, String>();
+		queryMap.put("year", Integer.toString(timestep.getYear()));
+		
+		List<Map<String, String>> rows = priceShockReader.query(queryMap);
+		for (Map<String, String> row : rows) {
+			String cropTypeS = row.get("crop");
+			String shockFactorS = row.get("shockFactor");
+			CropType crop = CropType.getForFaoName(cropTypeS);
+			
+			Double shockFactor = Double.valueOf(shockFactorS);
+			LogWriter.println("Got price shock at " + timestep + ": " + cropTypeS + " " + shockFactorS);
+			shocks.put(crop, shockFactor);
+		}
+		return shocks;
+	}
+}
\ No newline at end of file
diff --git a/src/ac/ed/lurg/shock/ProductionShockManager.java b/src/ac/ed/lurg/shock/ProductionShockManager.java
deleted file mode 100644
index 717f3eed..00000000
--- a/src/ac/ed/lurg/shock/ProductionShockManager.java
+++ /dev/null
@@ -1,53 +0,0 @@
-package ac.ed.lurg.shock;
-
-import java.io.File;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import ac.ed.lurg.ModelConfig;
-import ac.ed.lurg.Timestep;
-import ac.ed.lurg.country.CompositeCountry;
-import ac.ed.lurg.types.CropType;
-import ac.ed.lurg.utils.LogWriter;
-import ac.ed.lurg.utils.StringTabularReader;
-
-
-public class ProductionShockManager {
-
-	private StringTabularReader productionShockReader;
-
-	public ProductionShockManager() {
-
-		String shockFile = ModelConfig.PRODUCTIONSHOCKS_PARAMETER_FILE;
-		productionShockReader = new StringTabularReader(",", new String[]{"year", "country", "crop", "shockFactor", "region"});
-
-		if (new File(shockFile).isFile()) 
-			productionShockReader.read(shockFile);
-		else
-			LogWriter.println("Can't find a production shock file (" +shockFile + "), so will not shock production");
-	}
-	
-	public Map<CropType, Double> getShocksForCountry(Timestep timestep, CompositeCountry cc) {
-		Map<CropType, Double> shocks = new HashMap<CropType, Double>();
-
-		Map<String, String> queryMap = new HashMap<String, String>();
-		queryMap.put("year", Integer.toString(timestep.getYear()));
-		queryMap.put("country", cc.getName());
-		
-		List<Map<String, String>> rows = productionShockReader.query(queryMap);
-		for (Map<String, String> row : rows) {
-		String cropTypeS = row.get("crop");
-		String shockFactorS = row.get("shockFactor");
-		CropType crop = CropType.getForFaoName(cropTypeS);
-		Double shockFactor = Double.valueOf(shockFactorS);
-
-		LogWriter.println("Got production shock at " + timestep + ": " + cc.getName() + " " + cropTypeS + " " + shockFactorS);
-		
-		shocks.put(crop, shockFactor);
-		}
-		return shocks;
-
-	}
-
-}
diff --git a/src/ac/ed/lurg/shock/YieldShockManager.java b/src/ac/ed/lurg/shock/YieldShockManager.java
index 93a780f9..862b6715 100644
--- a/src/ac/ed/lurg/shock/YieldShockManager.java
+++ b/src/ac/ed/lurg/shock/YieldShockManager.java
@@ -25,7 +25,7 @@ public class YieldShockManager {
 	public YieldShockManager (RasterHeaderDetails desiredProjection) {
 		this.desiredProjection = desiredProjection;
 		String shockFile = ModelConfig.YIELDSHOCKS_PARAMETER_FILE;
-		yieldShockReader = new StringTabularReader(",", new String[]{"year", "mapFilename", "crop", "shockFactor", "region"});
+		yieldShockReader = new StringTabularReader(",", new String[]{"year", "mapFilename", "crop", "shockFactor"});
 
 		if (new File(shockFile).isFile()) 
 			yieldShockReader.read(shockFile);
-- 
GitLab