/// <summary> /// Given a line from Subs1, get the closest matching line from a list of Subs2 lines based on timestamp. /// May return null if Subs1 RemoveNoCounterpart is set and there is no obvious Subs2 counterpart. /// </summary> private InfoCombined getCombinedOverlap(InfoLine subs1LineInfo, List <InfoLine> subs2LineInfos) { InfoLine bestMatch = new InfoLine(); double bestOverlap = -999999999999999999.0; int stopCount = 0; // Compare the given Subs1 against each of the Subs2 lines foreach (InfoLine info in subs2LineInfos) { // How well did these lines overlap (1.0 is the max) double overlap = UtilsSubs.getOverlap(subs1LineInfo.StartTime, subs1LineInfo.EndTime, info.StartTime, info.EndTime); // Did the current pair of lines overlap more than any pair thus far? if (overlap >= bestOverlap) { bestMatch.Actor = info.Actor; bestMatch.EndTime = info.EndTime; bestMatch.StartTime = info.StartTime; bestMatch.Text = info.Text; bestOverlap = overlap; stopCount = 0; // Reset } else { stopCount++; // Stop trying to find matches after a while if (stopCount == 20) { break; } } } // If no overlap, don't use provided Subs1 line if (Settings.Instance.Subs[0].RemoveNoCounterpart && bestOverlap < 0.0) { return(null); } return(new InfoCombined(subs1LineInfo, bestMatch)); }
/// <summary> /// When Subs1 and Subs2 have different number of lines or the timings are mismatched, /// then lines from Subs2 can be skipped. This routine will combine the skipped lines with /// their closest match based on timestamp. /// /// Example: /// /// Subs1_A --> Subs2_A /// Subs1_B --> Subs2_C ; Subs2_B was skipped! /// Subs1_C --> Subs2_D /// Subs1_D --> Subs2_E /// /// Transform the above into: /// /// Subs1_A --> Subs2_A Subs2_B /// Subs1_B --> Subs2_C /// Subs1_C --> Subs2_D /// Subs1_D --> Subs2_E /// /// or: /// /// Subs1_A --> Subs2_A /// Subs1_B --> Subs2_B Subs2_C /// Subs1_C --> Subs2_D /// Subs1_D --> Subs2_E /// /// </summary> private List <InfoCombined> combineSkipped(List <InfoLine> subs2LineList, List <InfoCombined> combList) { // Get list of skipped lines List <InfoLine> skippedList = findSkippedLines(subs2LineList, combList); Dictionary <InfoCombined, List <InfoLine> > skipDic = new Dictionary <InfoCombined, List <InfoLine> >(); // Associate each skipped line with the closest non-skipped line in the Subs1 list foreach (InfoLine skip in skippedList) { InfoCombined bestMatch = new InfoCombined(new InfoLine(), new InfoLine()); double bestOverlap = -999999999999999999.0; foreach (InfoCombined comb in combList) { double overlap = UtilsSubs.getOverlap(skip.StartTime, skip.EndTime, comb.Subs1.StartTime, comb.Subs1.EndTime); if (overlap >= bestOverlap) { bestMatch = comb; bestOverlap = overlap; } } // If user wants to, toss out Subs2 with no obvious Subs1 counterpart if (Settings.Instance.Subs[1].RemoveNoCounterpart && bestOverlap < 0.0) { continue; } else { // Because multiple skipped lines can match the same line from Sub1, // add to dictionary so that they can be sorted lateer if (skipDic.ContainsKey(bestMatch)) { skipDic[bestMatch].Add(skip); } else { // Add Subs1 line to dictionary as the key skipDic.Add(bestMatch, new List <InfoLine>()); // Add the best matched line's Subs2 line skipDic[bestMatch].Add(bestMatch.Subs2); // Add the original skipped line skipDic[bestMatch].Add(skip); } } } // Sort the matched lines (for the case where multiple skipped lines match the same Subs1 line) foreach (List <InfoLine> infoList in skipDic.Values) { infoList.Sort(); } // Now change text and time info from the skipped lines into the comb list foreach (InfoCombined comb in skipDic.Keys) { string subs2Text = ""; // Combine the text foreach (InfoLine infoList in skipDic[comb]) { subs2Text += infoList.Text + " "; } comb.Subs2.Text = subs2Text.Trim(); comb.Subs2.StartTime = skipDic[comb][0].StartTime; int numInfoElements = skipDic[comb].Count - 1; comb.Subs2.EndTime = skipDic[comb][numInfoElements].EndTime; } return(combList); }