コード例 #1
0
        public override ConsequenceResult Calculate(ConsequenceRequest request)
        {
            if (request.TriggerMode != TriggerType.OneTime || request.InitialAmount < LowerThreshold || request.InitialAmount > UpperThreshold)
                return null;

            try {
                Money localizedCost = ExchangeRates.CurrentRates.ConvertToGiven(this.Cost, request.InitialAmount.CurrencyCode);

                decimal units = (request.InitialAmount / localizedCost).Value;

                return new ConsequenceResult (this,
                                             request,
                                             new Units (units),
                                             FormatCaption (Caption, new Dictionary<string,string> {
                    {"Cost", Cost.ToString()}
                }
                ), this.Image,
                   (units >= LowerResultLimit && units <= UpperResultLimit)
                );
            } catch (Exception ex) {
                Console.WriteLine ("{0} thrown when calculating units for price: {1}", ex.GetType().Name, ex.Message);
                return new ConsequenceResult (this,
                                              request,
                                              null,
                                              "Oops, something went wrong in this calculator",
                                              this.Image,
                                              false);
            }
        }
コード例 #2
0
        public override ConsequenceResult Calculate(ConsequenceRequest request)
        {
            if (Cost == 0m)
                return null;

            if (request.TriggerMode == TriggerType.OneTime)
                return null;

            try {
                Money localizedCost = ExchangeRates.CurrentRates.ConvertToGiven(this.Cost, request.InitialAmount.CurrencyCode);

                Money perDay = (request.InitialAmount / request.DaysPerPeriod);
                decimal unitsPerDay = (perDay / localizedCost).Value;
                decimal unitsPerPeriod = unitsPerDay * ConsequenceRequest.DaysPerUnit [Period];

                return new ConsequenceResult (this,
                                              request,
                                              new Units (unitsPerPeriod),
                                              FormatCaption (this.Caption, new Dictionary<string,string> {
                    {"Cost", this.Cost.ToString ()}
                }
                ), this.Image,
                  (unitsPerPeriod >= LowerResultLimit && unitsPerPeriod <= UpperResultLimit));
            } catch (Exception ex) {
                Console.WriteLine ("{0} thrown when computing Units per Period: {1}", ex.GetType().Name, ex.Message);
                return new ConsequenceResult (this,
                                              request,
                                              null,
                                              "Oops, something went wrong in this calculator",
                                              this.Image,
                                              false);
            }
        }
コード例 #3
0
		public void ComputeConsequences (ConsequenceRequest request)
		{	
			if (computeWorker != null && computeWorker.IsBusy)
				computeWorker.CancelAsync ();
			
			computeWorker = new BackgroundWorker ();
			computeWorker.DoWork += HandleDoWork;
			computeWorker.RunWorkerCompleted += HandleRunWorkerCompleted;
			computeWorker.WorkerSupportsCancellation = true;
			computeWorker.RunWorkerAsync (request);
		}
コード例 #4
0
        public override ConsequenceResult Calculate(ConsequenceRequest request)
        {
            if (Cost == 0m)
                return null;

            if (request.TriggerMode != TriggerType.OneTime)
                return null;

            try {
                Money localizedCost = ExchangeRates.CurrentRates.ConvertToGiven(this.Cost, request.InitialAmount.CurrencyCode);

                decimal serviceUnits = (request.InitialAmount / localizedCost).Value;
                decimal serviceSeconds = ConsequenceRequest.SecondsPerUnit [UnitForCost] * serviceUnits;

                if (UnitsPerDay > 0)
                {
                    // If the service is not provided 24 hours/day, then spread the time over whole days.
                    // This is mainly used to calculate how long it would take to earn $n, given an 8-hour day
                    decimal maxSecondsPerDay = UnitsPerDay * ConsequenceRequest.SecondsPerUnit[UnitForCost];
                    decimal wholeDays = Math.Floor(serviceSeconds / maxSecondsPerDay);
                    decimal wholeDaysInSeconds = wholeDays * ConsequenceRequest.SecondsPerUnit[TimeUnit.Day];
                    serviceSeconds = wholeDaysInSeconds + (serviceSeconds - (wholeDays * maxSecondsPerDay));
                }

                if (serviceSeconds > (decimal)TimeSpan.MaxValue.TotalSeconds)
                    return new ConsequenceResult (this,
                                                 request,
                                                 new OverflowMessage (),
                                                 "Try reducing the spending amount",
                                                 this.Image,
                                                 false);
                else
                    return new ConsequenceResult (this,
                                                  request,
                                                  new Time (TimeSpan.FromSeconds((double)serviceSeconds)),
                                                  this.FormatCaption (this.Caption, new Dictionary<string,string> {
                                                        {"Unit", this.UnitForCost.ToString ()},
                                                        {"Cost", this.Cost.ToString ()}
                                                    }),
                                                  this.Image,
                                                  (serviceSeconds <= (decimal)TimeSpan.MaxValue.TotalSeconds && serviceUnits >= LowerResultLimit && serviceUnits <= UpperResultLimit));
            } catch (Exception ex) {
                Console.WriteLine ("{0} thrown when calculating Time Of Service: {1}", ex.GetType().Name, ex.Message);
                return new ConsequenceResult (this,
                                              request,
                                              null,
                                              "Oops, something went wrong in this calculator",
                                              this.Image,
                                              false);
            }
        }
