private static List <RawScriptAction> ConvertToRawFunscript(List <RealTouchCommand> allCommands)
        {
            List <RawScriptAction>  actions          = new List <RawScriptAction>();
            List <RealTouchCommand> filteredcommands = FilterAndSortCommands(allCommands, RealTouchAxis.BothBelts, TimeSpan.FromMilliseconds(100));
            List <RealTouchCommand> commands         = RemoveRepeatingCommands(filteredcommands);

            for (int i = 0; i < commands.Count; i++)
            {
                TimeSpan nextCommand = TimeSpan.MaxValue;
                if (i < commands.Count - 1)
                {
                    nextCommand = commands[i + 1].TimeStamp;
                }

                if (commands[i] is RealTouchPeriodicMovementCommand periodicCommand)
                {
                    TimeSpan           endOfCommand = EarlierTimestamp(periodicCommand.TimeStamp + periodicCommand.Duration, nextCommand);
                    RealTouchDirection direction    = periodicCommand.Direction;
                    TimeSpan           timestamp    = periodicCommand.TimeStamp;
                    while (timestamp < endOfCommand)
                    {
                        actions.Add(new RawScriptAction
                        {
                            TimeStamp = timestamp,
                            Position  = ConvertDirectionToPosition(direction),
                            Speed     = ConvertMagnitudeToSpeed(periodicCommand.Magnitude)
                        });

                        direction  = InvertDirection(direction);
                        timestamp += periodicCommand.Period;
                    }

                    actions.Add(new RawScriptAction
                    {
                        TimeStamp = endOfCommand,
                        Position  = ConvertDirectionToPosition(direction),
                        Speed     = ConvertMagnitudeToSpeed(periodicCommand.Magnitude)
                    });
                }
                else if (commands[i] is RealTouchVectorMovementCommand vectorCommand)
                {
                    TimeSpan endOfCommand = EarlierTimestamp(vectorCommand.TimeStamp + vectorCommand.Duration, nextCommand);
                    actions.Add(new RawScriptAction
                    {
                        TimeStamp = vectorCommand.TimeStamp,
                        Position  = ConvertDirectionToPosition(vectorCommand.Direction),
                        Speed     = ConvertMagnitudeToSpeed(vectorCommand.Magnitude)
                    });
                    actions.Add(new RawScriptAction
                    {
                        TimeStamp = endOfCommand,
                        Position  = ConvertDirectionToPosition(InvertDirection(vectorCommand.Direction)),
                        Speed     = ConvertMagnitudeToSpeed(vectorCommand.Magnitude)
                    });
                }
            }

            return(actions);
        }
        private static RealTouchDirection InvertDirection(RealTouchDirection direction)
        {
            switch (direction)
            {
            case RealTouchDirection.In:
                return(RealTouchDirection.Out);

            case RealTouchDirection.Out:
                return(RealTouchDirection.In);

            default:
                throw new ArgumentOutOfRangeException(nameof(direction), direction, null);
            }
        }