diff --git a/BDD/BerlinClockFeatureSteps.cs b/BDD/BerlinClockFeatureSteps.cs index 4390f3cb..f8cd7bf1 100644 --- a/BDD/BerlinClockFeatureSteps.cs +++ b/BDD/BerlinClockFeatureSteps.cs @@ -1,27 +1,26 @@ -using System; -using TechTalk.SpecFlow; +using TechTalk.SpecFlow; using Microsoft.VisualStudio.TestTools.UnitTesting; -using System.Linq; +using BerlinClock.Converters; namespace BerlinClock { [Binding] public class TheBerlinClockSteps { - private ITimeConverter berlinClock = new TimeConverter(); - private String theTime; + private readonly ITimeConverter _berlinClock = new TimeConverter(); + private string _theTime; [When(@"the time is ""(.*)""")] public void WhenTheTimeIs(string time) { - theTime = time; + _theTime = time; } [Then(@"the clock should look like")] public void ThenTheClockShouldLookLike(string theExpectedBerlinClockOutput) { - Assert.AreEqual(berlinClock.convertTime(theTime), theExpectedBerlinClockOutput); + Assert.AreEqual(_berlinClock.ConvertTime(_theTime), theExpectedBerlinClockOutput); } } diff --git a/BerlinClock.Tests/BerlinClock.Tests.csproj b/BerlinClock.Tests/BerlinClock.Tests.csproj new file mode 100644 index 00000000..caebf629 --- /dev/null +++ b/BerlinClock.Tests/BerlinClock.Tests.csproj @@ -0,0 +1,76 @@ + + + + + + + Debug + AnyCPU + {74F9D721-6839-4776-97C9-718145CED3D0} + Library + Properties + BerlinClock.Tests + BerlinClock.Tests + v4.5 + 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\NUnit.3.12.0\lib\net45\nunit.framework.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/BerlinClock.Tests/Builders/YellowLampRowBuilderTests.cs b/BerlinClock.Tests/Builders/YellowLampRowBuilderTests.cs new file mode 100644 index 00000000..826bf54d --- /dev/null +++ b/BerlinClock.Tests/Builders/YellowLampRowBuilderTests.cs @@ -0,0 +1,30 @@ +using BerlinClock.Builders; +using BerlinClock.Models; +using NUnit.Framework; + +namespace BerlinClock.Tests.Builders +{ + [TestFixture] + public class YellowLampRowBuilderTests + { + private YellowLampRowBuilder _sut; + + [SetUp] + public void SetUp() + { + _sut = new YellowLampRowBuilder(); + } + + [Test] + public void Build_ShouldReturnDifferentResult_WhenOddAndEvenNumbersAreGiven() + { + var oddValue = 1; + var evenValue = 2; + + var resultForOddValue = _sut.Build(new Time(0, 0, oddValue)); + var resultForEvenValue = _sut.Build(new Time(0, 0, evenValue)); + + Assert.That(resultForEvenValue, Is.Not.EqualTo(resultForOddValue)); + } + } +} diff --git a/BerlinClock.Tests/Extensions/IntExtensionsTests.cs b/BerlinClock.Tests/Extensions/IntExtensionsTests.cs new file mode 100644 index 00000000..1d1034f0 --- /dev/null +++ b/BerlinClock.Tests/Extensions/IntExtensionsTests.cs @@ -0,0 +1,29 @@ +using BerlinClock.Extensions; +using NUnit.Framework; + +namespace BerlinClock.Tests.Extensions +{ + [TestFixture] + public class IntExtensionsTests + { + [Test] + public void IsEven_ShouldReturnTrue_WhenEvenNumberIsGiven() + { + var evenNumber = 2; + + var result = evenNumber.IsEven(); + + Assert.That(result, Is.True); + } + + [Test] + public void IsEven_ShouldReturnFalse_WhenOddNumberIsGiven() + { + var oddNumber = 3; + + var result = oddNumber.IsEven(); + + Assert.That(result, Is.False); + } + } +} diff --git a/BerlinClock.Tests/Extensions/StringExtensionsTests.cs b/BerlinClock.Tests/Extensions/StringExtensionsTests.cs new file mode 100644 index 00000000..33c3c99e --- /dev/null +++ b/BerlinClock.Tests/Extensions/StringExtensionsTests.cs @@ -0,0 +1,52 @@ +using BerlinClock.Extensions; +using NUnit.Framework; + +namespace BerlinClock.Tests.Extensions +{ + [TestFixture] + public class StringExtensionsTests + { + private string _value; + private char _valueToReplace; + private char _newValue; + + [SetUp] + public void SetUp() + { + _value = "OOOOOOO"; + _valueToReplace = 'O'; + _newValue = 'X'; + } + + [TestCase(null)] + [TestCase("")] + public void ReplaceEveryNthOccurence_ShouldReturnSameValue_WhenNullOrEmptyStringIsGiven(string value) + { + var result = value.ReplaceEveryNthOccurence(_valueToReplace, _newValue, 1); + + Assert.That(result, Is.EqualTo(value)); + } + + [Test] + public void ReplaceEveryNthOccurence_ShouldNotReplaceAnyValue_WhenNValueIsOutOfRange() + { + var outOfRangeNValue = _value.Length + 1; + + var result = _value.ReplaceEveryNthOccurence(_valueToReplace, _newValue, outOfRangeNValue); + + Assert.That(result, Is.EqualTo(_value)); + } + + [Test] + public void ReplaceEveryNthOccurence_ShouldReplaceEvery3thOccurence_WhenValueOccurred() + { + var value = "OOROOOOOO"; + var expectedValue = "OOROOXOOX"; + var n = 3; + + var result = value.ReplaceEveryNthOccurence(_valueToReplace, _newValue, n); + + Assert.That(result, Is.EqualTo(expectedValue)); + } + } +} diff --git a/BerlinClock.Tests/Parsers/TimeParserExtensions.cs b/BerlinClock.Tests/Parsers/TimeParserExtensions.cs new file mode 100644 index 00000000..b59342d3 --- /dev/null +++ b/BerlinClock.Tests/Parsers/TimeParserExtensions.cs @@ -0,0 +1,47 @@ +using BerlinClock.Parsers; +using NUnit.Framework; +using System; + +namespace BerlinClock.Tests.Parsers +{ + [TestFixture] + public class TimeParserExtensions + { + private TimeParser _sut; + + [SetUp] + public void SetUp() + { + _sut = new TimeParser(); + } + + [Test] + public void Parse_ShouldThrowException_WhenGivenValueIsNull() + { + Assert.Throws(() => _sut.Parse(null)); + } + + [Test] + public void Parse_ShouldThrowException_WhenWrongTimeFormatIsGiven() + { + var wrongTime = "123400"; + + Assert.Throws(() => _sut.Parse(wrongTime)); + } + + [Test] + public void Parse_ShouldCreateCorrectInstance_WhenCorrectTimeIsGiven() + { + var hour = 12; + var minute = 45; + var second = 30; + var timeValue = $"{hour}:{minute}:{second}"; + + var result = _sut.Parse(timeValue); + + Assert.That(result.Hour, Is.EqualTo(hour)); + Assert.That(result.Minute, Is.EqualTo(minute)); + Assert.That(result.Second, Is.EqualTo(second)); + } + } +} diff --git a/BerlinClock.Tests/Properties/AssemblyInfo.cs b/BerlinClock.Tests/Properties/AssemblyInfo.cs new file mode 100644 index 00000000..0a3129db --- /dev/null +++ b/BerlinClock.Tests/Properties/AssemblyInfo.cs @@ -0,0 +1,20 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +[assembly: AssemblyTitle("BerlinClock.Tests")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("BerlinClock.Tests")] +[assembly: AssemblyCopyright("Copyright © 2020")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +[assembly: ComVisible(false)] + +[assembly: Guid("74f9d721-6839-4776-97c9-718145ced3d0")] + +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/BerlinClock.Tests/Renderers/BerlinClockRowRendererTests.cs b/BerlinClock.Tests/Renderers/BerlinClockRowRendererTests.cs new file mode 100644 index 00000000..77f76427 --- /dev/null +++ b/BerlinClock.Tests/Renderers/BerlinClockRowRendererTests.cs @@ -0,0 +1,79 @@ +using BerlinClock.Models; +using BerlinClock.Renderers; +using NUnit.Framework; +using System; + +namespace BerlinClock.Tests.Renderers +{ + [TestFixture] + public class BerlinClockRowRendererTests + { + private BerlinClockRowRenderer _sut; + + [SetUp] + public void SetUp() + { + _sut = new BerlinClockRowRenderer(); + } + + [Test] + public void Render_ShouldNotModifyResult_WhenAdditionalFormattingIsNull() + { + var expectedValue = "XO"; + var request = new BerlinClockRendererRequest + { + AdditionalFormatting = null, + TurnedOnLampSign = 'X', + AmountOfTurnedOnLamps = 1, + AmountOfTurnedOffLamps = 1 + }; + + var result = _sut.Render(request); + + Assert.That(result, Is.EqualTo(expectedValue)); + } + + [Test] + public void Render_ShouldModifyResult_WhenAdditionalFormattingIsGiven() + { + var expectedValue = "TEST"; + var request = new BerlinClockRendererRequest + { + AdditionalFormatting = (row) => expectedValue, + TurnedOnLampSign = 'X', + AmountOfTurnedOnLamps = 1, + AmountOfTurnedOffLamps = 1 + }; + + var result = _sut.Render(request); + + Assert.That(result, Is.EqualTo(expectedValue)); + } + + [Test] + public void Render_ShouldThrowException_WhenNegativeTurnedOnLampsValueIsGiven() + { + var request = new BerlinClockRendererRequest + { + TurnedOnLampSign = 'X', + AmountOfTurnedOnLamps = -1, + AmountOfTurnedOffLamps = 1 + }; + + Assert.Throws(() => _sut.Render(request)); + } + + [Test] + public void Render_ShouldThrowException_WhenNegativeTurnedOffLampsValueIsGiven() + { + var request = new BerlinClockRendererRequest + { + TurnedOnLampSign = 'X', + AmountOfTurnedOnLamps = 1, + AmountOfTurnedOffLamps = -1 + }; + + Assert.Throws(() => _sut.Render(request)); + } + } +} diff --git a/BerlinClock.Tests/packages.config b/BerlinClock.Tests/packages.config new file mode 100644 index 00000000..929338d9 --- /dev/null +++ b/BerlinClock.Tests/packages.config @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/BerlinClock.csproj b/BerlinClock.csproj index ac8af99d..2a9b8c49 100644 --- a/BerlinClock.csproj +++ b/BerlinClock.csproj @@ -50,14 +50,26 @@ + + + + + + + + + + + + True True BerlinClockFeatureSteps.feature - - + + diff --git a/BerlinClock.sln b/BerlinClock.sln index 082911a2..1114bf1f 100644 --- a/BerlinClock.sln +++ b/BerlinClock.sln @@ -5,6 +5,8 @@ VisualStudioVersion = 12.0.21005.1 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}") = "BerlinClock.Tests", "BerlinClock.Tests\BerlinClock.Tests.csproj", "{74F9D721-6839-4776-97C9-718145CED3D0}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -15,6 +17,10 @@ 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 + {74F9D721-6839-4776-97C9-718145CED3D0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {74F9D721-6839-4776-97C9-718145CED3D0}.Debug|Any CPU.Build.0 = Debug|Any CPU + {74F9D721-6839-4776-97C9-718145CED3D0}.Release|Any CPU.ActiveCfg = Release|Any CPU + {74F9D721-6839-4776-97C9-718145CED3D0}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/Builders/BerlinClockEntityBuilder.cs b/Builders/BerlinClockEntityBuilder.cs new file mode 100644 index 00000000..95abd977 --- /dev/null +++ b/Builders/BerlinClockEntityBuilder.cs @@ -0,0 +1,46 @@ +using BerlinClock.Models; + +namespace BerlinClock.Builders +{ + public interface IBerlinClockEntityBuilder + { + BerlinClockEntity Build(Time time); + } + + public class BerlinClockEntityBuilder : IBerlinClockEntityBuilder + { + private readonly IHourRowsBuilder _hourRowsBuilder; + private readonly IMinuteRowsBuilder _minuteRowsBuilder; + private readonly IYellowLampRowBuilder _yellowLampRowBuilder; + + public BerlinClockEntityBuilder() : this(new HourRowsBuilder(), new MinuteRowsBuilder(), + new YellowLampRowBuilder()) + { + + } + + public BerlinClockEntityBuilder(IHourRowsBuilder hourRowsBuilder, IMinuteRowsBuilder minuteRowsBuilder, + IYellowLampRowBuilder yellowLampRowBuilder) + { + _hourRowsBuilder = hourRowsBuilder; + _minuteRowsBuilder = minuteRowsBuilder; + _yellowLampRowBuilder = yellowLampRowBuilder; + } + + public BerlinClockEntity Build(Time time) + { + var hourRows = _hourRowsBuilder.Build(time); + var minuteRows = _minuteRowsBuilder.Build(time); + var yellowLampRow = _yellowLampRowBuilder.Build(time); + + return new BerlinClockEntity + { + YellowLampRow = yellowLampRow, + FirstHoursRow = hourRows.FirstRow, + SecondHoursRow = hourRows.SecondRow, + FirstMinutesRow = minuteRows.FirstRow, + SecondMinutesRow = minuteRows.SecondRow + }; + } + } +} diff --git a/Builders/BerlinClockRowsBuilderBase.cs b/Builders/BerlinClockRowsBuilderBase.cs new file mode 100644 index 00000000..e9b04fb8 --- /dev/null +++ b/Builders/BerlinClockRowsBuilderBase.cs @@ -0,0 +1,57 @@ +using BerlinClock.Models; +using BerlinClock.Renderers; +using System; + +namespace BerlinClock.Builders +{ + public interface IBerlinClockRowsBuilder + { + BerlinClockRows Build(Time time); + } + + public abstract class BerlinClockRowsBuilderBase : IBerlinClockRowsBuilder + { + protected abstract int FirstRowLampsAmount { get; } + protected abstract int FirstRowLampValue { get; } + protected abstract int SecondRowLampsAmount { get; } + protected abstract int SecondRowLampValue { get; } + protected abstract char TurnedOnLampSign { get; } + protected virtual Func FirstRowAdditionalFormatting { get; } + + private readonly IBerlinClockRowRenderer _berlinClockRowRenderer; + + public BerlinClockRowsBuilderBase(IBerlinClockRowRenderer berlinClockRowRenderer) + { + _berlinClockRowRenderer = berlinClockRowRenderer; + } + + public BerlinClockRows Build(Time time) + { + var timePart = ExtractTimePart(time); + var amountOfTurnedOnLampsAtFirstRow = timePart / FirstRowLampValue; + var amountOfTurnedOffLampsAtFirstRow = FirstRowLampsAmount - amountOfTurnedOnLampsAtFirstRow; + + var amountOfTurnedOnLampsAtSecondRow = (timePart - (amountOfTurnedOnLampsAtFirstRow * FirstRowLampValue)) / SecondRowLampValue; + var amountOfTurnedOffLampsAtSecondRow = SecondRowLampsAmount - amountOfTurnedOnLampsAtSecondRow; + + return new BerlinClockRows + { + FirstRow = _berlinClockRowRenderer.Render(new BerlinClockRendererRequest + { + AmountOfTurnedOnLamps = amountOfTurnedOnLampsAtFirstRow, + AmountOfTurnedOffLamps = amountOfTurnedOffLampsAtFirstRow, + TurnedOnLampSign = TurnedOnLampSign, + AdditionalFormatting = FirstRowAdditionalFormatting + }), + SecondRow = _berlinClockRowRenderer.Render(new BerlinClockRendererRequest + { + AmountOfTurnedOnLamps = amountOfTurnedOnLampsAtSecondRow, + AmountOfTurnedOffLamps = amountOfTurnedOffLampsAtSecondRow, + TurnedOnLampSign = TurnedOnLampSign + }) + }; + } + + protected abstract int ExtractTimePart(Time time); + } +} diff --git a/Builders/HourRowsBuilder.cs b/Builders/HourRowsBuilder.cs new file mode 100644 index 00000000..aaae68b5 --- /dev/null +++ b/Builders/HourRowsBuilder.cs @@ -0,0 +1,31 @@ +using BerlinClock.Models; +using BerlinClock.Renderers; + +namespace BerlinClock.Builders +{ + public interface IHourRowsBuilder : IBerlinClockRowsBuilder + { + + } + + public class HourRowsBuilder : BerlinClockRowsBuilderBase, IHourRowsBuilder + { + public HourRowsBuilder() : this(new BerlinClockRowRenderer()) + { + + } + public HourRowsBuilder(IBerlinClockRowRenderer berlinClockRowRenderer) : base(berlinClockRowRenderer) + { + } + + protected override char TurnedOnLampSign => 'R'; + protected override int FirstRowLampsAmount => 4; + protected override int FirstRowLampValue => 5; + protected override int SecondRowLampsAmount => 4; + protected override int SecondRowLampValue => 1; + protected override int ExtractTimePart(Time time) + { + return time.Hour; + } + } +} diff --git a/Builders/MinuteRowsBuilder.cs b/Builders/MinuteRowsBuilder.cs new file mode 100644 index 00000000..62b49da2 --- /dev/null +++ b/Builders/MinuteRowsBuilder.cs @@ -0,0 +1,42 @@ +using BerlinClock.Extensions; +using BerlinClock.Models; +using BerlinClock.Renderers; +using System; + +namespace BerlinClock.Builders +{ + public interface IMinuteRowsBuilder : IBerlinClockRowsBuilder + { + + } + + public class MinuteRowsBuilder : BerlinClockRowsBuilderBase, IMinuteRowsBuilder + { + private const char QuarterSign = 'R'; + + public MinuteRowsBuilder() : this(new BerlinClockRowRenderer()) + { + + } + + public MinuteRowsBuilder(IBerlinClockRowRenderer berlinClockRowRenderer) : base(berlinClockRowRenderer) + { + } + + protected override int FirstRowLampsAmount => 11; + protected override int FirstRowLampValue => 5; + protected override int SecondRowLampsAmount => 4; + protected override int SecondRowLampValue => 1; + protected override char TurnedOnLampSign => 'Y'; + protected override int ExtractTimePart(Time time) + { + return time.Minute; + } + + protected override Func FirstRowAdditionalFormatting => (row) => + { + var n = 3; + return row.ReplaceEveryNthOccurence(TurnedOnLampSign, QuarterSign, n); + }; + } +} diff --git a/Builders/YellowLampRowBuilder.cs b/Builders/YellowLampRowBuilder.cs new file mode 100644 index 00000000..96c2d213 --- /dev/null +++ b/Builders/YellowLampRowBuilder.cs @@ -0,0 +1,23 @@ +using BerlinClock.Extensions; +using BerlinClock.Models; + +namespace BerlinClock.Builders +{ + public interface IYellowLampRowBuilder + { + char Build(Time time); + } + + public class YellowLampRowBuilder : IYellowLampRowBuilder + { + private const char LampOnSign = 'Y'; + private const char LampOffSign = 'O'; + + public char Build(Time time) + { + return time.Second.IsEven() + ? LampOnSign + : LampOffSign; + } + } +} diff --git a/Classes/ITimeConverter.cs b/Classes/ITimeConverter.cs deleted file mode 100644 index 1d9e4c27..00000000 --- a/Classes/ITimeConverter.cs +++ /dev/null @@ -1,12 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace BerlinClock -{ - public interface ITimeConverter - { - String convertTime(String aTime); - } -} diff --git a/Classes/TimeConverter.cs b/Classes/TimeConverter.cs deleted file mode 100644 index dd5bf4e0..00000000 --- a/Classes/TimeConverter.cs +++ /dev/null @@ -1,15 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace BerlinClock -{ - public class TimeConverter : ITimeConverter - { - public string convertTime(string aTime) - { - throw new NotImplementedException(); - } - } -} diff --git a/Converters/TimeConverter.cs b/Converters/TimeConverter.cs new file mode 100644 index 00000000..cd5264fb --- /dev/null +++ b/Converters/TimeConverter.cs @@ -0,0 +1,34 @@ +using BerlinClock.Builders; +using BerlinClock.Parsers; + +namespace BerlinClock.Converters +{ + public interface ITimeConverter + { + string ConvertTime(string aTime); + } + + public class TimeConverter : ITimeConverter + { + private readonly IBerlinClockEntityBuilder _berlinClockEntityBuilder; + private readonly ITimeParser _timeParser; + + public TimeConverter() : this(new BerlinClockEntityBuilder(), new TimeParser()) + { + + } + + public TimeConverter(IBerlinClockEntityBuilder berlinClockEntityBuilder, ITimeParser timeParser) + { + _berlinClockEntityBuilder = berlinClockEntityBuilder; + _timeParser = timeParser; + } + + public string ConvertTime(string aTime) + { + var time = _timeParser.Parse(aTime); + var berlinClockEntity = _berlinClockEntityBuilder.Build(time); + return berlinClockEntity.ToString(); + } + } +} diff --git a/Extensions/IntExtensions.cs b/Extensions/IntExtensions.cs new file mode 100644 index 00000000..65411e57 --- /dev/null +++ b/Extensions/IntExtensions.cs @@ -0,0 +1,7 @@ +namespace BerlinClock.Extensions +{ + public static class IntExtensions + { + public static bool IsEven(this int value) => value % 2 == 0; + } +} diff --git a/Extensions/StringExtensions.cs b/Extensions/StringExtensions.cs new file mode 100644 index 00000000..61a85a30 --- /dev/null +++ b/Extensions/StringExtensions.cs @@ -0,0 +1,19 @@ +using System; +using System.Linq; + +namespace BerlinClock.Extensions +{ + public static class StringExtensions + { + public static string ReplaceEveryNthOccurence(this string value, char valueToReplace, char newValue, int n) + { + if (string.IsNullOrWhiteSpace(value)) + return value; + + var chars = value.Select((val, index) => + val == valueToReplace && (index + 1) % n == 0 ? newValue : val); + + return new string(chars.ToArray()); + } + } +} diff --git a/Models/BerlinClockEntity.cs b/Models/BerlinClockEntity.cs new file mode 100644 index 00000000..22316206 --- /dev/null +++ b/Models/BerlinClockEntity.cs @@ -0,0 +1,20 @@ +using System; + +namespace BerlinClock.Models +{ + public class BerlinClockEntity + { + public char YellowLampRow { get; set; } + public string FirstHoursRow { get; set; } + public string SecondHoursRow { get; set; } + public string FirstMinutesRow { get; set; } + public string SecondMinutesRow { get; set; } + + public override string ToString() + { + return string.Join(Environment.NewLine, YellowLampRow, + FirstHoursRow, SecondHoursRow, + FirstMinutesRow, SecondMinutesRow); + } + } +} diff --git a/Models/BerlinClockRendererRequest.cs b/Models/BerlinClockRendererRequest.cs new file mode 100644 index 00000000..09b7a992 --- /dev/null +++ b/Models/BerlinClockRendererRequest.cs @@ -0,0 +1,12 @@ +using System; + +namespace BerlinClock.Models +{ + public class BerlinClockRendererRequest + { + public int AmountOfTurnedOnLamps { get; set; } + public int AmountOfTurnedOffLamps { get; set; } + public char TurnedOnLampSign { get; set; } + public Func AdditionalFormatting { get; set; } + } +} diff --git a/Models/BerlinClockRows.cs b/Models/BerlinClockRows.cs new file mode 100644 index 00000000..4bf6bd27 --- /dev/null +++ b/Models/BerlinClockRows.cs @@ -0,0 +1,8 @@ +namespace BerlinClock.Models +{ + public class BerlinClockRows + { + public string FirstRow { get; set; } + public string SecondRow { get; set; } + } +} diff --git a/Models/Time.cs b/Models/Time.cs new file mode 100644 index 00000000..e5be78b1 --- /dev/null +++ b/Models/Time.cs @@ -0,0 +1,15 @@ +namespace BerlinClock.Models +{ + public struct Time + { + public Time(int hour, int minute, int second) + { + Hour = hour; + Minute = minute; + Second = second; + } + public int Hour { get; private set; } + public int Minute { get; private set; } + public int Second { get; private set; } + } +} diff --git a/Parsers/TimeParser.cs b/Parsers/TimeParser.cs new file mode 100644 index 00000000..924a05fa --- /dev/null +++ b/Parsers/TimeParser.cs @@ -0,0 +1,30 @@ +using BerlinClock.Models; +using System; + +namespace BerlinClock.Parsers +{ + public interface ITimeParser + { + Time Parse(string time); + } + + public class TimeParser : ITimeParser + { + private const char Separator = ':'; + public Time Parse(string time) + { + if (time == null) + throw new Exception("Time must not be null"); + + var timeParts = time.Split(Separator); + if (timeParts.Length != 3) + throw new Exception("Wrong time format"); + + var hour = int.Parse(timeParts[0]); + var minute = int.Parse(timeParts[1]); + var second = int.Parse(timeParts[2]); + + return new Time(hour, minute, second); + } + } +} diff --git a/Renderers/BerlinClockRowRenderer.cs b/Renderers/BerlinClockRowRenderer.cs new file mode 100644 index 00000000..d6c2395e --- /dev/null +++ b/Renderers/BerlinClockRowRenderer.cs @@ -0,0 +1,30 @@ +using BerlinClock.Models; +using System; +using System.Text; + +namespace BerlinClock.Renderers +{ + public interface IBerlinClockRowRenderer + { + string Render(BerlinClockRendererRequest request); + } + + public class BerlinClockRowRenderer : IBerlinClockRowRenderer + { + private const char TurnedOffLampSign = 'O'; + + public string Render(BerlinClockRendererRequest request) + { + if (request.AmountOfTurnedOffLamps < 0 || request.AmountOfTurnedOnLamps < 0) + throw new Exception("Cannot render negative values"); + + var stringBuilder = new StringBuilder(); + stringBuilder.Append(request.TurnedOnLampSign, request.AmountOfTurnedOnLamps); + stringBuilder.Append(TurnedOffLampSign, request.AmountOfTurnedOffLamps); + + var row = stringBuilder.ToString(); + return request.AdditionalFormatting != null + ? request.AdditionalFormatting(row) : row; + } + } +}