namespace Ch2Weather; public record struct WeatherRecord(double Temperature, double Humidity, double Pressure); public interface IWeatherSubject { void Subscribe(IWeatherObserver o); void Unsubscribe(IWeatherObserver o); void NotifyObservers(); } public interface IWeatherObserver { void Update(WeatherRecord wr); } public interface IWeatherDisplay { void Display(); } public class WeatherData(WeatherRecord weatherRecord) : IWeatherSubject { private readonly List _observers = []; private WeatherRecord _weatherRecord = weatherRecord; public WeatherRecord WeatherRecord { get => _weatherRecord; set { _weatherRecord = value; NotifyObservers(); } } public void Subscribe(IWeatherObserver o) { _observers.Add(o); } public void Unsubscribe(IWeatherObserver o) { _observers.Remove(o); } public void NotifyObservers() { foreach (var o in _observers) { o.Update(_weatherRecord); } } } public class CurrentConditionsDisplay : IWeatherObserver, IWeatherDisplay { private IWeatherSubject _subject; private double _temperature = 0; private double _humidity = 0; public CurrentConditionsDisplay(IWeatherSubject subject) { _subject = subject; subject.Subscribe(this); } public void Update(WeatherRecord wr) { _temperature = wr.Temperature; _humidity = wr.Humidity; Display(); } public void Display() { Console.WriteLine($"Current conditions: {_temperature}C degrees and {_humidity}% humidity."); } } public class HeatIndexDisplay : IWeatherObserver, IWeatherDisplay { private IWeatherSubject _subject; private WeatherRecord _weatherRecord = new WeatherRecord(0,0,0); public HeatIndexDisplay(IWeatherSubject subject) { _subject = subject; subject.Subscribe(this); } private double ComputeHeatIndex(double t, double rh) { return (16.923 + (0.185212 * t) + (5.37941 * rh) - (0.100254 * t * rh) + (0.00941695 * (t * t)) + (0.00728898 * (rh * rh)) + (0.000345372 * (t * t * rh)) - (0.000814971 * (t * rh * rh)) + (0.0000102102 * (t * t * rh * rh)) - (0.000038646 * (t * t * t)) + (0.0000291583 * (rh * rh * rh)) + (0.00000142721 * (t * t * t * rh)) + (0.000000197483 * (t * rh * rh * rh)) - (0.0000000218429 * (t * t * t * rh * rh)) + 0.000000000843296 * (t * t * rh * rh * rh)) - (0.0000000000481975 * (t * t * t * rh * rh * rh)); } public void Update(WeatherRecord wr) { _weatherRecord = wr; Display(); } public void Display() { var heatIndex = ComputeHeatIndex(_weatherRecord.Temperature, _weatherRecord.Humidity); Console.WriteLine($"Heat Index is {heatIndex}"); } } public class TemperatureStatsDisplay : IWeatherObserver, IWeatherDisplay { private IWeatherSubject _subject; private double _n = 0; private double _avg = 0; private double _min = 0; private double _max = 0; public TemperatureStatsDisplay(IWeatherSubject subject) { _subject = subject; subject.Subscribe(this); } public void Update(WeatherRecord wr) { var temp = wr.Temperature; if (_n == 0) { _n = 1; _avg = temp; _min = temp; _max = temp; } else { _min = double.Min(_min, temp); _max = double.Max(_max, temp); _avg = (_avg * _n + temp) / (_n + 1); _n += 1; } Display(); } public void Display() { Console.WriteLine($"Avg/Max/Min Temperature: {_avg}/{_max}/{_min}"); } }