コード例 #5
0
        public override ConsequenceResult Calculate(ConsequenceRequest request)
        {
            Money total = request.TriggerMode == TriggerType.OneTime ? request.InitialAmount : request.AmountAfter(TimeSpan.FromDays((Double)ConsequenceRequest.DaysPerUnit[TimeUnit.Year] * this.Years));

            return new ConsequenceResult(this,
                                         request,
                                         total * PercentAsDecimal(this.Amount),
                                         FormatCaption(this.Caption, new Dictionary<string,string> {
                {"Percentage", String.Format("{0}%", this.Amount)},
                {"Years", Years.ToString()}
            }),
                                         this.Image,
                                         true);
        }
コード例 #6
0
        public ConsequenceResult(ACalculator calculator,
		                          ConsequenceRequest request,
		                          object computedValue, 
		                          string formattedCaption,
		                          Image image,
		                          bool recommended)
        {
            this.Calculator = calculator;
            this.Request = request;
            this.ComputedValue = computedValue;
            this.FormattedCaption = formattedCaption;
            this.Image = image;
            this.Recommended = recommended;
        }
コード例 #7
0
        public override ConsequenceResult Calculate(ConsequenceRequest request)
        {
            if (request.TriggerMode != TriggerType.OneTime)
                return null;

            Money convertedAmount = ExchangeRates.CurrentRates.ConvertToGiven(request.InitialAmount, this.CurrencyCode);

            return new ConsequenceResult(this,
                                         request,
                                         convertedAmount,
                                         this.FormatCaption (this.Caption, new Dictionary<string,string> {
                                                        {"CurrencyCode", this.CurrencyCode},
                                                        {"CurrencyName", ExchangeRates.GetCurrencyName(this.CurrencyCode)}
                                                    }),
                                         this.Image,
                                         true);
        }
コード例 #8
0
        public override ConsequenceResult Calculate(ConsequenceRequest request)
        {
            if (Cost == null || Cost == 0m)
                return null;

            if (request.TriggerMode == TriggerType.OneTime)
                return null;

            if (this.Cost < request.InitialAmount)
                return null;

            try {
                Money localizedCost = ExchangeRates.CurrentRates.ConvertToGiven(this.Cost, request.InitialAmount.CurrencyCode);

                decimal givenUnitsUntil = (localizedCost / request.InitialAmount).Value;

                if (givenUnitsUntil * request.DaysPerPeriod < MaxDays)
                {
                    TimeSpan timeUntil = TimeSpan.FromDays((double)(givenUnitsUntil * request.DaysPerPeriod));

                    return new ConsequenceResult (this,
                                                  request,
                                                  new Time (timeUntil),
                                                  this.FormatCaption (this.Caption, new Dictionary<string,string> {
                        {"Cost", this.Cost.ToString ()}
                    }
                    ), this.Image,
                       (timeUntil.TotalDays >= (double)LowerResultLimit && timeUntil.TotalDays <= (double)UpperResultLimit));
                } else {
                    return new ConsequenceResult(this,
                                                 request,
                                                 new OverflowMessage(),
                                                 "Try reducing the target price",
                                                 this.Image, false);
                }
            } catch (Exception ex) {
                Console.WriteLine("{0} thrown when computing Time Until: {1}", ex.GetType().Name, ex.Message);
                return new ConsequenceResult (this,
                                              request,
                                              null,
                                              "Oops, something went wrong in this calculator",
                                              this.Image,
                                              false);
            }
        }
