public List <CircleObject> generateHorizontalPattern(MapContextAwareness mapContext)
        {
            if (end)
            {
                number = (int)1e6;
            }

            var result = new List <CircleObject>();

            double angle = rotation;
            int    X     = mapContext.X;
            int    Y     = mapContext.Y;

            int shiftx = 0;
            int shifty = shift;

            for (int i = 0; i < number && mapContext.Offset < mapContext.endOffset; ++i)
            {
                Point2 pp = checkHorizontalJumpBounds(X, Y, spacing, angle);

                if (!ReferenceEquals(pp, null))
                {
                    X = (int)pp.X;
                    Y = (int)pp.Y;
                }

                var ps = PatternGenerator.generateHorizontalJump(new Point2(X, Y), spacing, angle, randomize);

                if (randomize)
                {
                    ps = PatternGenerator.shuffleOrder(ps);
                }

                foreach (var p in ps)
                {
                    p.Type = BMAPI.v1.HitObjectType.Circle;
                }

                ps[0].Type |= BMAPI.v1.HitObjectType.NewCombo;

                foreach (var obj in ps)
                {
                    obj.StartTime      = (int)mapContext.Offset;
                    mapContext.Offset += mapContext.bpm;
                }

                result.AddRange(ps);
                if (checkNextJumpBounds(X + shiftx, Y + shifty, angle))
                {
                    shifty = -shifty;
                }
                X += shiftx;
                Y += shifty;
            }

            double nextShift    = shift;
            Point2 nextPosition = PatternGenerator.findNextPosition(X, Y, nextShift);

            mapContext.X = (int)nextPosition.X;
            mapContext.Y = (int)nextPosition.Y;

            return(result);
        }
        private List <CircleObject> generateRotatingPattern(MapContextAwareness mapContext)
        {
            if (end)
            {
                number = (int)1e6;
            }

            var result = new List <CircleObject>();

            double angle = 0;
            int    X     = mapContext.X;
            int    Y     = mapContext.Y;

            int shiftx = shift;
            int shifty = shift;

            for (int i = 0; i < number && mapContext.Offset < mapContext.endOffset; ++i)
            {
                Point2 pp = checkVerticalJumpBounds(X, Y, spacing, angle);

                if (!ReferenceEquals(pp, null))
                {
                    X = (int)pp.X;
                    Y = (int)pp.Y;
                }

                var ps = PatternGenerator.generateRotationalJump(new Point2(X, Y), spacing, angle, randomize);

                if (randomize)
                {
                    ps = PatternGenerator.shuffleOrder(ps);
                }

                foreach (var p in ps)
                {
                    p.Type = BMAPI.v1.HitObjectType.Circle;
                }

                ps[0].Type |= BMAPI.v1.HitObjectType.NewCombo;

                foreach (var obj in ps)
                {
                    obj.StartTime      = (int)mapContext.Offset;
                    mapContext.Offset += mapContext.bpm;
                }

                result.AddRange(ps);
                angle += rotation;
                if (checkNextJumpBounds(X + shiftx, Y + shifty, angle))
                {
                    Point2 next = PatternGenerator.findNextPosition(X, Y, shift);
                    shiftx = (int)(next.X - X);
                    shifty = (int)(next.Y - Y);

                    double norm = Math.Sqrt(Utils.sqr(shiftx) + Utils.sqr(shifty));
                    double recommended_shift = Math.Sqrt(2 * Utils.sqr(shift));

                    shiftx = (int)(shiftx / norm * recommended_shift);
                    shifty = (int)(shifty / norm * recommended_shift);
                }
                X += shiftx;
                Y += shifty;
            }

            double nextShift    = shift;
            Point2 nextPosition = PatternGenerator.findNextPosition(X, Y, nextShift);

            mapContext.X = (int)nextPosition.X;
            mapContext.Y = (int)nextPosition.Y;

            return(result);
        }