private void ExecuteNewArg(User user)
        {
            //Generate the exercise
            Parser.InputSequence newSequence = GenerateExercise(InputGlobals.CurrentConsole);

            //Give greater credit rewards for longer input sequences
            long creditReward = newSequence.Inputs.Count * BaseCreditReward;

            InputExercise inputExercise = new InputExercise(newSequence, creditReward);

            UserExercises[user.Name] = inputExercise;

            OutputInputExercise(inputExercise);
        }
        public override void ExecuteCommand(EvtChatCommandArgs args)
        {
            List <string> arguments          = args.Command.ArgumentsAsList;
            string        userName           = args.Command.ChatMessage.Username.ToLowerInvariant();
            long          userControllerPort = 0;
            long          userLevel          = 0;

            using (BotDBContext context = DatabaseManager.OpenContext())
            {
                User user = DataHelper.GetUserNoOpen(userName, context);
                if (user == null)
                {
                    QueueMessage("Huh, looks like you're not in the database!");
                    return;
                }

                if (user.HasEnabledAbility(PermissionConstants.INPUT_EXERCISE_ABILITY) == false)
                {
                    QueueMessage("You do not have the ability to use input exercises!");
                    return;
                }

                userControllerPort = user.ControllerPort;
                userLevel          = user.Level;
            }

            //Get the last console used
            int lastConsoleID = (int)DataHelper.GetSettingInt(SettingsConstants.LAST_CONSOLE, 1L);

            GameConsole usedConsole = null;

            using (BotDBContext context = DatabaseManager.OpenContext())
            {
                GameConsole lastConsole = context.Consoles.FirstOrDefault(c => c.ID == lastConsoleID);

                if (lastConsole != null)
                {
                    //Create a new console using data from the database
                    usedConsole = new GameConsole(lastConsole.Name, lastConsole.InputList, lastConsole.InvalidCombos);
                }
            }

            //If there are no valid inputs, don't attempt to generate or solve
            if (usedConsole == null)
            {
                QueueMessage($"The current console does not point to valid data, making it impossible to solve or generate a new exercise. Please set a different console to use, or if none are available, add one.");
                return;
            }

            if (usedConsole.ConsoleInputs.Count == 0)
            {
                QueueMessage($"The current console, \"{usedConsole.Name}\", does not have any available inputs. Cannot determine solve or generate an exercise.");
                return;
            }

            string creditsName  = DataHelper.GetCreditsName();
            int    botCharLimit = (int)DataHelper.GetSettingInt(SettingsConstants.BOT_MSG_CHAR_LIMIT, 500L);

            ReverseParser.ReverseParserOptions parseOptions = new ReverseParser.ReverseParserOptions(ReverseParser.ShowPortTypes.None, (int)userControllerPort);

            //Handle no arguments
            if (arguments.Count == 0)
            {
                if (UserExercises.TryGetValue(userName, out InputExercise inputExercise) == true)
                {
                    OutputInputExercise(inputExercise, usedConsole, botCharLimit, creditsName, inputExercise.ParseOptions);
                }
                else
                {
                    QueueMessage(NO_EXERCISE_FOUND_MSG);
                }
                return;
            }

            //If "new" is specified, generate a new input sequence
            if ((arguments.Count == 1 || arguments.Count == 2) && arguments[0].ToLowerInvariant() == GENERATE_NEW_ARG)
            {
                //Check for a difficulty argument
                if (arguments.Count == 2)
                {
                    string difString = arguments[1].ToLowerInvariant();

                    //Check difficulty level
                    if (difString == EASY_DIFFICULTY_ARG)
                    {
                        parseOptions.ShowPortType = ReverseParser.ShowPortTypes.None;
                    }
                    else if (difString == HARD_DIFFICULTY_ARG)
                    {
                        parseOptions.ShowPortType = ReverseParser.ShowPortTypes.ShowNonDefaultPorts;
                    }
                    else
                    {
                        QueueMessage($"Invalid difficulty level specified. Please choose either \"{EASY_DIFFICULTY_ARG}\" or \"{HARD_DIFFICULTY_ARG}\".");
                        return;
                    }
                }

                //Use the global default input duration for consistency
                int defaultInputDur = (int)DataHelper.GetSettingInt(SettingsConstants.DEFAULT_INPUT_DURATION, 200L);

                //Generate the exercise
                ParsedInputSequence newSequence = GenerateExercise(userLevel, defaultInputDur, usedConsole, parseOptions);

                //Give greater credit rewards for longer input sequences
                long creditReward = (newSequence.Inputs.Count * BASE_CREDIT_REWARD) * CREDIT_REWARD_MULTIPLIER;

                //This parser option is set when performing a hard exercise
                if (parseOptions.ShowPortType == ReverseParser.ShowPortTypes.ShowNonDefaultPorts)
                {
                    creditReward = (long)Math.Ceiling(creditReward * HARD_EXERCISE_MULTIPLIER);
                }

                InputExercise inputExercise = new InputExercise(newSequence, parseOptions, creditReward);
                UserExercises[userName] = inputExercise;

                OutputInputExercise(inputExercise, usedConsole, botCharLimit, creditsName, parseOptions);
                return;
            }

            //Make sure the user has an exercise - if not, output the same message
            if (UserExercises.TryGetValue(userName, out InputExercise exercise) == false)
            {
                QueueMessage(NO_EXERCISE_FOUND_MSG);
                return;
            }

            //There's more than one argument and the user has an exercise; so it has to be the input
            //Let's validate it!
            if (ExecuteValidateInput(userName, args.Command.ArgumentsAsString, usedConsole, parseOptions) == true)
            {
                using (BotDBContext context = DatabaseManager.OpenContext())
                {
                    User user = DataHelper.GetUserNoOpen(userName, context);

                    //Grant credits if the user isn't opted out
                    if (user.IsOptedOut == false)
                    {
                        long creditReward = exercise.CreditReward;
                        user.Stats.Credits += creditReward;
                        context.SaveChanges();

                        QueueMessage($"Correct input! Awesome job! You've earned your {creditReward} {creditsName.Pluralize(false, creditReward)}!");
                    }
                    else
                    {
                        QueueMessage("Correct input! Awesome job!");
                    }
                }

                //Remove the entry
                UserExercises.TryRemove(userName, out InputExercise value);
            }
        }