Example #1
0
        public static MergerConfiguration ParseTOML(string tomlFilePath)
        {
            MergerConfiguration config = Toml.ReadFile <MergerConfiguration>(tomlFilePath);
            bool configOK = true;

            //validate the configuration
            foreach (InputInfo inputInfo in config.input)
            {
                foreach (List <int> region in inputInfo.ps3_regions)
                {
                    //check for a region which is not length 2
                    if (region.Count != 2)
                    {
                        Console.WriteLine($"Error parsing info for {inputInfo.path}: Region should be length 2 but is length {region.Count}");
                        configOK = false;
                        continue;
                    }

                    //check for a region where the start value is greater than the end value
                    if (region[0] > region[1])
                    {
                        Console.WriteLine($"Error parsing info for {inputInfo.path}: Start is greater than end [{region[0]},{region[1]}]");
                        configOK = false;
                        continue;
                    }
                }
            }

            return(configOK ? config : null);
        }
Example #2
0
        //wrapper to allow 'pausing' of program but still garbage collect everything to force files to write-out
        static void RunProgram()
        {
            Console.WriteLine("If japanese characters show as ???? please change your console font to MS Gothic or similar.");

            //MUST set this so that diff tool can output proper unicode (otherwise output is scrambled)
            //and so can see japanese characters (you might need to change your console font too to MS Gothic or similar)
            Console.OutputEncoding = System.Text.Encoding.UTF8;

            MergerConfiguration config = HintParser.ParseTOML("conf.toml");

            if (config == null)
            {
                Console.WriteLine("Can't continue - config file is not valid!");
                PauseThenErrorExit();
            }
            else
            {
                Console.WriteLine("Config file is valid.");
            }
            Directory.SetCurrentDirectory(config.working_directory);

            //Read in/merge the xml file according to the config
            string untranslatedXMLFilePath = null;

            if (File.Exists(config.ps3_xml_path))
            {
                untranslatedXMLFilePath = config.ps3_xml_path;
            }
            else if (Directory.Exists(config.ps3_xml_path))
            {
                FileConcatenator.MergeFilesInFolder(config.ps3_xml_path, config.ps3_merged_output_path);
                untranslatedXMLFilePath = config.ps3_merged_output_path;
            }
            else
            {
                Console.WriteLine($"Can't find ps3 input file/folder {Path.GetFullPath(config.ps3_xml_path)}");
                PauseThenErrorExit();
            }

            //begin processing
            List <PS3DialogueInstruction> pS3DialogueInstructionsPreFilter = PS3XMLReader.GetPS3DialoguesFromXML(untranslatedXMLFilePath);

            // >>>> Merge ModCallScriptSection: pre-process each file in the pre-input folder, ignoring sub scripts
            // >>>> this inserts the subscripts inline into the script
            Regex emptyMainRegex = new Regex(@"void\s*main\(\s*\)\s*{\s*}");

            foreach (string pathOfPossibleScript in Directory.EnumerateFiles(config.pre_input_folder, "*.*", SearchOption.AllDirectories))
            {
                // Skip scripts which have an empty main file - these are sub scripts
                string fileText = File.ReadAllText(pathOfPossibleScript);
                if (emptyMainRegex.Match(fileText).Success)
                {
                    Console.WriteLine($"Skipping script {pathOfPossibleScript} as it looks like a Sub-Script");
                    continue;
                }

                string filename = Path.GetFileName(pathOfPossibleScript);

                // >>>> Merge ModCallScriptSection: Before loading the manga gamer dialog, copy in any ModCallScriptSection(...) calls. This will be undone at a later stage
                List <string> mergedScriptLines = ForkingScriptMerger.MergeForkedScript(config.pre_input_folder, filename, true);

                File.WriteAllLines(Path.Combine(config.input_folder, filename), mergedScriptLines);
            }


            //TODO: scan for files, generate dummy input infos for files which haven't got specified regions.
            //ProcessSingleFile should then attempt to find the correct regions for those files and dump to toml file
            //TODO: clean up console output
            HashSet <string> filePathsToGetStartEnd = new HashSet <string>(); //note: this path includes the input folder name eg "input/test.txt"

            foreach (string fileInInputFolder in Directory.EnumerateFiles(config.input_folder, "*.*", SearchOption.AllDirectories))
            {
                filePathsToGetStartEnd.Add(Path.GetFullPath(fileInInputFolder));
            }

            Counter counter = new Counter();
            List <PartialSubScriptToMerge> forkedScriptContentToMergeList = new List <PartialSubScriptToMerge>();

            foreach (InputInfo inputInfo in config.input)
            {
                string tomlInputFilePathNormalized = Path.GetFullPath(Path.Combine(config.input_folder, inputInfo.path));

                if (filePathsToGetStartEnd.Contains(tomlInputFilePathNormalized))
                {
                    Console.WriteLine($"\n[  TOML OK   ]: {tomlInputFilePathNormalized} found in config file with region {StringUtils.PrettyPrintListOfListToString(inputInfo.ps3_regions)}");
                    filePathsToGetStartEnd.Remove(tomlInputFilePathNormalized);
                    forkedScriptContentToMergeList.AddRange(
                        ProcessSingleFile(pS3DialogueInstructionsPreFilter, config, inputInfo, new List <InputInfo>(), counter)
                        );
                }
            }

            //Unmerge all the sub-scripts (zonik_....txt)
            ForkingScriptMerger.UnMergeForkedScripts(config.pre_input_folder, config.output_folder, forkedScriptContentToMergeList);

            //Write out the counter statistics
            counter.WriteStatistics(Path.Combine(config.output_folder, "counter_statistics.txt"));

            //Save to a file so it can be copied into toml file (if already correct)
            var tempCounter = new Counter();

            using (StreamWriter sw = FileUtils.CreateDirectoriesAndOpen(config.guessed_matches, FileMode.Create))
            {
                List <InputInfo> guessedInputInfos = new List <InputInfo>();
                foreach (string filePathToGetStartEnd in filePathsToGetStartEnd)
                {
                    Console.WriteLine($"\n[TOML MISSING]: Start/End of [{filePathToGetStartEnd}] not specified.");
                    Console.WriteLine($"Will try best to do matching, but suggest manually inputting start and end.");
                    string relativePath = FileUtils.GetRelativePath(filePathToGetStartEnd, Path.GetFullPath(config.input_folder));

                    // Since no ps3 region specified, should just search the whole PS3 xml
                    InputInfo wholeFileInputInfo = new InputInfo
                    {
                        path        = relativePath,
                        ps3_regions = new List <List <int> >(),
                    };
                    ProcessSingleFile(pS3DialogueInstructionsPreFilter, config, wholeFileInputInfo, guessedInputInfos, tempCounter);

                    foreach (InputInfo info in guessedInputInfos)
                    {
                        sw.WriteLine("# Autogenerated Match");
                        sw.WriteLine("[[input]]");
                        sw.WriteLine($"filename = {info.path}");
                        sw.WriteLine($"ps3_regions = {StringUtils.PrettyPrintListOfListToString(info.ps3_regions)}");
                        sw.WriteLine();
                        sw.Flush();
                    }
                    guessedInputInfos.Clear();
                }
            }
        }