コード例 #9
0
        public override ConsequenceResult Calculate(ConsequenceRequest request)
        {
            if (Cost == 0m)
                return null;

            if (request.TriggerMode == TriggerType.OneTime)
                return null;

            decimal perYear = request.AmountAfter (oneYear);
            decimal units = perYear / Cost;

            if (units >= LowerResultLimit && units <= UpperResultLimit)
                return new ConsequenceResult (this,
                                              request,
                                              new Units(units),
                                              FormatCaption (this.Caption, new Dictionary<string,string> {
                        {"Cost", this.Cost.ToString ()}
                    }),
                                              this.ImageName);
            else
                return null;
        }
コード例 #10
0
        public static IEnumerable<InvestmentInstallment> InvestmentSchedule(ConsequenceRequest request,
		                                                                     Investment calculator)
        {
            decimal annualRate = ACalculator.PercentAsDecimal (calculator.Rate);
            decimal compoundingsPerYear = ACalculator.CompoundingsPerYear (calculator.Compounding);
            decimal periodRate = annualRate / compoundingsPerYear;

            Money balance = 0m;

            if (request.TriggerMode != TriggerType.OneTime) {
                Money periodicInvestment = request.InitialAmount;
                decimal totalInvestments = request.InvestmentsPerYear * calculator.Years;
                decimal compoundingsPerInvestment = compoundingsPerYear / request.InvestmentsPerYear;
                var baseSchedule = from p in Enumerable.Range (1, (int)Math.Floor (totalInvestments))
                                    let newBalance = balance += periodicInvestment
                                    let earnings = ((balance * periodRate) * compoundingsPerInvestment)
                                    select new InvestmentInstallment {
                                        Installment = p,
                                        Investment = periodicInvestment,
                                        Earnings = earnings,
                                        Balance = balance += earnings
                                    };

                return baseSchedule;
            } else {
                decimal totalCompoundings = compoundingsPerYear * calculator.Years;
                balance = request.InitialAmount;
                var baseSchedule = from p in Enumerable.Range (1, (int)Math.Floor (totalCompoundings))
                    let earnings = balance * periodRate
                    select new InvestmentInstallment {
                        Installment = p,
                        Investment = p == 1 ? request.InitialAmount : 0,
                        Earnings = earnings,
                        Balance = balance += earnings
                    };

                return baseSchedule;
            }
        }
コード例 #11
0
        public override ConsequenceResult Calculate(ConsequenceRequest request)
        {
            if (request.InitialAmount <= 0 || request.TriggerMode == TriggerType.OneTime)
                return null;

            try {
                int annualPayments = CompoundingsPerYear (PaymentFrequency);
                decimal ratePerPeriod = PercentAsDecimal (Rate) / annualPayments;
                Money paymentPerInstallment = (request.InitialAmount * (decimal)(InvestmentsPerYear (request.TriggerMode))) / annualPayments;

                Money totalPayment = paymentPerInstallment * Installments;
                Money maxLoanAmount = null;
                if (Rate > 0)
                    maxLoanAmount = ((paymentPerInstallment / ratePerPeriod) * (1 - (1 / Financials.Pow ((1 + ratePerPeriod), Installments))));
                else
                    maxLoanAmount = totalPayment;

                return new ConsequenceResult (this,
                                         request,
                                         maxLoanAmount,
                                         new TabularResult (request.Summary, string.Format ("Amortization of a {0} loan at {1}%", maxLoanAmount, Rate), this),
                                         FormatCaption (this.Caption, new Dictionary<string,string> {
                {"Installments", Installments.ToString ()},
                {"TotalPayment", totalPayment.ToString ()},
                {"TotalInterest", (totalPayment - maxLoanAmount).ToString()}
            }
                ), this.Image,
                   (maxLoanAmount >= LowerResultLimit && maxLoanAmount <= UpperResultLimit));
            } catch (Exception ex) {
                Console.WriteLine("{0} thrown when computing spending power: {1}", ex.GetType().Name, ex.Message);
                return new ConsequenceResult (this,
                                               request,
                                               null,
                                               "Oops, something went wrong in this calculator",
                                              this.Image,
                                              false);
            }
        }
