diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..240c8ae7 --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +################################################################################ +# This .gitignore file was automatically created by Microsoft(R) Visual Studio. +################################################################################ + +/.vs/BerlinClock/v16 +/.vs/VSProjects/v16 +/bin/Debug +/.vs +/obj/Debug +/packages/SpecFlow.1.9.0 diff --git a/BerlinClock.csproj b/BerlinClock.csproj index ac8af99d..22efef88 100644 --- a/BerlinClock.csproj +++ b/BerlinClock.csproj @@ -50,6 +50,10 @@ + + + + True diff --git a/Classes/Clock.cs b/Classes/Clock.cs new file mode 100644 index 00000000..1fdbf8fc --- /dev/null +++ b/Classes/Clock.cs @@ -0,0 +1,75 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace BerlinClock +{ + /// + /// clock model + /// + public class Clock + { + /// + /// time that should be converted + /// + private readonly TimeSpan _time; + private readonly ClockConfig _clockConfig; + + /// + /// clock state + /// + private List Rows => new List + { + new ClockRow + { + ComputeLampChar = x => ClockConfig.YellowLamp, + Length = _clockConfig.BlinkLamps, + LampsOn = _time.Seconds % _clockConfig.NumberOfBlinksStates == 0 ? 1 : 0 + }, + new ClockRow + { + ComputeLampChar = x => ClockConfig.RedLamp, + Length = _clockConfig.HourLampsPerRow, + LampsOn = (int)(_time.TotalHours - _time.TotalHours % _clockConfig.HoursPerLampRow1) / _clockConfig.HoursPerLampRow1 + }, + new ClockRow + { + ComputeLampChar = x => ClockConfig.RedLamp, + Length = _clockConfig.HourLampsPerRow, + LampsOn = (int)_time.TotalHours % _clockConfig.HoursPerLampRow1 + }, + new ClockRow + { + ComputeLampChar = x => (x + 1) % 3 == 0 ? ClockConfig.RedLamp : ClockConfig.YellowLamp, + Length = _clockConfig.MinuteLampsRow1, + LampsOn = (_time.Minutes - _time.Minutes % _clockConfig.MinutesPerLampRow1) / _clockConfig.MinutesPerLampRow1 + }, + new ClockRow + { + ComputeLampChar = x => ClockConfig.YellowLamp, + Length = _clockConfig.MinuteLampsRow2, + LampsOn = _time.Minutes % _clockConfig.MinutesPerLampRow1 + } + }; + + /// + /// clock model + /// + /// time that should be converted + public Clock(TimeSpan time, ClockConfig config) + { + _time = time; + _clockConfig = config; + } + + public Clock(string serializedTime, ClockConfig config) + : this(serializedTime.ParseTimeString(), config) + { + + } + + public override string ToString() => string.Join(Environment.NewLine, Rows.Select(x => x.ToString())); + } +} diff --git a/Classes/ClockConfig.cs b/Classes/ClockConfig.cs new file mode 100644 index 00000000..b2da741c --- /dev/null +++ b/Classes/ClockConfig.cs @@ -0,0 +1,52 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace BerlinClock +{ + public class ClockConfig + { + #region characters to represent lamps + + public const char RedLamp = 'R'; + public const char YellowLamp = 'Y'; + + #endregion + + #region number of lamps in clock rows + + public int BlinkLamps { get; private set; } + public int HourLampsPerRow { get; private set; } + public int MinuteLampsRow1 { get; private set; } + public int MinuteLampsRow2 { get; private set; } + + #endregion + + #region number of lamps in clock rows + + public int NumberOfBlinksStates { get; private set; } + public int HoursPerLampRow1 { get; private set; } + public int MinutesPerLampRow1 { get; private set; } + + #endregion + + public ClockConfig(int blinkLamps, + int hourLampsPerRow, + int minuteLampsRow1, + int minuteLampsRow2, + int numberOfBlinkStates, + int hoursPerLampRow1, + int minutesPerLampRow1) + { + BlinkLamps = blinkLamps; + HourLampsPerRow = hourLampsPerRow; + MinuteLampsRow1 = minuteLampsRow1; + MinuteLampsRow2 = minuteLampsRow2; + NumberOfBlinksStates = numberOfBlinkStates; + HoursPerLampRow1 = hoursPerLampRow1; + MinutesPerLampRow1 = minutesPerLampRow1; + } + } +} diff --git a/Classes/ClockRow.cs b/Classes/ClockRow.cs new file mode 100644 index 00000000..160680ae --- /dev/null +++ b/Classes/ClockRow.cs @@ -0,0 +1,41 @@ +using System; +using System.Linq; + +namespace BerlinClock +{ + /// + /// clock row model + /// + public class ClockRow + { + /// + /// filler for empty position in clock row + /// + const char EmptyValChar = 'O'; + + /// + /// lambda to compute appropriate lamp char + /// + public Func ComputeLampChar { get; set; } + + /// + /// defines whole length of clock row + /// + public int Length { private get; set; } + + /// + /// defines how many lamps should be highlighted + /// + public int LampsOn { private get; set; } + + public override string ToString() => + string + .Join( + string.Empty, + new string( + Enumerable.Range(0, LampsOn).Select(ComputeLampChar).ToArray() + ) + ) + .PadRight(Length, EmptyValChar); + } +} diff --git a/Classes/DateTimeUtilities.cs b/Classes/DateTimeUtilities.cs new file mode 100644 index 00000000..31782a57 --- /dev/null +++ b/Classes/DateTimeUtilities.cs @@ -0,0 +1,49 @@ +using System; +using System.Globalization; +using System.Text.RegularExpressions; + +namespace BerlinClock +{ + /// + /// helper that convert time string time stamp + /// + public static class DateTimeUtilities + { + /// + /// expected time string format + /// + private const string TimeFormat = "HH:mm:ss"; + + /// + /// template to check if string defines 24th hour + /// + private const string TimeTemplate = @"24(:[0-5][0-9]:[0-5][0-9])$"; + + /// + /// adjusts time string so it could be converted to timespan + /// + /// time string + /// + private static string Adjust(this string val) => + Regex.Replace(val, TimeTemplate, "00$1"); + + /// + /// parses formatted time string to timestamp + /// + /// time string + /// + private static TimeSpan ParseFormattedTimeString(this string val) => + DateTime.ParseExact(val, TimeFormat, CultureInfo.CurrentCulture).TimeOfDay; + + /// + /// parses time string to timespan. + /// hours overflow is taken into consideration. + /// + /// time string + /// + public static TimeSpan ParseTimeString(this string val) => + Regex.IsMatch(val, TimeTemplate) + ? val.Adjust().ParseFormattedTimeString().Add(TimeSpan.FromDays(1)) + : val.ParseFormattedTimeString(); + } +} diff --git a/Classes/TimeConverter.cs b/Classes/TimeConverter.cs index dd5bf4e0..8804c2d2 100644 --- a/Classes/TimeConverter.cs +++ b/Classes/TimeConverter.cs @@ -1,15 +1,21 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace BerlinClock +namespace BerlinClock { public class TimeConverter : ITimeConverter { + private ClockConfig _config = new ClockConfig( + blinkLamps: 1, + hourLampsPerRow: 4, + minuteLampsRow1: 11, + minuteLampsRow2: 4, + numberOfBlinkStates: 2, + hoursPerLampRow1: 5, + minutesPerLampRow1: 5); + public string convertTime(string aTime) { - throw new NotImplementedException(); + var clock = new Clock(aTime, _config); + + return clock.ToString(); } } }