Example #3
0
        /// <summary>
        /// processes a single mangagamer script, attempting to merge the matching ps3 instructions
        /// </summary>
        /// <param name="pS3DialogueInstructionsPreFilter"></param>
        /// <param name="config"></param>
        /// <param name="mgInfo"></param>
        /// <param name="guessedInputInfos"></param>
        static List <PartialSubScriptToMerge> ProcessSingleFile(
            List <PS3DialogueInstruction> pS3DialogueInstructionsPreFilter,
            MergerConfiguration config,
            InputInfo mgInfo,
            List <InputInfo> guessedInputInfos,
            Counter counter)
        {
            string fullPath  = Path.Combine(config.input_folder, mgInfo.path);
            string pathNoExt = Path.GetFileNameWithoutExtension(fullPath);

            string debug_side_by_side_diff_path_MG = Path.Combine(config.output_folder, pathNoExt + "_side_by_side_debug.html");
            string debug_alignment_statistics      = Path.Combine(config.output_folder, pathNoExt + "_statistics_debug.txt");

            List <PS3DialogueInstruction> pS3DialogueInstructions = GetFilteredPS3Instructions(pS3DialogueInstructionsPreFilter, mgInfo.ps3_regions);

            //load all the mangagamer lines from the mangagamer file
            List <MangaGamerDialogue> allMangaGamerDialogue = MangaGamerScriptReader.GetDialogueLinesFromMangaGamerScript(fullPath, out List <string> mg_leftovers);

            //PS3 Dialogue fragments
            List <PS3DialogueFragment> ps3DialogueFragments = new List <PS3DialogueFragment>();
            int ps3DialogueIndex = 0;

            foreach (PS3DialogueInstruction ps3Dialogue in pS3DialogueInstructions)
            {
                List <string>       splitDialogueStrings        = PS3DialogueTools.SplitPS3StringNoNames(ps3Dialogue.data);
                PS3DialogueFragment previousPS3DialogueFragment = null;
                for (int i = 0; i < splitDialogueStrings.Count; i++)
                {
                    //dummy instructions index into the ps3DialogueList (for now...)
                    PS3DialogueFragment ps3DialogueFragment = new PS3DialogueFragment(ps3Dialogue, splitDialogueStrings[i], i, previousPS3DialogueFragment);
                    ps3DialogueFragments.Add(ps3DialogueFragment);
                    previousPS3DialogueFragment = ps3DialogueFragment;
                }
                ps3DialogueIndex++;
            }

            //If no ps3 regions specified, scan for regions, then print and let user fill in?
            if (mgInfo.ps3_regions.Count == 0)
            {
                Console.WriteLine($"The file [{mgInfo.path}] does not have the PS3 region marked in the conf.toml file!");
                Console.WriteLine($"Scanning for PS3 region...");

                //print the first few and last mangagamer instructions
                //skip if length too small?
                Console.WriteLine("------- Finding first 5 entries -------");
                int?startResult = AnalyseEntries(ps3DialogueFragments, allMangaGamerDialogue, amount: 10, isStart: true);
                if (startResult.HasValue)
                {
                    Console.WriteLine($"Best guess at start PS3 ID: {startResult.Value}");
                }
                else
                {
                    Console.WriteLine("Not sure about start PS3 ID. Please inspect manually.");
                }

                Console.WriteLine("------- Finding last 5 entries -------");
                int?endResult = AnalyseEntries(ps3DialogueFragments, allMangaGamerDialogue, amount: 10, isStart: false);
                if (endResult.HasValue)
                {
                    Console.WriteLine($"Best guess at last PS3 ID: {endResult.Value}");
                }
                else
                {
                    Console.WriteLine("Not sure about last PS3 ID. Please inspect manually.");
                }

                string result_start_id = "<START_REGION>";
                string result_end_id   = "<END_REGION>";

                if (startResult.HasValue && endResult.HasValue)
                {
                    Console.WriteLine("AUTOREGION SUCCESS: You can copy this into the conf.toml file\n\n");
                    result_start_id = startResult.Value.ToString();
                    result_end_id   = endResult.Value.ToString();
                }
                else
                {
                    Console.WriteLine($"AUTOREGION FAIL: Region couldn't be determined confidently. Please use the above information and the ps3 script" +
                                      $"to determine the PS3 region manually, then place the results in the conf.toml file as per below");
                }

                Console.WriteLine("[[input]]");
                Console.WriteLine($@"path = ""{mgInfo.path}""");
                Console.WriteLine($"ps3_regions = [[{result_start_id}, {result_end_id}]]");
                Console.WriteLine("No output will be generated for this script until the program is run again.");
                Console.WriteLine("Press ENTER to move to the next script...");

                Console.ReadKey();
                return(new List <PartialSubScriptToMerge>());
            }

            //Diff the dialogue
            List <AlignmentPoint> allAlignmentPoints = Differ.DoDiff(config.temp_folder, allMangaGamerDialogue, ps3DialogueFragments, debugFilenamePrefix: pathNoExt);

            //Sanity check the alignment points by making sure there aren't missing any values
            SanityCheckAlignmentPoints(allAlignmentPoints, allMangaGamerDialogue, ps3DialogueFragments);

            //trim alignment points to reduce output
            List <AlignmentPoint> alignmentPoints = config.trim_after_diff ? TrimAlignmentPoints(allAlignmentPoints) : allAlignmentPoints;

            //Write statistics on how well matched the alignment points are
            WriteAlignmentStatistics(alignmentPoints, debug_alignment_statistics);

            //DEBUG: generate the side-by-side diff
            DifferDebugUtilities.PrintHTMLSideBySideDiff(alignmentPoints, debug_side_by_side_diff_path_MG);

            //Insert PS3 instructions
            string mergedOutputPath = Path.Combine(config.output_folder, pathNoExt + "_merged.xml.txt");

            SaveMergedMGScript(alignmentPoints, mergedOutputPath, mg_leftovers);

            // >>>> UnMerge ModCallScriptSection: Before using the results, we need to reverse the step we did earlier, by unmerging any merged files back into multiple files.

            //Use the inserted instructions
            string finalOutputWithMergedForkedScripts = Path.Combine(config.output_folder, pathNoExt + ".txt");

            MergedScriptPostProcessing.PostProcessingMain.InsertMGLinesUsingPS3XML(mergedOutputPath, finalOutputWithMergedForkedScripts, config, counter);

            List <PartialSubScriptToMerge> partialSubScriptsToMerge = ForkingScriptMerger.GetForkedScriptContentFromMergedScript(config.pre_input_folder, finalOutputWithMergedForkedScripts);

            ForkingScriptMerger.RemoveForkedScriptContentFromMergedScript(finalOutputWithMergedForkedScripts);

            return(partialSubScriptsToMerge);
        }