public void GetHumanReadableValue_ReturnsInRangeIfValueInTruthTable(params string[] numbers)
        {
            var result = TruthTable.GetHumanReadableValue(numbers);

            Assert.InRange(result, 0, 99);
        }
        public async Task <Response> AddObservation(Observation observation)
        {
            try
            {
                #region Validation

                if (string.IsNullOrWhiteSpace(observation.Color) ||
                    !new[] { "green", "red" }.Contains(observation.Color))
                {
                    throw new ArgumentException("Invalid color. Acceptable values: 'green' or 'red'.",
                                                nameof(observation.Color));
                }

                if (observation.Color.Equals("green") &&
                    (observation.Numbers.Any(str => str.Length != 7) || observation.Numbers.Any(str =>
                                                                                                str.Except(new[] { '0', '1' }).Any())))
                {
                    throw new ArgumentException(ErrorMessage.InvalidNumberFormat, nameof(observation.Numbers));
                }

                var existingSequence = await UnitOfWork.SequenceRepository.Get(observation.SequenceId);

                if (existingSequence == null)
                {
                    throw new KeyNotFoundException(ErrorMessage.SequenceNotFound);
                }

                if (!existingSequence.Observations.Any() && observation.Color.Equals("red"))
                {
                    throw new InvalidOperationException(ErrorMessage.NotEnoughData);
                }

                if (existingSequence.Observations.Any(ob => ob.Color.ToLower().Equals("red")))
                {
                    throw new InvalidOperationException(ErrorMessage.RedObservationShouldBeLast);
                }

                if (observation.Color.Equals("green") &&
                    (observation.Numbers.Length != 2 || existingSequence.Observations.Any(ob =>
                                                                                          ob.Numbers.SequenceEqual(observation.Numbers))))
                {
                    throw new ArgumentException(ErrorMessage.NoSolutionsFound);
                }

                #endregion

                if (observation.Color.Equals("red"))
                {
                    observation.Numbers                = new[] { "1110111", "1110111" };
                    observation.ReadableValue          = 0;
                    observation.PossibleReadableValues = new[] { 0 };
                }
                else
                {
                    observation.ReadableValue          = TruthTable.GetHumanReadableValue(observation.Numbers);
                    observation.PossibleReadableValues = TruthTable.GetPossibleNumbers(observation.Numbers).ToArray();
                }

                await UnitOfWork.ObservationRepository.Add(Mapper.Map <Data.Model.Observation>(observation));

                foreach (var(number, display) in observation.Numbers.Select((num, i) => (num, i)))
                {
                    var workingSections =
                        number.Select((c, section) => c == '1' ? section : -1).Where(index => index > -1);
                    await SetWorkingSections(display, workingSections, existingSequence);
                }

                await UnitOfWork.Save();

                var missing       = GetMissingSections(existingSequence.WorkingSections);
                var possibleStart = GetPossibleStart(existingSequence.Observations);
                if (possibleStart.Length == 0)
                {
                    throw new InvalidOperationException(ErrorMessage.NoSolutionsFound);
                }
                existingSequence.PossibleStart = possibleStart;
                existingSequence.Missing       = missing;
                UnitOfWork.SequenceRepository.Update(existingSequence);
                await UnitOfWork.Save();

                return(new Response
                {
                    Missing = missing,
                    Start = existingSequence.PossibleStart
                });
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
                throw;
            }
        }
        public void GetHumanReadableValue_ReturnsNegativeIfValueNotInTruthTable(params string[] numbers)
        {
            var result = TruthTable.GetHumanReadableValue(numbers);

            Assert.True(result < 0);
        }