/farmR/src/java/src/jfm/model/Location.java

https://code.google.com/p/javawfm/ · Java · 352 lines · 267 code · 26 blank · 59 comment · 9 complexity · 5c675c319d4f7ec366dab904cbfebd3c MD5 · raw file

  1. package jfm.model;
  2. import java.util.*;
  3. import jfm.model.Types.VariableType;
  4. import jfm.model.WorkableHoursCalculator;
  5. import jfm.xml.XMLSyntaxException;
  6. /** Representation of physical characteristics of the farm such as soiltype and rainfall.
  7. * Defines functions for calculating location dependent variables such as the number of workable hours
  8. * available in particular periods of the year
  9. * @author Ira Cooke
  10. * \todo fix the Location class. Make it immutable (Important so that updates are done correctly) */
  11. public final class Location extends VariableHolder {
  12. // private double soiltype;
  13. // private double rainfall;
  14. // private double summernetevap;
  15. private final int numPeriods;
  16. private final double[] hoursCache;
  17. private final double[] freeTimeHoursCache;
  18. public Location(double st,double rf,int numPeriods_){
  19. setVariable(VariableType.SOILTYPE,st);
  20. setVariable(VariableType.RAINFALL,rf);
  21. numPeriods=numPeriods_;
  22. hoursCache=new double[numPeriods];
  23. freeTimeHoursCache=new double[numPeriods];
  24. refreshHoursCache();
  25. }
  26. public Location copy(){
  27. return new Location(getVariable(VariableType.SOILTYPE),getVariable(VariableType.RAINFALL),numPeriods);
  28. }
  29. private static HashMap<Integer,double[] > freeTimeHoursMap = new HashMap<Integer,double[]>();
  30. static{
  31. double[] hours26=new double[26];
  32. hours26[0]=80;
  33. hours26[1]=80;
  34. hours26[2]=80;
  35. hours26[3]=80;
  36. hours26[4]=85;
  37. hours26[5]=90;
  38. hours26[6]=100;
  39. hours26[7]=110;
  40. hours26[8]=120;
  41. hours26[9]=120;
  42. hours26[10]=120;
  43. hours26[11]=120;
  44. hours26[12]=120;
  45. hours26[13]=120;
  46. hours26[14]=120;
  47. hours26[15]=120;
  48. hours26[16]=120;
  49. hours26[17]=120;
  50. hours26[18]=120;
  51. hours26[19]=110;
  52. hours26[20]=100;
  53. hours26[21]=90;
  54. hours26[22]=90;
  55. hours26[23]=90;
  56. hours26[24]=90;
  57. hours26[25]=90;
  58. double[] hours13=new double[13];
  59. for(int i=0;i<13;i++){
  60. hours13[i]=hours26[i*2]+hours26[i*2+1];
  61. }
  62. double[] hours2=new double[2];
  63. hours2[0]=140*13;
  64. hours2[1]=140*13;
  65. freeTimeHoursMap.put(26, hours26);
  66. freeTimeHoursMap.put(13,hours13);
  67. freeTimeHoursMap.put(2, hours2);
  68. }
  69. private static HashMap<Integer,double[] > hoursMap = new HashMap<Integer,double[]>();
  70. static{
  71. double[] hours26=new double[26];
  72. double[] hours13=new double[13];
  73. double[] hours2=new double[2];
  74. /*
  75. hours26[0]=51;
  76. hours26[1]=51;
  77. hours26[2]=50;
  78. hours26[3]=50;
  79. hours26[4]=78;
  80. hours26[5]=78;
  81. hours26[6]=88;
  82. hours26[7]=88;
  83. hours26[8]=118;
  84. hours26[9]=118;
  85. hours26[10]=120.4;
  86. hours26[11]=122.4;
  87. hours26[12]=125.4;
  88. hours26[13]=125.4;
  89. hours26[14]=118.4;
  90. hours26[15]=118.6;
  91. hours26[16]=110.6;
  92. hours26[17]=110.6;
  93. hours26[18]=110.6;
  94. hours26[19]=91.0;
  95. hours26[20]=79.8;
  96. hours26[21]=69.5;
  97. hours26[22]=56.3;
  98. hours26[23]=36.1;
  99. hours26[24]=36.9;
  100. hours26[25]=36.7;
  101. */
  102. hours26[0]=0.0;
  103. hours26[1]=0.0;
  104. hours26[2]=0.0;
  105. hours26[3]=0.7;
  106. hours26[4]=20.0;
  107. hours26[5]=47.8;
  108. hours26[6]=75.7;
  109. hours26[7]=103.5;
  110. hours26[8]=118.4;
  111. hours26[9]=118.4;
  112. hours26[10]=118.4;
  113. hours26[11]=118.4;
  114. hours26[12]=118.4;
  115. hours26[13]=118.4;
  116. hours26[14]=118.4;
  117. hours26[15]=117.3;
  118. hours26[16]=114.5;
  119. hours26[17]=100.0;
  120. hours26[18]=86.1;
  121. hours26[19]=72.3;
  122. hours26[20]=58.4;
  123. hours26[21]=44.6;
  124. hours26[22]=30.7;
  125. hours26[23]=16.9;
  126. hours26[24]=3.6;
  127. hours26[25]=0.0;
  128. for ( int i=0;i<13;i++){
  129. hours13[i]=hours26[2*i]+hours26[2*i+1];
  130. }
  131. for( int i=0;i<2;i++){
  132. hours2[i]=0;
  133. for ( int j=0;j<13;j++){
  134. hours2[i]+=hours26[i*13+j];
  135. }
  136. }
  137. hoursMap.put(26, hours26);
  138. hoursMap.put(13, hours13);
  139. hoursMap.put(2, hours2);
  140. }
  141. public static HashMap<String,Integer> month=new HashMap<String,Integer>();
  142. static {
  143. month.put("Jan",0);
  144. month.put("Feb",1);
  145. month.put("Mar",2);
  146. month.put("Apr",3);
  147. month.put("May",4);
  148. month.put("Jun",5);
  149. month.put("Jul",6);
  150. month.put("Aug",7);
  151. month.put("Sep",8);
  152. month.put("Oct",9);
  153. month.put("Nov",10);
  154. month.put("Dec",11);
  155. }
  156. /** In order to provide compatibility with the WFM this class is needed.
  157. * Each date represents the first day in a given period. The periods given are
  158. * unfolded periodic .. in order to fold use period-(year-1)*26 */
  159. public static ArrayList<GregorianCalendar> periods26=new ArrayList<GregorianCalendar>();
  160. static {
  161. periods26.add(new GregorianCalendar(2000,month.get("Jul"),16,0,0));//14
  162. periods26.add(new GregorianCalendar(2000,month.get("Jul"),30,0,0));//15
  163. periods26.add(new GregorianCalendar(2000,month.get("Aug"),13,0,0));//16
  164. periods26.add(new GregorianCalendar(2000,month.get("Aug"),27,0,0));//17
  165. periods26.add(new GregorianCalendar(2000,month.get("Sep"),10,0,0));//18
  166. periods26.add(new GregorianCalendar(2000,month.get("Sep"),24,0,0));//19
  167. periods26.add(new GregorianCalendar(2000,month.get("Oct"),8,0,0));//20
  168. periods26.add(new GregorianCalendar(2000,month.get("Oct"),22,0,0));//21
  169. periods26.add(new GregorianCalendar(2000,month.get("Nov"),5,0,0));//22
  170. periods26.add(new GregorianCalendar(2000,month.get("Nov"),19,0,0));//23
  171. periods26.add(new GregorianCalendar(2000,month.get("Dec"),3,0,0));//24
  172. periods26.add(new GregorianCalendar(2000,month.get("Dec"),17,0,0));//25
  173. periods26.add(new GregorianCalendar(2001,month.get("Jan"),1,0,0));//26
  174. periods26.add(new GregorianCalendar(2001,month.get("Jan"),15,0,0));//27
  175. periods26.add(new GregorianCalendar(2001,month.get("Jan"),29,0,0));//28
  176. periods26.add(new GregorianCalendar(2001,month.get("Feb"),12,0,0));//29
  177. periods26.add(new GregorianCalendar(2001,month.get("Feb"),26,0,0));//30
  178. periods26.add(new GregorianCalendar(2001,month.get("Mar"),12,0,0));//31
  179. periods26.add(new GregorianCalendar(2001,month.get("Mar"),26,0,0));//32
  180. periods26.add(new GregorianCalendar(2001,month.get("Apr"),9,0,0));//33
  181. periods26.add(new GregorianCalendar(2001,month.get("Apr"),23,0,0));//34
  182. periods26.add(new GregorianCalendar(2001,month.get("May"),7,0,0));//35
  183. periods26.add(new GregorianCalendar(2001,month.get("May"),21,0,0));//36
  184. periods26.add(new GregorianCalendar(2001,month.get("Jun"),4,0,0));//37
  185. periods26.add(new GregorianCalendar(2001,month.get("Jun"),18,0,0));//38
  186. periods26.add(new GregorianCalendar(2001,month.get("Jul"),1,0,0));//39
  187. periods26.add(new GregorianCalendar(2001,month.get("Jul"),16,0,0));//40
  188. periods26.add(new GregorianCalendar(2001,month.get("Jul"),30,0,0));//41
  189. periods26.add(new GregorianCalendar(2001,month.get("Aug"),13,0,0));//42
  190. periods26.add(new GregorianCalendar(2001,month.get("Aug"),27,0,0));//43
  191. periods26.add(new GregorianCalendar(2001,month.get("Sep"),10,0,0));//44
  192. periods26.add(new GregorianCalendar(2001,month.get("Sep"),24,0,0));//45
  193. periods26.add(new GregorianCalendar(2001,month.get("Oct"),8,0,0));//46
  194. periods26.add(new GregorianCalendar(2001,month.get("Oct"),22,0,0));//47
  195. periods26.add(new GregorianCalendar(2001,month.get("Nov"),5,0,0));//48
  196. periods26.add(new GregorianCalendar(2001,month.get("Nov"),19,0,0));//49
  197. periods26.add(new GregorianCalendar(2001,month.get("Dec"),3,0,0));//50
  198. periods26.add(new GregorianCalendar(2001,month.get("Dec"),16,0,0));//51
  199. }
  200. /** In order to provide compatibility with the WFM this class is needed.
  201. * Each date represents the first day in a given period. The periods given are
  202. * unfolded periodic .. in order to fold use period-(year-1)*26 */
  203. public static ArrayList<GregorianCalendar> periods13=new ArrayList<GregorianCalendar>();
  204. static {
  205. periods13.add(new GregorianCalendar(2000,month.get("Jul"),16,0,0));//7
  206. periods13.add(new GregorianCalendar(2000,month.get("Aug"),13,0,0));//8
  207. periods13.add(new GregorianCalendar(2000,month.get("Sep"),10,0,0));//9
  208. periods13.add(new GregorianCalendar(2000,month.get("Oct"),8,0,0));//10
  209. periods13.add(new GregorianCalendar(2000,month.get("Nov"),5,0,0));//11
  210. periods13.add(new GregorianCalendar(2000,month.get("Dec"),3,0,0));//12
  211. periods13.add(new GregorianCalendar(2001,month.get("Jan"),1,0,0));//13
  212. periods13.add(new GregorianCalendar(2001,month.get("Jan"),29,0,0));//14
  213. periods13.add(new GregorianCalendar(2001,month.get("Feb"),26,0,0));//15
  214. periods13.add(new GregorianCalendar(2001,month.get("Mar"),26,0,0));//16
  215. periods13.add(new GregorianCalendar(2001,month.get("Apr"),23,0,0));//17
  216. periods13.add(new GregorianCalendar(2001,month.get("May"),21,0,0));//18
  217. periods13.add(new GregorianCalendar(2001,month.get("Jun"),18,0,0));//19
  218. periods13.add(new GregorianCalendar(2001,month.get("Jul"),16,0,0));//20
  219. periods13.add(new GregorianCalendar(2001,month.get("Aug"),13,0,0));//21
  220. periods13.add(new GregorianCalendar(2001,month.get("Sep"),10,0,0));//22
  221. periods13.add(new GregorianCalendar(2001,month.get("Oct"),8,0,0));//23
  222. periods13.add(new GregorianCalendar(2001,month.get("Nov"),5,0,0));//24
  223. periods13.add(new GregorianCalendar(2001,month.get("Dec"),3,0,0));//25
  224. }
  225. public static ArrayList<GregorianCalendar> periods2=new ArrayList<GregorianCalendar>();
  226. static {
  227. periods2.add(new GregorianCalendar(2000,month.get("Jul"),16,0,0));//14
  228. periods2.add(new GregorianCalendar(2001,month.get("Jan"),15,0,0));//27
  229. }
  230. public static HashMap<Integer,ArrayList<GregorianCalendar>> periodsmap=new HashMap<Integer,ArrayList<GregorianCalendar>>();
  231. static{
  232. periodsmap.put(26,periods26);
  233. periodsmap.put(13,periods13);
  234. periodsmap.put(2,periods2);
  235. }
  236. public static int getWFMPeriod(GregorianCalendar caldate,int nperiods) throws XMLSyntaxException {
  237. ArrayList<GregorianCalendar> periods = periodsmap.get(nperiods);
  238. int wfmp;
  239. switch(nperiods){
  240. case 26:
  241. wfmp=14;
  242. break;
  243. case 13:
  244. wfmp=7;
  245. break;
  246. default:
  247. throw new XMLSyntaxException("Allowed numbers of periods are 2 26 or 13");
  248. }
  249. for(GregorianCalendar startperiod:periods ) {
  250. if(!startperiod.before(caldate)){
  251. return wfmp;
  252. }
  253. wfmp++;
  254. }
  255. throw new XMLSyntaxException("Date is outside WFM period range");
  256. }
  257. private double numberOfHoursInPeriodWithPeriods(int per,int numPeriods){
  258. int numPer = periodsmap.get(numPeriods).size();
  259. int offset=0;
  260. switch(numPeriods){
  261. case 26:
  262. offset=12;
  263. break;
  264. case 13:
  265. offset=6;
  266. break;
  267. case 2:
  268. offset=1;
  269. break;
  270. default:
  271. throw new Error("Allowed numbers of periods are 2 26 13");
  272. }
  273. per=per+offset;
  274. GregorianCalendar dstart;
  275. GregorianCalendar dfinish;
  276. // if ( per > numPer-1 ){
  277. // dstart=periodsmap.get(numPeriods).get(per-numPer);
  278. // } else {
  279. dstart = periodsmap.get(numPeriods).get(per);
  280. // }
  281. if ( per > numPer-2 ){
  282. dfinish=periodsmap.get(numPeriods).get(offset);
  283. } else {
  284. dfinish = periodsmap.get(numPeriods).get(per+1);
  285. }
  286. // System.out.println("Start p "+dstart.get(GregorianCalendar.DAY_OF_YEAR)+" end: "+dfinish.get(GregorianCalendar.DAY_OF_YEAR));
  287. return WorkableHoursCalculator.workableHours(dstart.get(GregorianCalendar.DAY_OF_YEAR), dfinish.get(GregorianCalendar.DAY_OF_YEAR),getVariable(VariableType.SOILTYPE),getVariable(VariableType.RAINFALL));
  288. }
  289. private void refreshHoursCache(){
  290. // System.out.println("Refreshing Hours Cache with: soil "+getVariable(VariableType.SOILTYPE)+" rf "+getVariable(VariableType.RAINFALL));
  291. for(int i=0;i<hoursCache.length;i++){
  292. // This is old code for when we needed to use fixed values
  293. // hoursCache[i]=hoursMap.get(numPeriods)[i];
  294. hoursCache[i]=numberOfHoursInPeriodWithPeriods(i,numPeriods);
  295. // System.out.println("Num Hours in period "+i+" "+hoursCache[i]+" "+freeTimeHoursMap.get(numPeriods)[i]);
  296. freeTimeHoursCache[i]=freeTimeHoursMap.get(numPeriods)[i];
  297. }
  298. }
  299. /*
  300. public double soiltype(){
  301. return soiltype;
  302. }
  303. public double rainfall(){
  304. return rainfall;
  305. }*/
  306. public double availableHours(int period){
  307. // System.out.println("In period "+period+" we get "+hoursCache[period]);
  308. return hoursCache[period];
  309. }
  310. public double availableFreeTimeHours(int period){
  311. return freeTimeHoursCache[period];
  312. }
  313. public void setSoilType(double soil){
  314. setVariable(VariableType.SOILTYPE,soil);
  315. refreshHoursCache();
  316. }
  317. public void setRainFall(double rain){
  318. setVariable(VariableType.RAINFALL,rain);
  319. refreshHoursCache();
  320. }
  321. public void set(double sl,double rn){
  322. setVariable(VariableType.SOILTYPE,sl);
  323. setVariable(VariableType.RAINFALL,rn);
  324. refreshHoursCache();
  325. }
  326. }