Example #1
0
        protected void buildBuyItSet()
        {
            action = new ContinuousDimension("Action", "-10 surely don't buy ... +10 surely buy", "", -10, +10);

            if (trackBarBuyItKernel.Value < -8)
            {
                trackBarBuyItKernel.Value = -8;
            }
            if (trackBarBuyItCrossover.Value < -9)
            {
                trackBarBuyItCrossover.Value = -9;
            }

            if (trackBarBuyItCrossover.Value > trackBarBuyItKernel.Value - 1)
            {
                trackBarBuyItCrossover.Value = trackBarBuyItKernel.Value - 1;
            }

            if (trackBarBuyItSupport.Value > trackBarBuyItCrossover.Value - 1)
            {
                trackBarBuyItSupport.Value = trackBarBuyItCrossover.Value - 1;
            }

            buyIt = new LeftQuadraticSet(action, "Buy it!", trackBarBuyItSupport.Value, trackBarBuyItCrossover.Value, trackBarBuyItKernel.Value);

            RelationImage imgBuyIt = new RelationImage(buyIt);
            Bitmap        bmpBuyIt = new Bitmap(pictureBoxBuyIt.Width, pictureBoxBuyIt.Height);

            imgBuyIt.DrawImage(Graphics.FromImage(bmpBuyIt));
            pictureBoxBuyIt.Image = bmpBuyIt;
        }
Example #2
0
        protected void buildTemperatureSets()
        {
            temperature = new ContinuousDimension("t", "Temperature detected by sensor", "°C", -30, +40);

            lowTemperature     = new RightQuadraticSet(temperature, "Low temperature", 10, 15, 20);
            highTemperature    = new LeftQuadraticSet(temperature, "High temperature", 20, 25, 30);
            correctTemperature = new BellSet(temperature, "Correct temperature", 20, 5, 10);

            #region Show it graphically
            RelationImage imgLowTemp     = new RelationImage(lowTemperature);
            RelationImage imgHighTemp    = new RelationImage(highTemperature);
            RelationImage imgCorrectTemp = new RelationImage(correctTemperature);

            Bitmap bmpLowTemp     = new Bitmap(pictureBoxLowTemp.Width, pictureBoxLowTemp.Height);
            Bitmap bmpHighTemp    = new Bitmap(pictureBoxHighTemp.Width, pictureBoxHighTemp.Height);
            Bitmap bmpCorrectTemp = new Bitmap(pictureBoxCorrectTemp.Width, pictureBoxCorrectTemp.Height);

            imgLowTemp.DrawImage(Graphics.FromImage(bmpLowTemp));
            imgHighTemp.DrawImage(Graphics.FromImage(bmpHighTemp));
            imgCorrectTemp.DrawImage(Graphics.FromImage(bmpCorrectTemp));

            pictureBoxLowTemp.Image     = bmpLowTemp;
            pictureBoxHighTemp.Image    = bmpHighTemp;
            pictureBoxCorrectTemp.Image = bmpCorrectTemp;
            #endregion
        }
Example #3
0
        protected void buildActionSets()
        {
            action = new ContinuousDimension("Action", "-10 Cool ... 0 Do nothing ... +10 heat", "", -10, +10);

            heat      = new SingletonSet(action, "Heat", 10);
            cool      = new SingletonSet(action, "Cool", -10);
            doNothing = new SingletonSet(action, "Do nothing", 0);

            #region Show it graphically
            RelationImage imgHeat      = new RelationImage(heat);
            RelationImage imgCool      = new RelationImage(cool);
            RelationImage imgDoNothing = new RelationImage(doNothing);

            Bitmap bmpHeat      = new Bitmap(pictureBoxHeat.Width, pictureBoxHeat.Height);
            Bitmap bmpCool      = new Bitmap(pictureBoxCool.Width, pictureBoxCool.Height);
            Bitmap bmpDoNothing = new Bitmap(pictureBoxDoNothing.Width, pictureBoxDoNothing.Height);

            imgHeat.DrawImage(Graphics.FromImage(bmpHeat));
            imgCool.DrawImage(Graphics.FromImage(bmpCool));
            imgDoNothing.DrawImage(Graphics.FromImage(bmpDoNothing));

            pictureBoxHeat.Image      = bmpHeat;
            pictureBoxCool.Image      = bmpCool;
            pictureBoxDoNothing.Image = bmpDoNothing;
            #endregion
        }
Example #4
0
        protected void buildDeltaTemperatureSets()
        {
            deltaTemperature = new ContinuousDimension("∆t", "Change of temperature detected by temperature sensor in time period", "°C/min", -5, +5);

            fallingTemperature  = new RightQuadraticSet(deltaTemperature, "Falling temperature", -3, -1, 0);
            risingTemperature   = new LeftQuadraticSet(deltaTemperature, "Rising temperature", 0, 1, 3);
            constantTemperature = new BellSet(deltaTemperature, "Constant temperature", 0, 1, 3);

            #region Show it graphically
            RelationImage imgFallingTemp  = new RelationImage(fallingTemperature);
            RelationImage imgRisingTemp   = new RelationImage(risingTemperature);
            RelationImage imgConstantTemp = new RelationImage(constantTemperature);

            Bitmap bmpFallingTemp  = new Bitmap(pictureBoxFallingTemp.Width, pictureBoxFallingTemp.Height);
            Bitmap bmpRisingTemp   = new Bitmap(pictureBoxRisingTemp.Width, pictureBoxRisingTemp.Height);
            Bitmap bmpConstantTemp = new Bitmap(pictureBoxConstantTemp.Width, pictureBoxConstantTemp.Height);

            imgFallingTemp.DrawImage(Graphics.FromImage(bmpFallingTemp));
            imgRisingTemp.DrawImage(Graphics.FromImage(bmpRisingTemp));
            imgConstantTemp.DrawImage(Graphics.FromImage(bmpConstantTemp));

            pictureBoxFallingTemp.Image  = bmpFallingTemp;
            pictureBoxRisingTemp.Image   = bmpRisingTemp;
            pictureBoxConstantTemp.Image = bmpConstantTemp;
            #endregion
        }
Example #5
0
        /// <summary>
        /// Returns a hash code for the specified object.
        /// </summary>
        /// <returns>
        /// A hash code for the specified object.
        /// </returns>
        /// <param name="obj">The object for which a hash code is to be returned.</param>
        /// <exception cref="T:System.ArgumentNullException">The type of <paramref name="obj"/> is a reference type and <paramref name="obj"/> is null.</exception>
        public int GetHashCode(ContinuousSet <T> obj)
        {
            if (obj == null)
            {
                throw new ArgumentNullException("obj");
            }

            return(ContinuousSet <T> .GetHashCode(this.eqT, obj, this.ignoreRedundantFalses, this.ignoreRedundantTrues));
        }
