diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..1c9a181a --- /dev/null +++ b/.gitignore @@ -0,0 +1,242 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. + +# User-specific files +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +[Xx]64/ +[Xx]86/ +[Bb]uild/ +bld/ +[Bb]in/ +[Oo]bj/ + +# Visual Studio 2015 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUNIT +*.VisualState.xml +TestResult.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# DNX +project.lock.json +artifacts/ + +*_i.c +*_p.c +*_i.h +*.ilk +*.meta +*.obj +*.pch +*.pdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# JustCode is a .NET coding add-in +.JustCode + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml + +# TODO: Un-comment the next line if you do not want to checkin +# your web deploy settings because they may include unencrypted +# passwords +#*.pubxml +*.publishproj + +# NuGet Packages +*.nupkg +# The packages folder can be ignored because of Package Restore +**/packages/* +# except build/, which is used as an MSBuild target. +!**/packages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/packages/repositories.config +# NuGet v3's project.json files produces more ignoreable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directory +AppPackages/ +BundleArtifacts/ + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!*.[Cc]ache/ + +# Others +ClientBin/ +[Ss]tyle[Cc]op.* +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.pfx +*.publishsettings +node_modules/ +orleans.codegen.cs + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm + +# SQL Server files +*.mdf +*.ldf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# LightSwitch generated files +GeneratedArtifacts/ +ModelManifest.xml + +# Paket dependency manager +.paket/paket.exe + +# FAKE - F# Make +.fake/ diff --git a/BDD/BerlinClockFeatureSteps.cs b/BDD/BerlinClockFeatureSteps.cs index 4390f3cb..e76f290f 100644 --- a/BDD/BerlinClockFeatureSteps.cs +++ b/BDD/BerlinClockFeatureSteps.cs @@ -1,7 +1,6 @@ using System; using TechTalk.SpecFlow; using Microsoft.VisualStudio.TestTools.UnitTesting; -using System.Linq; namespace BerlinClock { @@ -21,7 +20,7 @@ public void WhenTheTimeIs(string time) [Then(@"the clock should look like")] public void ThenTheClockShouldLookLike(string theExpectedBerlinClockOutput) { - Assert.AreEqual(berlinClock.convertTime(theTime), theExpectedBerlinClockOutput); + Assert.AreEqual(theExpectedBerlinClockOutput, berlinClock.convertTime(theTime)); } } diff --git a/BerlinClock.csproj b/BerlinClock.csproj index ac8af99d..6e05a898 100644 --- a/BerlinClock.csproj +++ b/BerlinClock.csproj @@ -50,6 +50,10 @@ + + + + True diff --git a/BerlinClock.sln b/BerlinClock.sln index 082911a2..fa9af929 100644 --- a/BerlinClock.sln +++ b/BerlinClock.sln @@ -1,10 +1,12 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 2013 -VisualStudioVersion = 12.0.21005.1 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.30011.22 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BerlinClock", "BerlinClock.csproj", "{0451204D-BF86-43E1-B560-FC9AC830B9A9}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BerlinClockUnitTests", "BerlinClockUnitTests\BerlinClockUnitTests.csproj", "{013DA9D0-D676-4BB8-9EE6-CA1FC180CA62}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -15,8 +17,15 @@ Global {0451204D-BF86-43E1-B560-FC9AC830B9A9}.Debug|Any CPU.Build.0 = Debug|Any CPU {0451204D-BF86-43E1-B560-FC9AC830B9A9}.Release|Any CPU.ActiveCfg = Release|Any CPU {0451204D-BF86-43E1-B560-FC9AC830B9A9}.Release|Any CPU.Build.0 = Release|Any CPU + {013DA9D0-D676-4BB8-9EE6-CA1FC180CA62}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {013DA9D0-D676-4BB8-9EE6-CA1FC180CA62}.Debug|Any CPU.Build.0 = Debug|Any CPU + {013DA9D0-D676-4BB8-9EE6-CA1FC180CA62}.Release|Any CPU.ActiveCfg = Release|Any CPU + {013DA9D0-D676-4BB8-9EE6-CA1FC180CA62}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {C5A693CA-E582-487C-8D8F-21FCA4544C3D} + EndGlobalSection EndGlobal diff --git a/BerlinClockUnitTests/BerlinClockUnitTests.csproj b/BerlinClockUnitTests/BerlinClockUnitTests.csproj new file mode 100644 index 00000000..84f52656 --- /dev/null +++ b/BerlinClockUnitTests/BerlinClockUnitTests.csproj @@ -0,0 +1,88 @@ + + + + + + Debug + AnyCPU + {013DA9D0-D676-4BB8-9EE6-CA1FC180CA62} + Library + Properties + BerlinClockUnitTests + BerlinClockUnitTests + v4.7.2 + 512 + {3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + 15.0 + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + $(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages + False + UnitTest + + + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + ..\packages\Castle.Core.4.4.0\lib\net45\Castle.Core.dll + + + ..\packages\MSTest.TestFramework.2.1.0\lib\net45\Microsoft.VisualStudio.TestPlatform.TestFramework.dll + + + ..\packages\MSTest.TestFramework.2.1.0\lib\net45\Microsoft.VisualStudio.TestPlatform.TestFramework.Extensions.dll + + + ..\packages\Moq.4.14.1\lib\net45\Moq.dll + + + + + + ..\packages\System.Runtime.CompilerServices.Unsafe.4.5.0\lib\netstandard2.0\System.Runtime.CompilerServices.Unsafe.dll + + + ..\packages\System.Threading.Tasks.Extensions.4.5.1\lib\netstandard2.0\System.Threading.Tasks.Extensions.dll + + + + + + + + + + + + + {0451204d-bf86-43e1-b560-fc9ac830b9a9} + BerlinClock + + + + + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + + + \ No newline at end of file diff --git a/BerlinClockUnitTests/BerlinUhrPrintStrategyTests.cs b/BerlinClockUnitTests/BerlinUhrPrintStrategyTests.cs new file mode 100644 index 00000000..3e3c1011 --- /dev/null +++ b/BerlinClockUnitTests/BerlinUhrPrintStrategyTests.cs @@ -0,0 +1,145 @@ +using BerlinClock.Classes; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Moq; + +namespace BerlinClockUnitTests +{ + [TestClass] + public class BerlinUhrPrintStrategyTests + { + private Mock berlinUhrMock; + + BerlinUhrPrintStrategy sut; + + [TestInitialize] + public void TestInitialize() + { + this.sut = new BerlinUhrPrintStrategy(); + + this.berlinUhrMock = new Mock(); + + this.berlinUhrMock + .Setup(uhr => uhr.OneFullMinutesRow) + .Returns(new bool[4]); + this.berlinUhrMock + .Setup(uhr => uhr.FiveFullMinutesRow) + .Returns(new bool[11]); + this.berlinUhrMock + .Setup(uhr => uhr.OneFullHoursRow) + .Returns(new bool[4]); + this.berlinUhrMock + .Setup(uhr => uhr.FiveFullHoursRow) + .Returns(new bool[4]); + } + + [TestMethod] + public void Should_AllDotsBeOff_When_EveryDotValueIsFalse() + { + var expected = + "O\r\n"+ + "OOOO\r\n" + + "OOOO\r\n" + + "OOOOOOOOOOO\r\n" + + "OOOO"; + + var actual = sut.Print(this.berlinUhrMock.Object); + + Assert.AreEqual(expected, actual); + } + + [TestMethod] + public void Should_SecondDotBeY_When_SecondDotValueIsTrue() + { + var expected = + "Y\r\n" + + "OOOO\r\n" + + "OOOO\r\n" + + "OOOOOOOOOOO\r\n" + + "OOOO"; + + this.berlinUhrMock + .Setup(uhr => uhr.SecondDot) + .Returns(true); + + var actual = sut.Print(this.berlinUhrMock.Object); + + Assert.AreEqual(expected, actual); + } + + [TestMethod] + public void Should_AllFullFiveHourDotsBeR_When_AllFullFiveHourValuesAreTrue() + { + var expected = + "O\r\n" + + "RRRR\r\n" + + "OOOO\r\n" + + "OOOOOOOOOOO\r\n" + + "OOOO"; + + this.berlinUhrMock + .Setup(uhr => uhr.FiveFullHoursRow) + .Returns(new[] { true, true, true, true}); + + var actual = sut.Print(this.berlinUhrMock.Object); + + Assert.AreEqual(expected, actual); + } + + [TestMethod] + public void Should_AllFullOneHourDotsBeR_When_AllFullOneHourValuesAreTrue() + { + var expected = + "O\r\n" + + "OOOO\r\n" + + "RRRR\r\n" + + "OOOOOOOOOOO\r\n" + + "OOOO"; + + this.berlinUhrMock + .Setup(uhr => uhr.OneFullHoursRow) + .Returns(new[] { true, true, true, true }); + + var actual = sut.Print(this.berlinUhrMock.Object); + + Assert.AreEqual(expected, actual); + } + + [TestMethod] + public void Should_AllQuarterMinutesBeRAndRestY_When_AllFullFiveMinutesaluesAreTrue() + { + var expected = + "O\r\n" + + "OOOO\r\n" + + "OOOO\r\n" + + "YYRYYRYYRYY\r\n" + + "OOOO"; + + this.berlinUhrMock + .Setup(uhr => uhr.FiveFullMinutesRow) + .Returns(new[] { true, true, true, true, true, true, true, true, true, true, true }); + + var actual = sut.Print(this.berlinUhrMock.Object); + + Assert.AreEqual(expected, actual); + } + + [TestMethod] + public void Should_AllFullOneMinutesDotsBeY_When_AllFullOneMinutesValuesAreTrue() + { + var expected = + "O\r\n" + + "OOOO\r\n" + + "OOOO\r\n" + + "OOOOOOOOOOO\r\n" + + "YYYY"; + + this.berlinUhrMock + .Setup(uhr => uhr.OneFullMinutesRow) + .Returns(new[] { true, true, true, true }); + + var actual = sut.Print(this.berlinUhrMock.Object); + + Assert.AreEqual(expected, actual); + } + } +} diff --git a/BerlinClockUnitTests/BerlinUhrTests.cs b/BerlinClockUnitTests/BerlinUhrTests.cs new file mode 100644 index 00000000..90d28e50 --- /dev/null +++ b/BerlinClockUnitTests/BerlinUhrTests.cs @@ -0,0 +1,335 @@ +using System; +using System.Linq; +using BerlinClock.Classes; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Moq; + +namespace BerlinClockUnitTests +{ + [TestClass] + public class BerlinUhrTests + { + [TestMethod] + public void Should_SecondDotBeLit_When_SettingTimeWithEvenSecond() + { + var sut = new BerlinUhr(null); + var time = new TimeSpan(0, 0, 12); + + sut.SetTime(time); + + Assert.IsTrue(sut.SecondDot); + } + + [TestMethod] + public void Should_SecondDotBeLit_When_SettingTimeWithZeroInSeconds() + { + var sut = new BerlinUhr(null); + var time = new TimeSpan(0, 0, 0); + + sut.SetTime(time); + + Assert.IsTrue(sut.SecondDot); + } + + [TestMethod] + public void Should_SecondDotBeUnlit_When_SettingTimeWithOddSecond() + { + var sut = new BerlinUhr(null); + var time = new TimeSpan(0, 0, 11); + + sut.SetTime(time); + + Assert.IsFalse(sut.SecondDot); + } + + [DataTestMethod] + [DataRow(0)] + [DataRow(5)] + [DataRow(10)] + [DataRow(15)] + [DataRow(20)] + [DataRow(25)] + [DataRow(30)] + [DataRow(35)] + [DataRow(40)] + [DataRow(45)] + [DataRow(50)] + [DataRow(55)] + public void Should_AllOneMinutesDotsBeUnlit_When_SettingTimeWithMinuteDivisibleBy5(int minute) + { + var sut = new BerlinUhr(null); + var time = new TimeSpan(0, minute, 0); + + sut.SetTime(time); + + var expected = new[] { false, false, false, false }; + + CollectionAssert.AreEqual(expected, sut.OneFullMinutesRow.ToArray()); + } + + [DataTestMethod] + [DataRow(1, new[] { true, false, false, false })] + [DataRow(7, new[] { true, true, false, false })] + [DataRow(13, new[] { true, true, true, false })] + [DataRow(54, new[] { true, true, true, true })] + public void Should_LitNextFewOneMinuteDots_When_SettingTimeWithMinuteNotDivisibleBy5(int minute, bool[] expected) + { + var sut = new BerlinUhr(null); + var time = new TimeSpan(0, minute, 0); + + sut.SetTime(time); + + CollectionAssert.AreEqual(expected, sut.OneFullMinutesRow.ToArray()); + } + + [TestMethod] + public void Should_AllFiveMinuteDotsBeUnlit_When_SettingTimeWithZeroInMinutes() + { + var sut = new BerlinUhr(null); + var time = new TimeSpan(0, 0, 0); + + sut.SetTime(time); + + var expected = new[] { false, false, false, false, false, false, false, false, false, false, false }; + + CollectionAssert.AreEqual(expected, sut.FiveFullMinutesRow.ToArray()); + } + + [DataTestMethod] + [DataRow(1)] + [DataRow(2)] + [DataRow(3)] + [DataRow(4)] + public void Should_AllFiveMinuteDotsBeUnlit_When_SettingTimeWithMinuteLowerThan5(int minute) + { + var sut = new BerlinUhr(null); + var time = new TimeSpan(0, minute, 0); + + sut.SetTime(time); + + var expected = new[] { false, false, false, false, false, false, false, false, false, false, false }; + + CollectionAssert.AreEqual(expected, sut.FiveFullMinutesRow.ToArray()); + } + + [DataTestMethod] + [DataRow(5, new[] { true, false, false, false, false, false, false, false, false, false, false })] + [DataRow(27, new[] { true, true, true, true, true, false, false, false, false, false, false })] + [DataRow(59, new[] { true, true, true, true, true, true, true, true, true, true, true })] + public void Should_LitNextFewFiveMinuteDots_When_SettingTimeWithMinuteGreaterThan5(int minute, bool[] expected) + { + var sut = new BerlinUhr(null); + var time = new TimeSpan(0, minute, 0); + + sut.SetTime(time); + + CollectionAssert.AreEqual(expected, sut.FiveFullMinutesRow.ToArray()); + } + + [DataTestMethod] + [DataRow(0)] + [DataRow(5)] + [DataRow(10)] + [DataRow(15)] + [DataRow(20)] + public void Should_AllOneHourDotsBeUnlit_When_SettingTimeWithHourDivisibleBy5(int hour) + { + var sut = new BerlinUhr(null); + var time = new TimeSpan(hour, 0, 0); + + sut.SetTime(time); + + var expected = new[] { false, false, false, false }; + + CollectionAssert.AreEqual(expected, sut.OneFullHoursRow.ToArray()); + } + + [DataTestMethod] + [DataRow(1, new[] { true, false, false, false })] + [DataRow(12, new[] { true, true, false, false })] + [DataRow(18, new[] { true, true, true, false })] + [DataRow(24, new[] { true, true, true, true })] + public void Should_LitNextFewOneHourDots_When_SettingTimeWithHourNotDivisibleBy5(int hour, bool[] expected) + { + var sut = new BerlinUhr(null); + var time = new TimeSpan(hour, 0, 0); + + sut.SetTime(time); + + CollectionAssert.AreEqual(expected, sut.OneFullHoursRow.ToArray()); + } + + [DataTestMethod] + [DataRow(1)] + [DataRow(2)] + [DataRow(3)] + [DataRow(4)] + public void Should_AllFiveHourDotsBeUnlit_When_SettingTimeWithHourLowerThan5(int hour) + { + var sut = new BerlinUhr(null); + var time = new TimeSpan(hour, 0, 0); + + sut.SetTime(time); + + var expected = new[] { false, false, false, false }; + + CollectionAssert.AreEqual(expected, sut.FiveFullHoursRow.ToArray()); + } + + [DataTestMethod] + [DataRow(6, new[] { true, false, false, false })] + [DataRow(12, new[] { true, true, false, false })] + [DataRow(19, new[] { true, true, true, false })] + [DataRow(21, new[] { true, true, true, true })] + public void Should_LitNextFewFiveHourDots_When_SettingTimeWithHourGreaterThan5(int hour, bool[] expected) + { + var sut = new BerlinUhr(null); + var time = new TimeSpan(hour, 0, 0); + + sut.SetTime(time); + + CollectionAssert.AreEqual(expected, sut.FiveFullHoursRow.ToArray()); + } + + [TestMethod] + public void Should_LitOnlySecondDot_When_SettingTimeAsMidnight0000() + { + var sut = new BerlinUhr(null); + var time = new TimeSpan(0, 0, 0); + + sut.SetTime(time); + + var expectedOneFullMinutes = new[] { false, false, false, false }; + var expectedFiveFullMinutes = new[] { false, false, false, false, false, false, false, false, false, false, false }; + var expectedOneFullHours = new[] { false, false, false, false }; + var expectedFiveFullHours = new[] { false, false, false, false }; + + + Assert.IsTrue(sut.SecondDot); + CollectionAssert.AreEqual(expectedOneFullMinutes, sut.OneFullMinutesRow.ToArray()); + CollectionAssert.AreEqual(expectedFiveFullMinutes, sut.FiveFullMinutesRow.ToArray()); + CollectionAssert.AreEqual(expectedOneFullHours, sut.OneFullHoursRow.ToArray()); + CollectionAssert.AreEqual(expectedFiveFullHours, sut.FiveFullHoursRow.ToArray()); + } + + [TestMethod] + public void Should_LitAllHourAndSecondAndNoMinuteDots_When_SettingTimeAsMidnight2400() + { + var sut = new BerlinUhr(null); + var time = new TimeSpan(24, 0, 0); + + sut.SetTime(time); + + var expectedOneFullMinutes = new[] { false, false, false, false }; + var expectedFiveFullMinutes = new[] { false, false, false, false, false, false, false, false, false, false, false }; + var expectedOneFullHours = new[] { true, true, true, true }; + var expectedFiveFullHours = new[] { true, true, true, true }; + + Assert.IsTrue(sut.SecondDot); + CollectionAssert.AreEqual(expectedOneFullMinutes, sut.OneFullMinutesRow.ToArray()); + CollectionAssert.AreEqual(expectedFiveFullMinutes, sut.FiveFullMinutesRow.ToArray()); + CollectionAssert.AreEqual(expectedOneFullHours, sut.OneFullHoursRow.ToArray()); + CollectionAssert.AreEqual(expectedFiveFullHours, sut.FiveFullHoursRow.ToArray()); + } + + [TestMethod] + public void Should_LitAllDotsExceptLastOnFullHourAndSecondDot_When_SettingTimeAsMidnight2359() + { + var sut = new BerlinUhr(null); + var time = new TimeSpan(23, 59, 59); + + sut.SetTime(time); + + var expectedOneFullMinutes = new[] { true, true, true, true }; + var expectedFiveFullMinutes = new[] { true, true, true, true, true, true, true, true, true, true, true }; + var expectedOneFullHours = new[] { true, true, true, false }; + var expectedFiveFullHours = new[] { true, true, true, true }; + + Assert.IsFalse(sut.SecondDot); + CollectionAssert.AreEqual(expectedOneFullMinutes, sut.OneFullMinutesRow.ToArray()); + CollectionAssert.AreEqual(expectedFiveFullMinutes, sut.FiveFullMinutesRow.ToArray()); + CollectionAssert.AreEqual(expectedOneFullHours, sut.OneFullHoursRow.ToArray()); + CollectionAssert.AreEqual(expectedFiveFullHours, sut.FiveFullHoursRow.ToArray()); + } + + [TestMethod] + public void Should_CorrectlySetTime_When_SettingExampleTime() + { + var sut = new BerlinUhr(null); + var time = new TimeSpan(13, 17, 01); + + sut.SetTime(time); + + var expectedOneFullMinutes = new[] { true, true, false, false }; + var expectedFiveFullMinutes = new[] { true, true, true, false, false, false, false, false, false, false, false }; + var expectedOneFullHours = new[] { true, true, true, false }; + var expectedFiveFullHours = new[] { true, true, false, false }; + + Assert.IsFalse(sut.SecondDot); + CollectionAssert.AreEqual(expectedOneFullMinutes, sut.OneFullMinutesRow.ToArray()); + CollectionAssert.AreEqual(expectedFiveFullMinutes, sut.FiveFullMinutesRow.ToArray()); + CollectionAssert.AreEqual(expectedOneFullHours, sut.OneFullHoursRow.ToArray()); + CollectionAssert.AreEqual(expectedFiveFullHours, sut.FiveFullHoursRow.ToArray()); + } + + [TestMethod] + public void Should_CorrectlySetTime_When_SettingTimeFromLitToUnlit() + { + var sut = new BerlinUhr(null); + var litTime = new TimeSpan(23, 59, 59); + var unlitTime = new TimeSpan(0, 0, 0); + + sut.SetTime(litTime); + sut.SetTime(unlitTime); + + var expectedOneFullMinutes = new[] { false, false, false, false }; + var expectedFiveFullMinutes = new[] { false, false, false, false, false, false, false, false, false, false, false }; + var expectedOneFullHours = new[] { false, false, false, false }; + var expectedFiveFullHours = new[] { false, false, false, false }; + + Assert.IsTrue(sut.SecondDot); + CollectionAssert.AreEqual(expectedOneFullMinutes, sut.OneFullMinutesRow.ToArray()); + CollectionAssert.AreEqual(expectedFiveFullMinutes, sut.FiveFullMinutesRow.ToArray()); + CollectionAssert.AreEqual(expectedOneFullHours, sut.OneFullHoursRow.ToArray()); + CollectionAssert.AreEqual(expectedFiveFullHours, sut.FiveFullHoursRow.ToArray()); + } + + [TestMethod] + public void Should_CorrectlySetTime_When_SettingTimeFromUnlitToLit() + { + var sut = new BerlinUhr(null); + var litTime = new TimeSpan(23, 59, 59); + var unlitTime = new TimeSpan(0, 0, 0); + + sut.SetTime(unlitTime); + sut.SetTime(litTime); + + var expectedOneFullMinutes = new[] { true, true, true, true }; + var expectedFiveFullMinutes = new[] { true, true, true, true, true, true, true, true, true, true, true }; + var expectedOneFullHours = new[] { true, true, true, false }; + var expectedFiveFullHours = new[] { true, true, true, true }; + + Assert.IsFalse(sut.SecondDot); + CollectionAssert.AreEqual(expectedOneFullMinutes, sut.OneFullMinutesRow.ToArray()); + CollectionAssert.AreEqual(expectedFiveFullMinutes, sut.FiveFullMinutesRow.ToArray()); + CollectionAssert.AreEqual(expectedOneFullHours, sut.OneFullHoursRow.ToArray()); + CollectionAssert.AreEqual(expectedFiveFullHours, sut.FiveFullHoursRow.ToArray()); + } + + [TestMethod] + public void Should_PrintTime_Using_SelectedStrategy() + { + var expected = "test"; + var strategyMock = new Mock(); + var sut = new BerlinUhr(strategyMock.Object); + + strategyMock + .Setup(strategy => strategy.Print(sut)) + .Returns(expected); + + var actual = sut.Print(); + + Assert.AreEqual(expected, actual); + } + } +} diff --git a/BerlinClockUnitTests/Properties/AssemblyInfo.cs b/BerlinClockUnitTests/Properties/AssemblyInfo.cs new file mode 100644 index 00000000..177f2311 --- /dev/null +++ b/BerlinClockUnitTests/Properties/AssemblyInfo.cs @@ -0,0 +1,20 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +[assembly: AssemblyTitle("BerlinClockUnitTests")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("BerlinClockUnitTests")] +[assembly: AssemblyCopyright("Copyright © 2020")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +[assembly: ComVisible(false)] + +[assembly: Guid("013da9d0-d676-4bb8-9ee6-ca1fc180ca62")] + +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/BerlinClockUnitTests/packages.config b/BerlinClockUnitTests/packages.config new file mode 100644 index 00000000..a443cbe4 --- /dev/null +++ b/BerlinClockUnitTests/packages.config @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/Classes/BerlinUhr.cs b/Classes/BerlinUhr.cs new file mode 100644 index 00000000..17ddb8c8 --- /dev/null +++ b/Classes/BerlinUhr.cs @@ -0,0 +1,96 @@ +using System; +using System.Collections.Generic; + +namespace BerlinClock.Classes +{ + public class BerlinUhr : IBerlinUhr + { + private readonly IBerlinUhrPrintStrategy printStrategy; + + private bool[] oneFullMinutesRow = new bool[4]; + private bool[] fiveFullMinutesRow = new bool[11]; + private bool[] oneFullHoursRow = new bool[4]; + private bool[] fiveFullHoursRow = new bool[4]; + + public BerlinUhr(IBerlinUhrPrintStrategy printStrategy) + { + this.printStrategy = printStrategy; + } + + public bool SecondDot { get; private set; } + + public IEnumerable FiveFullHoursRow => this.fiveFullHoursRow; + + public IEnumerable OneFullHoursRow => this.oneFullHoursRow; + + public IEnumerable FiveFullMinutesRow => this.fiveFullMinutesRow; + + public IEnumerable OneFullMinutesRow => this.oneFullMinutesRow; + + public string Print() + { + return this.printStrategy.Print(this); + } + + public void SetTime(TimeSpan time) + { + this.SetSecondDot(time); + this.SetOneFullMinutesRow(time); + this.SetFiveFullMinutesRow(time); + this.SetOneFullHoursRow(time); + this.SetFiveFullHoursRow(time); + } + + private void SetFiveFullHoursRow(TimeSpan time) + { + var litSquares = this.IsMidnight24(time) + ? this.fiveFullHoursRow.Length + : (int)time.TotalHours / 5; + + this.LitSquares(this.fiveFullHoursRow, litSquares); + } + + private void SetOneFullHoursRow(TimeSpan time) + { + var litSquares = this.IsMidnight24(time) + ? this.oneFullHoursRow.Length + : (int)time.TotalHours % 5; + + this.LitSquares(this.oneFullHoursRow, litSquares); + } + + private void SetFiveFullMinutesRow(TimeSpan time) + { + int litSquares = time.Minutes / 5; + + this.LitSquares(this.fiveFullMinutesRow, litSquares); + } + + private void SetOneFullMinutesRow(TimeSpan time) + { + var litSquares = time.Minutes % 5; + + this.LitSquares(this.oneFullMinutesRow, litSquares); + } + + private void SetSecondDot(TimeSpan time) + { + this.SecondDot = time.Seconds % 2 == 0; + } + + private void LitSquares(bool[] rows, int litSquares) + { + var size = rows.Length; + + for (int i = 0; i < size; i++) + { + rows[i] = i < litSquares; + } + } + + private bool IsMidnight24(TimeSpan time) + { + return time.TotalHours == 24; + } + } +} diff --git a/Classes/BerlinUhrPrintStrategy.cs b/Classes/BerlinUhrPrintStrategy.cs new file mode 100644 index 00000000..481fabf6 --- /dev/null +++ b/Classes/BerlinUhrPrintStrategy.cs @@ -0,0 +1,83 @@ +using System.Linq; +using System.Text; + +namespace BerlinClock.Classes +{ + public class BerlinUhrPrintStrategy : IBerlinUhrPrintStrategy + { + private const string offValue = "O"; + private const string hourValue = "R"; + private const string minuteValue = "Y"; + private const string quarterValue = "R"; + private const string secondValue = "Y"; + + public string Print(IBerlinUhr berlinUhr) + { + var stringBuilder = new StringBuilder(); + + stringBuilder.AppendLine(this.GetSecondDotString(berlinUhr)); + stringBuilder.AppendLine(this.GetFiveFullHoursRowString(berlinUhr)); + stringBuilder.AppendLine(this.GetOneFullHoursRowString(berlinUhr)); + stringBuilder.AppendLine(this.GetFiveFullMinutesRowString(berlinUhr)); + stringBuilder.Append(this.GetOneFullMinutesRowString(berlinUhr)); + + return stringBuilder.ToString(); + } + + private string GetOneFullMinutesRowString(IBerlinUhr berlinUhr) + { + var stringBuilder = new StringBuilder(); + + foreach (var fullOne in berlinUhr.OneFullMinutesRow) + { + stringBuilder.Append(fullOne ? minuteValue : offValue); + } + + return stringBuilder.ToString(); + } + + private string GetFiveFullMinutesRowString(IBerlinUhr berlinUhr) + { + var stringBuilder = new StringBuilder(); + var fullFiveMinutes = berlinUhr.FiveFullMinutesRow.ToList(); + + for (int i = 1; i <= fullFiveMinutes.Count; i++) + { + var isQuarter = i % 3 == 0; + var onValue = isQuarter ? quarterValue : minuteValue; + stringBuilder.Append(fullFiveMinutes[i-1] ? onValue : offValue); + } + + return stringBuilder.ToString(); + } + + private string GetOneFullHoursRowString(IBerlinUhr berlinUhr) + { + var stringBuilder = new StringBuilder(); + + foreach (var fullOne in berlinUhr.OneFullHoursRow) + { + stringBuilder.Append(fullOne ? hourValue : offValue); + } + + return stringBuilder.ToString(); + } + + private string GetFiveFullHoursRowString(IBerlinUhr berlinUhr) + { + var stringBuilder = new StringBuilder(); + + foreach (var fullFive in berlinUhr.FiveFullHoursRow) + { + stringBuilder.Append(fullFive ? hourValue : offValue); + } + + return stringBuilder.ToString(); + } + + private string GetSecondDotString(IBerlinUhr berlinUhr) + { + return berlinUhr.SecondDot ? secondValue : offValue; + } + } +} diff --git a/Classes/IBerlinUhr.cs b/Classes/IBerlinUhr.cs new file mode 100644 index 00000000..ba324323 --- /dev/null +++ b/Classes/IBerlinUhr.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; + +namespace BerlinClock.Classes +{ + public interface IBerlinUhr + { + bool SecondDot { get; } + IEnumerable FiveFullHoursRow { get; } + IEnumerable OneFullHoursRow { get; } + IEnumerable FiveFullMinutesRow { get; } + IEnumerable OneFullMinutesRow { get; } + + void SetTime(TimeSpan time); + string Print(); + } +} diff --git a/Classes/IBerlinUhrPrintStrategy.cs b/Classes/IBerlinUhrPrintStrategy.cs new file mode 100644 index 00000000..6c74b211 --- /dev/null +++ b/Classes/IBerlinUhrPrintStrategy.cs @@ -0,0 +1,7 @@ +namespace BerlinClock.Classes +{ + public interface IBerlinUhrPrintStrategy + { + string Print(IBerlinUhr berlinUhr); + } +} diff --git a/Classes/ITimeConverter.cs b/Classes/ITimeConverter.cs index 1d9e4c27..e3e45785 100644 --- a/Classes/ITimeConverter.cs +++ b/Classes/ITimeConverter.cs @@ -1,7 +1,4 @@ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; namespace BerlinClock { diff --git a/Classes/TimeConverter.cs b/Classes/TimeConverter.cs index dd5bf4e0..24816d0c 100644 --- a/Classes/TimeConverter.cs +++ b/Classes/TimeConverter.cs @@ -1,7 +1,6 @@ -using System; -using System.Collections.Generic; +using BerlinClock.Classes; +using System; using System.Linq; -using System.Text; namespace BerlinClock { @@ -9,7 +8,22 @@ public class TimeConverter : ITimeConverter { public string convertTime(string aTime) { - throw new NotImplementedException(); + var time = this.GetTime(aTime); + var berlinUhr = new BerlinUhr(new BerlinUhrPrintStrategy()); + + berlinUhr.SetTime(time); + + return berlinUhr.Print(); + } + + private TimeSpan GetTime(string aTime) + { + var timeParts = aTime + .Split(':') + .Select(tpart => int.Parse(tpart)) + .ToArray(); + + return new TimeSpan(timeParts[0], timeParts[1], timeParts[2]); } } }