private SDate dayToSDate(int day) { int initialYearStart = (initialDate.Year - 1) * 112 + 1; int initialDay = initialDate.DaysSinceStart - initialYearStart; int offset = (day < initialDay) ? 112 : 0; return(SDate.FromDaysSinceStart(initialYearStart + day + offset)); }
// Finds the next Garbage Hat to be available on or after the given date. public static Prediction?FindGarbageHat(SDate fromDate) { for (int days = fromDate.DaysSinceStart; days < fromDate.DaysSinceStart + Utilities.MaxHorizon; ++days) { List <Prediction> predictions = ListLootForDate(SDate.FromDaysSinceStart(days), true) .Where((p) => p.loot is Hat).ToList(); if (predictions.Count > 0) { return(predictions[0]); } } return(null); }
// Lists the next several trains to arrive on or after the given date, // up to the given limit. public static List <Prediction> ListNextTrainsFromDate(SDate fromDate, uint limit) { Utilities.CheckWorldReady(); if (!IsAvailable) { throw new UnavailableException("trains"); } // Logic from StardewValley.Locations.Railroad.DayUpdate() // as implemented in Stardew Predictor by MouseyPounds. List <Prediction> predictions = new (); for (int days = Math.Max(fromDate.DaysSinceStart, 31); predictions.Count < limit && days < fromDate.DaysSinceStart + Utilities.MaxHorizon; ++days) { Random rng = new (((int)Game1.uniqueIDForThisGame / 2) + days); if (!(rng.NextDouble() < 0.2)) { continue; } int time = rng.Next(900, 1800); time -= time % 10; if (time % 100 >= 60) { continue; } // No train on the first day after loading the game. SDate date = SDate.FromDaysSinceStart(days); if (date == Utilities.LoadDate) { continue; } predictions.Add(new Prediction { date = date, time = time }); } return(predictions); }
/// <summary>Print the UV value (no scaling) and UV index high for a specific date (int days since start).</summary> /// <param name="_command">The name of the command invoked.</param> /// <param name="_args">The arguments received by the command. Each word after the command name is a separate argument.</param> private static void getUV(string _command, string[] _args) { try { int days; int dailyMaxUV; int uvIndex; if (_args.Length > 0) { days = int.Parse(_args[0]); SDate date = SDate.FromDaysSinceStart(days); if (date == SDate.Now().AddDays(1)) //date is tomorrow, can be more accurate with weather { dailyMaxUV = UVIndex.DailyMaxUV(days, Game1.weatherForTomorrow); uvIndex = Convert.ToInt32((double)dailyMaxUV / 25); Monitor.Log($"Tomorrow's max UV value: {dailyMaxUV} | UV Index: {uvIndex}", LogLevel.Debug); return; } else if (date != SDate.Now()) //any other day except today { dailyMaxUV = UVIndex.DailyMaxUV(days); uvIndex = Convert.ToInt32((double)dailyMaxUV / 25); Monitor.Log($"Forecasted max UV value (if sunny): {dailyMaxUV} | UV Index: {uvIndex}", LogLevel.Debug); return; } } //No date argument provided OR day provided is today days = SDate.Now().DaysSinceStart; dailyMaxUV = UVIndex.DailyMaxUV(days, UVIndex.GetTodaysWeather()); uvIndex = Convert.ToInt32((double)dailyMaxUV / 25); Monitor.Log($"Today's max UV value: {dailyMaxUV} | UV Index: {uvIndex}", LogLevel.Debug); } catch (Exception ex) { Monitor.Log($"Command getUV failed:\n{ex}", LogLevel.Warn); } }
// Finds the next Garbage Hat to be available on or after the given date. public static Prediction?FindGarbageHat(SDate fromDate) { Utilities.CheckWorldReady(); if (!IsAvailable) { throw new UnavailableException("garbage"); } for (int days = fromDate.DaysSinceStart; days < fromDate.DaysSinceStart + Utilities.MaxHorizon; ++days) { List <Prediction> predictions = ListLootForDate(SDate.FromDaysSinceStart(days), true) .Where((p) => p.loot is Hat).ToList(); if (predictions.Count > 0) { return(predictions[0]); } } return(null); }
// Lists the next several night events to occur on or after the given // date, up to the given limit, optionally of a given type. public static List <Prediction> ListNextEventsFromDate (SDate fromDate, uint limit, Event?onlyType = null) { Utilities.CheckWorldReady(); // Logic from StardewValley.Utility.<>c.<pickFarmEvent>b__146_0() // as implemented in Stardew Predictor by MouseyPounds. List <Prediction> predictions = new List <Prediction> (); for (int days = fromDate.DaysSinceStart; predictions.Count < limit && days < fromDate.DaysSinceStart + Utilities.MaxHorizon; ++days) { SDate tonight = SDate.FromDaysSinceStart(days); SDate tomorrow = SDate.FromDaysSinceStart(days + 1); // No event if there is a wedding tomorrow. foreach (Farmer farmer in Game1.getAllFarmers()) { Friendship spouse = farmer.GetSpouseFriendship(); if (spouse != null && spouse.WeddingDate == tomorrow.ToWorldDate()) { continue; } } Event @event = Event.None; Random rng = new Random(((int)Game1.uniqueIDForThisGame / 2) + days + 1); if (days == 29) { @event = Event.Earthquake; } // Ignoring the possibility of bundle completion here. else if (rng.NextDouble() < 0.01 && tomorrow.Season != "winter") { @event = Event.Fairy; } else if (rng.NextDouble() < 0.01) { @event = Event.Witch; } else if (rng.NextDouble() < 0.01) { @event = Event.Meteorite; } else if (rng.NextDouble() < 0.01 && tomorrow.Year > 1) { @event = Event.StrangeCapsule; } else if (rng.NextDouble() < 0.01) { @event = Event.StoneOwl; } if (@event == Event.None || (onlyType != null && @event != onlyType)) { continue; } predictions.Add(new Prediction { date = tonight, @event = @event }); } return(predictions); }
// Lists the next several night events to occur on or after the given // date, up to the given limit, optionally of a given type. public static List <Prediction> ListNextEventsFromDate(SDate fromDate, uint limit, Event?onlyType = null) { Utilities.CheckWorldReady(); if (!IsAvailable) { throw new UnavailableException("night events"); } // Logic from StardewValley.Utility.pickFarmEvent // as implemented in Stardew Predictor by MouseyPounds. List <Prediction> predictions = new (); for (int days = fromDate.DaysSinceStart; predictions.Count < limit && days < fromDate.DaysSinceStart + Utilities.MaxHorizon; ++days) { SDate tonight = SDate.FromDaysSinceStart(days); SDate tomorrow = SDate.FromDaysSinceStart(days + 1); // No event if there is a wedding tomorrow. foreach (Farmer farmer in Game1.getAllFarmers()) { Friendship spouse = farmer.GetSpouseFriendship(); if (spouse != null && spouse.WeddingDate == tomorrow.ToWorldDate()) { continue; } } Event @event = Event.None; Random rng = new (((int)Game1.uniqueIDForThisGame / 2) + days + 1); if (days == 29) { @event = Event.Earthquake; } // Ignoring the possibility of a WorldChangeEvent here. else if (rng.NextDouble() < 0.01 && tomorrow.Season != "winter") { @event = Event.Fairy; } else if (rng.NextDouble() < 0.01) { @event = Event.Witch; } else if (rng.NextDouble() < 0.01) { @event = Event.Meteorite; } else if (rng.NextDouble() < 0.005) { @event = Event.StoneOwl; } else if (rng.NextDouble() < 0.008 && tomorrow.Year > 1 && !Utility.doesMasterPlayerHaveMailReceivedButNotMailForTomorrow("Got_Capsule")) { @event = Event.StrangeCapsule; } if (@event == Event.None || (onlyType != null && @event != onlyType)) { continue; } predictions.Add(new Prediction { date = tonight, @event = @event }); } return(predictions); }
public string FromDaysSinceStart(int daysSinceStart) { // act return(SDate.FromDaysSinceStart(daysSinceStart).ToString()); }
public void FromDaysSinceStart_RejectsInvalidValues(int daysSinceStart) { // act & assert Assert.Throws <ArgumentException>(() => _ = SDate.FromDaysSinceStart(daysSinceStart), "Passing the invalid number of days didn't throw the expected exception."); }