<commit_before>using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using UnityEngine;

public static class ComponentSolverFactory
{
    private delegate ComponentSolver ModComponentSolverDelegate(BombCommander bombCommander, MonoBehaviour bombComponent, IRCConnection ircConnection, CoroutineCanceller canceller);
    private static readonly Dictionary<string, ModComponentSolverDelegate> ModComponentSolverCreators;
    private static readonly Dictionary<string, ModuleInformation> ModComponentSolverInformation;

    private enum ModCommandType
    {
        Simple,
        Coroutine
    }

    static ComponentSolverFactory()
    {
        ModComponentSolverCreators = new Dictionary<string, ModComponentSolverDelegate>();
        ModComponentSolverInformation = new Dictionary<string, ModuleInformation>();

        //AT_Bash Modules
        ModComponentSolverCreators["MotionSense"] = (bombCommander, bombComponent, ircConnection, canceller) => new MotionSenseComponentSolver(bombCommander, bombComponent, ircConnection, canceller);

       //Hexi Modules
        ModComponentSolverCreators["MemoryV2"] = (bombCommander, bombComponent, ircConnection, canceller) => new ForgetMeNotComponentSolver(bombCommander, bombComponent, ircConnection, canceller);
        ModComponentSolverCreators["KeypadV2"] = (bombCommander, bombComponent, ircConnection, canceller) => new RoundKeypadComponentSolver(bombCommander, bombComponent, ircConnection, canceller);
        ModComponentSolverCreators["ButtonV2"] = (bombCommander, bombComponent, ircConnection, canceller) => new SquareButtonComponentSolver(bombCommander, bombComponent, ircConnection, canceller);
        ModComponentSolverCreators["SimonV2"] = (bombCommander, bombComponent, ircConnection, canceller) => new SimonStatesComponentSolver(bombCommander, bombComponent, ircConnection, canceller);
        ModComponentSolverCreators["PasswordV2"] = (bombCommander, bombComponent, ircConnection, canceller) => new SafetySafeComponentSolver(bombCommander, bombComponent, ircConnection, canceller);
        ModComponentSolverCreators["MazeV2"] = (bombCommander, bombComponent, ircConnection, canceller) => new PlumbingComponentSolver(bombCommander, bombComponent, ircConnection, canceller);
        ModComponentSolverCreators["MorseV2"] = (bombCommander, bombComponent, ircConnection, canceller) => new MorsematicsComponentSolver(bombCommander, bombComponent, ircConnection, canceller);
        ModComponentSolverCreators["NeedyVentV2"] = (bombCommander, bombComponent, ircConnection, canceller) => new NeedyQuizComponentSolver(bombCommander, bombComponent, ircConnection, canceller);
		ModComponentSolverCreators["NeedyKnobV2"] = (bombCommander, bombComponent, ircConnection, canceller) => new NeedyRotaryPhoneComponentSolver(bombCommander, bombComponent, ircConnection, canceller);

        //Perky Modules  (Silly Slots is maintained by Timwi, and as such its handler lives there.)
        ModComponentSolverCreators["CrazyTalk"] = (bombCommander, bombComponent, ircConnection, canceller) => new CrazyTalkComponentSolver(bombCommander, bombComponent, ircConnection, canceller);
        ModComponentSolverCreators["CryptModule"] = (bombCommander, bombComponent, ircConnection, canceller) => new CryptographyComponentSolver(bombCommander, bombComponent, ircConnection, canceller);
        ModComponentSolverCreators["ForeignExchangeRates"] = (bombCommander, bombComponent, ircConnection, canceller) => new ForeignExchangeRatesComponentSolver(bombCommander, bombComponent, ircConnection, canceller);
        ModComponentSolverCreators["Listening"] = (bombCommander, bombComponent, ircConnection, canceller) => new ListeningComponentSolver(bombCommander, bombComponent, ircConnection, canceller);
        ModComponentSolverCreators["OrientationCube"] = (bombCommander, bombComponent, ircConnection, canceller) => new OrientationCubeComponentSolver(bombCommander, bombComponent, ircConnection, canceller);
        ModComponentSolverCreators["Probing"] = (bombCommander, bombComponent, ircConnection, canceller) => new ProbingComponentSolver(bombCommander, bombComponent, ircConnection, canceller);
        ModComponentSolverCreators["TurnTheKey"] = (bombCommander, bombComponent, ircConnection, canceller) => new TurnTheKeyComponentSolver(bombCommander, bombComponent, ircConnection, canceller);
        ModComponentSolverCreators["TurnTheKeyAdvanced"] = (bombCommander, bombComponent, ircConnection, canceller) => new TurnTheKeyAdvancedComponentSolver(bombCommander, bombComponent, ircConnection, canceller);

        //Kaneb Modules
        ModComponentSolverCreators["TwoBits"] = (bombCommander, bombComponent, ircConnection, canceller) => new TwoBitsComponentSolver(bombCommander, bombComponent, ircConnection, canceller);

        //Asimir Modules
        ModComponentSolverCreators["murder"] = (bombCommander, bombComponent, ircConnection, canceller) => new MurderComponentSolver(bombCommander, bombComponent, ircConnection, canceller);
        ModComponentSolverCreators["shapeshift"] = (bombCommander, bombComponent, ircConnection, canceller) => new ShapeShiftComponentSolver(bombCommander, bombComponent, ircConnection, canceller);
        ModComponentSolverCreators["SeaShells"] = (bombCommander, bombComponent, ircConnection, canceller) => new SeaShellsComponentSolver(bombCommander, bombComponent, ircConnection, canceller);
        ModComponentSolverCreators["ThirdBase"] = (bombCommander, bombComponent, ircConnection, canceller) => new ThirdBaseComponentSolver(bombCommander, bombComponent, ircConnection, canceller);

        //Spare Wizard Modules
        ModComponentSolverCreators["spwiz3DMaze"] = (bombCommander, bombComponent, ircConnection, canceller) => new ThreeDMazeComponentSolver(bombCommander, bombComponent, ircConnection, canceller);

		//Mock Army Modules
		ModComponentSolverCreators["Emoji Math"] = (bombCommander, bombComponent, ircConnection, canceller) => new EmojiMathComponentSolver(bombCommander, bombComponent, ircConnection, canceller);
        ModComponentSolverCreators["AnagramsModule"] = (bombCommander, bombComponent, ircConnection, canceller) => new AnagramsComponentSolver(bombCommander, bombComponent, ircConnection, canceller);
        ModComponentSolverCreators["WordScrambleModule"] = (bombCommander, bombComponent, ircConnection, canceller) => new AnagramsComponentSolver(bombCommander, bombComponent, ircConnection, canceller);

        //Misc Modules
        ModComponentSolverCreators["alphabet"] = (bombCommander, bombComponent, ircConnection, canceller) => new AlphabetComponentSolver(bombCommander, bombComponent, ircConnection, canceller);
        ModComponentSolverCreators["NumberPad"] = (bombCommander, bombComponent, ircConnection, canceller) => new NumberPadComponentSolver(bombCommander, bombComponent, ircConnection, canceller);
        ModComponentSolverCreators["switchModule"] = (bombCommander, bombComponent, ircConnection, canceller) => new SwitchesComponentSolver(bombCommander, bombComponent, ircConnection, canceller);
        ModComponentSolverCreators["resistors"] = (bombCommander, bombComponent, ircConnection, canceller) => new ResistorsComponentSolver(bombCommander, bombComponent, ircConnection, canceller);
        ModComponentSolverCreators["Microcontroller"] = (bombCommander, bombComponent, ircConnection, canceller) => new MicrocontrollerComponentSolver(bombCommander, bombComponent, ircConnection, canceller);
        ModComponentSolverCreators["ChordQualities"] = (bombCommander, bombComponent, ircConnection, canceller) => new ChordQualitiesComponentSolver(bombCommander, bombComponent, ircConnection, canceller);
        ModComponentSolverCreators["LetterKeys"] = (bombCommander, bombComponent, ircConnection, canceller) => new LetteredKeysComponentSolver(bombCommander, bombComponent, ircConnection, canceller);

        //Module Information
        //Information declared here will be used to generate ModuleInformation.json if it doesn't already exist, and will be overwritten by ModuleInformation.json if it does exist.
        /*
         * 
            Typical ModuleInformation json entry
            {
                "moduleDisplayName": "Double-Oh",
                "moduleID": "DoubleOhModule",
                "helpText": "Cycle the buttons with !{0} cycle. (Cycle presses each button 3 times, in the order of vert1, horiz1, horiz2, vert2, submit.)  Submit your answer with !{0} press vert1 horiz1 horiz2 vert2 submit.",
                "manualCode": null,
                "statusLightLeft": false,
                "statusLightDown": false,
                "chatRotation": 0.0,
                "validCommands": null,
                "DoesTheRightThing": false,
                "helpTextOverride": false,
                "manualCodeOverride": false,
                "statusLightOverride": true,
                "validCommandsOverride": false
            },
         * 
         * moduleDisplayName - The name of the module as displayed in Mod Selector or the chat box.
         * moduleID - The unique identifier of the module.
         * 
         * helpTextOverride - Specifies whether the help text should not be overwritten by what is present in the module.
         * helpText - Instructions on how to interact with the module in twitch plays.
         * 
         * manualCodeOverride - Specifies whether the manual code should not be overwritten by what is present in the module.
         * manualCode - If defined, is used instead of moduleDisplayName to look up the html/pdf manual.
         * 
         * statusLightOverride - Specifies an override of the ID# position / rotation. (This must be set if you wish to have the ID be anywhere other than
         *      Above the status light, or if you wish to rotate the ID / chat box.)
         * statusLightLeft - Specifies whether the ID should be on the left side of the module.
         * statusLightDown - Specifies whether the ID should be on the bottom side of the module.
         * chatRotation - Specifies whether the chat box / ID should be rotated.  (not currently implemented yet.)
         * 
         * Finally, validCommands, DoesTheRightThing and all of the override flags will only show up in modules not built into Twitch plays.
         * validCommandsOverride - Specifies whether the valid regular expression list should not be updated from the module.
         * validCommands - A list of valid regular expression commands that define if the command should be passed onto the modules Twitch plays handler.
         *      If null, the command will always be passed on.
         *      
         * DoesTheRightThing - Specifies whether the module properly yields return something BEFORE interacting with any buttons.
         * 
         * 
         */

        //All of these modules are built into Twitch plays.

        //Asimir
        ModComponentSolverInformation["murder"] = new ModuleInformation { builtIntoTwitchPlays = true, moduleID = "murder", moduleDisplayName = "Murder", moduleScore = 10, helpText = "CycleCycle the options with !{0} cycle or !{0} cycle people (also weapons and rooms). Make an accusation with !{0} It was Peacock, with the candlestick, in the kitchen. Or you can set the options individually, and accuse with !{0} accuse." };
        ModComponentSolverInformation["SeaShells"] = new ModuleInformation { builtIntoTwitchPlays = true, moduleID = "SeaShells", moduleDisplayName = "Sea Shells", helpText = "Press buttons by typing !{0} press alar llama. You can submit partial text as long it only matches one button. NOTE: Each button press is separated by a space so typing \"burglar alarm\" will press a button twice." , moduleScore = 7};
        ModComponentSolverInformation["shapeshift"] = new ModuleInformation { builtIntoTwitchPlays = true, moduleID = "shapeshift", moduleDisplayName = "Shape Shift", helpText = "Submit your anwser with !{0} submit point round. Reset to initial state with !{0} reset. Valid shapes: flat, point, round and ticket.", moduleScore = 8 };
        ModComponentSolverInformation["ThirdBase"] = new ModuleInformation { builtIntoTwitchPlays = true, statusLightDown = true, statusLightLeft = true, moduleScore = 5, moduleID = "ThirdBase", moduleDisplayName = "Third Base", helpText = "Press a button with !{0} z0s8. Word must match the button as it would appear if the module was the right way up. Not case sensitive." };

        //AT_Bash / Bashly
        ModComponentSolverInformation["MotionSense"] = new ModuleInformation {builtIntoTwitchPlays = true, moduleID = "MotionSense", moduleDisplayName = "Motion Sense", helpText = "I am a passive module that awards strikes for motion while I am active. Use !{0} status to find out if I am active, and for how long."};

        //Hexicube
        ModComponentSolverInformation["MemoryV2"] = new ModuleInformation { builtIntoTwitchPlays = true, moduleID = "MemoryV2", moduleDisplayName = "Forget Me Not", helpText = "Enter forget me not sequence with !{0} press 5 3 1 8 2 0... The Sequence length depends on how many modules were on the bomb.", moduleScoreIsDynamic = true, moduleScore = 0, CameraPinningAlwaysAllowed = true };
        ModComponentSolverInformation["KeypadV2"] = new ModuleInformation { builtIntoTwitchPlays = true, moduleID = "KeypadV2", moduleDisplayName = "Round Keypad", helpText = "Solve the module with !{0} press 2 4 6 7 8. Button 1 is the top most botton, and are numbered in clockwise order.", moduleScore = 6 };
        ModComponentSolverInformation["ButtonV2"] = new ModuleInformation { builtIntoTwitchPlays = true, moduleID = "ButtonV2", moduleDisplayName = "Square Button", helpText = "Click the button with !{0} tap. Click the button at time with !{0} tap 8:55 8:44 8:33. Hold the button with !{0} hold. Release the button with !{0} release 9:58 9:49 9:30.", moduleScore = 6 };
        ModComponentSolverInformation["SimonV2"] = new ModuleInformation { builtIntoTwitchPlays = true, moduleID = "SimonV2", moduleDisplayName = "Simon States", helpText = "Enter the response with !{0} press B Y R G.", moduleScore = 8 };
        ModComponentSolverInformation["PasswordV2"] = new ModuleInformation { builtIntoTwitchPlays = true, moduleID = "PasswordV2", moduleDisplayName = "Safety Safe", helpText = "Listen to the dials with !{0} cycle. Listen to a single dial with !{0} cycle BR. Make a correction to a single dial with !{0} BM 3. Enter the solution with !{0} 6 0 6 8 2 5. Submit the answer with !{0} submit. Dial positions are TL, TM, TR, BL, BM, BR.", moduleScore = 15 };
        ModComponentSolverInformation["MazeV2"] = new ModuleInformation { builtIntoTwitchPlays = true, moduleID = "MazeV2", moduleDisplayName = "Plumbing", helpText = "Rotate the pipes with !{0} rotate A1 A1 B2 B3 C2 C3 C3. Check your work for leaks Kappa with !{0} submit. (Pipes rotate clockwise. Top left is A1, Bottom right is F6)", moduleScore = 20 };
        ModComponentSolverInformation["MorseV2"] = new ModuleInformation { builtIntoTwitchPlays = true, moduleID = "MorseV2", moduleDisplayName = "Moresmatics", helpText = "Turn the lights off with !{0} lights off. Turn the lights on with !{0} lights on. Tranmit the answer with !{0} transmit -..-", moduleScore = 12 };
        ModComponentSolverInformation["NeedyVentV2"] = new ModuleInformation { builtIntoTwitchPlays = true, moduleID = "NeedyVentV2", moduleDisplayName = "Needy Answering Questions", helpText = "Answer the question with !{0} Y or !{0} N.", manualCode = "Answering%20Questions" };
        ModComponentSolverInformation["NeedyKnobV2"] = new ModuleInformation { builtIntoTwitchPlays = true, moduleID = "NeedyKnobV2", moduleDisplayName = "Needy Rotary Phone", helpText = "Respond to the phone call with !{0} press 8 4 9.", manualCode = "Rotary%20Phone" };

        //Perky
        ModComponentSolverInformation["CrazyTalk"] = new ModuleInformation { builtIntoTwitchPlays = true, moduleID = "CrazyTalk", moduleDisplayName = "Crazy Talk", helpText = "Toggle the switch down and up with !{0} toggle 4 5. The order is down, then up.", moduleScore = 3 };<commit_msg>Add more details about the moduleinformation.json format.<commit_after>using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using UnityEngine;

public static class ComponentSolverFactory
{
    private delegate ComponentSolver ModComponentSolverDelegate(BombCommander bombCommander, MonoBehaviour bombComponent, IRCConnection ircConnection, CoroutineCanceller canceller);
    private static readonly Dictionary<string, ModComponentSolverDelegate> ModComponentSolverCreators;
    private static readonly Dictionary<string, ModuleInformation> ModComponentSolverInformation;

    private enum ModCommandType
    {
        Simple,
        Coroutine
    }

    static ComponentSolverFactory()
    {
        ModComponentSolverCreators = new Dictionary<string, ModComponentSolverDelegate>();
        ModComponentSolverInformation = new Dictionary<string, ModuleInformation>();

        //AT_Bash Modules
        ModComponentSolverCreators["MotionSense"] = (bombCommander, bombComponent, ircConnection, canceller) => new MotionSenseComponentSolver(bombCommander, bombComponent, ircConnection, canceller);

       //Hexi Modules
        ModComponentSolverCreators["MemoryV2"] = (bombCommander, bombComponent, ircConnection, canceller) => new ForgetMeNotComponentSolver(bombCommander, bombComponent, ircConnection, canceller);
        ModComponentSolverCreators["KeypadV2"] = (bombCommander, bombComponent, ircConnection, canceller) => new RoundKeypadComponentSolver(bombCommander, bombComponent, ircConnection, canceller);
        ModComponentSolverCreators["ButtonV2"] = (bombCommander, bombComponent, ircConnection, canceller) => new SquareButtonComponentSolver(bombCommander, bombComponent, ircConnection, canceller);
        ModComponentSolverCreators["SimonV2"] = (bombCommander, bombComponent, ircConnection, canceller) => new SimonStatesComponentSolver(bombCommander, bombComponent, ircConnection, canceller);
        ModComponentSolverCreators["PasswordV2"] = (bombCommander, bombComponent, ircConnection, canceller) => new SafetySafeComponentSolver(bombCommander, bombComponent, ircConnection, canceller);
        ModComponentSolverCreators["MazeV2"] = (bombCommander, bombComponent, ircConnection, canceller) => new PlumbingComponentSolver(bombCommander, bombComponent, ircConnection, canceller);
        ModComponentSolverCreators["MorseV2"] = (bombCommander, bombComponent, ircConnection, canceller) => new MorsematicsComponentSolver(bombCommander, bombComponent, ircConnection, canceller);
        ModComponentSolverCreators["NeedyVentV2"] = (bombCommander, bombComponent, ircConnection, canceller) => new NeedyQuizComponentSolver(bombCommander, bombComponent, ircConnection, canceller);
		ModComponentSolverCreators["NeedyKnobV2"] = (bombCommander, bombComponent, ircConnection, canceller) => new NeedyRotaryPhoneComponentSolver(bombCommander, bombComponent, ircConnection, canceller);

        //Perky Modules  (Silly Slots is maintained by Timwi, and as such its handler lives there.)
        ModComponentSolverCreators["CrazyTalk"] = (bombCommander, bombComponent, ircConnection, canceller) => new CrazyTalkComponentSolver(bombCommander, bombComponent, ircConnection, canceller);
        ModComponentSolverCreators["CryptModule"] = (bombCommander, bombComponent, ircConnection, canceller) => new CryptographyComponentSolver(bombCommander, bombComponent, ircConnection, canceller);
        ModComponentSolverCreators["ForeignExchangeRates"] = (bombCommander, bombComponent, ircConnection, canceller) => new ForeignExchangeRatesComponentSolver(bombCommander, bombComponent, ircConnection, canceller);
        ModComponentSolverCreators["Listening"] = (bombCommander, bombComponent, ircConnection, canceller) => new ListeningComponentSolver(bombCommander, bombComponent, ircConnection, canceller);
        ModComponentSolverCreators["OrientationCube"] = (bombCommander, bombComponent, ircConnection, canceller) => new OrientationCubeComponentSolver(bombCommander, bombComponent, ircConnection, canceller);
        ModComponentSolverCreators["Probing"] = (bombCommander, bombComponent, ircConnection, canceller) => new ProbingComponentSolver(bombCommander, bombComponent, ircConnection, canceller);
        ModComponentSolverCreators["TurnTheKey"] = (bombCommander, bombComponent, ircConnection, canceller) => new TurnTheKeyComponentSolver(bombCommander, bombComponent, ircConnection, canceller);
        ModComponentSolverCreators["TurnTheKeyAdvanced"] = (bombCommander, bombComponent, ircConnection, canceller) => new TurnTheKeyAdvancedComponentSolver(bombCommander, bombComponent, ircConnection, canceller);

        //Kaneb Modules
        ModComponentSolverCreators["TwoBits"] = (bombCommander, bombComponent, ircConnection, canceller) => new TwoBitsComponentSolver(bombCommander, bombComponent, ircConnection, canceller);

        //Asimir Modules
        ModComponentSolverCreators["murder"] = (bombCommander, bombComponent, ircConnection, canceller) => new MurderComponentSolver(bombCommander, bombComponent, ircConnection, canceller);
        ModComponentSolverCreators["shapeshift"] = (bombCommander, bombComponent, ircConnection, canceller) => new ShapeShiftComponentSolver(bombCommander, bombComponent, ircConnection, canceller);
        ModComponentSolverCreators["SeaShells"] = (bombCommander, bombComponent, ircConnection, canceller) => new SeaShellsComponentSolver(bombCommander, bombComponent, ircConnection, canceller);
        ModComponentSolverCreators["ThirdBase"] = (bombCommander, bombComponent, ircConnection, canceller) => new ThirdBaseComponentSolver(bombCommander, bombComponent, ircConnection, canceller);

        //Spare Wizard Modules
        ModComponentSolverCreators["spwiz3DMaze"] = (bombCommander, bombComponent, ircConnection, canceller) => new ThreeDMazeComponentSolver(bombCommander, bombComponent, ircConnection, canceller);

		//Mock Army Modules
		ModComponentSolverCreators["Emoji Math"] = (bombCommander, bombComponent, ircConnection, canceller) => new EmojiMathComponentSolver(bombCommander, bombComponent, ircConnection, canceller);
        ModComponentSolverCreators["AnagramsModule"] = (bombCommander, bombComponent, ircConnection, canceller) => new AnagramsComponentSolver(bombCommander, bombComponent, ircConnection, canceller);
        ModComponentSolverCreators["WordScrambleModule"] = (bombCommander, bombComponent, ircConnection, canceller) => new AnagramsComponentSolver(bombCommander, bombComponent, ircConnection, canceller);

        //Misc Modules
        ModComponentSolverCreators["alphabet"] = (bombCommander, bombComponent, ircConnection, canceller) => new AlphabetComponentSolver(bombCommander, bombComponent, ircConnection, canceller);
        ModComponentSolverCreators["NumberPad"] = (bombCommander, bombComponent, ircConnection, canceller) => new NumberPadComponentSolver(bombCommander, bombComponent, ircConnection, canceller);
        ModComponentSolverCreators["switchModule"] = (bombCommander, bombComponent, ircConnection, canceller) => new SwitchesComponentSolver(bombCommander, bombComponent, ircConnection, canceller);
        ModComponentSolverCreators["resistors"] = (bombCommander, bombComponent, ircConnection, canceller) => new ResistorsComponentSolver(bombCommander, bombComponent, ircConnection, canceller);
        ModComponentSolverCreators["Microcontroller"] = (bombCommander, bombComponent, ircConnection, canceller) => new MicrocontrollerComponentSolver(bombCommander, bombComponent, ircConnection, canceller);
        ModComponentSolverCreators["ChordQualities"] = (bombCommander, bombComponent, ircConnection, canceller) => new ChordQualitiesComponentSolver(bombCommander, bombComponent, ircConnection, canceller);
        ModComponentSolverCreators["LetterKeys"] = (bombCommander, bombComponent, ircConnection, canceller) => new LetteredKeysComponentSolver(bombCommander, bombComponent, ircConnection, canceller);

        //Module Information
        //Information declared here will be used to generate ModuleInformation.json if it doesn't already exist, and will be overwritten by ModuleInformation.json if it does exist.
        /*
         * 
            Typical ModuleInformation json entry
            {
                "moduleDisplayName": "Double-Oh",
                "moduleID": "DoubleOhModule",
                "moduleScore": 8,
                "strikePenalty": -6,
                "moduleScoreIsDynamic": false,
                "helpTextOverride": false,
                "helpText": "Cycle the buttons with !{0} cycle. (Cycle presses each button 3 times, in the order of vert1, horiz1, horiz2, vert2, submit.)  Submit your answer with !{0} press vert1 horiz1 horiz2 vert2 submit.",
                "manualCodeOverride": false,
                "manualCode": null,
                "statusLightOverride": true,
                "statusLightLeft": false,
                "statusLightDown": false,
                "chatRotation": 0.0,
                "validCommandsOverride": false,
                "validCommands": null,
                "DoesTheRightThing": false,
                "CameraPinningAlwaysAllowed": false
            },
         * 
         * moduleDisplayName - The name of the module as displayed in Mod Selector or the chat box.
         * moduleID - The unique identifier of the module.
         * 
         * moduleScore - The number of points the module will award the defuser on solve
         * strikePenalty - The number of points the module will take away from the defuser on a strike.
         * moduleScoreIsDynamic - Only used in limited cases. If true, moduleScore will define the scoring rules that apply.
         * 
         * helpTextOverride - Specifies whether the help text should not be overwritten by what is present in the module.
         * helpText - Instructions on how to interact with the module in twitch plays.
         * 
         * manualCodeOverride - Specifies whether the manual code should not be overwritten by what is present in the module.
         * manualCode - If defined, is used instead of moduleDisplayName to look up the html/pdf manual.
         * 
         * statusLightOverride - Specifies an override of the ID# position / rotation. (This must be set if you wish to have the ID be anywhere other than
         *      Above the status light, or if you wish to rotate the ID / chat box.)
         * statusLightLeft - Specifies whether the ID should be on the left side of the module.
         * statusLightDown - Specifies whether the ID should be on the bottom side of the module.
         * chatRotation - Specifies whether the chat box / ID should be rotated.  (not currently implemented yet.)
         * 
         * Finally, validCommands, DoesTheRightThing and all of the override flags will only show up in modules not built into Twitch plays.
         * validCommandsOverride - Specifies whether the valid regular expression list should not be updated from the module.
         * validCommands - A list of valid regular expression commands that define if the command should be passed onto the modules Twitch plays handler.
         *      If null, the command will always be passed on.
         *      
         * DoesTheRightThing - Specifies whether the module properly yields return something BEFORE interacting with any buttons.
         * 
         * CameraPinningAlwaysAllowed - Defines if a normal user is allowed to use view pin on this module.
         * 
         * 
         */

        //All of these modules are built into Twitch plays.

        //Asimir
        ModComponentSolverInformation["murder"] = new ModuleInformation { builtIntoTwitchPlays = true, moduleID = "murder", moduleDisplayName = "Murder", moduleScore = 10, helpText = "CycleCycle the options with !{0} cycle or !{0} cycle people (also weapons and rooms). Make an accusation with !{0} It was Peacock, with the candlestick, in the kitchen. Or you can set the options individually, and accuse with !{0} accuse." };
        ModComponentSolverInformation["SeaShells"] = new ModuleInformation { builtIntoTwitchPlays = true, moduleID = "SeaShells", moduleDisplayName = "Sea Shells", helpText = "Press buttons by typing !{0} press alar llama. You can submit partial text as long it only matches one button. NOTE: Each button press is separated by a space so typing \"burglar alarm\" will press a button twice." , moduleScore = 7};
        ModComponentSolverInformation["shapeshift"] = new ModuleInformation { builtIntoTwitchPlays = true, moduleID = "shapeshift", moduleDisplayName = "Shape Shift", helpText = "Submit your anwser with !{0} submit point round. Reset to initial state with !{0} reset. Valid shapes: flat, point, round and ticket.", moduleScore = 8 };
        ModComponentSolverInformation["ThirdBase"] = new ModuleInformation { builtIntoTwitchPlays = true, statusLightDown = true, statusLightLeft = true, moduleScore = 5, moduleID = "ThirdBase", moduleDisplayName = "Third Base", helpText = "Press a button with !{0} z0s8. Word must match the button as it would appear if the module was the right way up. Not case sensitive." };

        //AT_Bash / Bashly
        ModComponentSolverInformation["MotionSense"] = new ModuleInformation {builtIntoTwitchPlays = true, moduleID = "MotionSense", moduleDisplayName = "Motion Sense", helpText = "I am a passive module that awards strikes for motion while I am active. Use !{0} status to find out if I am active, and for how long."};

        //Hexicube
        ModComponentSolverInformation["MemoryV2"] = new ModuleInformation { builtIntoTwitchPlays = true, moduleID = "MemoryV2", moduleDisplayName = "Forget Me Not", helpText = "Enter forget me not sequence with !{0} press 5 3 1 8 2 0... The Sequence length depends on how many modules were on the bomb.", moduleScoreIsDynamic = true, moduleScore = 0, CameraPinningAlwaysAllowed = true };
        ModComponentSolverInformation["KeypadV2"] = new ModuleInformation { builtIntoTwitchPlays = true, moduleID = "KeypadV2", moduleDisplayName = "Round Keypad", helpText = "Solve the module with !{0} press 2 4 6 7 8. Button 1 is the top most botton, and are numbered in clockwise order.", moduleScore = 6 };
        ModComponentSolverInformation["ButtonV2"] = new ModuleInformation { builtIntoTwitchPlays = true, moduleID = "ButtonV2", moduleDisplayName = "Square Button", helpText = "Click the button with !{0} tap. Click the button at time with !{0} tap 8:55 8:44 8:33. Hold the button with !{0} hold. Release the button with !{0} release 9:58 9:49 9:30.", moduleScore = 6 };
        ModComponentSolverInformation["SimonV2"] = new ModuleInformation { builtIntoTwitchPlays = true, moduleID = "SimonV2", moduleDisplayName = "Simon States", helpText = "Enter the response with !{0} press B Y R G.", moduleScore = 8 };
        ModComponentSolverInformation["PasswordV2"] = new ModuleInformation { builtIntoTwitchPlays = true, moduleID = "PasswordV2", moduleDisplayName = "Safety Safe", helpText = "Listen to the dials with !{0} cycle. Listen to a single dial with !{0} cycle BR. Make a correction to a single dial with !{0} BM 3. Enter the solution with !{0} 6 0 6 8 2 5. Submit the answer with !{0} submit. Dial positions are TL, TM, TR, BL, BM, BR.", moduleScore = 15 };
        ModComponentSolverInformation["MazeV2"] = new ModuleInformation { builtIntoTwitchPlays = true, moduleID = "MazeV2", moduleDisplayName = "Plumbing", helpText = "Rotate the pipes with !{0} rotate A1 A1 B2 B3 C2 C3 C3. Check your work for leaks Kappa with !{0} submit. (Pipes rotate clockwise. Top left is A1, Bottom right is F6)", moduleScore = 20 };
        ModComponentSolverInformation["MorseV2"] = new ModuleInformation { builtIntoTwitchPlays = true, moduleID = "MorseV2", moduleDisplayName = "Moresmatics", helpText = "Turn the lights off with !{0} lights off. Turn the lights on with !{0} lights on. Tranmit the answer with !{0} transmit -..-", moduleScore = 12 };
        ModComponentSolverInformation["NeedyVentV2"] = new ModuleInformation { builtIntoTwitchPlays = true, moduleID = "NeedyVentV2", moduleDisplayName = "Needy Answering Questions", helpText = "Answer the question with !{0} Y or !{0} N.", manualCode = "Answering%20Questions" };
        ModComponentSolverInformation["NeedyKnobV2"] = new ModuleInformation { builtIntoTwitchPlays = true, moduleID = "NeedyKnobV2", moduleDisplayName = "Needy Rotary Phone", helpText = "Respond to the phone call with !{0} press 8 4 9.", manualCode = "Rotary%20Phone" };

        //Perky
        ModComponentSolverInformation["CrazyTalk"] = new ModuleInformation { builtIntoTwitchPlays = true, moduleID = "CrazyTalk", moduleDisplayName = "Crazy Talk", helpText = "Toggle the switch down and up with !{0} toggle 4 5. The order is down, then up.", moduleScore = 3 };
{'fraction_non_alphanumeric': 0.08445402386084211, 'fraction_numerical': 0.00880361859081388, 'mean_word_length': 4.631111111111111, 'pattern_counts': {'":': 30, '<': 11, '<?xml version=': 0, '>': 79, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5831352', 'n_tokens_mistral': 8982, 'n_tokens_neox': 8628, 'n_words': 2796}