コード例 #12
0
        public override ConsequenceResult Calculate(ConsequenceRequest request)
        {
            if (Threshold == 0m)
                return null;

            decimal upper = Threshold + (Threshold * 0.10m);
            decimal lower = Threshold - (Threshold * 0.10m);

            if (request.InitialAmount >= lower && request.InitialAmount <= upper)
                return new ConsequenceResult (this, Threshold, this.Caption, this.ImageName);

            for (int i = 1; i <= Limit; i++) {
                decimal accumilated = request.AmountAfter (TimeSpan.FromDays (30 * i));
                if (accumilated >= lower && accumilated <= upper)
                    return new ConsequenceResult (this, Threshold, this.FormatCaption (this.Caption, new Dictionary<string,string> {
                        {"Months", i.ToString ()},
                        {"Threshold", this.Threshold.ToString ()}
                    }),
                                                  this.ImageName);
            }

            return null;
        }
コード例 #13
0
 public abstract ConsequenceResult Calculate(ConsequenceRequest request);
コード例 #14
0
        public override ConsequenceResult Calculate(ConsequenceRequest request)
        {
            // For some of the scenarios below we have to sacrifice a bit of accuracy in order to produce results
            // within a few milliseconds. EG: A savings account may compound monthly but calculate interest daily, but
            // that would require more CPU time than we can afford.

            if (request.InitialAmount == 0m)
                return null;

            int annualCompoundings = CompoundingsPerYear (Compounding);

            int compoundingPeriods = Years * annualCompoundings;
            decimal ratePerPeriod = PercentAsDecimal (Rate) / annualCompoundings;
            decimal investmentsPerYear = InvestmentsPerYear (request.TriggerMode);

            Money result = null;

            try {
                if (request.TriggerMode == TriggerType.OneTime) {
                    // A one-time investment means we can use the compound interest formula

                    result = request.InitialAmount * Financials.Pow (1 + ratePerPeriod, compoundingPeriods);

                } else if (annualCompoundings == investmentsPerYear) {
                    // Compounding frequency is the same as the investment frequency, so we can
                    // use a mathematical series.
                    // Described here: http://mathdude.quickanddirtytips.com/math-dude-web-bonus.aspx

                    decimal seriesSum = Enumerable.Range (1, compoundingPeriods).Sum (x => Financials.Pow (1 + ratePerPeriod, x));

                    result = request.InitialAmount.Value * seriesSum;

                } else if (annualCompoundings > investmentsPerYear) {
                    // We need to take the sum of sub-periods and apply the standard compound interest formula to each

                    decimal investmentPeriods = Years * investmentsPerYear;
                    int compoundingsPerInvestment = ((int)Math.Floor (annualCompoundings / investmentsPerYear));

                    Money sum = request.InitialAmount * Financials.Pow (1 + ratePerPeriod, compoundingsPerInvestment);
                    for (int i = 1; i <= investmentPeriods - 1; i++)
                        sum = (sum + (request.InitialAmount * Financials.Pow (1 + ratePerPeriod, compoundingsPerInvestment)));

                    result = sum;

                } else if (investmentsPerYear > annualCompoundings) {
                    // Apply the interest to the midpoint of the previous + next balance for each compounding period

                    decimal investmentsPerPeriod = (decimal)(investmentsPerYear / annualCompoundings);
                    decimal amountPerPeriod = (investmentsPerPeriod * request.InitialAmount.Value);

                    decimal sum = 0;
                    for (int i = 1; i <= compoundingPeriods; i++) {
                        sum = sum + amountPerPeriod + ((sum + amountPerPeriod / 2) * (decimal)ratePerPeriod);
                    }

                    result = sum;
                }
            } catch (OverflowException oex) {
                Console.WriteLine (String.Format ("Number overflow in investment calculator: {0}", oex.Message));
                return new ConsequenceResult (this,
                                              request,
                                              new OverflowMessage (),
                                              "Try reducing the interest rate or years",
                                              this.Image,
                                              false
                );
            } catch (Exception ex) {
                Console.WriteLine (String.Format ("{0} thrown in investment calculator: {1}", ex.GetType ().Name, ex.Message));
                return new ConsequenceResult (this,
                                              request,
                                              null,
                                              "Oops, something went wrong in this calculation",
                                              this.Image,
                                              false
                );
            }

            return new ConsequenceResult (this,
                                          request,
                                          result,
                                          new TabularResult(request.Summary, string.Format ("{0} invested at {1:0.00}%", request.Summary, Rate), this),
                                          FormatMyCaption (),
                                          this.Image,
                                          (result >= this.LowerResultLimit && result <= this.UpperResultLimit));
        }
        private void CreateNewConsequence(TriggerType mode, Template template)
        {
            if (template == null)
                return;

            SubProfile userProfile = Profile.GetSubProfile("user");
            if (userProfile == null)
            {
                userProfile = SubProfile.Create("user");
                Profile.AddSubProfile("user", userProfile);
            }

            XElement unwrappedTemplate = template.GetUsableTemplateDefinition();
            if (unwrappedTemplate != null)
            {
                ACalculator calculator = userProfile.AddConsequenceFromDefinition(unwrappedTemplate);
                calculator.SortOrder = -1;

                // Switch to a compatible mode
                if (!calculator.TriggersOn.Contains(this.CurrentMode))
                    if (calculator.TriggersOn.Contains(TriggerType.Repeating))
                        this.CurrentMode = TriggerType.PerDay;
                else
                    if (calculator.TriggersOn.Contains(TriggerType.OneTime))
                        this.CurrentMode = TriggerType.OneTime;

                // Create a prototype request in order to load the Details View in edit mode
                Money prototypeAmount = this.CurrentAmount;
                if (prototypeAmount == null)
                    prototypeAmount = 100;
                ConsequenceRequest prototypeRequest = new ConsequenceRequest(prototypeAmount, this.CurrentMode);
                ConsequenceResult prototypeResult = calculator.Calculate(prototypeRequest);
                DisplayConsequenceDetails(prototypeResult);
            }
        }
