diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..36ebf9e4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,12 @@ +################################################################################ +# This .gitignore file was automatically created by Microsoft(R) Visual Studio. +################################################################################ + +/C#/TollCalculatorTests/TollCalculatorTests/TollCalculatorTests/obj/Debug/netcoreapp3.1 +/C#/TollCalculator/TollCalculator/obj +/C#/TollCalculator/.vs/TollCalculator/v16 +/C#/TollCalculator/App/obj +/C#/TollCalculator/App/bin/Debug/netcoreapp3.1 +/C#/TollCalculator/.vs/TollCalculator/DesignTimeBuild +/C#/TollCalculator/TollCalculatorTests/bin/Debug/netcoreapp3.1 +/C#/TollCalculator/TollCalculatorTests/obj diff --git a/C#/Car.cs b/C#/Car.cs deleted file mode 100644 index 6015da69..00000000 --- a/C#/Car.cs +++ /dev/null @@ -1,16 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace TollFeeCalculator -{ - public class Car : Vehicle - { - public String GetVehicleType() - { - return "Car"; - } - } -} \ No newline at end of file diff --git a/C#/Motorbike.cs b/C#/Motorbike.cs deleted file mode 100644 index 8258109f..00000000 --- a/C#/Motorbike.cs +++ /dev/null @@ -1,16 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace TollFeeCalculator -{ - public class Motorbike : Vehicle - { - public string GetVehicleType() - { - return "Motorbike"; - } - } -} diff --git a/C#/TollCalculator.cs b/C#/TollCalculator.cs deleted file mode 100644 index b24c794d..00000000 --- a/C#/TollCalculator.cs +++ /dev/null @@ -1,108 +0,0 @@ -using System; -using System.Globalization; -using TollFeeCalculator; - -public class TollCalculator -{ - - /** - * Calculate the total toll fee for one day - * - * @param vehicle - the vehicle - * @param dates - date and time of all passes on one day - * @return - the total toll fee for that day - */ - - public int GetTollFee(Vehicle vehicle, DateTime[] dates) - { - DateTime intervalStart = dates[0]; - int totalFee = 0; - foreach (DateTime date in dates) - { - int nextFee = GetTollFee(date, vehicle); - int tempFee = GetTollFee(intervalStart, vehicle); - - long diffInMillies = date.Millisecond - intervalStart.Millisecond; - long minutes = diffInMillies/1000/60; - - if (minutes <= 60) - { - if (totalFee > 0) totalFee -= tempFee; - if (nextFee >= tempFee) tempFee = nextFee; - totalFee += tempFee; - } - else - { - totalFee += nextFee; - } - } - if (totalFee > 60) totalFee = 60; - return totalFee; - } - - private bool IsTollFreeVehicle(Vehicle vehicle) - { - if (vehicle == null) return false; - String vehicleType = vehicle.GetVehicleType(); - return vehicleType.Equals(TollFreeVehicles.Motorbike.ToString()) || - vehicleType.Equals(TollFreeVehicles.Tractor.ToString()) || - vehicleType.Equals(TollFreeVehicles.Emergency.ToString()) || - vehicleType.Equals(TollFreeVehicles.Diplomat.ToString()) || - vehicleType.Equals(TollFreeVehicles.Foreign.ToString()) || - vehicleType.Equals(TollFreeVehicles.Military.ToString()); - } - - public int GetTollFee(DateTime date, Vehicle vehicle) - { - if (IsTollFreeDate(date) || IsTollFreeVehicle(vehicle)) return 0; - - int hour = date.Hour; - int minute = date.Minute; - - if (hour == 6 && minute >= 0 && minute <= 29) return 8; - else if (hour == 6 && minute >= 30 && minute <= 59) return 13; - else if (hour == 7 && minute >= 0 && minute <= 59) return 18; - else if (hour == 8 && minute >= 0 && minute <= 29) return 13; - else if (hour >= 8 && hour <= 14 && minute >= 30 && minute <= 59) return 8; - else if (hour == 15 && minute >= 0 && minute <= 29) return 13; - else if (hour == 15 && minute >= 0 || hour == 16 && minute <= 59) return 18; - else if (hour == 17 && minute >= 0 && minute <= 59) return 13; - else if (hour == 18 && minute >= 0 && minute <= 29) return 8; - else return 0; - } - - private Boolean IsTollFreeDate(DateTime date) - { - int year = date.Year; - int month = date.Month; - int day = date.Day; - - if (date.DayOfWeek == DayOfWeek.Saturday || date.DayOfWeek == DayOfWeek.Sunday) return true; - - if (year == 2013) - { - if (month == 1 && day == 1 || - month == 3 && (day == 28 || day == 29) || - month == 4 && (day == 1 || day == 30) || - month == 5 && (day == 1 || day == 8 || day == 9) || - month == 6 && (day == 5 || day == 6 || day == 21) || - month == 7 || - month == 11 && day == 1 || - month == 12 && (day == 24 || day == 25 || day == 26 || day == 31)) - { - return true; - } - } - return false; - } - - private enum TollFreeVehicles - { - Motorbike = 0, - Tractor = 1, - Emergency = 2, - Diplomat = 3, - Foreign = 4, - Military = 5 - } -} \ No newline at end of file diff --git a/C#/TollCalculator/App/Car.cs b/C#/TollCalculator/App/Car.cs new file mode 100644 index 00000000..cf98ab13 --- /dev/null +++ b/C#/TollCalculator/App/Car.cs @@ -0,0 +1,12 @@ +using TollCalculatorApp; + +namespace TollFeeCalculator +{ + public class Car : IVehicle + { + public VehicleType GetVehicleType() + { + return VehicleType.Car; + } + } +} \ No newline at end of file diff --git a/C#/TollCalculator/App/Extensions/DateTimeExtension.cs b/C#/TollCalculator/App/Extensions/DateTimeExtension.cs new file mode 100644 index 00000000..38d5bea9 --- /dev/null +++ b/C#/TollCalculator/App/Extensions/DateTimeExtension.cs @@ -0,0 +1,34 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace TollCalculatorApp +{ + public static class DateTimeExtension + { + + /// + /// Determines if date is between two Timespans representing time of day + /// + public static bool IsBetweenTimes(this DateTime date, TimeSpan start, TimeSpan end) + { + if(start <= end) + return date.TimeOfDay >= start && date.TimeOfDay < end; + else + throw new ArgumentException("End must be later than start"); + } + + /// + /// This method returns wether a datetime is a weekend day or not + /// + public static bool IsWeekend(this DateTime date) + { + if (date.DayOfWeek == DayOfWeek.Saturday || date.DayOfWeek == DayOfWeek.Sunday) + return true; + + return false; + } + } +} + diff --git a/C#/TollCalculator/App/IVehicle.cs b/C#/TollCalculator/App/IVehicle.cs new file mode 100644 index 00000000..a4232455 --- /dev/null +++ b/C#/TollCalculator/App/IVehicle.cs @@ -0,0 +1,9 @@ +using TollCalculatorApp; + +namespace TollFeeCalculator +{ + public interface IVehicle + { + VehicleType GetVehicleType(); + } +} diff --git a/C#/TollCalculator/App/Motorbike.cs b/C#/TollCalculator/App/Motorbike.cs new file mode 100644 index 00000000..98460948 --- /dev/null +++ b/C#/TollCalculator/App/Motorbike.cs @@ -0,0 +1,13 @@ + +using TollCalculatorApp; + +namespace TollFeeCalculator +{ + public class Motorbike : IVehicle + { + public VehicleType GetVehicleType() + { + return VehicleType.Motorbike; + } + } +} diff --git a/C#/TollCalculator/App/Program.cs b/C#/TollCalculator/App/Program.cs new file mode 100644 index 00000000..a3de7ee2 --- /dev/null +++ b/C#/TollCalculator/App/Program.cs @@ -0,0 +1,13 @@ +using System; + +namespace TollFeeCalculator +{ + class Program + { + static void Main(string[] args) + { + Console.WriteLine("Hello World!"); + + } + } +} diff --git a/C#/TollCalculator/App/Services/Interfaces/IHolidayService.cs b/C#/TollCalculator/App/Services/Interfaces/IHolidayService.cs new file mode 100644 index 00000000..0903a7c0 --- /dev/null +++ b/C#/TollCalculator/App/Services/Interfaces/IHolidayService.cs @@ -0,0 +1,11 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace TollCalculatorApp.Services.Interfaces +{ + public interface IHolidayService + { + bool IsHoliday(DateTime date); + } +} diff --git a/C#/TollCalculator/App/Services/SwedishHolidayService.cs b/C#/TollCalculator/App/Services/SwedishHolidayService.cs new file mode 100644 index 00000000..013480a8 --- /dev/null +++ b/C#/TollCalculator/App/Services/SwedishHolidayService.cs @@ -0,0 +1,139 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using TollCalculatorApp.Services.Interfaces; + +namespace TollCalculatorApp.Services +{ + + public class SwedishHolidayService : IHolidayService + { + + /// + /// Determines if date is the same day as any of the swedish bank-holidays + /// + public bool IsHoliday(DateTime date) + { + var holidays = GetSwedishHolidays(date.Year); + + if (holidays.Any(holiday => holiday.Month == date.Month && holiday.Day == date.Day)) + return true; + + return false; + } + + /// + /// This method returns the swedish bank holidays + /// + /// The year you want days to be generated for + /// List of DateTimes where swedish holidays occur + /// + /// *I assumed that the "holidays" in the description in this repository meant bank-holidays + /// Used the following list of holidays https://www.riksbank.se/en-gb/press-and-published/calendar/bank-holidays-2021/ + private List GetSwedishHolidays(int year) + { + //Holidays that are in terms of date of month - they occur at the same date of a month each year. + var Holidays = new List() { + new DateTime(year, 1, 1), //New years day + new DateTime(year, 1, 6), //Epiphany + new DateTime(year, 5,1), //First of May + new DateTime(year, 6,6), //Swedish national day + new DateTime(year, 12,24), //Christmas eve + new DateTime(year, 12,25), //Chirstmas day + new DateTime(year, 12,26), //Boxing day + new DateTime(year, 12,31) //New years eve + }; + + //Holidays that are not the same date of month each year + var calculatedHolidays = new List(); + calculatedHolidays.Add(GetEasterDay(year).AddDays(-2)); //Good Friday + calculatedHolidays.Add(GetEasterDay(year).AddDays(-1)); //Easter Eve + calculatedHolidays.Add(GetEasterDay(year)); // Easter Sunday + calculatedHolidays.Add(GetEasterDay(year).AddDays(1)); // Easter Monday + calculatedHolidays.Add(GetMidsummerDay(year).AddDays(-1)); //Midsummers eve + calculatedHolidays.Add(GetMidsummerDay(year)); + calculatedHolidays.Add(GetAllSaintsDay(year)); + calculatedHolidays.Add(GetAscensionDay(year)); + calculatedHolidays.Add(GetPentecostDay(year)); + calculatedHolidays.Add(GetPentecostDay(year).AddDays(-1)); //Whitsun + + var swedishHolidays = new List(); + swedishHolidays.AddRange(Holidays); + swedishHolidays.AddRange(calculatedHolidays); + + return swedishHolidays; + } + + + + //This method uses Gauss algorithm to calculate easter day + //The algorithm used here was copied from following stack-exchange article: https://codereview.stackexchange.com/q/193847 + /// + /// This method calculates the day that Easter day occur on + /// + /// The year you want to get the date of Easter day for + /// DateTime that Easter day occur on + private DateTime GetEasterDay(int year) + { + int a = year % 19; + int b = year / 100; + int c = (b - (b / 4) - ((8 * b + 13) / 25) + (19 * a) + 15) % 30; + int d = c - (c / 28) * (1 - (c / 28) * (29 / (c + 1)) * ((21 - a) / 11)); + int e = d - ((year + (year / 4) + d + 2 - b + (b / 4)) % 7); + int month = 3 + ((e + 40) / 44); + int day = e + 28 - (31 * (month / 4)); + return new DateTime(year, month, day); + } + + /// + /// This method calculates the day that All saints day occur on + /// + /// The year you want to get the date of all saints day for + /// DateTime that all saints day occur on + private DateTime GetAllSaintsDay(int year) + { + var date = new DateTime(year, 10, 31); + while (date.DayOfWeek != DayOfWeek.Saturday) + { + date = date.AddDays(1); + } + return date; + } + + /// + /// This method calculates the day that All saints day occur on + /// + /// The year you want to get the date of All saints day for + /// DateTime that ascension day occur on + private DateTime GetAscensionDay(int year) + { + return GetEasterDay(year).AddDays(39); + } + + /// + /// This method calculates the day that Pentecost occur on + /// + /// The year you want to get the date of Pentecost for + /// DateTime that Pentecost occur on + private DateTime GetPentecostDay(int year) + { + return GetEasterDay(year).AddDays(49); + } + + /// + /// This method calculates the day that Midsummer day occur on + /// + /// The year you want to get the date of Midsummer day for + /// DateTime that Midsummer day occur on + private DateTime GetMidsummerDay(int year) + { + var date = new DateTime(year, 6, 20); + while (date.DayOfWeek != DayOfWeek.Saturday) + { + date = date.AddDays(1); + } + + return date; + } + } +} diff --git a/C#/TollCalculator/App/TollCalculator.cs b/C#/TollCalculator/App/TollCalculator.cs new file mode 100644 index 00000000..0a9fa182 --- /dev/null +++ b/C#/TollCalculator/App/TollCalculator.cs @@ -0,0 +1,108 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using TollCalculatorApp; +using TollCalculatorApp.Services.Interfaces; + +namespace TollFeeCalculator +{ + public class TollCalculator + { + + private readonly IHolidayService _holidayService; + + public TollCalculator(IHolidayService holidayService) + { + _holidayService = holidayService; + } + const int MaxTollFee = 60; + private readonly List _tollFreeVehicles = new List + { + VehicleType.Motorbike, + VehicleType.Tractor, + VehicleType.Emergency, + VehicleType.Diplomat, + VehicleType.Foreign, + VehicleType.Military + }; + + /** + * Calculate the total toll fee for one day + * + * @param vehicle - the vehicle + * @param dates - date and time of all passes on one day + * @return - the total toll fee for that day + */ + public int GetTollFee(IVehicle vehicle, DateTime[] dates) + { + var sortedDate = dates.OrderBy(date => date.Ticks).ToList(); + DateTime intervalStart = sortedDate[0]; + int totalFee = 0; + foreach (DateTime date in sortedDate) + { + int nextFee = GetTollFee(date, vehicle); + int tempFee = GetTollFee(intervalStart, vehicle); + + TimeSpan diffBetweenDates = date - intervalStart; + if (diffBetweenDates.TotalMinutes <= 60) + { + if (totalFee > 0) totalFee -= tempFee; + if (nextFee >= tempFee) tempFee = nextFee; + totalFee += tempFee; + } + else + { + totalFee += nextFee; + } + } + if (totalFee > MaxTollFee) + return MaxTollFee; + + return totalFee; + } + public int GetTollFee(DateTime date, IVehicle vehicle) + { + if (IsTollFreeVehicle(vehicle) || IsTollFreeDate(date)) + return 0; + + + if (date.IsBetweenTimes(TimeSpan.Parse("06:00"), TimeSpan.Parse("06:30"))) return 8; + if (date.IsBetweenTimes(TimeSpan.Parse("06:30"), TimeSpan.Parse("07:00"))) return 13; + if (date.IsBetweenTimes(TimeSpan.Parse("07:00"), TimeSpan.Parse("08:00"))) return 18; + if (date.IsBetweenTimes(TimeSpan.Parse("08:00"), TimeSpan.Parse("08:30"))) return 13; + + //The following condition was translated from previous code - I think it might have contained an error + // else if (hour >= 8 && hour <= 14 && minute >= 30 && minute <= 59) return 8; + // would have been translated to x:30 - x:59 where x would be the hours 8 to 14 + // leaving x:00 - x.29 toll free for each of the hours between 8-14. + if (date.IsBetweenTimes(TimeSpan.Parse("08:30"), TimeSpan.Parse("15:00"))) return 8; + + if (date.IsBetweenTimes(TimeSpan.Parse("15:00"), TimeSpan.Parse("15:30"))) return 13; + if (date.IsBetweenTimes(TimeSpan.Parse("15:30"), TimeSpan.Parse("17:00"))) return 18; + if (date.IsBetweenTimes(TimeSpan.Parse("17:00"), TimeSpan.Parse("18:00"))) return 13; + if (date.IsBetweenTimes(TimeSpan.Parse("18:00"), TimeSpan.Parse("18:30"))) return 8; + + return 0; + } + private bool IsTollFreeVehicle(IVehicle vehicle) + { + if (vehicle == null) return false; + + if (_tollFreeVehicles.Any(tollFreeVehicle => tollFreeVehicle == vehicle.GetVehicleType())) + return true; + else + { + return false; + } + } + private bool IsTollFreeDate(DateTime date) + { + if (date.IsWeekend() || _holidayService.IsHoliday(date)) + { + return true; + } + + return false; + } + } +} diff --git a/C#/TollCalculator/App/TollFeeCalculator.csproj b/C#/TollCalculator/App/TollFeeCalculator.csproj new file mode 100644 index 00000000..783b01e7 --- /dev/null +++ b/C#/TollCalculator/App/TollFeeCalculator.csproj @@ -0,0 +1,10 @@ + + + + Exe + netcoreapp3.1 + TollCalculatorApp + TollCalculatorApp + + + diff --git a/C#/TollCalculator/App/VehicleType.cs b/C#/TollCalculator/App/VehicleType.cs new file mode 100644 index 00000000..4c675b5f --- /dev/null +++ b/C#/TollCalculator/App/VehicleType.cs @@ -0,0 +1,13 @@ +namespace TollCalculatorApp +{ + public enum VehicleType + { + Car = 0, + Motorbike = 1, + Tractor = 2, + Emergency = 3, + Diplomat = 4, + Foreign = 5, + Military = 6 + } +} diff --git a/C#/TollCalculator/TollCalculator.sln b/C#/TollCalculator/TollCalculator.sln new file mode 100644 index 00000000..58051d6f --- /dev/null +++ b/C#/TollCalculator/TollCalculator.sln @@ -0,0 +1,31 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.31702.278 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TollCalculatorTests", "TollCalculatorTests\TollCalculatorTests.csproj", "{F39C7F86-39BB-4DEF-9173-B29CE4505CC7}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TollFeeCalculator", "App\TollFeeCalculator.csproj", "{FA02706B-6499-4B92-96B0-8ED66B852982}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {F39C7F86-39BB-4DEF-9173-B29CE4505CC7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F39C7F86-39BB-4DEF-9173-B29CE4505CC7}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F39C7F86-39BB-4DEF-9173-B29CE4505CC7}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F39C7F86-39BB-4DEF-9173-B29CE4505CC7}.Release|Any CPU.Build.0 = Release|Any CPU + {FA02706B-6499-4B92-96B0-8ED66B852982}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {FA02706B-6499-4B92-96B0-8ED66B852982}.Debug|Any CPU.Build.0 = Debug|Any CPU + {FA02706B-6499-4B92-96B0-8ED66B852982}.Release|Any CPU.ActiveCfg = Release|Any CPU + {FA02706B-6499-4B92-96B0-8ED66B852982}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {B2FD73E7-0D65-4896-B94F-9788D8030169} + EndGlobalSection +EndGlobal diff --git a/C#/TollCalculator/TollCalculatorTests/Extensions/DateTimeExtensionTests.cs b/C#/TollCalculator/TollCalculatorTests/Extensions/DateTimeExtensionTests.cs new file mode 100644 index 00000000..6c8c5f76 --- /dev/null +++ b/C#/TollCalculator/TollCalculatorTests/Extensions/DateTimeExtensionTests.cs @@ -0,0 +1,62 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; +using System; +using System.Collections.Generic; +using System.Text; +using TollCalculatorApp; + +namespace TollFeeCalculatorTests +{ + [TestClass] + public class DateTimeExtensionTests + { + #region IsBetweenTimes + [TestMethod] + public void IsBetweenTimes_Simple_DateTime_Comparison() + { + var testDate = new DateTime(2020, 01, 01, 10, 0, 0); + var isBetween = testDate.IsBetweenTimes(TimeSpan.Parse("09:00"), TimeSpan.Parse("10:30")); + + Assert.IsTrue(isBetween); + } + [TestMethod] + public void IsBetweenTimes_Start_Same_As_Date_Being_Compared() + { + var testDate = new DateTime(2020, 01, 01, 9, 0, 0); + var isBetween = testDate.IsBetweenTimes(TimeSpan.Parse("09:00"), TimeSpan.Parse("10:30")); + + Assert.IsTrue(isBetween); + } + [TestMethod] + public void IsBetweenTimes_End_Same_As_Date_Being_Compared() + { + var testDate = new DateTime(2020, 01, 01, 10, 0, 0); + var isBetween = testDate.IsBetweenTimes(TimeSpan.Parse("09:00"), TimeSpan.Parse("10:00")); + + Assert.IsFalse(isBetween); + } + + + #endregion + + #region IsWeekend + [TestMethod] + public void IsWeekend_Saturday() + { + var testDate = new DateTime(2021, 01, 02, 10, 0, 0); + Assert.IsTrue(testDate.IsWeekend()); + } + [TestMethod] + public void IsWeekend_Sunday() + { + var testDate = new DateTime(2021, 01, 03, 10, 0, 0); + Assert.IsTrue(testDate.IsWeekend()); + } + [TestMethod] + public void IsWeekend_Weekday() + { + var testDate = new DateTime(2021, 01, 04, 10, 0, 0); + Assert.IsFalse(testDate.IsWeekend()); + } + #endregion + } +} diff --git a/C#/TollCalculator/TollCalculatorTests/Services/SwedishHolidayServiceTest.cs b/C#/TollCalculator/TollCalculatorTests/Services/SwedishHolidayServiceTest.cs new file mode 100644 index 00000000..016a56f3 --- /dev/null +++ b/C#/TollCalculator/TollCalculatorTests/Services/SwedishHolidayServiceTest.cs @@ -0,0 +1,130 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; +using System; +using TollCalculatorApp.Services; +using TollCalculatorApp.Services.Interfaces; + +namespace TollFeeCalculatorTests +{ + [TestClass] + public class SwedishHolidayServiceTest + { + private IHolidayService _holidayService; + + [TestInitialize] + public void TestInitialize() + { + _holidayService = new SwedishHolidayService(); + } + + #region IsSwedishHoliday Tests + [TestMethod] + public void NewYearsDayTest() + { + var date = new DateTime(2021, 1, 1); + Assert.IsTrue(_holidayService.IsHoliday(date), "Expected New Years day to be in list of holidays"); + } + [TestMethod] + public void EpiphanyTest() + { + var date = new DateTime(2021, 1, 6); + Assert.IsTrue(_holidayService.IsHoliday(date), "Expected Epiphany to be holiday"); + } + [TestMethod] + public void GoodFridayTest() + { + var date = new DateTime(2021, 4, 2); + Assert.IsTrue(_holidayService.IsHoliday(date), "Expected Good friday to be holiday"); + } + [TestMethod] + public void EasterEveTest() + { + var date = new DateTime(2021, 4, 3); + Assert.IsTrue(_holidayService.IsHoliday(date), "Expected Easter Eve to be holiday"); + } + [TestMethod] + public void EasterSundayTest() + { + var date = new DateTime(2021, 4, 4); + Assert.IsTrue(_holidayService.IsHoliday(date), "Expected Easter Sunday to be holiday"); + } + [TestMethod] + public void EasterMondayTest() + { + var date = new DateTime(2021, 4, 5); + Assert.IsTrue(_holidayService.IsHoliday(date), "Expected Easter Monday to be holiday"); + } + [TestMethod] + public void LabourDayTest() + { + var date = new DateTime(2021, 5, 1); + Assert.IsTrue(_holidayService.IsHoliday(date), "Expected Labour Day to be holiday"); + } + [TestMethod] + public void AcensionDayTest() + { + var date = new DateTime(2021, 5, 13); + Assert.IsTrue(_holidayService.IsHoliday(date), "Expected Acension Day to be holiday"); + } + [TestMethod] + public void WhitsunTest() + { + var date = new DateTime(2021, 5, 22); + Assert.IsTrue(_holidayService.IsHoliday(date), "Expected Whitsun to be holiday"); + } + [TestMethod] + public void PentecostTest() + { + var date = new DateTime(2021, 5, 23); + Assert.IsTrue(_holidayService.IsHoliday(date), "Expected Pentecost to be holiday"); + } + [TestMethod] + public void NationalDayTest() + { + var date = new DateTime(2021, 6, 6); + Assert.IsTrue(_holidayService.IsHoliday(date), "Expected National Day to be holiday"); + } + [TestMethod] + public void MidsummerEveTest() + { + var date = new DateTime(2021, 6, 25); + Assert.IsTrue(_holidayService.IsHoliday(date), "Expected Midsummer Eve to be holiday"); + } + [TestMethod] + public void MidsummerDayTest() + { + var date = new DateTime(2021, 6, 26); + Assert.IsTrue(_holidayService.IsHoliday(date), "Expected Midsummer Day to be holiday"); + } + [TestMethod] + public void AllSaintsDayTest() + { + var date = new DateTime(2021, 11, 6); + Assert.IsTrue(_holidayService.IsHoliday(date), "Expected All saints Day to be holiday"); + } + [TestMethod] + public void ChristmasEveTest() + { + var date = new DateTime(2021, 12, 24); + Assert.IsTrue(_holidayService.IsHoliday(date), "Expected Christmas Eve to be holiday"); + } + [TestMethod] + public void ChristmasDayTest() + { + var date = new DateTime(2021, 12, 25); + Assert.IsTrue(_holidayService.IsHoliday(date), "Expected Christmas Day to be holiday"); + } + [TestMethod] + public void BoxingDayTest() + { + var date = new DateTime(2021, 12, 26); + Assert.IsTrue(_holidayService.IsHoliday(date), "Expected Boxing to be holiday"); + } + [TestMethod] + public void NewYearsEveTest() + { + var date = new DateTime(2021, 12, 31); + Assert.IsTrue(_holidayService.IsHoliday(date), "Expected New Year's Eve to be holiday"); + } + #endregion + } +} diff --git a/C#/TollCalculator/TollCalculatorTests/TollCalculatorTests.cs b/C#/TollCalculator/TollCalculatorTests/TollCalculatorTests.cs new file mode 100644 index 00000000..2d470fa1 --- /dev/null +++ b/C#/TollCalculator/TollCalculatorTests/TollCalculatorTests.cs @@ -0,0 +1,121 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; +using System; +using TollCalculatorApp.Services; +using TollFeeCalculator; + +namespace TollFeeCalculatorTests +{ + [TestClass] + public class TollCalculatorTests + { + private TollCalculator _tollCalculator; + + [TestInitialize] + public void TestInitialize() + { + var holidayService = new SwedishHolidayService(); + _tollCalculator = new TollCalculator(holidayService); + } + + [TestMethod] + public void Maximum_Fee_Per_Day() + { + //Arrange + var vehicle = new Car(); + + var dates = new DateTime[] { + new DateTime(2021, 10, 6, 7, 0, 0), + new DateTime(2021, 10, 6, 9, 0, 0), + new DateTime(2021, 10, 6, 11, 0, 0), + new DateTime(2021, 10, 6, 13, 0, 0), + new DateTime(2021, 10, 6, 15, 0, 0), + new DateTime(2021, 10, 6, 17, 0, 0) + }; + + //Act + var tollFee = _tollCalculator.GetTollFee(vehicle, dates); + + //Assert + Assert.AreEqual(60, tollFee, "Expected max fee for a day to be 60"); + } + + [TestMethod] + public void Fee_Free_Vehicle_Returns_No_Fee() + { + //Arrange + var vehicle = new Motorbike(); + var dates = new DateTime[] { new DateTime(2021, 01, 01, 10, 0, 0) }; + + //Act + var tollFee = _tollCalculator.GetTollFee(vehicle, dates); + + //Assert + Assert.AreEqual(0, tollFee, "Expected motorbike to be tollfree vehicle"); + } + + [TestMethod] + public void Fee_Free_Holiday_Returns_No_Fee() + { + //Arrange + var vehicle = new Car(); + var dates = new DateTime[] { new DateTime(2021, 01, 01, 10, 0, 0) }; + + //Act + var tollFee = _tollCalculator.GetTollFee(vehicle, dates); + + //Assert + Assert.AreEqual(0, tollFee, "Expected no tax on holiday"); + } + + [TestMethod] + public void Highest_Fee_Is_Applied_For_Fees_Within_60_Minutes() + { + //Arrange + var vehicle = new Car(); + var dates = new DateTime[] { + new DateTime(2021, 02, 01, 15, 0, 0), + new DateTime(2021, 02, 01, 15, 35, 0) + }; + + //Act + var tollFee = _tollCalculator.GetTollFee(vehicle, dates); + + //Assert + Assert.AreEqual(18, tollFee, "Expected highest fee to be returned"); + } + + [TestMethod] + public void One_TollStation_Pass_Returns_Correct_Fee() + { + //Arrange + var vehicle = new Car(); + var dates = new DateTime[] { + new DateTime(2021, 02, 01, 15, 0, 0) + }; + + //Act + var tollFee = _tollCalculator.GetTollFee(vehicle, dates); + + //Assert + Assert.AreEqual(13, tollFee); + } + [TestMethod] + public void Large_Amount_of_TollStation_Passes_Returns_Correct_Fee() + { + //Arrange + var vehicle = new Car(); + var dates = new DateTime[] { + new DateTime(2021, 02, 01, 6, 0, 0), + new DateTime(2021, 02, 01, 10, 0, 0), + new DateTime(2021, 02, 01, 15, 0, 0), + new DateTime(2021, 02, 01, 18, 0, 0), + }; + + //Act + var tollFee = _tollCalculator.GetTollFee(vehicle, dates); + + //Assert + Assert.AreEqual(37, tollFee); + } + } +} diff --git a/C#/TollCalculator/TollCalculatorTests/TollCalculatorTests.csproj b/C#/TollCalculator/TollCalculatorTests/TollCalculatorTests.csproj new file mode 100644 index 00000000..2c5f18f5 --- /dev/null +++ b/C#/TollCalculator/TollCalculatorTests/TollCalculatorTests.csproj @@ -0,0 +1,24 @@ + + + + netcoreapp3.1 + + false + + TollFeeCalculator + + TollFeeCalculator + + + + + + + + + + + + + + diff --git a/C#/Vehicle.cs b/C#/Vehicle.cs deleted file mode 100644 index 19fe04e4..00000000 --- a/C#/Vehicle.cs +++ /dev/null @@ -1,13 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace TollFeeCalculator -{ - public interface Vehicle - { - String GetVehicleType(); - } -} \ No newline at end of file