static double CalculateTotalWaterVolume (BrewData data) { //Designing Great Beers by Ray Daniels pg. 65 var runoffVolume = (data.FinishedBeerVolume + data.TrubLoss) / (1.0 - ShrinkageFactor) / CalculateEvaportation (data); var grainWaterRetention = GrainRetentionFactor * data.GrainBill; return runoffVolume + data.EquipmentLoss + grainWaterRetention; }
static double CalculateTotalWaterVolume(BrewData data) { //Designing Great Beers by Ray Daniels pg. 65 var runoffVolume = (data.FinishedBeerVolume + data.TrubLoss) / (1.0 - ShrinkageFactor) / CalculateEvaportation(data); var grainWaterRetention = GrainRetentionFactor * data.GrainBill; return(runoffVolume + data.EquipmentLoss + grainWaterRetention); }
static double CaluclateStrikeWaterTemperature(BrewData data) { //http://www.howtobrew.com/section3/chapter16-3.html //Initial infusion equation //Tw = (.2 / r) * (T2 - T1) + T2; // r = The ratio of water to grain in quarts per pound. // Wa = The amount of boiling water added (in quarts). // Wm = The total amount of water in the mash (in quarts). // T1 = The initial temperature (¡F) of the mash. // T2 = The target temperature (¡F) of the mash. // Tw = The actual temperature (¡F) of the infusion water. // G = The amount of grain in the mash (in pounds). return((.2 / data.MashThickness) * (data.MashTemperature - data.GrainTemperature) + data.MashTemperature); }
public MashStatsViewModel(IScreen hostScreen, BrewData data) { HostScreen = hostScreen ?? Locator.Current.GetService <IScreen> (); SetMashTempTo = ReactiveCommand.Create(); SetMashTempTo .StartWith(DefaultMashTemp) .Select(x => (double)x) .Where(x => x > 0.0) .Select(x => data.MashTemperature = x) .ToProperty(this, vm => vm.MashTemperature, out _MashTemperature); SetGrainTempTo = ReactiveCommand.Create(); SetGrainTempTo .StartWith(DefaultGrainTemp) .Select(x => (double)x) .Where(x => x > 0.0) .Select(x => data.GrainTemperature = x) .ToProperty(this, vm => vm.GrainTemperature, out _GrainTemperature); SetMashThicknessTo = ReactiveCommand.Create(); SetMashThicknessTo .StartWith(DefaultMashThickness) .Select(x => (double)x) .Where(x => x > 0.0) .Select(x => data.MashThickness = x) .ToProperty(this, vm => vm.MashThickness, out _MashThickness); SetMashLengthTo = ReactiveCommand.Create(); SetMashLengthTo .StartWith(DefaultMashLength) .Select(x => data.MashTime = TimeSpan.FromMinutes((double)x)) .Select(x => x.TotalMinutes) .ToProperty(this, vm => vm.MashLength, out _MashLength); SetBoilLengthTo = ReactiveCommand.Create(); SetBoilLengthTo .StartWith(DefaultBoilLength) .Select(x => data.BoilTime = TimeSpan.FromMinutes((double)x)) .Select(x => x.TotalMinutes) .ToProperty(this, vm => vm.BoilLength, out _BoilLength); NavigateToWaterProjections = ReactiveCommand.Create(); NavigateToWaterProjections .Select(x => new WaterProjectionsViewModel(HostScreen, data)) .Subscribe(HostScreen.Router.Navigate.Execute); }
public MashStatsViewModel (IScreen hostScreen, BrewData data) { HostScreen = hostScreen ?? Locator.Current.GetService<IScreen> (); SetMashTempTo = ReactiveCommand.Create (); SetMashTempTo .StartWith (DefaultMashTemp) .Select (x => (double)x) .Where (x => x > 0.0) .Select (x => data.MashTemperature = x) .ToProperty (this, vm => vm.MashTemperature, out _MashTemperature); SetGrainTempTo = ReactiveCommand.Create (); SetGrainTempTo .StartWith (DefaultGrainTemp) .Select (x => (double)x) .Where (x => x > 0.0) .Select (x => data.GrainTemperature = x) .ToProperty (this, vm => vm.GrainTemperature, out _GrainTemperature); SetMashThicknessTo = ReactiveCommand.Create (); SetMashThicknessTo .StartWith (DefaultMashThickness) .Select (x => (double)x) .Where (x => x > 0.0) .Select (x => data.MashThickness = x) .ToProperty (this, vm => vm.MashThickness, out _MashThickness); SetMashLengthTo = ReactiveCommand.Create (); SetMashLengthTo .StartWith (DefaultMashLength) .Select (x => data.MashTime = TimeSpan.FromMinutes ((double)x)) .Select (x => x.TotalMinutes) .ToProperty (this, vm => vm.MashLength, out _MashLength); SetBoilLengthTo = ReactiveCommand.Create (); SetBoilLengthTo .StartWith (DefaultBoilLength) .Select (x => data.BoilTime = TimeSpan.FromMinutes ((double)x)) .Select (x => x.TotalMinutes) .ToProperty (this, vm => vm.BoilLength, out _BoilLength); NavigateToWaterProjections = ReactiveCommand.Create (); NavigateToWaterProjections .Select (x => new WaterProjectionsViewModel (HostScreen, data)) .Subscribe (HostScreen.Router.Navigate.Execute); }
public WaterProjectionsViewModel(IScreen hostScreen, BrewData data) { HostScreen = hostScreen ?? Locator.Current.GetService <IScreen> (); TotalWaterVolume = Math.Round(CalculateTotalWaterVolume(data), 2); StrikeWaterVolume = Math.Round(CalculateStrikeWaterVolume(data), 2); StrikeWaterTemperature = Math.Round(CaluclateStrikeWaterTemperature(data), 2); SpargeWaterVolume = Math.Round(TotalWaterVolume - StrikeWaterVolume, 2); //TODO: Research sparge water temp. In a single infusion it seems to always be //170. Not sure why. Is is like a second infusion or just empirically good //for the grain wash SpargeWaterTemperature = 170.0; NavigateToMashTimer = ReactiveCommand.Create(); NavigateToMashTimer .ObserveOn(RxApp.MainThreadScheduler) .Subscribe(x => HostScreen.Router.Navigate.Execute(new MashTimerViewModel(HostScreen, data))); }
public WaterProjectionsViewModel (IScreen hostScreen, BrewData data) { HostScreen = hostScreen ?? Locator.Current.GetService<IScreen> (); TotalWaterVolume = Math.Round (CalculateTotalWaterVolume (data), 2); StrikeWaterVolume = Math.Round (CalculateStrikeWaterVolume (data), 2); StrikeWaterTemperature = Math.Round (CaluclateStrikeWaterTemperature (data), 2); SpargeWaterVolume = Math.Round (TotalWaterVolume - StrikeWaterVolume, 2); //TODO: Research sparge water temp. In a single infusion it seems to always be //170. Not sure why. Is is like a second infusion or just empirically good //for the grain wash SpargeWaterTemperature = 170.0; NavigateToMashTimer = ReactiveCommand.Create (); NavigateToMashTimer .ObserveOn (RxApp.MainThreadScheduler) .Subscribe (x => HostScreen.Router.Navigate.Execute (new MashTimerViewModel (HostScreen, data))); }
public MashTimerViewModel(IScreen hostScreen, BrewData data) { HostScreen = hostScreen ?? Locator.Current.GetService <IScreen> (); CurrentTimeRemaining = (int)data.MashTime.TotalSeconds; var canStartOrReset = this.WhenAnyValue(x => x.IsTimerRunning).Where(x => !x); StartTimer = ReactiveCommand.Create(canStartOrReset); var start = StartTimer.Select(x => true); PauseTimer = ReactiveCommand.Create(this.WhenAnyValue(x => x.IsTimerRunning).Where(x => x)); var pause = PauseTimer.Select(x => false); Observable.Merge(start, pause) .StartWith(false) .ToProperty(this, vm => vm.IsTimerRunning, out _IsTimerRunning); ResetTimer = ReactiveCommand.Create(canStartOrReset); ResetTimer.Subscribe(_ => { CurrentTimeRemaining = (int)data.MashTime.TotalSeconds; }); this.WhenAnyValue(x => x.IsTimerRunning) .Where(x => x == true) .Subscribe(_ => Device.StartTimer(TimeSpan.FromSeconds(1), () => { if (CurrentTimeRemaining > 0) { CurrentTimeRemaining -= 1; } return(IsTimerRunning); })); this.WhenAnyValue(x => x.CurrentTimeRemaining) .Select(x => TimeSpan.FromSeconds(x).ToString()) .ToProperty(this, vm => vm.ClockText, out _ClockText); }
public MashTimerViewModel (IScreen hostScreen, BrewData data) { HostScreen = hostScreen ?? Locator.Current.GetService<IScreen> (); CurrentTimeRemaining = (int)data.MashTime.TotalSeconds; var canStartOrReset = this.WhenAnyValue (x => x.IsTimerRunning).Where (x => !x); StartTimer = ReactiveCommand.Create (canStartOrReset); var start = StartTimer.Select (x => true); PauseTimer = ReactiveCommand.Create (this.WhenAnyValue (x => x.IsTimerRunning).Where (x => x)); var pause = PauseTimer.Select (x => false); Observable.Merge (start, pause) .StartWith (false) .ToProperty (this, vm => vm.IsTimerRunning, out _IsTimerRunning); ResetTimer = ReactiveCommand.Create (canStartOrReset); ResetTimer.Subscribe (_ => { CurrentTimeRemaining = (int)data.MashTime.TotalSeconds; }); this.WhenAnyValue (x => x.IsTimerRunning) .Where (x => x == true) .Subscribe (_ => Device.StartTimer (TimeSpan.FromSeconds (1), () => { if (CurrentTimeRemaining > 0) CurrentTimeRemaining -= 1; return IsTimerRunning; })); this.WhenAnyValue (x => x.CurrentTimeRemaining) .Select (x => TimeSpan.FromSeconds (x).ToString ()) .ToProperty (this, vm => vm.ClockText, out _ClockText); }
static double CalculateStrikeWaterVolume (BrewData data) { return ((data.GrainBill * data.MashThickness) / QuartsPerGallon) + data.EquipmentLoss; }
static double CalculateEvaportation (BrewData data) { return 1 - ((EvaporatationFactor / MinutesPerHour) * data.BoilTime.TotalMinutes); }
static double CaluclateStrikeWaterTemperature (BrewData data) { //http://www.howtobrew.com/section3/chapter16-3.html //Initial infusion equation //Tw = (.2 / r) * (T2 - T1) + T2; // r = The ratio of water to grain in quarts per pound. // Wa = The amount of boiling water added (in quarts). // Wm = The total amount of water in the mash (in quarts). // T1 = The initial temperature (¡F) of the mash. // T2 = The target temperature (¡F) of the mash. // Tw = The actual temperature (¡F) of the infusion water. // G = The amount of grain in the mash (in pounds). return (.2 / data.MashThickness) * (data.MashTemperature - data.GrainTemperature) + data.MashTemperature; }
static double CalculateEvaportation(BrewData data) { return(1 - ((EvaporatationFactor / MinutesPerHour) * data.BoilTime.TotalMinutes)); }
static double CalculateStrikeWaterVolume(BrewData data) { return(((data.GrainBill * data.MashThickness) / QuartsPerGallon) + data.EquipmentLoss); }