Example #6
0
        protected void buildCheapSet()
        {
            price = new ContinuousDimension("Price", "Price we are about to pay for an offer", "$", 0, 1000);

            if (trackBarCheapSupport.Value < trackBarCheapKernel.Value)
            {
                trackBarCheapSupport.Value = trackBarCheapKernel.Value;
            }

            cheap = new RightLinearSet(price, "Cheap", trackBarCheapKernel.Value, trackBarCheapSupport.Value);

            RelationImage imgCheap = new RelationImage(cheap);
            Bitmap        bmpCheap = new Bitmap(pictureBoxCheap.Width, pictureBoxCheap.Height);

            imgCheap.DrawImage(Graphics.FromImage(bmpCheap));
            pictureBoxCheap.Image = bmpCheap;
        }
        public void SetSplitingEveryMonth()
        {
            #region snapSetIntervals = ...
            // the following snapshot was generated from a good result using the method GenerateCode("snapSetIntervals")
            var snapSetIntervals = new[]
                {
                    // [01/01/2000 00:00:00 to 10/10/2002 00:00:00]
                    new Interval<DateTime>(new DateTime(2000, 01, 01, 00, 00, 00), PointState.Included, new DateTime(2002, 10, 10, 00, 00, 00), PointState.Included, isPositive: true),

                    // [01/01/2010 00:00:00 to 10/10/2012 00:00:00]
                    new Interval<DateTime>(new DateTime(2010, 01, 01, 00, 00, 00), PointState.Included, new DateTime(2012, 10, 10, 00, 00, 00), PointState.Included, isPositive: true)
                };
            #endregion

            #region snapSetIntervalsPoint = ...
            // the following snapshot was generated from a good result using the method GenerateCode("snapSetIntervalsPoint")
            var snapSetIntervalsPoint = new[]
                {
                    // [01/01/2000 00:00:00 to 10/10/2002 00:00:00]
                    new Interval<DateTime>(new DateTime(2000, 01, 01, 00, 00, 00), PointState.Included, new DateTime(2002, 10, 10, 00, 00, 00), PointState.Included, isPositive: true),

                    // [04/05/2005 12:35:20]
                    new Interval<DateTime>(new DateTime(2005, 04, 05, 12, 35, 20), PointState.Included, new DateTime(2005, 04, 05, 12, 35, 20), PointState.Included, isPositive: true),

                    // [01/01/2010 00:00:00 to 10/10/2012 00:00:00]
                    new Interval<DateTime>(new DateTime(2010, 01, 01, 00, 00, 00), PointState.Included, new DateTime(2012, 10, 10, 00, 00, 00), PointState.Included, isPositive: true)
                };
            #endregion

            #region snapSetIntervalsSplit = ...
            // the following snapshot was generated from a good result using the method GenerateCode("snapSetIntervalsSplit")
            var snapSetIntervalsSplit = new[]
                {
                    // [01/01/2000 00:00:00 to 05/01/2000 00:00:00[
                    new Interval<DateTime>(new DateTime(2000, 01, 01, 00, 00, 00), PointState.Included, new DateTime(2000, 05, 01, 00, 00, 00), PointState.Excluded, isPositive: true),

                    // [05/01/2000 00:00:00 to 09/01/2000 00:00:00[
                    new Interval<DateTime>(new DateTime(2000, 05, 01, 00, 00, 00), PointState.Included, new DateTime(2000, 09, 01, 00, 00, 00), PointState.Excluded, isPositive: true),

                    // [09/01/2000 00:00:00 to 01/01/2001 00:00:00[
                    new Interval<DateTime>(new DateTime(2000, 09, 01, 00, 00, 00), PointState.Included, new DateTime(2001, 01, 01, 00, 00, 00), PointState.Excluded, isPositive: true),

                    // [01/01/2001 00:00:00 to 05/01/2001 00:00:00[
                    new Interval<DateTime>(new DateTime(2001, 01, 01, 00, 00, 00), PointState.Included, new DateTime(2001, 05, 01, 00, 00, 00), PointState.Excluded, isPositive: true),

                    // [05/01/2001 00:00:00 to 09/01/2001 00:00:00[
                    new Interval<DateTime>(new DateTime(2001, 05, 01, 00, 00, 00), PointState.Included, new DateTime(2001, 09, 01, 00, 00, 00), PointState.Excluded, isPositive: true),

                    // [09/01/2001 00:00:00 to 01/01/2002 00:00:00[
                    new Interval<DateTime>(new DateTime(2001, 09, 01, 00, 00, 00), PointState.Included, new DateTime(2002, 01, 01, 00, 00, 00), PointState.Excluded, isPositive: true),

                    // [01/01/2002 00:00:00 to 05/01/2002 00:00:00[
                    new Interval<DateTime>(new DateTime(2002, 01, 01, 00, 00, 00), PointState.Included, new DateTime(2002, 05, 01, 00, 00, 00), PointState.Excluded, isPositive: true),

                    // [05/01/2002 00:00:00 to 09/01/2002 00:00:00[
                    new Interval<DateTime>(new DateTime(2002, 05, 01, 00, 00, 00), PointState.Included, new DateTime(2002, 09, 01, 00, 00, 00), PointState.Excluded, isPositive: true),

                    // [09/01/2002 00:00:00 to 10/10/2002 00:00:00]
                    new Interval<DateTime>(new DateTime(2002, 09, 01, 00, 00, 00), PointState.Included, new DateTime(2002, 10, 10, 00, 00, 00), PointState.Included, isPositive: true),

                    // [01/01/2010 00:00:00 to 05/01/2010 00:00:00[
                    new Interval<DateTime>(new DateTime(2010, 01, 01, 00, 00, 00), PointState.Included, new DateTime(2010, 05, 01, 00, 00, 00), PointState.Excluded, isPositive: true),

                    // [05/01/2010 00:00:00 to 09/01/2010 00:00:00[
                    new Interval<DateTime>(new DateTime(2010, 05, 01, 00, 00, 00), PointState.Included, new DateTime(2010, 09, 01, 00, 00, 00), PointState.Excluded, isPositive: true),

                    // [09/01/2010 00:00:00 to 01/01/2011 00:00:00[
                    new Interval<DateTime>(new DateTime(2010, 09, 01, 00, 00, 00), PointState.Included, new DateTime(2011, 01, 01, 00, 00, 00), PointState.Excluded, isPositive: true),

                    // [01/01/2011 00:00:00 to 05/01/2011 00:00:00[
                    new Interval<DateTime>(new DateTime(2011, 01, 01, 00, 00, 00), PointState.Included, new DateTime(2011, 05, 01, 00, 00, 00), PointState.Excluded, isPositive: true),

                    // [05/01/2011 00:00:00 to 09/01/2011 00:00:00[
                    new Interval<DateTime>(new DateTime(2011, 05, 01, 00, 00, 00), PointState.Included, new DateTime(2011, 09, 01, 00, 00, 00), PointState.Excluded, isPositive: true),

                    // [09/01/2011 00:00:00 to 01/01/2012 00:00:00[
                    new Interval<DateTime>(new DateTime(2011, 09, 01, 00, 00, 00), PointState.Included, new DateTime(2012, 01, 01, 00, 00, 00), PointState.Excluded, isPositive: true),

                    // [01/01/2012 00:00:00 to 05/01/2012 00:00:00[
                    new Interval<DateTime>(new DateTime(2012, 01, 01, 00, 00, 00), PointState.Included, new DateTime(2012, 05, 01, 00, 00, 00), PointState.Excluded, isPositive: true),

                    // [05/01/2012 00:00:00 to 09/01/2012 00:00:00[
                    new Interval<DateTime>(new DateTime(2012, 05, 01, 00, 00, 00), PointState.Included, new DateTime(2012, 09, 01, 00, 00, 00), PointState.Excluded, isPositive: true),

                    // [09/01/2012 00:00:00 to 10/10/2012 00:00:00]
                    new Interval<DateTime>(new DateTime(2012, 09, 01, 00, 00, 00), PointState.Included, new DateTime(2012, 10, 10, 00, 00, 00), PointState.Included, isPositive: true)
                };
            #endregion

            #region snapSetIntervalsSplitPoint = ...
            // the following snapshot was generated from a good result using the method GenerateCode("snapSetIntervalsSplitPoint")
            var snapSetIntervalsSplitPoint = new[]
                {
                    // [01/01/2000 00:00:00 to 05/01/2000 00:00:00[
                    new Interval<DateTime>(new DateTime(2000, 01, 01, 00, 00, 00), PointState.Included, new DateTime(2000, 05, 01, 00, 00, 00), PointState.Excluded, isPositive: true),

                    // [05/01/2000 00:00:00 to 09/01/2000 00:00:00[
                    new Interval<DateTime>(new DateTime(2000, 05, 01, 00, 00, 00), PointState.Included, new DateTime(2000, 09, 01, 00, 00, 00), PointState.Excluded, isPositive: true),

                    // [09/01/2000 00:00:00 to 01/01/2001 00:00:00[
                    new Interval<DateTime>(new DateTime(2000, 09, 01, 00, 00, 00), PointState.Included, new DateTime(2001, 01, 01, 00, 00, 00), PointState.Excluded, isPositive: true),

                    // [01/01/2001 00:00:00 to 05/01/2001 00:00:00[
                    new Interval<DateTime>(new DateTime(2001, 01, 01, 00, 00, 00), PointState.Included, new DateTime(2001, 05, 01, 00, 00, 00), PointState.Excluded, isPositive: true),

                    // [05/01/2001 00:00:00 to 09/01/2001 00:00:00[
                    new Interval<DateTime>(new DateTime(2001, 05, 01, 00, 00, 00), PointState.Included, new DateTime(2001, 09, 01, 00, 00, 00), PointState.Excluded, isPositive: true),

                    // [09/01/2001 00:00:00 to 01/01/2002 00:00:00[
                    new Interval<DateTime>(new DateTime(2001, 09, 01, 00, 00, 00), PointState.Included, new DateTime(2002, 01, 01, 00, 00, 00), PointState.Excluded, isPositive: true),

                    // [01/01/2002 00:00:00 to 05/01/2002 00:00:00[
                    new Interval<DateTime>(new DateTime(2002, 01, 01, 00, 00, 00), PointState.Included, new DateTime(2002, 05, 01, 00, 00, 00), PointState.Excluded, isPositive: true),

                    // [05/01/2002 00:00:00 to 09/01/2002 00:00:00[
                    new Interval<DateTime>(new DateTime(2002, 05, 01, 00, 00, 00), PointState.Included, new DateTime(2002, 09, 01, 00, 00, 00), PointState.Excluded, isPositive: true),

                    // [09/01/2002 00:00:00 to 10/10/2002 00:00:00]
                    new Interval<DateTime>(new DateTime(2002, 09, 01, 00, 00, 00), PointState.Included, new DateTime(2002, 10, 10, 00, 00, 00), PointState.Included, isPositive: true),

                    // [04/05/2005 12:35:20]
                    new Interval<DateTime>(new DateTime(2005, 04, 05, 12, 35, 20), PointState.Included, new DateTime(2005, 04, 05, 12, 35, 20), PointState.Included, isPositive: true),

                    // [01/01/2010 00:00:00 to 05/01/2010 00:00:00[
                    new Interval<DateTime>(new DateTime(2010, 01, 01, 00, 00, 00), PointState.Included, new DateTime(2010, 05, 01, 00, 00, 00), PointState.Excluded, isPositive: true),

                    // [05/01/2010 00:00:00 to 09/01/2010 00:00:00[
                    new Interval<DateTime>(new DateTime(2010, 05, 01, 00, 00, 00), PointState.Included, new DateTime(2010, 09, 01, 00, 00, 00), PointState.Excluded, isPositive: true),

                    // [09/01/2010 00:00:00 to 01/01/2011 00:00:00[
                    new Interval<DateTime>(new DateTime(2010, 09, 01, 00, 00, 00), PointState.Included, new DateTime(2011, 01, 01, 00, 00, 00), PointState.Excluded, isPositive: true),

                    // [01/01/2011 00:00:00 to 05/01/2011 00:00:00[
                    new Interval<DateTime>(new DateTime(2011, 01, 01, 00, 00, 00), PointState.Included, new DateTime(2011, 05, 01, 00, 00, 00), PointState.Excluded, isPositive: true),

                    // [05/01/2011 00:00:00 to 09/01/2011 00:00:00[
                    new Interval<DateTime>(new DateTime(2011, 05, 01, 00, 00, 00), PointState.Included, new DateTime(2011, 09, 01, 00, 00, 00), PointState.Excluded, isPositive: true),

                    // [09/01/2011 00:00:00 to 01/01/2012 00:00:00[
                    new Interval<DateTime>(new DateTime(2011, 09, 01, 00, 00, 00), PointState.Included, new DateTime(2012, 01, 01, 00, 00, 00), PointState.Excluded, isPositive: true),

                    // [01/01/2012 00:00:00 to 05/01/2012 00:00:00[
                    new Interval<DateTime>(new DateTime(2012, 01, 01, 00, 00, 00), PointState.Included, new DateTime(2012, 05, 01, 00, 00, 00), PointState.Excluded, isPositive: true),

                    // [05/01/2012 00:00:00 to 09/01/2012 00:00:00[
                    new Interval<DateTime>(new DateTime(2012, 05, 01, 00, 00, 00), PointState.Included, new DateTime(2012, 09, 01, 00, 00, 00), PointState.Excluded, isPositive: true),

                    // [09/01/2012 00:00:00 to 10/10/2012 00:00:00]
                    new Interval<DateTime>(new DateTime(2012, 09, 01, 00, 00, 00), PointState.Included, new DateTime(2012, 10, 10, 00, 00, 00), PointState.Included, isPositive: true)
                };
            #endregion

            #region set2Intervals = ...
            // the following snapshot was generated from a good result using the method GenerateCode("set2Intervals")
            var set2Intervals = new[]
                {
                    // ]10/05/1999 00:00:00 to 08/05/2000 15:44:30[
                    new Interval<DateTime>(new DateTime(1999, 10, 05, 00, 00, 00), PointState.Excluded, new DateTime(2000, 08, 05, 15, 44, 30), PointState.Excluded, isPositive: true),

                    // [01/02/2001 00:00:00 to 02/03/2011 14:00:00]
                    new Interval<DateTime>(new DateTime(2001, 01, 02, 00, 00, 00), PointState.Included, new DateTime(2011, 02, 03, 14, 00, 00), PointState.Included, isPositive: true)
                };
            #endregion

            #region intervals = ...
            // the following snapshot was generated from a good result using the method GenerateCode("intervals")
            var intervals = new[]
                {
                    // [01/01/2000 00:00:00 to 05/01/2000 00:00:00[
                    new Interval<DateTime>(new DateTime(2000, 01, 01, 00, 00, 00), PointState.Included, new DateTime(2000, 05, 01, 00, 00, 00), PointState.Excluded, isPositive: true),

                    // [05/01/2000 00:00:00 to 08/05/2000 15:44:30[
                    new Interval<DateTime>(new DateTime(2000, 05, 01, 00, 00, 00), PointState.Included, new DateTime(2000, 08, 05, 15, 44, 30), PointState.Excluded, isPositive: true),

                    // [01/02/2001 00:00:00 to 05/01/2001 00:00:00[
                    new Interval<DateTime>(new DateTime(2001, 01, 02, 00, 00, 00), PointState.Included, new DateTime(2001, 05, 01, 00, 00, 00), PointState.Excluded, isPositive: true),

                    // [05/01/2001 00:00:00 to 09/01/2001 00:00:00[
                    new Interval<DateTime>(new DateTime(2001, 05, 01, 00, 00, 00), PointState.Included, new DateTime(2001, 09, 01, 00, 00, 00), PointState.Excluded, isPositive: true),

                    // [09/01/2001 00:00:00 to 01/01/2002 00:00:00[
                    new Interval<DateTime>(new DateTime(2001, 09, 01, 00, 00, 00), PointState.Included, new DateTime(2002, 01, 01, 00, 00, 00), PointState.Excluded, isPositive: true),

                    // [01/01/2002 00:00:00 to 05/01/2002 00:00:00[
                    new Interval<DateTime>(new DateTime(2002, 01, 01, 00, 00, 00), PointState.Included, new DateTime(2002, 05, 01, 00, 00, 00), PointState.Excluded, isPositive: true),

                    // [05/01/2002 00:00:00 to 09/01/2002 00:00:00[
                    new Interval<DateTime>(new DateTime(2002, 05, 01, 00, 00, 00), PointState.Included, new DateTime(2002, 09, 01, 00, 00, 00), PointState.Excluded, isPositive: true),

                    // [09/01/2002 00:00:00 to 10/10/2002 00:00:00]
                    new Interval<DateTime>(new DateTime(2002, 09, 01, 00, 00, 00), PointState.Included, new DateTime(2002, 10, 10, 00, 00, 00), PointState.Included, isPositive: true),

                    // [04/05/2005 12:35:20]
                    new Interval<DateTime>(new DateTime(2005, 04, 05, 12, 35, 20), PointState.Included, new DateTime(2005, 04, 05, 12, 35, 20), PointState.Included, isPositive: true),

                    // [01/01/2010 00:00:00 to 05/01/2010 00:00:00[
                    new Interval<DateTime>(new DateTime(2010, 01, 01, 00, 00, 00), PointState.Included, new DateTime(2010, 05, 01, 00, 00, 00), PointState.Excluded, isPositive: true),

                    // [05/01/2010 00:00:00 to 09/01/2010 00:00:00[
                    new Interval<DateTime>(new DateTime(2010, 05, 01, 00, 00, 00), PointState.Included, new DateTime(2010, 09, 01, 00, 00, 00), PointState.Excluded, isPositive: true),

                    // [09/01/2010 00:00:00 to 01/01/2011 00:00:00[
                    new Interval<DateTime>(new DateTime(2010, 09, 01, 00, 00, 00), PointState.Included, new DateTime(2011, 01, 01, 00, 00, 00), PointState.Excluded, isPositive: true),

                    // [01/01/2011 00:00:00 to 02/03/2011 14:00:00]
                    new Interval<DateTime>(new DateTime(2011, 01, 01, 00, 00, 00), PointState.Included, new DateTime(2011, 02, 03, 14, 00, 00), PointState.Included, isPositive: true)
                };
            #endregion

            #region snapSetNot = ...
            // the following snapshot was generated from a good result using the method GenerateCode("snapSetNot")
            var snapSetNot = new[]
                {
                    // -∞ to 01/01/2000 00:00:00[
                    new Interval<DateTime>(default(DateTime), PointState.Open, new DateTime(2000, 01, 01, 00, 00, 00), PointState.Excluded, isPositive: true),

                    // [08/05/2000 15:44:30 to 01/02/2001 00:00:00[
                    new Interval<DateTime>(new DateTime(2000, 08, 05, 15, 44, 30), PointState.Included, new DateTime(2001, 01, 02, 00, 00, 00), PointState.Excluded, isPositive: true),

                    // ]10/10/2002 00:00:00 to 04/05/2005 12:35:20[
                    new Interval<DateTime>(new DateTime(2002, 10, 10, 00, 00, 00), PointState.Excluded, new DateTime(2005, 04, 05, 12, 35, 20), PointState.Excluded, isPositive: true),

                    // ]04/05/2005 12:35:20 to 01/01/2010 00:00:00[
                    new Interval<DateTime>(new DateTime(2005, 04, 05, 12, 35, 20), PointState.Excluded, new DateTime(2010, 01, 01, 00, 00, 00), PointState.Excluded, isPositive: true),

                    // ]02/03/2011 14:00:00 to +∞
                    new Interval<DateTime>(new DateTime(2011, 02, 03, 14, 00, 00), PointState.Excluded, default(DateTime), PointState.Open, isPositive: true)
                };
            #endregion

            // commented code: useful to recreate the snapshots at the top of this method
            // string code = null;
            var set = new ContinuousSet<DateTime>();
            set.AddInterval(new DateTime(2000, 1, 1), true, new DateTime(2002, 10, 10), true);
            set.AddInterval(new DateTime(2010, 1, 1), true, new DateTime(2012, 10, 10), true);

            var setClone = set.Clone();

            // commented code: useful to recreate the snapshots at the top of this method
            // code += GenerateCode(setClone.PositiveIntervals.ToArray(), "snapSetIntervals");
            CollectionAssert.AreEqual(snapSetIntervals, setClone.PositiveIntervals.ToArray());

            setClone.AddPoint(new DateTime(2005, 04, 05, 12, 35, 20));

            // commented code: useful to recreate the snapshots at the top of this method
            // code += GenerateCode(setClone.PositiveIntervals.ToArray(), "snapSetIntervalsPoint");
            CollectionAssert.AreEqual(snapSetIntervalsPoint, setClone.PositiveIntervals.ToArray());

            setClone.SplitAt(DateTimeHelper.Range(new DateTime(1990, 1, 1), new DateTime(2020, 1, 1), d => d.AddMonths(4)));
            set.SplitAt(DateTimeHelper.Range(new DateTime(1990, 1, 1), new DateTime(2020, 1, 1), d => d.AddMonths(4)));

            CollectionAssert.AreEqual(snapSetIntervalsSplitPoint, setClone.PositiveIntervals.ToArray());

            // commented code: useful to recreate the snapshots at the top of this method
            // code += GenerateCode(set.PositiveIntervals.ToArray(), "snapSetIntervalsSplit");
            CollectionAssert.AreEqual(snapSetIntervalsSplit, set.PositiveIntervals.ToArray());

            set.AddPoint(new DateTime(2005, 04, 05, 12, 35, 20));
            set.Flatten(mergeRedundantTrues: false);

            // commented code: useful to recreate the snapshots at the top of this method
            // code += GenerateCode(set.PositiveIntervals.ToArray(), "snapSetIntervalsSplitPoint");
            CollectionAssert.AreEqual(snapSetIntervalsSplitPoint, set.PositiveIntervals.ToArray());

            CollectionAssert.AreEqual(set.PositiveIntervals.ToArray(), setClone.PositiveIntervals.ToArray());

            var set2 = new ContinuousSet<DateTime>();
            set2.AddInterval(new DateTime(1999, 10, 5), false, new DateTime(2000, 08, 05, 15, 44, 30), false);
            set2.AddInterval(new DateTime(2001, 01, 2), true, new DateTime(2011, 02, 03, 14, 00, 00), true);
            set.Flatten();

            // commented code: useful to recreate the snapshots at the top of this method
            // code += GenerateCode(set2.PositiveIntervals.ToArray(), "set2Intervals");
            CollectionAssert.AreEqual(set2Intervals, set2.PositiveIntervals.ToArray());

            set.Operator = ContinuousSet.OpIntersection;
            set.AddContinuousSet(set2);
            set.Flatten(mergeRedundantTrues: false);

            var allIntervals = set.PositiveIntervals.ToArray();

            // commented code: useful to recreate the snapshots at the top of this method
            // code += GenerateCode(allIntervals, "intervals");
            CollectionAssert.AreEqual(intervals, allIntervals);

            var set3 = new ContinuousSet<DateTime>();
            set3.AddIntervalRange(intervals);
            set3.Flatten(mergeRedundantTrues: false);
            CollectionAssert.AreEqual(intervals, set3.PositiveIntervals.ToArray());

            var setNot = !set;

            // commented code: useful to recreate the snapshots at the top of this method
            // code += GenerateCode(setNot.PositiveIntervals.ToArray(), "snapSetNot");
            CollectionAssert.AreEqual(snapSetNot, setNot.PositiveIntervals.ToArray());

            #region snapSetFull = ...
            // the following snapshot was generated from a good result using the method GenerateCode("snapSetFull")
            var snapSetFull = new[]
                {
                    // -∞ to 01/01/2000 00:00:00]
                    new Interval<DateTime>(default(DateTime), PointState.Open, new DateTime(2000, 01, 01, 00, 00, 00), PointState.Included, isPositive: true),

                    // [01/01/2000 00:00:00 to 05/01/2000 00:00:00[
                    new Interval<DateTime>(new DateTime(2000, 01, 01, 00, 00, 00), PointState.Included, new DateTime(2000, 05, 01, 00, 00, 00), PointState.Excluded, isPositive: true),

                    // [05/01/2000 00:00:00 to 08/05/2000 15:44:30[
                    new Interval<DateTime>(new DateTime(2000, 05, 01, 00, 00, 00), PointState.Included, new DateTime(2000, 08, 05, 15, 44, 30), PointState.Excluded, isPositive: true),

                    // [08/05/2000 15:44:30 to 01/02/2001 00:00:00[
                    new Interval<DateTime>(new DateTime(2000, 08, 05, 15, 44, 30), PointState.Included, new DateTime(2001, 01, 02, 00, 00, 00), PointState.Excluded, isPositive: true),

                    // [01/02/2001 00:00:00 to 05/01/2001 00:00:00[
                    new Interval<DateTime>(new DateTime(2001, 01, 02, 00, 00, 00), PointState.Included, new DateTime(2001, 05, 01, 00, 00, 00), PointState.Excluded, isPositive: true),

                    // [05/01/2001 00:00:00 to 09/01/2001 00:00:00[
                    new Interval<DateTime>(new DateTime(2001, 05, 01, 00, 00, 00), PointState.Included, new DateTime(2001, 09, 01, 00, 00, 00), PointState.Excluded, isPositive: true),

                    // [09/01/2001 00:00:00 to 01/01/2002 00:00:00[
                    new Interval<DateTime>(new DateTime(2001, 09, 01, 00, 00, 00), PointState.Included, new DateTime(2002, 01, 01, 00, 00, 00), PointState.Excluded, isPositive: true),

                    // [01/01/2002 00:00:00 to 05/01/2002 00:00:00[
                    new Interval<DateTime>(new DateTime(2002, 01, 01, 00, 00, 00), PointState.Included, new DateTime(2002, 05, 01, 00, 00, 00), PointState.Excluded, isPositive: true),

                    // [05/01/2002 00:00:00 to 09/01/2002 00:00:00[
                    new Interval<DateTime>(new DateTime(2002, 05, 01, 00, 00, 00), PointState.Included, new DateTime(2002, 09, 01, 00, 00, 00), PointState.Excluded, isPositive: true),

                    // [09/01/2002 00:00:00 to 10/10/2002 00:00:00[
                    new Interval<DateTime>(new DateTime(2002, 09, 01, 00, 00, 00), PointState.Included, new DateTime(2002, 10, 10, 00, 00, 00), PointState.Excluded, isPositive: true),

                    // [10/10/2002 00:00:00 to 04/05/2005 12:35:20[
                    new Interval<DateTime>(new DateTime(2002, 10, 10, 00, 00, 00), PointState.Included, new DateTime(2005, 04, 05, 12, 35, 20), PointState.Excluded, isPositive: true),

                    // [04/05/2005 12:35:20 to 01/01/2010 00:00:00[
                    new Interval<DateTime>(new DateTime(2005, 04, 05, 12, 35, 20), PointState.Included, new DateTime(2010, 01, 01, 00, 00, 00), PointState.Excluded, isPositive: true),

                    // [01/01/2010 00:00:00 to 05/01/2010 00:00:00[
                    new Interval<DateTime>(new DateTime(2010, 01, 01, 00, 00, 00), PointState.Included, new DateTime(2010, 05, 01, 00, 00, 00), PointState.Excluded, isPositive: true),

                    // [05/01/2010 00:00:00 to 09/01/2010 00:00:00[
                    new Interval<DateTime>(new DateTime(2010, 05, 01, 00, 00, 00), PointState.Included, new DateTime(2010, 09, 01, 00, 00, 00), PointState.Excluded, isPositive: true),

                    // [09/01/2010 00:00:00 to 01/01/2011 00:00:00[
                    new Interval<DateTime>(new DateTime(2010, 09, 01, 00, 00, 00), PointState.Included, new DateTime(2011, 01, 01, 00, 00, 00), PointState.Excluded, isPositive: true),

                    // [01/01/2011 00:00:00 to 02/03/2011 14:00:00[
                    new Interval<DateTime>(new DateTime(2011, 01, 01, 00, 00, 00), PointState.Included, new DateTime(2011, 02, 03, 14, 00, 00), PointState.Excluded, isPositive: true),

                    // [02/03/2011 14:00:00 to +∞
                    new Interval<DateTime>(new DateTime(2011, 02, 03, 14, 00, 00), PointState.Included, default(DateTime), PointState.Open, isPositive: true)
                };
            #endregion

            #region snapSetFullMerged = ...
            // the following snapshot was generated from a good result using the method GenerateCode("snapSetFullMerged")
            var snapSetFullMerged = new[]
                {
                    // -∞ to +∞
                    new Interval<DateTime>(default(DateTime), PointState.Open, default(DateTime), PointState.Open, isPositive: true)
                };
            #endregion

            var setFull = set | !set;

            // code += GenerateCode(setFull.PositiveIntervals.ToArray(), "snapSetFull");
            CollectionAssert.AreEqual(snapSetFull, setFull.PositiveIntervals.ToArray());

            var setEmpty = !setFull;
            CollectionAssert.AreEqual(new DateTime[0], setEmpty.PositiveIntervals.ToArray());
            setFull.MergeRedundant();

            // code += GenerateCode(setFull.PositiveIntervals.ToArray(), "snapSetFullMerged");
            CollectionAssert.AreEqual(snapSetFullMerged, setFull.PositiveIntervals.ToArray());

            setEmpty.MergeRedundant();
            CollectionAssert.AreEqual(new DateTime[0], setEmpty.PositiveIntervals.ToArray());

            #region snapTransformed = ...
            // the following snapshot was generated from a good result using the method GenerateCode("snapTransformed")
            var snapTransformed = new[]
                {
                    // [02/20/2000 00:00:00 to 06/20/2000 00:00:00[
                    new Interval<DateTime>(new DateTime(2000, 02, 20, 00, 00, 00), PointState.Included, new DateTime(2000, 06, 20, 00, 00, 00), PointState.Excluded, isPositive: true),

                    // [06/20/2000 00:00:00 to 09/24/2000 15:44:30[
                    new Interval<DateTime>(new DateTime(2000, 06, 20, 00, 00, 00), PointState.Included, new DateTime(2000, 09, 24, 15, 44, 30), PointState.Excluded, isPositive: true),

                    // [02/21/2001 00:00:00 to 06/20/2001 00:00:00[
                    new Interval<DateTime>(new DateTime(2001, 02, 21, 00, 00, 00), PointState.Included, new DateTime(2001, 06, 20, 00, 00, 00), PointState.Excluded, isPositive: true),

                    // [06/20/2001 00:00:00 to 10/21/2001 00:00:00[
                    new Interval<DateTime>(new DateTime(2001, 06, 20, 00, 00, 00), PointState.Included, new DateTime(2001, 10, 21, 00, 00, 00), PointState.Excluded, isPositive: true),

                    // [10/21/2001 00:00:00 to 02/20/2002 00:00:00[
                    new Interval<DateTime>(new DateTime(2001, 10, 21, 00, 00, 00), PointState.Included, new DateTime(2002, 02, 20, 00, 00, 00), PointState.Excluded, isPositive: true),

                    // [02/20/2002 00:00:00 to 06/20/2002 00:00:00[
                    new Interval<DateTime>(new DateTime(2002, 02, 20, 00, 00, 00), PointState.Included, new DateTime(2002, 06, 20, 00, 00, 00), PointState.Excluded, isPositive: true),

                    // [06/20/2002 00:00:00 to 10/21/2002 00:00:00[
                    new Interval<DateTime>(new DateTime(2002, 06, 20, 00, 00, 00), PointState.Included, new DateTime(2002, 10, 21, 00, 00, 00), PointState.Excluded, isPositive: true),

                    // [10/21/2002 00:00:00 to 11/29/2002 00:00:00]
                    new Interval<DateTime>(new DateTime(2002, 10, 21, 00, 00, 00), PointState.Included, new DateTime(2002, 11, 29, 00, 00, 00), PointState.Included, isPositive: true),

                    // [05/25/2005 12:35:20]
                    new Interval<DateTime>(new DateTime(2005, 05, 25, 12, 35, 20), PointState.Included, new DateTime(2005, 05, 25, 12, 35, 20), PointState.Included, isPositive: true),

                    // [02/20/2010 00:00:00 to 06/20/2010 00:00:00[
                    new Interval<DateTime>(new DateTime(2010, 02, 20, 00, 00, 00), PointState.Included, new DateTime(2010, 06, 20, 00, 00, 00), PointState.Excluded, isPositive: true),

                    // [06/20/2010 00:00:00 to 10/21/2010 00:00:00[
                    new Interval<DateTime>(new DateTime(2010, 06, 20, 00, 00, 00), PointState.Included, new DateTime(2010, 10, 21, 00, 00, 00), PointState.Excluded, isPositive: true),

                    // [10/21/2010 00:00:00 to 02/20/2011 00:00:00[
                    new Interval<DateTime>(new DateTime(2010, 10, 21, 00, 00, 00), PointState.Included, new DateTime(2011, 02, 20, 00, 00, 00), PointState.Excluded, isPositive: true),

                    // [02/20/2011 00:00:00 to 03/25/2011 14:00:00]
                    new Interval<DateTime>(new DateTime(2011, 02, 20, 00, 00, 00), PointState.Included, new DateTime(2011, 03, 25, 14, 00, 00), PointState.Included, isPositive: true)
                };
            #endregion

            var setTransform = set.Clone();
            setTransform.Transform(k => k + TimeSpan.FromDays(50));

            // code += GenerateCode(setFull.PositiveIntervals.ToArray(), "snapSetFullMerged");
            // var code = GenerateCode(setTransform.PositiveIntervals.ToArray(), "snapTransformed");
            CollectionAssert.AreEqual(snapTransformed, setTransform.PositiveIntervals.ToArray());

            #region snapTransformedInvMul = ...
            // the following snapshot was generated from a good result using the method GenerateCode("snapTransformedInvMul")
            var snapTransformedInvMul = new[]
                {
                    // [07/16/1977 20:00:00 to 09/22/1977 00:00:00[
                    new Interval<DateTime>(new DateTime(1977, 07, 16, 20, 00, 00), PointState.Included, new DateTime(1977, 09, 22, 00, 00, 00), PointState.Excluded, isPositive: true),

                    // [09/22/1977 00:00:00 to 05/24/1978 00:00:00[
                    new Interval<DateTime>(new DateTime(1977, 09, 22, 00, 00, 00), PointState.Included, new DateTime(1978, 05, 24, 00, 00, 00), PointState.Excluded, isPositive: true),

                    // [05/24/1978 00:00:00 to 01/25/1979 00:00:00[
                    new Interval<DateTime>(new DateTime(1978, 05, 24, 00, 00, 00), PointState.Included, new DateTime(1979, 01, 25, 00, 00, 00), PointState.Excluded, isPositive: true),

                    // [01/25/1979 00:00:00 to 09/22/1979 00:00:00]
                    new Interval<DateTime>(new DateTime(1979, 01, 25, 00, 00, 00), PointState.Included, new DateTime(1979, 09, 22, 00, 00, 00), PointState.Included, isPositive: true),

                    // [03/15/1989 22:49:20]
                    new Interval<DateTime>(new DateTime(1989, 03, 15, 22, 49, 20), PointState.Included, new DateTime(1989, 03, 15, 22, 49, 20), PointState.Included, isPositive: true),

                    // [03/07/1994 00:00:00 to 05/24/1994 00:00:00[
                    new Interval<DateTime>(new DateTime(1994, 03, 07, 00, 00, 00), PointState.Included, new DateTime(1994, 05, 24, 00, 00, 00), PointState.Excluded, isPositive: true),

                    // [05/24/1994 00:00:00 to 01/25/1995 00:00:00[
                    new Interval<DateTime>(new DateTime(1994, 05, 24, 00, 00, 00), PointState.Included, new DateTime(1995, 01, 25, 00, 00, 00), PointState.Excluded, isPositive: true),

                    // [01/25/1995 00:00:00 to 09/22/1995 00:00:00[
                    new Interval<DateTime>(new DateTime(1995, 01, 25, 00, 00, 00), PointState.Included, new DateTime(1995, 09, 22, 00, 00, 00), PointState.Excluded, isPositive: true),

                    // [09/22/1995 00:00:00 to 05/23/1996 00:00:00[
                    new Interval<DateTime>(new DateTime(1995, 09, 22, 00, 00, 00), PointState.Included, new DateTime(1996, 05, 23, 00, 00, 00), PointState.Excluded, isPositive: true),

                    // [05/23/1996 00:00:00 to 01/24/1997 00:00:00[
                    new Interval<DateTime>(new DateTime(1996, 05, 23, 00, 00, 00), PointState.Included, new DateTime(1997, 01, 24, 00, 00, 00), PointState.Excluded, isPositive: true),

                    // [01/24/1997 00:00:00 to 09/19/1997 00:00:00]
                    new Interval<DateTime>(new DateTime(1997, 01, 24, 00, 00, 00), PointState.Included, new DateTime(1997, 09, 19, 00, 00, 00), PointState.Included, isPositive: true),

                    // ]07/14/1998 16:31:00 to 01/24/1999 00:00:00[
                    new Interval<DateTime>(new DateTime(1998, 07, 14, 16, 31, 00), PointState.Excluded, new DateTime(1999, 01, 24, 00, 00, 00), PointState.Excluded, isPositive: true),

                    // [01/24/1999 00:00:00 to 09/23/1999 00:00:00]
                    new Interval<DateTime>(new DateTime(1999, 01, 24, 00, 00, 00), PointState.Included, new DateTime(1999, 09, 23, 00, 00, 00), PointState.Included, isPositive: true)
                };
            #endregion

            setTransform.Transform(k => new DateTime(2000, 1, 1) - (k - new DateTime(2000, 1, 1)) - (k - new DateTime(2000, 1, 1)));

            // code += GenerateCode(setFull.PositiveIntervals.ToArray(), "snapSetFullMerged");
            // var code2 = GenerateCode(setTransform.PositiveIntervals.ToArray(), "snapTransformedInvMul");
            CollectionAssert.AreEqual(snapTransformedInvMul, setTransform.PositiveIntervals.ToArray());
        }
        private static List <InvoiceInfo> GetAccountInvoices(Practice practice, DateTime utcNow)
        {
            // getting info about the services that are being used, that is all active AccountContracts
            var activeAccountContracts = new[] { practice.AccountContract }
            .Concat(
                practice.AccountContracts
                .Where(ac => ac.EndDate == null || ac.EndDate >= utcNow)
                .Where(ac => ac.Id != practice.AccountContract.Id))
            .ToList();

            // The main account contract dictates the billing periods of subcontracts.
            // We must see what products (active account contracts) don't have
            // billing items in any period.
            var mainIntervals = GetAccountContractBillingCycles(practice.AccountContract)
                                .TakeWhile(it => it.Start < utcNow)
                                .ToList();

            var dateSetBillingCycles = new ContinuousSet <DateTime>(mainIntervals.Count * 2);

            foreach (var dateTimeInterval in mainIntervals)
            {
                dateSetBillingCycles.AddInterval(dateTimeInterval.Start, true, dateTimeInterval.End, false);
            }
            dateSetBillingCycles.Flatten(mergeRedundantTrues: false);

            var billingsDic = new Dictionary <DateTime, InvoiceInfo>();

            foreach (var activeAccountContract in activeAccountContracts)
            {
                var accountStart = PracticeController.ConvertToLocalDateTime(practice, activeAccountContract.StartDate);
                var accountEnd   = PracticeController.ConvertToLocalDateTime(practice, activeAccountContract.EndDate);

                var currentContractInterval = new ContinuousSet <DateTime>();
                if (accountStart.HasValue)
                {
                    currentContractInterval.AddPoint(accountStart.Value, false, true, true);
                }
                if (accountEnd.HasValue)
                {
                    currentContractInterval.AddPoint(accountEnd.Value, true, false, false);
                }

                // Getting intervals that already have invoices.
                var dateSetBillings = new ContinuousSet <DateTime>();
                foreach (var eachBilling in activeAccountContract.Billings)
                {
                    if (eachBilling.ReferenceDate == null)
                    {
                        continue;
                    }

                    var billingRefStart = PracticeController.ConvertToLocalDateTime(practice, (DateTime)eachBilling.ReferenceDate);
                    var billingRefEnd   = PracticeController.ConvertToLocalDateTime(practice, eachBilling.ReferenceDateEnd);

                    if (billingRefEnd.HasValue)
                    {
                        dateSetBillings.AddInterval(billingRefStart, true, billingRefEnd.Value, false);
                    }
                    else
                    {
                        dateSetBillings.AddPoint(billingRefStart, false, true, true);
                    }

                    InvoiceInfo billingInfo;
                    if (!billingsDic.TryGetValue(billingRefStart, out billingInfo))
                    {
                        billingsDic[billingRefStart] = billingInfo = new InvoiceInfo
                        {
                            IsSaved = true,
                            Start   = billingRefStart,
                            End     = billingRefEnd,
                            DueDate = PracticeController.ConvertToLocalDateTime(practice, eachBilling.DueDate),
                        }
                    }
                    ;

                    billingInfo.Items.Add(
                        new InvoiceInfo.Item
                    {
                        Amount         = activeAccountContract.BillingAmount ?? 0,
                        DiscountAmount = activeAccountContract.BillingDiscountAmount ?? 0,
                        ContractType   = (ContractTypes)activeAccountContract.ContractTypeId,
                    });
                }

                dateSetBillings.Flatten();

                // Merging date sets, to see where there are holes without any invoice.
                var dateSetResult = !dateSetBillings & dateSetBillingCycles & currentContractInterval;

                // Getting the intervals that represents missing invoices.
                foreach (var eachMissingInterval in dateSetResult.PositiveIntervals)
                {
                    Debug.Assert(practice.AccountContract.BillingDueDay != null, "practice.AccountContract.BillingDueDay != null");
                    var dueDay  = practice.AccountContract.BillingDueDay.Value;
                    var dueDate = DateTimeHelper.FindDayOfMonthOrNearest(eachMissingInterval.Start, dueDay);
                    if (dueDate >= eachMissingInterval.Start.AddDays(10))
                    {
                        dueDate = dueDate.AddMonths(1, dueDay);
                    }

                    InvoiceInfo billingInfo;
                    if (!billingsDic.TryGetValue(eachMissingInterval.Start, out billingInfo))
                    {
                        billingsDic[eachMissingInterval.Start] = billingInfo = new InvoiceInfo
                        {
                            Start   = eachMissingInterval.Start,
                            End     = eachMissingInterval.End,
                            DueDate = dueDate,
                        }
                    }
                    ;

                    billingInfo.Items.Add(
                        new InvoiceInfo.Item
                    {
                        Amount         = activeAccountContract.BillingAmount ?? 0,
                        DiscountAmount = activeAccountContract.BillingDiscountAmount ?? 0,
                        ContractType   = (ContractTypes)activeAccountContract.ContractTypeId,
                    });
                }
            }

            var result = billingsDic.Values.OrderBy(bi => bi.Start).ToList();

            return(result);
        }