コード例 #16
0
        public override ConsequenceResult Calculate(ConsequenceRequest request)
        {
            if (request.InitialAmount == 0 || request.InitialAmount < LowerThreshold || request.InitialAmount > UpperThreshold)
                return null;

            try {
                Money localizedMinPayment = ExchangeRates.CurrentRates.ConvertToGiven(MinimumPayment, request.InitialAmount.CurrencyCode);

                var amortization = Financials.Amortization (request.InitialAmount,
                                                 CompoundingsPerYear (Compounding),
                                                 PercentAsDecimal (Rate),
                                                 PercentAsDecimal (MinPayPercent),
                                                 localizedMinPayment,
                                                 PayoffMode);

                int installments = 0;
                Money totalInterest = new Money(0, request.InitialAmount.CurrencyCode);
                foreach (var i in amortization) {
                    installments++;
                    totalInterest += i.Interest;
                }

                Money payoff = request.InitialAmount + totalInterest;

                return new ConsequenceResult (this,
                                                 request,
                                                 payoff,
                                                 new TabularResult (
                        request.Summary,
                        String.Format ("Amortization of a {0} loan at {1}%", request.InitialAmount, Rate),
                        this),
                                                 FormatCaption (this.Caption, new Dictionary<string,string> {
                        {"Periods", installments.ToString()},
                        {"Interest", totalInterest.ToString()}
                    }
                ), this.Image,
                       (payoff >= LowerResultLimit && payoff <= UpperResultLimit));
            } catch (Exception ex) {
                Console.WriteLine("{0} thrown when computing loan payoff: {1}", ex.GetType().Name, ex.Message);
                return new ConsequenceResult(this,
                                             request,
                                             null,
                                             "Oops, something went wrong in this calculator",
                                             this.Image,
                                             false);
            }
        }