public int Merge(MainEntity toMerge, MergerConfiguration conf) { toMerge.NotNull("mainEntity"); var oldExpressions = _dataAccess.GetAllExpressions(); if (conf.ImportStatisticsForOld) { UpdateStatistics(toMerge.Expressions, oldExpressions); } MergeExpressionsWithUnknownTranslations(toMerge.Expressions, oldExpressions, conf); return(MergeUnknownExpressions(toMerge.Expressions, oldExpressions, conf)); }
/// <summary> /// Given an original manga gamer script file, attempts to detect which channel is used for BGM /// As input it needs to know the filenames of the BGM music files. /// It obtains this from the MergerConfiguration argument (the .toml file) /// It also uses the bgm length threshold to determine the difference between a BGM and a sound effect. /// </summary> /// <param name="mgScriptPath"></param> /// <param name="configuration"></param> /// <returns></returns> public static int?DetectBGMChannel(string mgScriptPath, MergerConfiguration configuration) { Dictionary <int, int> channelCounter = new Dictionary <int, int>(); using (StreamReader mgScript = new StreamReader(mgScriptPath, Encoding.UTF8)) { //Count how many times each channel plays a BGM //channel is considered to play a BGM if the file being played is longer than the configured length string line; while ((line = mgScript.ReadLine()) != null) { int?maybeBGMChannel = TryGetBGMMusicChannelOnSingleLine(line, searchFolders: configuration.bgm_folders, bgmLengthThresholdSeconds: configuration.music_threshold_seconds); if (maybeBGMChannel != null) { int BGMChannel = (int)maybeBGMChannel; if (channelCounter.ContainsKey(BGMChannel)) { channelCounter[BGMChannel] += 1; } else { channelCounter[BGMChannel] = 0; } } } //TODO: Debug - remove later foreach (KeyValuePair <int, int> item in channelCounter) { Console.WriteLine($"channel: {item.Key} count: {item.Value}"); } //return the channel which has the max number of BGM plays foreach (KeyValuePair <int, int> item in channelCounter.OrderByDescending(key => key.Value)) { return(item.Key); } } //if no playBGMs were found, return null return(null); }
/// <summary> /// Same as DetectBGMChannel() but if bgm channel couldn't be detected, uses user supplied default /// </summary> /// <returns></returns> public static int DetectBGMChannelOrDefault(string mgScriptPath, MergerConfiguration configuration, int defaultChannel, bool PrintOnFoundChannelAndWarnings) { int?maybeBGMChannel = MGScriptBGMChannelDetector.DetectBGMChannel(mgScriptPath, configuration); if (maybeBGMChannel != null) { if (PrintOnFoundChannelAndWarnings) { Console.WriteLine($"Detected channel [{maybeBGMChannel.Value}] as BGM Channel number"); } ; return(maybeBGMChannel.Value); } else { if (PrintOnFoundChannelAndWarnings) { Console.WriteLine($"WARNING: Could not detect bgmChannel. Will use channel {defaultChannel} when inserting PS3 music"); } return(defaultChannel); } }
private void Merge(MainEntity source, bool inbackground = true) { Log.StartTiming("Merge"); var conf = new MergerConfiguration { ImportCreationDate = ImportCreationDate, ImportRecentlyUsedDate = ImportRecentlyUsedDate, ImportDefinedDate = ImportDefinedDate, ImportStatisticsForNew = ImportStatisticsForNew, ImportStatisticsForOld = ImportStatisticsForOld }; if (inbackground) { WindowService.DoBackgroundTask( () => Merger.Merge(source, conf)); } else { Merger.Merge(source, conf); } Log.StopTiming("Merge"); }
private int MergeUnknownExpressions(IEnumerable <ExpressionEntity> toMerge, IEnumerable <ExpressionEntity> oldExpressions, MergerConfiguration conf) { var unknownExpressions = from ex in toMerge where !oldExpressions.Any(oex => String.Equals(oex.Expression, ex.Expression, StringComparison.InvariantCultureIgnoreCase)) select ex; foreach (var u in unknownExpressions) { if (!conf.ImportCreationDate) { u.CreationDate = _dateTimeProvider.Current; } var toRemove = new List <TranslationEntity>(); foreach (var t in u.Translations) { if (String.IsNullOrWhiteSpace(t.Translation) && String.IsNullOrWhiteSpace(t.Translation2)) { toRemove.Add(t); } else { if (!conf.ImportRecentlyUsedDate) { t.RecentlyUsed = null; } if (!conf.ImportDefinedDate) { t.Defined = _dateTimeProvider.Current; } if (!conf.ImportStatisticsForNew) { ClearStatistics(t); } } } toRemove.ForEach(t => u.Translations.Remove(t)); } _dataAccess.Save(unknownExpressions); return(unknownExpressions.Count()); }
private void MergeTranslations(ExpressionEntity source, ExpressionEntity dest, MergerConfiguration conf) { foreach (var sourceTran in source.Translations) { var destTran = dest.Translations.Where(t => t.Language == sourceTran.Language).FirstOrDefault(); if (destTran == null) { if (!conf.ImportStatisticsForNew) { ClearStatistics(sourceTran); } dest.Translations.Add(sourceTran); } else { if (conf.ImportStatisticsForNew) { CopyStatistics(sourceTran, destTran); } else { ClearStatistics(destTran); } destTran.Translation = sourceTran.Translation; destTran.Translation2 = sourceTran.Translation2; } } }
private void MergeExpressionsWithUnknownTranslations(IEnumerable <ExpressionEntity> toMerge, IEnumerable <ExpressionEntity> oldExpressions, MergerConfiguration conf) { var withUnknownTranslation = from ex in toMerge where oldExpressions.Any(oldEx => String.Equals(oldEx.Expression, ex.Expression, StringComparison.InvariantCultureIgnoreCase)) && !oldExpressions.Contains(ex) select ex; foreach (var ex in withUnknownTranslation) { var res = oldExpressions.Where(oldEx => String.Equals(ex.Expression, oldEx.Expression, StringComparison.InvariantCultureIgnoreCase)); foreach (var oldEx in res) { MergeTranslations(ex, oldEx, conf); } _dataAccess.Save(res); } }
public static void InsertMGLinesUsingPS3XML(string mergedMGScriptPath, string outputPath, MergerConfiguration configuration, Counter counter) { const bool USE_OLD_METHOD_FOR_INSERT_BGM = false; Console.WriteLine($"--------- Begin Applying Postprocessing Stage 1 to {mergedMGScriptPath} ------"); //Detect the BGM channel of the original Manga Gamer script. This is used for BGM insertion and FadeOut insertion int bgmChannelNumber = MGScriptBGMChannelDetector.DetectBGMChannelOrDefault(mergedMGScriptPath, configuration, defaultChannel: 2, PrintOnFoundChannelAndWarnings: true); // --------- Perform stage 1 - this converts the raw merged script into a list of MangaGamerInstructions --------- //Iterate over the the Manga Gamer chunks and the PS3 XML Instructions Chunks of the merged script int debug_i = 0; List <InstructionAssociation> workingInstructionAssociations = new List <InstructionAssociation>(); List <MangaGamerInstruction> newChunk = new List <MangaGamerInstruction>(); foreach (var chunk in PS3XMLChunkFinder.GetAllChunksFromMergedScript(mergedMGScriptPath)) { if (chunk.isPS3Chunk) { //PS3 XML reader doesn't care about newlines, so just join each line directly to next line HandlePS3Chunk(String.Join("", chunk.lines), newChunk, bgmChannelNumber); HandleChunk(workingInstructionAssociations, newChunk); newChunk = new List <MangaGamerInstruction>(); } else { //handle a mangagamer chunk foreach (string mgScriptLine in chunk.lines) { newChunk.Add(ParseMangaGamerInstruction(mgScriptLine, false)); } } } //If there are any leftovers (probably just mangagamer original instructions), just add them to the output. HandleChunk(workingInstructionAssociations, newChunk); // Extract BGM associations of mgBGM -> ps3BGM ExtractBGMAssociations(workingInstructionAssociations, counter); // Convert the instruction associations to regular mangagamer instructions for stage 2 List <MangaGamerInstruction> outputStage1 = new List <MangaGamerInstruction>(); foreach (var instructionAssociation in workingInstructionAssociations) { outputStage1.Add(instructionAssociation.mgOriginalInstruction); //check for a "failed" section. If failed section, just insert the whole section. bool failed = false; foreach (var inst in instructionAssociation.associatedPS3Instructions) { if (inst is FailInstruction) { failed = true; } } if (failed) { outputStage1.AddRange(instructionAssociation.associatedPS3Instructions); continue; } foreach (var ps3Inst in instructionAssociation.associatedPS3Instructions) { MangaGamerInstruction outputInstruction = ps3Inst; switch (ps3Inst) { case MGPlayBGM ps3MGPlayBGM: if (instructionAssociation.mgOriginalInstruction is MGPlayBGM) { MGPlayBGM mgPlayBGM = (MGPlayBGM)instructionAssociation.mgOriginalInstruction; outputInstruction = mgPlayBGM.CloneWithFilename(ps3MGPlayBGM.bgmFileName, ps3MGPlayBGM.IsPS3()); } break; case MGPlaySE ps3MGPlaySE: if (instructionAssociation.mgOriginalInstruction is MGPlaySE) { MGPlaySE mgPlaySE = (MGPlaySE)instructionAssociation.mgOriginalInstruction; outputInstruction = mgPlaySE.CloneWithFilename(ps3MGPlaySE.filename, ps3MGPlaySE.IsPS3()); } break; } outputStage1.Add(outputInstruction); } } // --------- Perform stage 2 filtering to 'tidy up' the script --------- //This section runs filters after all the other filters have run. //This stage converts the list of MangaGamerInstructions to a list of strings List <string> outputStage2 = new List <string>(); foreach (MangaGamerInstruction inst in outputStage1) { //TODO: correctly interpret mangagamer instructions instead of using regexes to determine the line typ if (inst.IsPS3()) { //Disable PS3 fade instructions for now if (!(inst is MGFadeOutBGM)) { //wrap all ps3-origin instructions in GAltBGMflow outputStage2.Add($"\tif (GetGlobalFlag(GAltBGMflow) == 1) {{ {inst.GetInstruction()} }}"); } } else if (//fadeOutBGMMusicRegex.IsMatch(inst.GetInstruction()) || playBGMMusicRegex.IsMatch(inst.GetInstruction()) || playSERegex.IsMatch(inst.GetInstruction())) { //wrap only the above types of MG-origin instructions in GAltBGMflow outputStage2.Add($"\tif (GetGlobalFlag(GAltBGMflow) == 0) {{ {inst.GetInstruction()} }}"); } else { //all other MG-origin instructions are output as-is outputStage2.Add(inst.GetInstructionStandalone()); } } // --------- Finally, write the output to file. --------- File.WriteAllLines(outputPath, outputStage2); }