Example #9
0
 /// <summary>
 /// Determines whether the specified objects are equal.
 /// </summary>
 /// <returns>
 /// true if the specified objects are equal; otherwise, false.
 /// </returns>
 /// <param name="x">The first object of type <paramref name="T"/> to compare.</param><param name="y">The second object of type <paramref name="T"/> to compare.</param>
 public bool Equals(ContinuousSet <T> x, ContinuousSet <T> y)
 {
     return(ContinuousSet <T> .Equals(x, y, this.ignoreRedundantFalses, this.ignoreRedundantTrues));
 }
        private static List<InvoiceInfo> GetAccountInvoices(Practice practice, DateTime utcNow)
        {
            // getting info about the services that are being used, that is all active AccountContracts
            var activeAccountContracts = new[] { practice.AccountContract }
                .Concat(
                    practice.AccountContracts
                        .Where(ac => ac.EndDate == null || ac.EndDate >= utcNow)
                        .Where(ac => ac.Id != practice.AccountContract.Id))
                .ToList();

            // The main account contract dictates the billing periods of subcontracts.
            // We must see what products (active account contracts) don't have
            // billing items in any period.
            var mainIntervals = GetAccountContractBillingCycles(practice.AccountContract)
                .TakeWhile(it => it.Start < utcNow)
                .ToList();

            var dateSetBillingCycles = new ContinuousSet<DateTime>(mainIntervals.Count * 2);
            foreach (var dateTimeInterval in mainIntervals)
                dateSetBillingCycles.AddInterval(dateTimeInterval.Start, true, dateTimeInterval.End, false);
            dateSetBillingCycles.Flatten(mergeRedundantTrues: false);

            var billingsDic = new Dictionary<DateTime, InvoiceInfo>();
            foreach (var activeAccountContract in activeAccountContracts)
            {
                var accountStart = PracticeController.ConvertToLocalDateTime(practice, activeAccountContract.StartDate);
                var accountEnd = PracticeController.ConvertToLocalDateTime(practice, activeAccountContract.EndDate);

                var currentContractInterval = new ContinuousSet<DateTime>();
                if (accountStart.HasValue)
                    currentContractInterval.AddPoint(accountStart.Value, false, true, true);
                if (accountEnd.HasValue)
                    currentContractInterval.AddPoint(accountEnd.Value, true, false, false);

                // Getting intervals that already have invoices.
                var dateSetBillings = new ContinuousSet<DateTime>();
                foreach (var eachBilling in activeAccountContract.Billings)
                {
                    if (eachBilling.ReferenceDate == null)
                        continue;

                    var billingRefStart = PracticeController.ConvertToLocalDateTime(practice, (DateTime)eachBilling.ReferenceDate);
                    var billingRefEnd = PracticeController.ConvertToLocalDateTime(practice, eachBilling.ReferenceDateEnd);

                    if (billingRefEnd.HasValue)
                        dateSetBillings.AddInterval(billingRefStart, true, billingRefEnd.Value, false);
                    else
                        dateSetBillings.AddPoint(billingRefStart, false, true, true);

                    InvoiceInfo billingInfo;
                    if (!billingsDic.TryGetValue(billingRefStart, out billingInfo))
                        billingsDic[billingRefStart] = billingInfo = new InvoiceInfo
                            {
                                IsSaved = true,
                                Start = billingRefStart,
                                End = billingRefEnd,
                                DueDate = PracticeController.ConvertToLocalDateTime(practice, eachBilling.DueDate),
                            };

                    billingInfo.Items.Add(
                        new InvoiceInfo.Item
                        {
                            Amount = activeAccountContract.BillingAmount ?? 0,
                            DiscountAmount = activeAccountContract.BillingDiscountAmount ?? 0,
                            ContractType = (ContractTypes)activeAccountContract.ContractTypeId,
                        });
                }

                dateSetBillings.Flatten();

                // Merging date sets, to see where there are holes without any invoice.
                var dateSetResult = !dateSetBillings & dateSetBillingCycles & currentContractInterval;

                // Getting the intervals that represents missing invoices.
                foreach (var eachMissingInterval in dateSetResult.PositiveIntervals)
                {
                    Debug.Assert(practice.AccountContract.BillingDueDay != null, "practice.AccountContract.BillingDueDay != null");
                    var dueDay = practice.AccountContract.BillingDueDay.Value;
                    var dueDate = DateTimeHelper.FindDayOfMonthOrNearest(eachMissingInterval.Start, dueDay);
                    if (dueDate >= eachMissingInterval.Start.AddDays(10))
                        dueDate = dueDate.AddMonths(1, dueDay);

                    InvoiceInfo billingInfo;
                    if (!billingsDic.TryGetValue(eachMissingInterval.Start, out billingInfo))
                        billingsDic[eachMissingInterval.Start] = billingInfo = new InvoiceInfo
                            {
                                Start = eachMissingInterval.Start,
                                End = eachMissingInterval.End,
                                DueDate = dueDate,
                            };

                    billingInfo.Items.Add(
                        new InvoiceInfo.Item
                            {
                                Amount = activeAccountContract.BillingAmount ?? 0,
                                DiscountAmount = activeAccountContract.BillingDiscountAmount ?? 0,
                                ContractType = (ContractTypes)activeAccountContract.ContractTypeId,
                            });
                }
            }

            var result = billingsDic.Values.OrderBy(bi => bi.Start).ToList();
            return result;
        }
        public void SetSplitingEveryMonth()
        {
            #region snapSetIntervals = ...
            // the following snapshot was generated from a good result using the method GenerateCode("snapSetIntervals")
            var snapSetIntervals = new[]
            {
                // [01/01/2000 00:00:00 to 10/10/2002 00:00:00]
                new Interval <DateTime>(new DateTime(2000, 01, 01, 00, 00, 00), PointState.Included, new DateTime(2002, 10, 10, 00, 00, 00), PointState.Included, isPositive: true),

                // [01/01/2010 00:00:00 to 10/10/2012 00:00:00]
                new Interval <DateTime>(new DateTime(2010, 01, 01, 00, 00, 00), PointState.Included, new DateTime(2012, 10, 10, 00, 00, 00), PointState.Included, isPositive: true)
            };
            #endregion

            #region snapSetIntervalsPoint = ...
            // the following snapshot was generated from a good result using the method GenerateCode("snapSetIntervalsPoint")
            var snapSetIntervalsPoint = new[]
            {
                // [01/01/2000 00:00:00 to 10/10/2002 00:00:00]
                new Interval <DateTime>(new DateTime(2000, 01, 01, 00, 00, 00), PointState.Included, new DateTime(2002, 10, 10, 00, 00, 00), PointState.Included, isPositive: true),

                // [04/05/2005 12:35:20]
                new Interval <DateTime>(new DateTime(2005, 04, 05, 12, 35, 20), PointState.Included, new DateTime(2005, 04, 05, 12, 35, 20), PointState.Included, isPositive: true),

                // [01/01/2010 00:00:00 to 10/10/2012 00:00:00]
                new Interval <DateTime>(new DateTime(2010, 01, 01, 00, 00, 00), PointState.Included, new DateTime(2012, 10, 10, 00, 00, 00), PointState.Included, isPositive: true)
            };
            #endregion

            #region snapSetIntervalsSplit = ...
            // the following snapshot was generated from a good result using the method GenerateCode("snapSetIntervalsSplit")
            var snapSetIntervalsSplit = new[]
            {
                // [01/01/2000 00:00:00 to 05/01/2000 00:00:00[
                new Interval <DateTime>(new DateTime(2000, 01, 01, 00, 00, 00), PointState.Included, new DateTime(2000, 05, 01, 00, 00, 00), PointState.Excluded, isPositive: true),

                // [05/01/2000 00:00:00 to 09/01/2000 00:00:00[
                new Interval <DateTime>(new DateTime(2000, 05, 01, 00, 00, 00), PointState.Included, new DateTime(2000, 09, 01, 00, 00, 00), PointState.Excluded, isPositive: true),

                // [09/01/2000 00:00:00 to 01/01/2001 00:00:00[
                new Interval <DateTime>(new DateTime(2000, 09, 01, 00, 00, 00), PointState.Included, new DateTime(2001, 01, 01, 00, 00, 00), PointState.Excluded, isPositive: true),

                // [01/01/2001 00:00:00 to 05/01/2001 00:00:00[
                new Interval <DateTime>(new DateTime(2001, 01, 01, 00, 00, 00), PointState.Included, new DateTime(2001, 05, 01, 00, 00, 00), PointState.Excluded, isPositive: true),

                // [05/01/2001 00:00:00 to 09/01/2001 00:00:00[
                new Interval <DateTime>(new DateTime(2001, 05, 01, 00, 00, 00), PointState.Included, new DateTime(2001, 09, 01, 00, 00, 00), PointState.Excluded, isPositive: true),

                // [09/01/2001 00:00:00 to 01/01/2002 00:00:00[
                new Interval <DateTime>(new DateTime(2001, 09, 01, 00, 00, 00), PointState.Included, new DateTime(2002, 01, 01, 00, 00, 00), PointState.Excluded, isPositive: true),

                // [01/01/2002 00:00:00 to 05/01/2002 00:00:00[
                new Interval <DateTime>(new DateTime(2002, 01, 01, 00, 00, 00), PointState.Included, new DateTime(2002, 05, 01, 00, 00, 00), PointState.Excluded, isPositive: true),

                // [05/01/2002 00:00:00 to 09/01/2002 00:00:00[
                new Interval <DateTime>(new DateTime(2002, 05, 01, 00, 00, 00), PointState.Included, new DateTime(2002, 09, 01, 00, 00, 00), PointState.Excluded, isPositive: true),

                // [09/01/2002 00:00:00 to 10/10/2002 00:00:00]
                new Interval <DateTime>(new DateTime(2002, 09, 01, 00, 00, 00), PointState.Included, new DateTime(2002, 10, 10, 00, 00, 00), PointState.Included, isPositive: true),

                // [01/01/2010 00:00:00 to 05/01/2010 00:00:00[
                new Interval <DateTime>(new DateTime(2010, 01, 01, 00, 00, 00), PointState.Included, new DateTime(2010, 05, 01, 00, 00, 00), PointState.Excluded, isPositive: true),

                // [05/01/2010 00:00:00 to 09/01/2010 00:00:00[
                new Interval <DateTime>(new DateTime(2010, 05, 01, 00, 00, 00), PointState.Included, new DateTime(2010, 09, 01, 00, 00, 00), PointState.Excluded, isPositive: true),

                // [09/01/2010 00:00:00 to 01/01/2011 00:00:00[
                new Interval <DateTime>(new DateTime(2010, 09, 01, 00, 00, 00), PointState.Included, new DateTime(2011, 01, 01, 00, 00, 00), PointState.Excluded, isPositive: true),

                // [01/01/2011 00:00:00 to 05/01/2011 00:00:00[
                new Interval <DateTime>(new DateTime(2011, 01, 01, 00, 00, 00), PointState.Included, new DateTime(2011, 05, 01, 00, 00, 00), PointState.Excluded, isPositive: true),

                // [05/01/2011 00:00:00 to 09/01/2011 00:00:00[
                new Interval <DateTime>(new DateTime(2011, 05, 01, 00, 00, 00), PointState.Included, new DateTime(2011, 09, 01, 00, 00, 00), PointState.Excluded, isPositive: true),

                // [09/01/2011 00:00:00 to 01/01/2012 00:00:00[
                new Interval <DateTime>(new DateTime(2011, 09, 01, 00, 00, 00), PointState.Included, new DateTime(2012, 01, 01, 00, 00, 00), PointState.Excluded, isPositive: true),

                // [01/01/2012 00:00:00 to 05/01/2012 00:00:00[
                new Interval <DateTime>(new DateTime(2012, 01, 01, 00, 00, 00), PointState.Included, new DateTime(2012, 05, 01, 00, 00, 00), PointState.Excluded, isPositive: true),

                // [05/01/2012 00:00:00 to 09/01/2012 00:00:00[
                new Interval <DateTime>(new DateTime(2012, 05, 01, 00, 00, 00), PointState.Included, new DateTime(2012, 09, 01, 00, 00, 00), PointState.Excluded, isPositive: true),

                // [09/01/2012 00:00:00 to 10/10/2012 00:00:00]
                new Interval <DateTime>(new DateTime(2012, 09, 01, 00, 00, 00), PointState.Included, new DateTime(2012, 10, 10, 00, 00, 00), PointState.Included, isPositive: true)
            };
            #endregion

            #region snapSetIntervalsSplitPoint = ...
            // the following snapshot was generated from a good result using the method GenerateCode("snapSetIntervalsSplitPoint")
            var snapSetIntervalsSplitPoint = new[]
            {
                // [01/01/2000 00:00:00 to 05/01/2000 00:00:00[
                new Interval <DateTime>(new DateTime(2000, 01, 01, 00, 00, 00), PointState.Included, new DateTime(2000, 05, 01, 00, 00, 00), PointState.Excluded, isPositive: true),

                // [05/01/2000 00:00:00 to 09/01/2000 00:00:00[
                new Interval <DateTime>(new DateTime(2000, 05, 01, 00, 00, 00), PointState.Included, new DateTime(2000, 09, 01, 00, 00, 00), PointState.Excluded, isPositive: true),

                // [09/01/2000 00:00:00 to 01/01/2001 00:00:00[
                new Interval <DateTime>(new DateTime(2000, 09, 01, 00, 00, 00), PointState.Included, new DateTime(2001, 01, 01, 00, 00, 00), PointState.Excluded, isPositive: true),

                // [01/01/2001 00:00:00 to 05/01/2001 00:00:00[
                new Interval <DateTime>(new DateTime(2001, 01, 01, 00, 00, 00), PointState.Included, new DateTime(2001, 05, 01, 00, 00, 00), PointState.Excluded, isPositive: true),

                // [05/01/2001 00:00:00 to 09/01/2001 00:00:00[
                new Interval <DateTime>(new DateTime(2001, 05, 01, 00, 00, 00), PointState.Included, new DateTime(2001, 09, 01, 00, 00, 00), PointState.Excluded, isPositive: true),

                // [09/01/2001 00:00:00 to 01/01/2002 00:00:00[
                new Interval <DateTime>(new DateTime(2001, 09, 01, 00, 00, 00), PointState.Included, new DateTime(2002, 01, 01, 00, 00, 00), PointState.Excluded, isPositive: true),

                // [01/01/2002 00:00:00 to 05/01/2002 00:00:00[
                new Interval <DateTime>(new DateTime(2002, 01, 01, 00, 00, 00), PointState.Included, new DateTime(2002, 05, 01, 00, 00, 00), PointState.Excluded, isPositive: true),

                // [05/01/2002 00:00:00 to 09/01/2002 00:00:00[
                new Interval <DateTime>(new DateTime(2002, 05, 01, 00, 00, 00), PointState.Included, new DateTime(2002, 09, 01, 00, 00, 00), PointState.Excluded, isPositive: true),

                // [09/01/2002 00:00:00 to 10/10/2002 00:00:00]
                new Interval <DateTime>(new DateTime(2002, 09, 01, 00, 00, 00), PointState.Included, new DateTime(2002, 10, 10, 00, 00, 00), PointState.Included, isPositive: true),

                // [04/05/2005 12:35:20]
                new Interval <DateTime>(new DateTime(2005, 04, 05, 12, 35, 20), PointState.Included, new DateTime(2005, 04, 05, 12, 35, 20), PointState.Included, isPositive: true),

                // [01/01/2010 00:00:00 to 05/01/2010 00:00:00[
                new Interval <DateTime>(new DateTime(2010, 01, 01, 00, 00, 00), PointState.Included, new DateTime(2010, 05, 01, 00, 00, 00), PointState.Excluded, isPositive: true),

                // [05/01/2010 00:00:00 to 09/01/2010 00:00:00[
                new Interval <DateTime>(new DateTime(2010, 05, 01, 00, 00, 00), PointState.Included, new DateTime(2010, 09, 01, 00, 00, 00), PointState.Excluded, isPositive: true),

                // [09/01/2010 00:00:00 to 01/01/2011 00:00:00[
                new Interval <DateTime>(new DateTime(2010, 09, 01, 00, 00, 00), PointState.Included, new DateTime(2011, 01, 01, 00, 00, 00), PointState.Excluded, isPositive: true),

                // [01/01/2011 00:00:00 to 05/01/2011 00:00:00[
                new Interval <DateTime>(new DateTime(2011, 01, 01, 00, 00, 00), PointState.Included, new DateTime(2011, 05, 01, 00, 00, 00), PointState.Excluded, isPositive: true),

                // [05/01/2011 00:00:00 to 09/01/2011 00:00:00[
                new Interval <DateTime>(new DateTime(2011, 05, 01, 00, 00, 00), PointState.Included, new DateTime(2011, 09, 01, 00, 00, 00), PointState.Excluded, isPositive: true),

                // [09/01/2011 00:00:00 to 01/01/2012 00:00:00[
                new Interval <DateTime>(new DateTime(2011, 09, 01, 00, 00, 00), PointState.Included, new DateTime(2012, 01, 01, 00, 00, 00), PointState.Excluded, isPositive: true),

                // [01/01/2012 00:00:00 to 05/01/2012 00:00:00[
                new Interval <DateTime>(new DateTime(2012, 01, 01, 00, 00, 00), PointState.Included, new DateTime(2012, 05, 01, 00, 00, 00), PointState.Excluded, isPositive: true),

                // [05/01/2012 00:00:00 to 09/01/2012 00:00:00[
                new Interval <DateTime>(new DateTime(2012, 05, 01, 00, 00, 00), PointState.Included, new DateTime(2012, 09, 01, 00, 00, 00), PointState.Excluded, isPositive: true),

                // [09/01/2012 00:00:00 to 10/10/2012 00:00:00]
                new Interval <DateTime>(new DateTime(2012, 09, 01, 00, 00, 00), PointState.Included, new DateTime(2012, 10, 10, 00, 00, 00), PointState.Included, isPositive: true)
            };
            #endregion

            #region set2Intervals = ...
            // the following snapshot was generated from a good result using the method GenerateCode("set2Intervals")
            var set2Intervals = new[]
            {
                // ]10/05/1999 00:00:00 to 08/05/2000 15:44:30[
                new Interval <DateTime>(new DateTime(1999, 10, 05, 00, 00, 00), PointState.Excluded, new DateTime(2000, 08, 05, 15, 44, 30), PointState.Excluded, isPositive: true),

                // [01/02/2001 00:00:00 to 02/03/2011 14:00:00]
                new Interval <DateTime>(new DateTime(2001, 01, 02, 00, 00, 00), PointState.Included, new DateTime(2011, 02, 03, 14, 00, 00), PointState.Included, isPositive: true)
            };
            #endregion

            #region intervals = ...
            // the following snapshot was generated from a good result using the method GenerateCode("intervals")
            var intervals = new[]
            {
                // [01/01/2000 00:00:00 to 05/01/2000 00:00:00[
                new Interval <DateTime>(new DateTime(2000, 01, 01, 00, 00, 00), PointState.Included, new DateTime(2000, 05, 01, 00, 00, 00), PointState.Excluded, isPositive: true),

                // [05/01/2000 00:00:00 to 08/05/2000 15:44:30[
                new Interval <DateTime>(new DateTime(2000, 05, 01, 00, 00, 00), PointState.Included, new DateTime(2000, 08, 05, 15, 44, 30), PointState.Excluded, isPositive: true),

                // [01/02/2001 00:00:00 to 05/01/2001 00:00:00[
                new Interval <DateTime>(new DateTime(2001, 01, 02, 00, 00, 00), PointState.Included, new DateTime(2001, 05, 01, 00, 00, 00), PointState.Excluded, isPositive: true),

                // [05/01/2001 00:00:00 to 09/01/2001 00:00:00[
                new Interval <DateTime>(new DateTime(2001, 05, 01, 00, 00, 00), PointState.Included, new DateTime(2001, 09, 01, 00, 00, 00), PointState.Excluded, isPositive: true),

                // [09/01/2001 00:00:00 to 01/01/2002 00:00:00[
                new Interval <DateTime>(new DateTime(2001, 09, 01, 00, 00, 00), PointState.Included, new DateTime(2002, 01, 01, 00, 00, 00), PointState.Excluded, isPositive: true),

                // [01/01/2002 00:00:00 to 05/01/2002 00:00:00[
                new Interval <DateTime>(new DateTime(2002, 01, 01, 00, 00, 00), PointState.Included, new DateTime(2002, 05, 01, 00, 00, 00), PointState.Excluded, isPositive: true),

                // [05/01/2002 00:00:00 to 09/01/2002 00:00:00[
                new Interval <DateTime>(new DateTime(2002, 05, 01, 00, 00, 00), PointState.Included, new DateTime(2002, 09, 01, 00, 00, 00), PointState.Excluded, isPositive: true),

                // [09/01/2002 00:00:00 to 10/10/2002 00:00:00]
                new Interval <DateTime>(new DateTime(2002, 09, 01, 00, 00, 00), PointState.Included, new DateTime(2002, 10, 10, 00, 00, 00), PointState.Included, isPositive: true),

                // [04/05/2005 12:35:20]
                new Interval <DateTime>(new DateTime(2005, 04, 05, 12, 35, 20), PointState.Included, new DateTime(2005, 04, 05, 12, 35, 20), PointState.Included, isPositive: true),

                // [01/01/2010 00:00:00 to 05/01/2010 00:00:00[
                new Interval <DateTime>(new DateTime(2010, 01, 01, 00, 00, 00), PointState.Included, new DateTime(2010, 05, 01, 00, 00, 00), PointState.Excluded, isPositive: true),

                // [05/01/2010 00:00:00 to 09/01/2010 00:00:00[
                new Interval <DateTime>(new DateTime(2010, 05, 01, 00, 00, 00), PointState.Included, new DateTime(2010, 09, 01, 00, 00, 00), PointState.Excluded, isPositive: true),

                // [09/01/2010 00:00:00 to 01/01/2011 00:00:00[
                new Interval <DateTime>(new DateTime(2010, 09, 01, 00, 00, 00), PointState.Included, new DateTime(2011, 01, 01, 00, 00, 00), PointState.Excluded, isPositive: true),

                // [01/01/2011 00:00:00 to 02/03/2011 14:00:00]
                new Interval <DateTime>(new DateTime(2011, 01, 01, 00, 00, 00), PointState.Included, new DateTime(2011, 02, 03, 14, 00, 00), PointState.Included, isPositive: true)
            };
            #endregion

            #region snapSetNot = ...
            // the following snapshot was generated from a good result using the method GenerateCode("snapSetNot")
            var snapSetNot = new[]
            {
                // -∞ to 01/01/2000 00:00:00[
                new Interval <DateTime>(default(DateTime), PointState.Open, new DateTime(2000, 01, 01, 00, 00, 00), PointState.Excluded, isPositive: true),

                // [08/05/2000 15:44:30 to 01/02/2001 00:00:00[
                new Interval <DateTime>(new DateTime(2000, 08, 05, 15, 44, 30), PointState.Included, new DateTime(2001, 01, 02, 00, 00, 00), PointState.Excluded, isPositive: true),

                // ]10/10/2002 00:00:00 to 04/05/2005 12:35:20[
                new Interval <DateTime>(new DateTime(2002, 10, 10, 00, 00, 00), PointState.Excluded, new DateTime(2005, 04, 05, 12, 35, 20), PointState.Excluded, isPositive: true),

                // ]04/05/2005 12:35:20 to 01/01/2010 00:00:00[
                new Interval <DateTime>(new DateTime(2005, 04, 05, 12, 35, 20), PointState.Excluded, new DateTime(2010, 01, 01, 00, 00, 00), PointState.Excluded, isPositive: true),

                // ]02/03/2011 14:00:00 to +∞
                new Interval <DateTime>(new DateTime(2011, 02, 03, 14, 00, 00), PointState.Excluded, default(DateTime), PointState.Open, isPositive: true)
            };
            #endregion

            // commented code: useful to recreate the snapshots at the top of this method
            // string code = null;
            var set = new ContinuousSet <DateTime>();
            set.AddInterval(new DateTime(2000, 1, 1), true, new DateTime(2002, 10, 10), true);
            set.AddInterval(new DateTime(2010, 1, 1), true, new DateTime(2012, 10, 10), true);

            var setClone = set.Clone();

            // commented code: useful to recreate the snapshots at the top of this method
            // code += GenerateCode(setClone.PositiveIntervals.ToArray(), "snapSetIntervals");
            CollectionAssert.AreEqual(snapSetIntervals, setClone.PositiveIntervals.ToArray());

            setClone.AddPoint(new DateTime(2005, 04, 05, 12, 35, 20));

            // commented code: useful to recreate the snapshots at the top of this method
            // code += GenerateCode(setClone.PositiveIntervals.ToArray(), "snapSetIntervalsPoint");
            CollectionAssert.AreEqual(snapSetIntervalsPoint, setClone.PositiveIntervals.ToArray());

            setClone.SplitAt(DateTimeHelper.Range(new DateTime(1990, 1, 1), new DateTime(2020, 1, 1), d => d.AddMonths(4)));
            set.SplitAt(DateTimeHelper.Range(new DateTime(1990, 1, 1), new DateTime(2020, 1, 1), d => d.AddMonths(4)));

            CollectionAssert.AreEqual(snapSetIntervalsSplitPoint, setClone.PositiveIntervals.ToArray());

            // commented code: useful to recreate the snapshots at the top of this method
            // code += GenerateCode(set.PositiveIntervals.ToArray(), "snapSetIntervalsSplit");
            CollectionAssert.AreEqual(snapSetIntervalsSplit, set.PositiveIntervals.ToArray());

            set.AddPoint(new DateTime(2005, 04, 05, 12, 35, 20));
            set.Flatten(mergeRedundantTrues: false);

            // commented code: useful to recreate the snapshots at the top of this method
            // code += GenerateCode(set.PositiveIntervals.ToArray(), "snapSetIntervalsSplitPoint");
            CollectionAssert.AreEqual(snapSetIntervalsSplitPoint, set.PositiveIntervals.ToArray());

            CollectionAssert.AreEqual(set.PositiveIntervals.ToArray(), setClone.PositiveIntervals.ToArray());

            var set2 = new ContinuousSet <DateTime>();
            set2.AddInterval(new DateTime(1999, 10, 5), false, new DateTime(2000, 08, 05, 15, 44, 30), false);
            set2.AddInterval(new DateTime(2001, 01, 2), true, new DateTime(2011, 02, 03, 14, 00, 00), true);
            set.Flatten();

            // commented code: useful to recreate the snapshots at the top of this method
            // code += GenerateCode(set2.PositiveIntervals.ToArray(), "set2Intervals");
            CollectionAssert.AreEqual(set2Intervals, set2.PositiveIntervals.ToArray());

            set.Operator = ContinuousSet.OpIntersection;
            set.AddContinuousSet(set2);
            set.Flatten(mergeRedundantTrues: false);

            var allIntervals = set.PositiveIntervals.ToArray();

            // commented code: useful to recreate the snapshots at the top of this method
            // code += GenerateCode(allIntervals, "intervals");
            CollectionAssert.AreEqual(intervals, allIntervals);

            var set3 = new ContinuousSet <DateTime>();
            set3.AddIntervalRange(intervals);
            set3.Flatten(mergeRedundantTrues: false);
            CollectionAssert.AreEqual(intervals, set3.PositiveIntervals.ToArray());

            var setNot = !set;

            // commented code: useful to recreate the snapshots at the top of this method
            // code += GenerateCode(setNot.PositiveIntervals.ToArray(), "snapSetNot");
            CollectionAssert.AreEqual(snapSetNot, setNot.PositiveIntervals.ToArray());

            #region snapSetFull = ...
            // the following snapshot was generated from a good result using the method GenerateCode("snapSetFull")
            var snapSetFull = new[]
            {
                // -∞ to 01/01/2000 00:00:00]
                new Interval <DateTime>(default(DateTime), PointState.Open, new DateTime(2000, 01, 01, 00, 00, 00), PointState.Included, isPositive: true),

                // [01/01/2000 00:00:00 to 05/01/2000 00:00:00[
                new Interval <DateTime>(new DateTime(2000, 01, 01, 00, 00, 00), PointState.Included, new DateTime(2000, 05, 01, 00, 00, 00), PointState.Excluded, isPositive: true),

                // [05/01/2000 00:00:00 to 08/05/2000 15:44:30[
                new Interval <DateTime>(new DateTime(2000, 05, 01, 00, 00, 00), PointState.Included, new DateTime(2000, 08, 05, 15, 44, 30), PointState.Excluded, isPositive: true),

                // [08/05/2000 15:44:30 to 01/02/2001 00:00:00[
                new Interval <DateTime>(new DateTime(2000, 08, 05, 15, 44, 30), PointState.Included, new DateTime(2001, 01, 02, 00, 00, 00), PointState.Excluded, isPositive: true),

                // [01/02/2001 00:00:00 to 05/01/2001 00:00:00[
                new Interval <DateTime>(new DateTime(2001, 01, 02, 00, 00, 00), PointState.Included, new DateTime(2001, 05, 01, 00, 00, 00), PointState.Excluded, isPositive: true),

                // [05/01/2001 00:00:00 to 09/01/2001 00:00:00[
                new Interval <DateTime>(new DateTime(2001, 05, 01, 00, 00, 00), PointState.Included, new DateTime(2001, 09, 01, 00, 00, 00), PointState.Excluded, isPositive: true),

                // [09/01/2001 00:00:00 to 01/01/2002 00:00:00[
                new Interval <DateTime>(new DateTime(2001, 09, 01, 00, 00, 00), PointState.Included, new DateTime(2002, 01, 01, 00, 00, 00), PointState.Excluded, isPositive: true),

                // [01/01/2002 00:00:00 to 05/01/2002 00:00:00[
                new Interval <DateTime>(new DateTime(2002, 01, 01, 00, 00, 00), PointState.Included, new DateTime(2002, 05, 01, 00, 00, 00), PointState.Excluded, isPositive: true),

                // [05/01/2002 00:00:00 to 09/01/2002 00:00:00[
                new Interval <DateTime>(new DateTime(2002, 05, 01, 00, 00, 00), PointState.Included, new DateTime(2002, 09, 01, 00, 00, 00), PointState.Excluded, isPositive: true),

                // [09/01/2002 00:00:00 to 10/10/2002 00:00:00[
                new Interval <DateTime>(new DateTime(2002, 09, 01, 00, 00, 00), PointState.Included, new DateTime(2002, 10, 10, 00, 00, 00), PointState.Excluded, isPositive: true),

                // [10/10/2002 00:00:00 to 04/05/2005 12:35:20[
                new Interval <DateTime>(new DateTime(2002, 10, 10, 00, 00, 00), PointState.Included, new DateTime(2005, 04, 05, 12, 35, 20), PointState.Excluded, isPositive: true),

                // [04/05/2005 12:35:20 to 01/01/2010 00:00:00[
                new Interval <DateTime>(new DateTime(2005, 04, 05, 12, 35, 20), PointState.Included, new DateTime(2010, 01, 01, 00, 00, 00), PointState.Excluded, isPositive: true),

                // [01/01/2010 00:00:00 to 05/01/2010 00:00:00[
                new Interval <DateTime>(new DateTime(2010, 01, 01, 00, 00, 00), PointState.Included, new DateTime(2010, 05, 01, 00, 00, 00), PointState.Excluded, isPositive: true),

                // [05/01/2010 00:00:00 to 09/01/2010 00:00:00[
                new Interval <DateTime>(new DateTime(2010, 05, 01, 00, 00, 00), PointState.Included, new DateTime(2010, 09, 01, 00, 00, 00), PointState.Excluded, isPositive: true),

                // [09/01/2010 00:00:00 to 01/01/2011 00:00:00[
                new Interval <DateTime>(new DateTime(2010, 09, 01, 00, 00, 00), PointState.Included, new DateTime(2011, 01, 01, 00, 00, 00), PointState.Excluded, isPositive: true),

                // [01/01/2011 00:00:00 to 02/03/2011 14:00:00[
                new Interval <DateTime>(new DateTime(2011, 01, 01, 00, 00, 00), PointState.Included, new DateTime(2011, 02, 03, 14, 00, 00), PointState.Excluded, isPositive: true),

                // [02/03/2011 14:00:00 to +∞
                new Interval <DateTime>(new DateTime(2011, 02, 03, 14, 00, 00), PointState.Included, default(DateTime), PointState.Open, isPositive: true)
            };
            #endregion

            #region snapSetFullMerged = ...
            // the following snapshot was generated from a good result using the method GenerateCode("snapSetFullMerged")
            var snapSetFullMerged = new[]
            {
                // -∞ to +∞
                new Interval <DateTime>(default(DateTime), PointState.Open, default(DateTime), PointState.Open, isPositive: true)
            };
            #endregion

            var setFull = set | !set;

            // code += GenerateCode(setFull.PositiveIntervals.ToArray(), "snapSetFull");
            CollectionAssert.AreEqual(snapSetFull, setFull.PositiveIntervals.ToArray());

            var setEmpty = !setFull;
            CollectionAssert.AreEqual(new DateTime[0], setEmpty.PositiveIntervals.ToArray());
            setFull.MergeRedundant();

            // code += GenerateCode(setFull.PositiveIntervals.ToArray(), "snapSetFullMerged");
            CollectionAssert.AreEqual(snapSetFullMerged, setFull.PositiveIntervals.ToArray());

            setEmpty.MergeRedundant();
            CollectionAssert.AreEqual(new DateTime[0], setEmpty.PositiveIntervals.ToArray());

            #region snapTransformed = ...
            // the following snapshot was generated from a good result using the method GenerateCode("snapTransformed")
            var snapTransformed = new[]
            {
                // [02/20/2000 00:00:00 to 06/20/2000 00:00:00[
                new Interval <DateTime>(new DateTime(2000, 02, 20, 00, 00, 00), PointState.Included, new DateTime(2000, 06, 20, 00, 00, 00), PointState.Excluded, isPositive: true),

                // [06/20/2000 00:00:00 to 09/24/2000 15:44:30[
                new Interval <DateTime>(new DateTime(2000, 06, 20, 00, 00, 00), PointState.Included, new DateTime(2000, 09, 24, 15, 44, 30), PointState.Excluded, isPositive: true),

                // [02/21/2001 00:00:00 to 06/20/2001 00:00:00[
                new Interval <DateTime>(new DateTime(2001, 02, 21, 00, 00, 00), PointState.Included, new DateTime(2001, 06, 20, 00, 00, 00), PointState.Excluded, isPositive: true),

                // [06/20/2001 00:00:00 to 10/21/2001 00:00:00[
                new Interval <DateTime>(new DateTime(2001, 06, 20, 00, 00, 00), PointState.Included, new DateTime(2001, 10, 21, 00, 00, 00), PointState.Excluded, isPositive: true),

                // [10/21/2001 00:00:00 to 02/20/2002 00:00:00[
                new Interval <DateTime>(new DateTime(2001, 10, 21, 00, 00, 00), PointState.Included, new DateTime(2002, 02, 20, 00, 00, 00), PointState.Excluded, isPositive: true),

                // [02/20/2002 00:00:00 to 06/20/2002 00:00:00[
                new Interval <DateTime>(new DateTime(2002, 02, 20, 00, 00, 00), PointState.Included, new DateTime(2002, 06, 20, 00, 00, 00), PointState.Excluded, isPositive: true),

                // [06/20/2002 00:00:00 to 10/21/2002 00:00:00[
                new Interval <DateTime>(new DateTime(2002, 06, 20, 00, 00, 00), PointState.Included, new DateTime(2002, 10, 21, 00, 00, 00), PointState.Excluded, isPositive: true),

                // [10/21/2002 00:00:00 to 11/29/2002 00:00:00]
                new Interval <DateTime>(new DateTime(2002, 10, 21, 00, 00, 00), PointState.Included, new DateTime(2002, 11, 29, 00, 00, 00), PointState.Included, isPositive: true),

                // [05/25/2005 12:35:20]
                new Interval <DateTime>(new DateTime(2005, 05, 25, 12, 35, 20), PointState.Included, new DateTime(2005, 05, 25, 12, 35, 20), PointState.Included, isPositive: true),

                // [02/20/2010 00:00:00 to 06/20/2010 00:00:00[
                new Interval <DateTime>(new DateTime(2010, 02, 20, 00, 00, 00), PointState.Included, new DateTime(2010, 06, 20, 00, 00, 00), PointState.Excluded, isPositive: true),

                // [06/20/2010 00:00:00 to 10/21/2010 00:00:00[
                new Interval <DateTime>(new DateTime(2010, 06, 20, 00, 00, 00), PointState.Included, new DateTime(2010, 10, 21, 00, 00, 00), PointState.Excluded, isPositive: true),

                // [10/21/2010 00:00:00 to 02/20/2011 00:00:00[
                new Interval <DateTime>(new DateTime(2010, 10, 21, 00, 00, 00), PointState.Included, new DateTime(2011, 02, 20, 00, 00, 00), PointState.Excluded, isPositive: true),

                // [02/20/2011 00:00:00 to 03/25/2011 14:00:00]
                new Interval <DateTime>(new DateTime(2011, 02, 20, 00, 00, 00), PointState.Included, new DateTime(2011, 03, 25, 14, 00, 00), PointState.Included, isPositive: true)
            };
            #endregion

            var setTransform = set.Clone();
            setTransform.Transform(k => k + TimeSpan.FromDays(50));

            // code += GenerateCode(setFull.PositiveIntervals.ToArray(), "snapSetFullMerged");
            // var code = GenerateCode(setTransform.PositiveIntervals.ToArray(), "snapTransformed");
            CollectionAssert.AreEqual(snapTransformed, setTransform.PositiveIntervals.ToArray());

            #region snapTransformedInvMul = ...
            // the following snapshot was generated from a good result using the method GenerateCode("snapTransformedInvMul")
            var snapTransformedInvMul = new[]
            {
                // [07/16/1977 20:00:00 to 09/22/1977 00:00:00[
                new Interval <DateTime>(new DateTime(1977, 07, 16, 20, 00, 00), PointState.Included, new DateTime(1977, 09, 22, 00, 00, 00), PointState.Excluded, isPositive: true),

                // [09/22/1977 00:00:00 to 05/24/1978 00:00:00[
                new Interval <DateTime>(new DateTime(1977, 09, 22, 00, 00, 00), PointState.Included, new DateTime(1978, 05, 24, 00, 00, 00), PointState.Excluded, isPositive: true),

                // [05/24/1978 00:00:00 to 01/25/1979 00:00:00[
                new Interval <DateTime>(new DateTime(1978, 05, 24, 00, 00, 00), PointState.Included, new DateTime(1979, 01, 25, 00, 00, 00), PointState.Excluded, isPositive: true),

                // [01/25/1979 00:00:00 to 09/22/1979 00:00:00]
                new Interval <DateTime>(new DateTime(1979, 01, 25, 00, 00, 00), PointState.Included, new DateTime(1979, 09, 22, 00, 00, 00), PointState.Included, isPositive: true),

                // [03/15/1989 22:49:20]
                new Interval <DateTime>(new DateTime(1989, 03, 15, 22, 49, 20), PointState.Included, new DateTime(1989, 03, 15, 22, 49, 20), PointState.Included, isPositive: true),

                // [03/07/1994 00:00:00 to 05/24/1994 00:00:00[
                new Interval <DateTime>(new DateTime(1994, 03, 07, 00, 00, 00), PointState.Included, new DateTime(1994, 05, 24, 00, 00, 00), PointState.Excluded, isPositive: true),

                // [05/24/1994 00:00:00 to 01/25/1995 00:00:00[
                new Interval <DateTime>(new DateTime(1994, 05, 24, 00, 00, 00), PointState.Included, new DateTime(1995, 01, 25, 00, 00, 00), PointState.Excluded, isPositive: true),

                // [01/25/1995 00:00:00 to 09/22/1995 00:00:00[
                new Interval <DateTime>(new DateTime(1995, 01, 25, 00, 00, 00), PointState.Included, new DateTime(1995, 09, 22, 00, 00, 00), PointState.Excluded, isPositive: true),

                // [09/22/1995 00:00:00 to 05/23/1996 00:00:00[
                new Interval <DateTime>(new DateTime(1995, 09, 22, 00, 00, 00), PointState.Included, new DateTime(1996, 05, 23, 00, 00, 00), PointState.Excluded, isPositive: true),

                // [05/23/1996 00:00:00 to 01/24/1997 00:00:00[
                new Interval <DateTime>(new DateTime(1996, 05, 23, 00, 00, 00), PointState.Included, new DateTime(1997, 01, 24, 00, 00, 00), PointState.Excluded, isPositive: true),

                // [01/24/1997 00:00:00 to 09/19/1997 00:00:00]
                new Interval <DateTime>(new DateTime(1997, 01, 24, 00, 00, 00), PointState.Included, new DateTime(1997, 09, 19, 00, 00, 00), PointState.Included, isPositive: true),

                // ]07/14/1998 16:31:00 to 01/24/1999 00:00:00[
                new Interval <DateTime>(new DateTime(1998, 07, 14, 16, 31, 00), PointState.Excluded, new DateTime(1999, 01, 24, 00, 00, 00), PointState.Excluded, isPositive: true),

                // [01/24/1999 00:00:00 to 09/23/1999 00:00:00]
                new Interval <DateTime>(new DateTime(1999, 01, 24, 00, 00, 00), PointState.Included, new DateTime(1999, 09, 23, 00, 00, 00), PointState.Included, isPositive: true)
            };
            #endregion

            setTransform.Transform(k => new DateTime(2000, 1, 1) - (k - new DateTime(2000, 1, 1)) - (k - new DateTime(2000, 1, 1)));

            // code += GenerateCode(setFull.PositiveIntervals.ToArray(), "snapSetFullMerged");
            // var code2 = GenerateCode(setTransform.PositiveIntervals.ToArray(), "snapTransformedInvMul");
            CollectionAssert.AreEqual(snapTransformedInvMul, setTransform.PositiveIntervals.ToArray());
        }