From dfbdf56ff5a1537e7f5ca52bd26780e25b167956 Mon Sep 17 00:00:00 2001 From: Kalakoi Date: Mon, 11 May 2026 14:26:48 -0400 Subject: [PATCH] Add project files. --- RetirementCalculator.sln | 25 +++ RetirementCalculator/App.xaml | 9 ++ RetirementCalculator/App.xaml.cs | 14 ++ RetirementCalculator/AssemblyInfo.cs | 10 ++ .../DataModels/DeductionInformation.cs | 9 ++ RetirementCalculator/DataModels/FederalTax.cs | 147 ++++++++++++++++++ .../DataModels/FederalTaxRate.cs | 8 + .../DataModels/FilingStatus.cs | 7 + .../DataModels/PayInformation.cs | 8 + RetirementCalculator/DataModels/PayPeriod.cs | 7 + RetirementCalculator/DataModels/TaxRates.cs | 130 ++++++++++++++++ RetirementCalculator/MVVM/ModelBase.cs | 13 ++ .../MVVM/PropertyChangedBase.cs | 10 ++ RetirementCalculator/MVVM/RelayCommand.cs | 33 ++++ RetirementCalculator/MainWindow.xaml | 40 +++++ RetirementCalculator/MainWindow.xaml.cs | 24 +++ RetirementCalculator/MainWindowModel.cs | 141 +++++++++++++++++ RetirementCalculator/MainWindowViewModel.cs | 107 +++++++++++++ .../RetirementCalculator.csproj | 17 ++ 19 files changed, 759 insertions(+) create mode 100644 RetirementCalculator.sln create mode 100644 RetirementCalculator/App.xaml create mode 100644 RetirementCalculator/App.xaml.cs create mode 100644 RetirementCalculator/AssemblyInfo.cs create mode 100644 RetirementCalculator/DataModels/DeductionInformation.cs create mode 100644 RetirementCalculator/DataModels/FederalTax.cs create mode 100644 RetirementCalculator/DataModels/FederalTaxRate.cs create mode 100644 RetirementCalculator/DataModels/FilingStatus.cs create mode 100644 RetirementCalculator/DataModels/PayInformation.cs create mode 100644 RetirementCalculator/DataModels/PayPeriod.cs create mode 100644 RetirementCalculator/DataModels/TaxRates.cs create mode 100644 RetirementCalculator/MVVM/ModelBase.cs create mode 100644 RetirementCalculator/MVVM/PropertyChangedBase.cs create mode 100644 RetirementCalculator/MVVM/RelayCommand.cs create mode 100644 RetirementCalculator/MainWindow.xaml create mode 100644 RetirementCalculator/MainWindow.xaml.cs create mode 100644 RetirementCalculator/MainWindowModel.cs create mode 100644 RetirementCalculator/MainWindowViewModel.cs create mode 100644 RetirementCalculator/RetirementCalculator.csproj diff --git a/RetirementCalculator.sln b/RetirementCalculator.sln new file mode 100644 index 0000000..06ee323 --- /dev/null +++ b/RetirementCalculator.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.8.36227.8 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RetirementCalculator", "RetirementCalculator\RetirementCalculator.csproj", "{5671F58E-2971-479E-BA6A-C71C80163039}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {5671F58E-2971-479E-BA6A-C71C80163039}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5671F58E-2971-479E-BA6A-C71C80163039}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5671F58E-2971-479E-BA6A-C71C80163039}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5671F58E-2971-479E-BA6A-C71C80163039}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {9372217B-44E3-4776-A872-2CC4C1E2068F} + EndGlobalSection +EndGlobal diff --git a/RetirementCalculator/App.xaml b/RetirementCalculator/App.xaml new file mode 100644 index 0000000..2857e33 --- /dev/null +++ b/RetirementCalculator/App.xaml @@ -0,0 +1,9 @@ + + + + + diff --git a/RetirementCalculator/App.xaml.cs b/RetirementCalculator/App.xaml.cs new file mode 100644 index 0000000..c11e68f --- /dev/null +++ b/RetirementCalculator/App.xaml.cs @@ -0,0 +1,14 @@ +using System.Configuration; +using System.Data; +using System.Windows; + +namespace RetirementCalculator +{ + /// + /// Interaction logic for App.xaml + /// + public partial class App : Application + { + } + +} diff --git a/RetirementCalculator/AssemblyInfo.cs b/RetirementCalculator/AssemblyInfo.cs new file mode 100644 index 0000000..b0ec827 --- /dev/null +++ b/RetirementCalculator/AssemblyInfo.cs @@ -0,0 +1,10 @@ +using System.Windows; + +[assembly: ThemeInfo( + ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located + //(used if a resource is not found in the page, + // or application resource dictionaries) + ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located + //(used if a resource is not found in the page, + // app, or any theme specific resource dictionaries) +)] diff --git a/RetirementCalculator/DataModels/DeductionInformation.cs b/RetirementCalculator/DataModels/DeductionInformation.cs new file mode 100644 index 0000000..bc5c18b --- /dev/null +++ b/RetirementCalculator/DataModels/DeductionInformation.cs @@ -0,0 +1,9 @@ +namespace RetirementCalculator +{ + public class DeductionInformation + { + public double PreTaxDeductions { get; set; } + public double PostTaxDeductions { get; set; } + public double RetirementPercentage { get; set; } + } +} diff --git a/RetirementCalculator/DataModels/FederalTax.cs b/RetirementCalculator/DataModels/FederalTax.cs new file mode 100644 index 0000000..d88981b --- /dev/null +++ b/RetirementCalculator/DataModels/FederalTax.cs @@ -0,0 +1,147 @@ +namespace RetirementCalculator +{ + public class FederalTax + { + public FilingStatus Status { get; set; } + public double StandardDeduction { get; set; } + public List FederalTaxRates { get; set; } + + public FederalTax() + { + FederalTaxRates = new(); + } + + public FederalTax(FilingStatus status) + { + Status = status; + switch (status) + { + case FilingStatus.Single: + StandardDeduction = 16100; + FederalTaxRates = + [ + .. new FederalTaxRate[] + { + new() { TaxableIncomeMinimum = 0, TaxPercentage = 0.1 }, + new() { TaxableIncomeMinimum = 12400, TaxPercentage = 0.12 }, + new() { TaxableIncomeMinimum = 50400, TaxPercentage = 0.22 }, + new() { TaxableIncomeMinimum = 105700, TaxPercentage = 0.24 }, + new() { TaxableIncomeMinimum = 201775, TaxPercentage = 0.32 }, + new() { TaxableIncomeMinimum = 256225, TaxPercentage = 0.35 }, + new() { TaxableIncomeMinimum = 640600, TaxPercentage = 0.37 } + }, + ]; + break; + case FilingStatus.Married: + StandardDeduction = 32200; + FederalTaxRates = + [ + .. new FederalTaxRate[] + { + new() { TaxableIncomeMinimum = 0, TaxPercentage = 0 }, + new() { TaxableIncomeMinimum = 19300, TaxPercentage = 0.10 }, + new() { TaxableIncomeMinimum = 44100, TaxPercentage = 0.12 }, + new() { TaxableIncomeMinimum = 120100, TaxPercentage = 0.22 }, + new() { TaxableIncomeMinimum = 230700, TaxPercentage = 0.24 }, + new() { TaxableIncomeMinimum = 422850, TaxPercentage = 0.32 }, + new() { TaxableIncomeMinimum = 531750, TaxPercentage = 0.35 }, + new() { TaxableIncomeMinimum = 788000, TaxPercentage = 0.37 } + }, + ]; + break; + case FilingStatus.HeadOfHousehold: + StandardDeduction = 24150; + FederalTaxRates = + [ + .. new FederalTaxRate[] + { + new() { TaxableIncomeMinimum = 0, TaxPercentage = 0 }, + new() { TaxableIncomeMinimum = 15550, TaxPercentage = 0.10 }, + new() { TaxableIncomeMinimum = 33250, TaxPercentage = 0.12 }, + new() { TaxableIncomeMinimum = 83000, TaxPercentage = 0.22 }, + new() { TaxableIncomeMinimum = 121250, TaxPercentage = 0.24 }, + new() { TaxableIncomeMinimum = 217300, TaxPercentage = 0.32 }, + new() { TaxableIncomeMinimum = 271750, TaxPercentage = 0.35 }, + new() { TaxableIncomeMinimum = 656150, TaxPercentage = 0.37 } + }, + ]; + break; + default: + throw new InvalidOperationException(); + } + } + + public FederalTax(FilingStatus status, double standardDeduction, params FederalTaxRate[] federalTaxRates) + { + Status = status; + StandardDeduction = standardDeduction; + FederalTaxRates = new(); + foreach (FederalTaxRate ftr in federalTaxRates) + { + if (FederalTaxRates.Count == 0) + { + FederalTaxRates.Add(ftr); + } + else + { + bool Inserted = false; + for (int i = 0; i < FederalTaxRates.Count; i++) + { + if (ftr.TaxableIncomeMinimum <= FederalTaxRates.ElementAt(i).TaxableIncomeMinimum) + { + FederalTaxRates.Insert(i, ftr); + Inserted = true; + break; + } + } + if (!Inserted) + { + FederalTaxRates.Add(ftr); + } + } + } + } + + public double CalculateTax(PayInformation Pay, DeductionInformation Deductions) + { + double PayPeriods = 1; + switch (Pay.Period) + { + case PayPeriod.Annually: + PayPeriods = 1; + break; + case PayPeriod.Monthly: + PayPeriods = 12; + break; + case PayPeriod.TwiceMonthly: + PayPeriods = 24; + break; + case PayPeriod.EveryOtherWeek: + PayPeriods = 26; + break; + case PayPeriod.EveryWeek: + PayPeriods = 52; + break; + default: + PayPeriods = 1; + break; + } + double WorkingIncome = Pay.Salary - StandardDeduction - (Deductions.PreTaxDeductions * PayPeriods) - (Pay.Salary * Deductions.RetirementPercentage); + double RunningTax = 0; + if (WorkingIncome <= 0) + return 0; + List TempRates = new(FederalTaxRates); + TempRates.Reverse(); + foreach (FederalTaxRate ftr in TempRates) + { + if (WorkingIncome > ftr.TaxableIncomeMinimum) + { + double TaxableAmount = WorkingIncome - ftr.TaxableIncomeMinimum; + RunningTax += (TaxableAmount * ftr.TaxPercentage); + WorkingIncome -= TaxableAmount; + } + } + return RunningTax / PayPeriods; + } + } +} diff --git a/RetirementCalculator/DataModels/FederalTaxRate.cs b/RetirementCalculator/DataModels/FederalTaxRate.cs new file mode 100644 index 0000000..d28e91c --- /dev/null +++ b/RetirementCalculator/DataModels/FederalTaxRate.cs @@ -0,0 +1,8 @@ +namespace RetirementCalculator +{ + public class FederalTaxRate + { + public double TaxableIncomeMinimum { get; set; } + public double TaxPercentage { get; set; } + } +} diff --git a/RetirementCalculator/DataModels/FilingStatus.cs b/RetirementCalculator/DataModels/FilingStatus.cs new file mode 100644 index 0000000..ba6a9d2 --- /dev/null +++ b/RetirementCalculator/DataModels/FilingStatus.cs @@ -0,0 +1,7 @@ +namespace RetirementCalculator +{ + public enum FilingStatus + { + Single, Married, HeadOfHousehold + } +} diff --git a/RetirementCalculator/DataModels/PayInformation.cs b/RetirementCalculator/DataModels/PayInformation.cs new file mode 100644 index 0000000..fdbc3ef --- /dev/null +++ b/RetirementCalculator/DataModels/PayInformation.cs @@ -0,0 +1,8 @@ +namespace RetirementCalculator +{ + public class PayInformation + { + public PayPeriod Period { get; set; } + public double Salary { get; set; } + } +} diff --git a/RetirementCalculator/DataModels/PayPeriod.cs b/RetirementCalculator/DataModels/PayPeriod.cs new file mode 100644 index 0000000..ca026c5 --- /dev/null +++ b/RetirementCalculator/DataModels/PayPeriod.cs @@ -0,0 +1,7 @@ +namespace RetirementCalculator +{ + public enum PayPeriod + { + EveryWeek, EveryOtherWeek, TwiceMonthly, Monthly, Annually + } +} diff --git a/RetirementCalculator/DataModels/TaxRates.cs b/RetirementCalculator/DataModels/TaxRates.cs new file mode 100644 index 0000000..de6e22b --- /dev/null +++ b/RetirementCalculator/DataModels/TaxRates.cs @@ -0,0 +1,130 @@ +namespace RetirementCalculator +{ + public class TaxRates + { + public double StateTax { get; set; } + public double LocalTax { get; set; } + public double SocialSecurityTax { get; set; } + public double MedicareTax { get; set; } + + public TaxRates() + { + StateTax = 0.0425; + LocalTax = 0.01; + SocialSecurityTax = 0.062; + MedicareTax = 0.0145; + } + + public double CalculateStateTax(PayInformation Pay, DeductionInformation Deductions) + { + double PayPeriods = 1; + switch (Pay.Period) + { + case PayPeriod.Annually: + PayPeriods = 1; + break; + case PayPeriod.Monthly: + PayPeriods = 12; + break; + case PayPeriod.TwiceMonthly: + PayPeriods = 24; + break; + case PayPeriod.EveryOtherWeek: + PayPeriods = 26; + break; + case PayPeriod.EveryWeek: + PayPeriods = 52; + break; + default: + PayPeriods = 1; + break; + } + return ((Pay.Salary - (Deductions.PreTaxDeductions * PayPeriods) - (Pay.Salary * Deductions.RetirementPercentage)) * StateTax) / PayPeriods; + } + + + public double CalculateLocalTax(PayInformation Pay, DeductionInformation Deductions) + { + double PayPeriods = 1; + switch (Pay.Period) + { + case PayPeriod.Annually: + PayPeriods = 1; + break; + case PayPeriod.Monthly: + PayPeriods = 12; + break; + case PayPeriod.TwiceMonthly: + PayPeriods = 24; + break; + case PayPeriod.EveryOtherWeek: + PayPeriods = 26; + break; + case PayPeriod.EveryWeek: + PayPeriods = 52; + break; + default: + PayPeriods = 1; + break; + } + return ((Pay.Salary - (Deductions.PreTaxDeductions * PayPeriods) - (Pay.Salary * Deductions.RetirementPercentage)) * LocalTax) / PayPeriods; + } + + + public double CalculateSocialSecurityTax(PayInformation Pay, DeductionInformation Deductions) + { + double PayPeriods = 1; + switch (Pay.Period) + { + case PayPeriod.Annually: + PayPeriods = 1; + break; + case PayPeriod.Monthly: + PayPeriods = 12; + break; + case PayPeriod.TwiceMonthly: + PayPeriods = 24; + break; + case PayPeriod.EveryOtherWeek: + PayPeriods = 26; + break; + case PayPeriod.EveryWeek: + PayPeriods = 52; + break; + default: + PayPeriods = 1; + break; + } + return ((Pay.Salary - (Deductions.PreTaxDeductions * PayPeriods)) * SocialSecurityTax) / PayPeriods; + } + + + public double CalculateMedicareTax(PayInformation Pay, DeductionInformation Deductions) + { + double PayPeriods = 1; + switch (Pay.Period) + { + case PayPeriod.Annually: + PayPeriods = 1; + break; + case PayPeriod.Monthly: + PayPeriods = 12; + break; + case PayPeriod.TwiceMonthly: + PayPeriods = 24; + break; + case PayPeriod.EveryOtherWeek: + PayPeriods = 26; + break; + case PayPeriod.EveryWeek: + PayPeriods = 52; + break; + default: + PayPeriods = 1; + break; + } + return ((Pay.Salary - (Deductions.PreTaxDeductions * PayPeriods)) * MedicareTax) / PayPeriods; + } + + } +} diff --git a/RetirementCalculator/MVVM/ModelBase.cs b/RetirementCalculator/MVVM/ModelBase.cs new file mode 100644 index 0000000..51af92b --- /dev/null +++ b/RetirementCalculator/MVVM/ModelBase.cs @@ -0,0 +1,13 @@ +namespace RetirementCalculator +{ + public abstract class ModelBase : PropertyChangedBase + { + public void SetProperty(ref T storage, T value, string name) + { + if (value == null) + throw new InvalidCastException("ModelBase.UpdateProperty\nValue cannot be null."); + storage = value; + OnPropertyChanged(name); + } + } +} diff --git a/RetirementCalculator/MVVM/PropertyChangedBase.cs b/RetirementCalculator/MVVM/PropertyChangedBase.cs new file mode 100644 index 0000000..dc16eee --- /dev/null +++ b/RetirementCalculator/MVVM/PropertyChangedBase.cs @@ -0,0 +1,10 @@ +using System.ComponentModel; + +namespace RetirementCalculator +{ + public abstract class PropertyChangedBase : INotifyPropertyChanged + { + public event PropertyChangedEventHandler PropertyChanged; + public void OnPropertyChanged(string name) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name)); + } +} diff --git a/RetirementCalculator/MVVM/RelayCommand.cs b/RetirementCalculator/MVVM/RelayCommand.cs new file mode 100644 index 0000000..2632ead --- /dev/null +++ b/RetirementCalculator/MVVM/RelayCommand.cs @@ -0,0 +1,33 @@ +using System.Windows.Input; + +namespace RetirementCalculator +{ + public class RelayCommand : ICommand + { + private Action execute; + private Func? canExecute; + + + public event EventHandler? CanExecuteChanged + { + add { CommandManager.RequerySuggested += value; } + remove { CommandManager.RequerySuggested -= value; } + } + + public RelayCommand(Action execute, Func? canExecute = null) + { + this.execute = execute; + this.canExecute = canExecute; + } + + public bool CanExecute(object? parameter) + { + return this.canExecute == null || this.canExecute(parameter); + } + + public void Execute(object? parameter) + { + this.execute(parameter); + } + } +} diff --git a/RetirementCalculator/MainWindow.xaml b/RetirementCalculator/MainWindow.xaml new file mode 100644 index 0000000..850fe0e --- /dev/null +++ b/RetirementCalculator/MainWindow.xaml @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +