Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- package weather;
- import java.util.Random;
- public class Weather {
- public static enum WeatherState {
- CLEAR, CLOUDY, RAINING;
- private final static WeatherState[] weatherStateValues = WeatherState.values();
- public static WeatherState fromInteger(int i) {
- return weatherStateValues[i];
- }
- }
- // Change these to fine tune the day to day weather transition
- private static double[][] transitionTable = {{0.625, 0.300, 0.075}, // 0.625 + 0.300 + 0.075 = 1.000
- {0.400, 0.400, 0.200}, // 0.400 + 0.400 + 0.200 = 1.000
- {0.800, 0.050, 0.150}};// 0.800 + 0.050 + 0.150 = 1.000
- // Change these to fine tune the seasonal variation
- private static final double tempPhaseShift = 0.0; // Horizontal adjustment. Max temp in summer
- private static final double yearlyTempMax = 25.0; // degC
- private static final double yearlyTempMin = -5.0; // degC
- private static final double yearlyTempAverage = (yearlyTempMax + yearlyTempMin) / 2; // degC => vertical adjustment of sine wave
- private static final double yearlyTempVariation = (yearlyTempMax - yearlyTempMin) / 2; // +/- degC => amplitude of sine wave
- private static final double precipPhaseShift = Math.PI; // Horizontal adjustment. Max precip in winter
- private static final double yearlyPrecipMax = 0.075; // % chance
- private static final double yearlyPrecipMin = -0.075; // % chance
- private static final double yearlyPrecipAverage = (yearlyPrecipMax + yearlyPrecipMin) / 2; // vertical adjustment of sine wave
- private static final double yearlyPrecipVariation = (yearlyPrecipMax - yearlyPrecipMin) / 2; // amplitude of sine wave
- public static double seasonalAdjustment(int dayOfYear, double phaseShift ) {
- // Assuming there are 365 days in a year
- dayOfYear = dayOfYear % 365; // Modulo, to put it back in the range of 0-365
- double degrees = 360.0 * ((double) dayOfYear / 365.0); // Convert days to degrees
- return Math.sin(Math.toRadians(degrees) + phaseShift); // Get the sine and shift horizontally
- }
- public static double tempAdjustment(int dayOfYear) {
- // Scale the amplitude and shift vertically
- return (seasonalAdjustment(dayOfYear, tempPhaseShift) * yearlyTempVariation) + yearlyTempAverage;
- }
- public static double precipAdjustment(int dayOfYear) {
- // Scale the amplitude and shift vertically
- return (seasonalAdjustment(dayOfYear, precipPhaseShift) * yearlyPrecipVariation) + yearlyPrecipAverage;
- }
- public static double nextTemperature(int dayOfYear) {
- return tempAdjustment(dayOfYear + 1);
- }
- public static WeatherState nextWeatherState(WeatherState currentWeather, int dayOfYear, double nextTemp) {
- Random rand = new Random();
- WeatherState nextWeather = WeatherState.CLEAR;
- double precipAdjustment = precipAdjustment(dayOfYear);
- // Create an empty table, all cells initialized to 0.0
- double[][] adjustedTable = new double[transitionTable.length][transitionTable[0].length];
- for(int i = 0; i < adjustedTable.length; i++) {
- double subtotal = 0.0;
- // Adjust the chance for Cloudy and Raining, etc.
- for(int j = 1; j < adjustedTable[i].length; j++) {
- // Check for boundary conditions
- if(transitionTable[i][j] + precipAdjustment < 0.0) {
- adjustedTable[i][j] = 0.0;
- } else if(transitionTable[i][j] + precipAdjustment > 1.0) {
- adjustedTable[i][j] = 1.0;
- } else {
- adjustedTable[i][j] = transitionTable[i][j] + precipAdjustment;
- }
- }
- // If any of them get to 1.0, the rest, by definition, must all equal 0.0
- for(int j = adjustedTable[i].length - 1; j > 0; j--) {
- if(adjustedTable[i][j] == 1.0) {
- for(int k = 1; k < adjustedTable[i].length; k++) {
- if(k != j) {
- adjustedTable[i][k] = 0.0;
- }
- }
- }
- subtotal += adjustedTable[i][j];
- }
- // The row must sum to 1.0. Adjust the chance for Clear
- // Check for boundary conditions
- if(1.0 - subtotal < 0.0) {
- adjustedTable[i][0] = 0.0;
- } else if(1.0 - subtotal > 1.0) {
- adjustedTable[i][0] = 1.0;
- } else {
- adjustedTable[i][0] = 1.0 - subtotal;
- }
- }
- double probability = 0.0;
- double sum = 0.0;
- int row = currentWeather.ordinal();
- for(int column = 0; column < adjustedTable[row].length; column++) {
- probability = rand.nextDouble();
- sum += adjustedTable[row][column];
- if(probability <= sum) {
- nextWeather = WeatherState.fromInteger(column);
- break;
- }
- }
- return nextWeather;
- }
- public static String describeState(WeatherState state, double temp) {
- String stateDescription = "";
- if(state == WeatherState.RAINING && temp <= 0.0) {
- stateDescription = "Snowing"; // A special case
- } else {
- stateDescription = state.name();
- // Capitalize the first letter
- stateDescription = stateDescription.substring(0,1).toUpperCase()
- + stateDescription.substring(1,stateDescription.length()).toLowerCase();
- }
- return stateDescription;
- }
- public static final double dayPeriod = 24.0;
- public static final double solarYear = 365.2425; // this accounts for leap-years & leap-centuries
- public double dayLength(int dayOfYear) {
- double d_sun = dayOfYear / solarYear;
- // assume latitude ~= 45deg
- // the time from sunrise to noon on the equinox
- return 2 * (((dayPeriod / 4) - 1.53 * Math.cos(2 * Math.PI * d_sun)) + 0.15 * Math.sin(4 * Math.PI * d_sun));
- }
- public double nightLength(int dayOfYear) {
- return dayPeriod - dayLength(dayOfYear);
- }
- public double calcSunrise(int dayOfYear) {
- double noon = dayPeriod / 2;
- return noon - (dayLength(dayOfYear) / 2);
- }
- public double calcSunset(int dayOfYear) {
- double noon = dayPeriod / 2;
- return noon + (dayLength(dayOfYear) / 2);
- }
- 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
- public static final double lunarMonth = 28.8; // days in a lunar month
- public double moonUpLength(int dayOfYear) {
- int dayOfLunarMonth = (int) ((dayOfYear / lunarPeriod) % lunarMonth);
- double d_moon = dayOfLunarMonth / lunarMonth;
- // assume latitude ~= 45deg
- // the time from moonrise to highMoon, when the moon up/down ratio is equal.
- return 2 * (((lunarPeriod / 4) - 1.53 * Math.cos(2 * Math.PI * d_moon)) + 0.15 * Math.sin(4 * Math.PI * d_moon));
- }
- public double moonDownLength(int dayOfYear) {
- return lunarPeriod - moonUpLength(dayOfYear);
- }
- public double calcMoonrise(int dayOfYear) {
- double highMoon = ((int) (dayOfYear * dayPeriod / lunarPeriod)) % dayPeriod;
- double time = highMoon - moonUpLength(dayOfYear) / 2;
- if(time < 0.0 || time > 24.0) { // if it would happen yesterday or tomorrow
- time = -1; // set to -1 if out of bounds
- }
- return time;
- }
- public double calcMoonset(int dayOfYear) {
- double highMoon = ((int) (dayOfYear * dayPeriod / lunarPeriod)) % dayPeriod;
- double time = highMoon + moonUpLength(dayOfYear) / 2;
- if(time < 0.0 || time > 24.0) { // if it would happen yesterday or tomorrow
- time = -1; // set to -1 if out of bounds
- }
- return time;
- }
- public static void main(String args[]) {
- double currentTemp = tempAdjustment(0);
- double nextTemp = nextTemperature(0);
- WeatherState currentState = WeatherState.CLEAR;
- WeatherState nextState = nextWeatherState(currentState, 0, nextTemp);
- for(int i = 0; i < limit; i++) {
- // Do today's stuff
- // Display in all outdoor locations
- System.out.println("Today is " + String.format("%.2f", currentTemp) + "degC, and "
- + describeState(currentState, currentTemp) + ".");
- // Normally hidden from the player, but potentially useful for planning purposes
- System.out.println("Tomorrow is expected to be : "
- + String.format("%.2f", nextTemp) + "degC, and "
- + describeState(nextState, nextTemp) + ".");
- // You could learn a "weather prediction" skill, or get a newspaper with tomorrow's prediction or something
- // Night-time transition to the next day
- double tempTemp = nextTemp;
- nextTemp = nextTemperature(dayOfYear);
- currentTemp = tempTemp;
- WeatherState tempState = nextState;
- nextState = nextWeatherState(currentState, dayOfYear, nextTemp); // Get a new nextState for the day after
- currentState = tempState; // Tomorrow becomes today, so the nextState becomes the currentState
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement