Advertisement
docarrol

Untitled

Feb 1st, 2015
225
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 8.36 KB | None | 0 0
  1. package weather;
  2.  
  3. import java.util.Random;
  4.  
  5. public class Weather {
  6.  
  7. public static enum WeatherState {
  8. CLEAR, CLOUDY, RAINING;
  9.  
  10. private final static WeatherState[] weatherStateValues = WeatherState.values();
  11.  
  12. public static WeatherState fromInteger(int i) {
  13. return weatherStateValues[i];
  14. }
  15. }
  16.  
  17. // Change these to fine tune the day to day weather transition
  18. private static double[][] transitionTable = {{0.625, 0.300, 0.075}, // 0.625 + 0.300 + 0.075 = 1.000
  19. {0.400, 0.400, 0.200}, // 0.400 + 0.400 + 0.200 = 1.000
  20. {0.800, 0.050, 0.150}};// 0.800 + 0.050 + 0.150 = 1.000
  21.  
  22. // Change these to fine tune the seasonal variation
  23. private static final double tempPhaseShift = 0.0; // Horizontal adjustment. Max temp in summer
  24. private static final double yearlyTempMax = 25.0; // degC
  25. private static final double yearlyTempMin = -5.0; // degC
  26. private static final double yearlyTempAverage = (yearlyTempMax + yearlyTempMin) / 2; // degC => vertical adjustment of sine wave
  27. private static final double yearlyTempVariation = (yearlyTempMax - yearlyTempMin) / 2; // +/- degC => amplitude of sine wave
  28.  
  29. private static final double precipPhaseShift = Math.PI; // Horizontal adjustment. Max precip in winter
  30. private static final double yearlyPrecipMax = 0.075; // % chance
  31. private static final double yearlyPrecipMin = -0.075; // % chance
  32. private static final double yearlyPrecipAverage = (yearlyPrecipMax + yearlyPrecipMin) / 2; // vertical adjustment of sine wave
  33. private static final double yearlyPrecipVariation = (yearlyPrecipMax - yearlyPrecipMin) / 2; // amplitude of sine wave
  34.  
  35.  
  36. public static double seasonalAdjustment(int dayOfYear, double phaseShift ) {
  37. // Assuming there are 365 days in a year
  38. dayOfYear = dayOfYear % 365; // Modulo, to put it back in the range of 0-365
  39. double degrees = 360.0 * ((double) dayOfYear / 365.0); // Convert days to degrees
  40.  
  41. return Math.sin(Math.toRadians(degrees) + phaseShift); // Get the sine and shift horizontally
  42. }
  43.  
  44. public static double tempAdjustment(int dayOfYear) {
  45. // Scale the amplitude and shift vertically
  46. return (seasonalAdjustment(dayOfYear, tempPhaseShift) * yearlyTempVariation) + yearlyTempAverage;
  47. }
  48.  
  49. public static double precipAdjustment(int dayOfYear) {
  50. // Scale the amplitude and shift vertically
  51. return (seasonalAdjustment(dayOfYear, precipPhaseShift) * yearlyPrecipVariation) + yearlyPrecipAverage;
  52. }
  53.  
  54. public static double nextTemperature(int dayOfYear) {
  55. return tempAdjustment(dayOfYear + 1);
  56. }
  57.  
  58. public static WeatherState nextWeatherState(WeatherState currentWeather, int dayOfYear, double nextTemp) {
  59. Random rand = new Random();
  60. WeatherState nextWeather = WeatherState.CLEAR;
  61.  
  62. double precipAdjustment = precipAdjustment(dayOfYear);
  63.  
  64. // Create an empty table, all cells initialized to 0.0
  65. double[][] adjustedTable = new double[transitionTable.length][transitionTable[0].length];
  66. for(int i = 0; i < adjustedTable.length; i++) {
  67. double subtotal = 0.0;
  68.  
  69. // Adjust the chance for Cloudy and Raining, etc.
  70. for(int j = 1; j < adjustedTable[i].length; j++) {
  71. // Check for boundary conditions
  72. if(transitionTable[i][j] + precipAdjustment < 0.0) {
  73. adjustedTable[i][j] = 0.0;
  74. } else if(transitionTable[i][j] + precipAdjustment > 1.0) {
  75. adjustedTable[i][j] = 1.0;
  76. } else {
  77. adjustedTable[i][j] = transitionTable[i][j] + precipAdjustment;
  78. }
  79. }
  80.  
  81. // If any of them get to 1.0, the rest, by definition, must all equal 0.0
  82. for(int j = adjustedTable[i].length - 1; j > 0; j--) {
  83. if(adjustedTable[i][j] == 1.0) {
  84. for(int k = 1; k < adjustedTable[i].length; k++) {
  85. if(k != j) {
  86. adjustedTable[i][k] = 0.0;
  87. }
  88. }
  89. }
  90. subtotal += adjustedTable[i][j];
  91. }
  92.  
  93. // The row must sum to 1.0. Adjust the chance for Clear
  94. // Check for boundary conditions
  95. if(1.0 - subtotal < 0.0) {
  96. adjustedTable[i][0] = 0.0;
  97. } else if(1.0 - subtotal > 1.0) {
  98. adjustedTable[i][0] = 1.0;
  99. } else {
  100. adjustedTable[i][0] = 1.0 - subtotal;
  101. }
  102. }
  103.  
  104. double probability = 0.0;
  105. double sum = 0.0;
  106.  
  107. int row = currentWeather.ordinal();
  108. for(int column = 0; column < adjustedTable[row].length; column++) {
  109. probability = rand.nextDouble();
  110. sum += adjustedTable[row][column];
  111.  
  112. if(probability <= sum) {
  113. nextWeather = WeatherState.fromInteger(column);
  114. break;
  115. }
  116. }
  117.  
  118. return nextWeather;
  119. }
  120.  
  121. public static String describeState(WeatherState state, double temp) {
  122. String stateDescription = "";
  123.  
  124. if(state == WeatherState.RAINING && temp <= 0.0) {
  125. stateDescription = "Snowing"; // A special case
  126. } else {
  127. stateDescription = state.name();
  128. // Capitalize the first letter
  129. stateDescription = stateDescription.substring(0,1).toUpperCase()
  130. + stateDescription.substring(1,stateDescription.length()).toLowerCase();
  131. }
  132.  
  133. return stateDescription;
  134. }
  135.  
  136. public static final double dayPeriod = 24.0;
  137. public static final double solarYear = 365.2425; // this accounts for leap-years & leap-centuries
  138.  
  139. public double dayLength(int dayOfYear) {
  140. double d_sun = dayOfYear / solarYear;
  141.  
  142. // assume latitude ~= 45deg
  143. // the time from sunrise to noon on the equinox
  144. return 2 * (((dayPeriod / 4) - 1.53 * Math.cos(2 * Math.PI * d_sun)) + 0.15 * Math.sin(4 * Math.PI * d_sun));
  145. }
  146.  
  147. public double nightLength(int dayOfYear) {
  148. return dayPeriod - dayLength(dayOfYear);
  149. }
  150.  
  151. public double calcSunrise(int dayOfYear) {
  152. double noon = dayPeriod / 2;
  153. return noon - (dayLength(dayOfYear) / 2);
  154. }
  155.  
  156. public double calcSunset(int dayOfYear) {
  157. double noon = dayPeriod / 2;
  158. return noon + (dayLength(dayOfYear) / 2);
  159. }
  160.  
  161. public static final double lunarPeriod = 24 + (50 / 60); // orbital period = 24:50, the time it takes for the moon to be in the same place in the sky
  162. public static final double lunarMonth = 28.8; // days in a lunar month
  163.  
  164. public double moonUpLength(int dayOfYear) {
  165. int dayOfLunarMonth = (int) ((dayOfYear / lunarPeriod) % lunarMonth);
  166. double d_moon = dayOfLunarMonth / lunarMonth;
  167.  
  168. // assume latitude ~= 45deg
  169. // the time from moonrise to highMoon, when the moon up/down ratio is equal.
  170. return 2 * (((lunarPeriod / 4) - 1.53 * Math.cos(2 * Math.PI * d_moon)) + 0.15 * Math.sin(4 * Math.PI * d_moon));
  171. }
  172.  
  173. public double moonDownLength(int dayOfYear) {
  174. return lunarPeriod - moonUpLength(dayOfYear);
  175. }
  176.  
  177. public double calcMoonrise(int dayOfYear) {
  178. double highMoon = ((int) (dayOfYear * dayPeriod / lunarPeriod)) % dayPeriod;
  179.  
  180. double time = highMoon - moonUpLength(dayOfYear) / 2;
  181.  
  182. if(time < 0.0 || time > 24.0) { // if it would happen yesterday or tomorrow
  183. time = -1; // set to -1 if out of bounds
  184. }
  185.  
  186. return time;
  187. }
  188.  
  189. public double calcMoonset(int dayOfYear) {
  190. double highMoon = ((int) (dayOfYear * dayPeriod / lunarPeriod)) % dayPeriod;
  191.  
  192. double time = highMoon + moonUpLength(dayOfYear) / 2;
  193.  
  194. if(time < 0.0 || time > 24.0) { // if it would happen yesterday or tomorrow
  195. time = -1; // set to -1 if out of bounds
  196. }
  197.  
  198. return time;
  199. }
  200.  
  201. public static void main(String args[]) {
  202. double currentTemp = tempAdjustment(0);
  203. double nextTemp = nextTemperature(0);
  204.  
  205. WeatherState currentState = WeatherState.CLEAR;
  206. WeatherState nextState = nextWeatherState(currentState, 0, nextTemp);
  207.  
  208. for(int i = 0; i < limit; i++) {
  209. // Do today's stuff
  210.  
  211. // Display in all outdoor locations
  212. System.out.println("Today is " + String.format("%.2f", currentTemp) + "degC, and "
  213. + describeState(currentState, currentTemp) + ".");
  214. // Normally hidden from the player, but potentially useful for planning purposes
  215. System.out.println("Tomorrow is expected to be : "
  216. + String.format("%.2f", nextTemp) + "degC, and "
  217. + describeState(nextState, nextTemp) + ".");
  218. // You could learn a "weather prediction" skill, or get a newspaper with tomorrow's prediction or something
  219.  
  220. // Night-time transition to the next day
  221. double tempTemp = nextTemp;
  222. nextTemp = nextTemperature(dayOfYear);
  223. currentTemp = tempTemp;
  224.  
  225. WeatherState tempState = nextState;
  226. nextState = nextWeatherState(currentState, dayOfYear, nextTemp); // Get a new nextState for the day after
  227. currentState = tempState; // Tomorrow becomes today, so the nextState becomes the currentState
  228. }
  229. }
  230. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement