diff --git a/PBChance.dll b/PBChance.dll index aa2b3b2..baf67fb 100644 Binary files a/PBChance.dll and b/PBChance.dll differ diff --git a/PBChance/UI/Components/PBChanceComponent.cs b/PBChance/UI/Components/PBChanceComponent.cs index faf895c..1dde6e6 100644 --- a/PBChance/UI/Components/PBChanceComponent.cs +++ b/PBChance/UI/Components/PBChanceComponent.cs @@ -9,6 +9,8 @@ using System.Drawing; using System.Windows.Forms; using System.Xml; +using System.Threading; +//using System.Diagnostics; namespace PBChance.UI.Components { @@ -19,6 +21,44 @@ class PBChanceComponent : IComponent protected LiveSplitState State; protected Random rand; protected string category; + protected Thread thread;//, thread1, thread2; + protected bool KeepAlive;//, thread1running; + protected double fLiveChanceAct; + protected double fLiveChanceAvg; + protected double fLastUpdate; + protected bool bCheckUpdate; + protected bool bRndInformationOn; + protected bool bRndInformationActive; + protected double fNumberOfCombinations; + protected double fDeviation; + protected double fAvgTime; + protected long iMinCalcTime; + protected bool bCalcComplete; + protected string sInformationName; + protected string sInformationValue; + protected string[] sInformationAlternative; + private int iFaster, iSlower, iCountMalus, iFasterPace; + //private List[] splitsExt;// = new List[1000]; + private double fSecStart, fProbStart, fTotalBestTime; + private int iCurrentSplitIndex, iMaxSplit; + //private static Semaphore _pool;// = new Semaphore(0, 10); + //private Mutex mut = new Mutex(); + //int[] lAliveSplits; + protected double[] lSumPBTimes; + protected double[] lActPBTimes; + protected double[] lWorstPBTimes; + protected int[] lCountSplits; + protected int[] lCountTimedSplits; + protected int[] lCountSkippedSplits; + protected int[] lOldestAttempt; + protected List[] splits; + protected List[] splitsExt; + protected Time pb; + protected int iFirstAttempt = 1, iLastAttempt, iSurvivalFailure, iSurvivalSuccess, iSurvivalFailurePast, iNextSurvSuc, iNextSurvFail , + iSurvToHereAttempt, iSurvToHereCount; + protected TimingMethod tmTimingMethod; + System.String sWriteDebug1 = "", sWriteDebug2 = "", sWriteDebug3 = ""; + System.Diagnostics.Stopwatch watch; string IComponent.ComponentName => "PB Chance"; @@ -48,17 +88,85 @@ void IComponent.SetSettings(XmlNode settings) Settings.SetSettings(settings); } + double factorial(int x) + { + double factorial = 1; + for (int i = 2; i <= x; i++) + factorial *= i; + return factorial; + } + + double summ(int x) + { + double fSumm = 0; + for (int i = 1; i <= x; i++) + fSumm += i; + return fSumm; + } + + double RoundExtended(double d, int iDecimals) + { + if (iDecimals >= 0) + return Math.Round(d, iDecimals); + else + return Math.Round(d * Math.Pow(10, iDecimals)) * Math.Pow(10, -iDecimals); + } + + string getLargeNumber(double fIn) + { + string[] varA = new string[] { "Kilo", "Mega", "Giga", "Tera", "Peta", "Exa", "Zetta", "Yotta", "Oct", "Non" }; + string[] varB = new string[] { "", "Un", "Duo", "Tre", "Quattuor", "Quinqua", "Se", "Septen", "Octo", "Nonven" }; + string[] varC = new string[] { "", "Un", "Duo", "Tres", "Quattuor", "Quinqua", "Ses", "Septem", "Octo", "Nonvem" }; + string[] varD = new string[] { "", "Un", "Duo", "Tres", "Quattuor", "Quinqua", "Ses", "Septen", "Octo", "Nonven" }; + string[] varMeta = new string[] { "", "dec", "vigint", "trigint", "quadragint", "quinquagint", "sexagint", "septuagint", "octogint", "nonagint", "cent", "decicent", "viginticent", "trigintacent", "quadragintacent", "Quinquagintacent", "Sexagintacent", "Septuagintacent", "Octogintacent", "Nonagintacent", "Ducent" }; + + long iStellen, i; + string sZahl = ""; + double iNumber; + + iStellen = (long)Math.Log10(fIn); + iNumber = Math.Round(fIn / Math.Pow(10, (iStellen - iStellen % 3)), iStellen % 3 == 0 ? 1 : 0); + i = ((iStellen - 3) / 30); + + if (iStellen < 3) + sZahl = iNumber.ToString(); + else if (iStellen < 27) + sZahl = iNumber + " " + varA[(iStellen - 3) / 3] + varMeta[i]; + else if (iStellen < 33) + sZahl = iNumber + " " + varA[(iStellen - 3) / 3] + varMeta[i] + "illion"; + else if (iStellen < 63) + sZahl = iNumber + " " + varB[(iStellen - 33) / 3] + varMeta[i] + "illion"; + else if (iStellen < 93) + sZahl = iNumber + " " + varC[(iStellen - 63) / 3] + varMeta[i] + "illion"; + else if (iStellen < 630) + sZahl = iNumber + " " + varD[(iStellen - i * 30 - 3) / 3] + varMeta[i] + "illion"; + else + sZahl = iNumber.ToString("E1"); + + return sZahl + " E" + (iStellen / 3 * 3); + } + + string secondsToTime(double fIn, int iPrecision, bool bAutoHours) + { + if (bAutoHours && fIn<60*60) + if (iPrecision == 0) + return TimeSpan.FromSeconds(fIn).ToString(@"mm\:ss"); + else + return TimeSpan.FromSeconds(fIn).ToString(@"mm\:ss\" + (iPrecision > 0 ? "." + (iPrecision > 2 ? "fff" : iPrecision == 2 ? "ff" : "f") : "")); + else + if (iPrecision == 0) + return TimeSpan.FromSeconds(fIn).ToString(@"h\:mm\:ss"); + else + return TimeSpan.FromSeconds(fIn).ToString(@"h\:mm\:ss\" + (iPrecision > 0 ? "." + (iPrecision>2?"fff": iPrecision==2?"ff":"f"):"")); + + //return (fIn >= 3600 ? ((int)(fIn / 3600)).ToString("00:") : "") + ((int)(fIn / 60) % 60).ToString("00:") + (fIn % 60).ToString("00") + + // (iPrecision > 0 ? ":" + (((iPrecision==3?1000: iPrecision==2?100:10) * fIn) % (iPrecision == 3 ? 1000 : iPrecision == 2 ? 100 : 10)).ToString((iPrecision == 3 ? "000" : iPrecision == 2 ? "00" : "0")) : ""); + } + public PBChanceComponent(LiveSplitState state) { State = state; - InternalComponent = new InfoTextComponent("PB Chance .", "0.0%") - { - AlternateNameText = new string[] - { - "PB Chance", - "PB%:" - } - }; + InternalComponent = new InfoTextComponent("PB Chance", "Starting"); Settings = new PBChanceSettings(); Settings.SettingChanged += OnSettingChanged; rand = new Random(); @@ -71,50 +179,495 @@ public PBChanceComponent(LiveSplitState state) state.OnStart += OnStart; state.RunManuallyModified += OnRunManuallyModified; - Recalculate(); + iMinCalcTime = 1900; + StartRecalculate(true); } private void OnRunManuallyModified(object sender, EventArgs e) { - Recalculate(); + iMinCalcTime = (State.CurrentSplitIndex < 1 && Settings.iCalctime < 1900) ? 1900 : Settings.iCalctime; + StartRecalculate(true); } private void OnSettingChanged(object sender, EventArgs e) { - Recalculate(); + iMinCalcTime = Settings.iCalctime; + StartRecalculate(true); } private void OnStart(object sender, EventArgs e) { - Recalculate(); + iMinCalcTime = 1900; + StartRecalculate(true); } protected void OnUndoSplit(object sender, EventArgs e) { - Recalculate(); + iMinCalcTime = (State.CurrentSplitIndex < 1 && Settings.iCalctime < 1900) ? 1900 : Settings.iCalctime; + StartRecalculate(true); } protected void OnSkipSplit(object sender, EventArgs e) { - Recalculate(); + iMinCalcTime = (State.CurrentSplitIndex < 1 && Settings.iCalctime < 1900) ? 1900 : Settings.iCalctime; + if (Settings.bSkipSplitStroke) { InternalComponent.InformationName = "PB Chance"; InternalComponent.InformationValue = "-"; return; } + if (!Settings.bIgnoreSkipClip) StartRecalculate(true); } protected void OnReset(object sender, TimerPhase value) { - Recalculate(); + iMinCalcTime = 1900; + StartRecalculate(true); } protected void OnSplit(object sender, EventArgs e) { - Recalculate(); + iMinCalcTime = Settings.iCalctime; + StartRecalculate(true); + } + + protected void StartRecalculate(bool bForceNewcalc) + { + if (thread != null) + if (thread.ThreadState == System.Threading.ThreadState.Running) + { + if (!bForceNewcalc) return; + KeepAlive = false; + thread.Join(); + } + KeepAlive = true; + bCheckUpdate = false; + bRndInformationOn = false; + fLiveChanceAvg = 0; + thread = new Thread(new ThreadStart(Recalculate)); + thread.Start(); + /* + KeepAlive = true; + bCheckUpdate = false; + bRndInformationOn = false; + Recalculate();*/ + } + + private void PrepareSplits() + { + int iLastKnownSplit, iSegment, iFailState; + // 0 = init, 1=Success, 2=Fail next Split, 3=Fail later Split + + + // Create the lists of split times + //List[] splits = new List[iMaxSplit]; + //for (int i = 0; i < iMaxSplit; i++) + // splits[i] = new List(); + + //iLastAttempt = State.Run.AttemptHistory.Count - Settings.iSkipNewest; + //if (!Settings.IgnoreRunCount) + // iFirstAttempt = iLastAttempt - (Settings.UseFixedAttempts ? Settings.AttemptCount - 1 : iLastAttempt * (Settings.AttemptCount - 1 - Settings.iSkipNewest) / 100); + //if (iFirstAttempt < 1) iFirstAttempt = 1; + //iSurvToHereAttempt = iLastAttempt; + + try + { + + for (int iAttempt = iLastAttempt; iAttempt >= 0; iAttempt--) + { + iFailState = 0; + iLastKnownSplit = 0; + for (iSegment = iMaxSplit - 1; iSegment >= 0; iSegment--) + { + if (State.Run.Count>iSegment) + if (State.Run[iSegment].SegmentHistory == null || State.Run[iSegment].SegmentHistory.Count == 0) + { + if (State.Run[iSegment].BestSegmentTime[tmTimingMethod].HasValue) + { + splits[iSegment].Add(State.Run[iSegment].BestSegmentTime); // no split times available, take the best split time, display a warning + InternalComponent.InformationValue = "W1 no times found in S" + (1 + iSegment) + " " + State.Run[iSegment].Name; + if (Settings.bDebug) sWriteDebug2 += "Segment: " + iSegment.ToString("00") + " Attempt: " + iAttempt.ToString("0000") + " Best: " + State.Run[iSegment].BestSegmentTime[tmTimingMethod].Value.TotalSeconds.ToString("000.000") + " Time: " + State.Run[iSegment].SegmentHistory[iAttempt][tmTimingMethod].Value.TotalSeconds.ToString("0000.000") + " Name: " + State.Run[iSegment].Name + " (Warning 1: no historial times found)\r\n"; + lCountSplits[iSegment]++; + lOldestAttempt[iSegment] = iAttempt; + } + else + { + InternalComponent.InformationValue = "E1 no (best) times found in S" + (1 + iSegment) + " " + State.Run[iSegment].Name; + System.IO.File.AppendAllText(@"pbchance_Debug.txt", sWriteDebug1 + "\r\n--- Clipping segments --- " + watch.ElapsedMilliseconds + "ms\r\n" + sWriteDebug2); + return; + } + } + else if (State.Run[iSegment].SegmentHistory.ContainsKey(iAttempt) && State.Run[iSegment].SegmentHistory[iAttempt][tmTimingMethod] > TimeSpan.Zero) + { + if (State.Run[iSegment].BestSegmentTime[tmTimingMethod].HasValue) + { + if ((State.Run[iSegment].SegmentHistory[iAttempt][tmTimingMethod].Value.TotalSeconds <= Settings.SplitclipCount * 0.01 * State.Run[iSegment].BestSegmentTime[tmTimingMethod].Value.TotalSeconds)) // | (State.Run[iSegment].BestSegmentTime[tmTimingMethod].Value.TotalSeconds < 60)) + { + if (iAttempt >= iFirstAttempt || lCountSplits[iSegment] < Settings.iMinTimes) + { + splits[iSegment].Add(State.Run[iSegment].SegmentHistory[iAttempt]); // add a valid split time + lCountSplits[iSegment]++; + lOldestAttempt[iSegment] = iAttempt; + + while (iLastKnownSplit > iSegment + 1) + lCountSkippedSplits[iLastKnownSplit--]++; + lCountTimedSplits[iSegment]++; + iLastKnownSplit = iSegment; + + + if (iSegment == iCurrentSplitIndex - 1) { iSurvToHereCount++; if (iSurvToHereAttempt > iAttempt) iSurvToHereAttempt = iAttempt; } + if (Settings.bDebug && iAttempt < iFirstAttempt) sWriteDebug3 += "Segment: " + iSegment.ToString("00") + " Attempt: " + iAttempt.ToString("0000") + " Added Time: " + State.Run[iSegment].SegmentHistory[iAttempt][tmTimingMethod].Value.ToString() + " Factor: " + Math.Round(State.Run[iSegment].SegmentHistory[iAttempt][tmTimingMethod].Value.TotalSeconds / (State.Run[iSegment].BestSegmentTime[tmTimingMethod].Value.TotalSeconds + .0001), 2).ToString("0.00") + " Count of Valid/Total Times: " + lCountSplits[iSegment].ToString("0000") + "/" + splits[iSegment].Count.ToString("0000") + " Name: " + State.Run[iSegment].Name + "\r\n"; + + //while (iLastSetSegment > 0 && iSegment < iLastSetSegment - 1) + //{ lCountSkippedSplits[iLastSetSegment--]++; + // //sWriteDebug1 +="Atp" + iAttempt + " Segm " + iLastSetSegment + " skipped \n"; + //} + //iLastSetSegment = iSegment; + } + + if (iSegment == iMaxSplit - 1) + iFailState = 1; // Run is finished + else if (iFailState == 0) // Run didn't finish, add a failure for the last known split + { + iFailState = (iSegment == iCurrentSplitIndex - 1) ? 2 : (iSegment > iCurrentSplitIndex - 1) ? 3 : 4; // Failure is set + if (iAttempt >= iFirstAttempt || (lCountSplits[iSegment + 1] < Settings.iMinTimes && Settings.bConsiderFails)) + { + splits[iSegment + 1].Add(null); + if (Settings.bDebug) sWriteDebug1 += "#" + iSurvivalFailure.ToString("00") + ": Attempt: " + iAttempt.ToString("00") + " Segment: " + (iSegment + 1).ToString("00") + " LastSegment: " + iSegment.ToString("00") + " CountSplit: " + lCountSplits[iSegment].ToString("00") + "\r\n"; + } + } + } + else + //{ if (iAttempt >= iFirstAttempt || lCountSplits[iSegment] < Settings.iMinTimes) if (iSegment == iCurrentSplitIndex - 1) { iSurvToHereCount++; if (iSurvToHereAttempt > iAttempt) iSurvToHereAttempt = iAttempt; } + if (Settings.bDebug && (iAttempt >= iFirstAttempt || lCountSplits[iSegment] < Settings.iMinTimes)) sWriteDebug2 += "Segment: " + iSegment.ToString("00") + " Attempt: " + iAttempt.ToString("0000") + " Factor: " + Math.Round(State.Run[iSegment].SegmentHistory[iAttempt][tmTimingMethod].Value.TotalSeconds / State.Run[iSegment].BestSegmentTime[tmTimingMethod].Value.TotalSeconds, 2).ToString("0.00") + " Best: " + State.Run[iSegment].BestSegmentTime[tmTimingMethod].Value.TotalSeconds.ToString("000.000") + " Time: " + State.Run[iSegment].SegmentHistory[iAttempt][tmTimingMethod].Value.TotalSeconds.ToString("0000.000") + " Name: " + State.Run[iSegment].Name + "\r\n"; + } + else // no Best Time, then allways add + { + if (iAttempt >= iFirstAttempt || lCountSplits[iSegment] < Settings.iMinTimes) + { + splits[iSegment].Add(State.Run[iSegment].SegmentHistory[iAttempt]); + InternalComponent.InformationValue = "W2 no best time found in S" + (1 + iSegment) + " " + State.Run[iSegment].Name; + lCountSplits[iSegment]++; + lOldestAttempt[iSegment] = iAttempt; + if (iSegment == iCurrentSplitIndex - 1) { iSurvToHereCount++; if (iSurvToHereAttempt > iAttempt) iSurvToHereAttempt = iAttempt; } + if (Settings.bDebug) sWriteDebug2 += "Segment: " + iSegment.ToString("00") + " Attempt: " + iAttempt.ToString("0000") + " Time: " + State.Run[iSegment].SegmentHistory[iAttempt][tmTimingMethod].Value.TotalSeconds.ToString("0000.000") + " Name: " + State.Run[iSegment].Name + " Warning 2: No best Time found\r\n"; + } + + if (iSegment == iMaxSplit - 1) + iFailState = 1; // Run is finished + else if (iFailState == 0) // Run didn't finish, add a failure for the last known split + { + iFailState = (iSegment == iCurrentSplitIndex - 1) ? 2 : (iSegment > iCurrentSplitIndex - 1) ? 3 : 4; // Failure is set + if (iAttempt >= iFirstAttempt || lCountSplits[iSegment + 1] < Settings.iMinTimes) + { + splits[iSegment + 1].Add(null); + if (Settings.bDebug) sWriteDebug1 += "#" + iSurvivalFailure.ToString("00") + ": Attempt: " + iAttempt.ToString("00") + " Segment: " + (iSegment + 1).ToString("00") + " LastSegment: " + iSegment.ToString("00") + "\r\n"; + } + } + } + } + } + + if (iAttempt >= iFirstAttempt || lCountSplits[iCurrentSplitIndex] < Settings.iMinTimes) + { + if (iFailState == 0 && iCurrentSplitIndex == 0) // Failure on first Split + { + splits[iCurrentSplitIndex].Add(null); + if (Settings.bDebug) sWriteDebug1 += "#" + iSurvivalFailure.ToString("00") + ": Attempt: " + iAttempt.ToString("00") + " Segment: 00 LastSegment: -1\r\n"; + + if (iAttempt >= iFirstAttempt || (iNextSurvSuc < Settings.iMinTimes)) + { + iNextSurvFail++; + iSurvivalFailure++; + } + } + } + if (iAttempt >= iFirstAttempt || (iNextSurvSuc < Settings.iMinTimes))//+++++++++++++++++++++++ + { + switch (iFailState) + { + case 1: // Run is finished + iNextSurvSuc++; + break; + case 2: // Failure on next Split + iNextSurvFail++; + break; + case 3: // Failure is in Future + iNextSurvSuc++; + break; + case 4: // Failure is in Past + default: + break; + } + } + if (iAttempt >= iFirstAttempt || (iSurvivalSuccess < Settings.iMinTimes))//+++++++++++++++++++++++ + { + switch (iFailState) + { + case 1: // Run is finished + iSurvivalSuccess++; + break; + case 2: // Failure on next Split + iSurvivalFailure++; + break; + case 3: // Failure is in Future + iSurvivalFailure++; + break; + case 4: // Failure is in Past + iSurvivalFailurePast++; + break; + default: + break; + } + } + } + if (Settings.iAddBest > 0) + for (iSegment = 0; iSegment < iMaxSplit; iSegment++) + if (State.Run.Count > iSegment) + if (State.Run[iSegment].BestSegmentTime[tmTimingMethod].HasValue) + splits[iSegment].Insert(splits[iSegment].Count * (100 - Settings.iAddBest) / 99, State.Run[iSegment].BestSegmentTime); + } + catch (System.ArgumentOutOfRangeException e) // CS0168 + { + InternalComponent.InformationValue = "W3 Out of Range " + e.Message; + //throw new System.ArgumentOutOfRangeException("index parameter is out of range.", e); + } + } + + private int CheckForPB() + { + int iAttempt, iCountActMalus, iMaxAtempts = 10000, iSegment, i, iMalusRange = 2 * Settings.MalusCount + 1; + uint iPseudoRnd = 0; + double fSec = 0, fSecMalus = 0, fToBeat, fToBeatGoal; + Time? split; + int k, iCheckDistance = Settings.SamplesCount > 1000 ? 1000 : Settings.SamplesCount; + iFaster = 0; iSlower = 0; iFasterPace = 0; + fToBeat = -fSecStart + pb[tmTimingMethod].Value.TotalMilliseconds * .001 + Settings.TimediffCount; + fToBeatGoal= fToBeat - Settings.iPaceExtraGoalMS * .001; + //mut.WaitOne(); + for (iSegment = iCurrentSplitIndex; iSegment < iMaxSplit; iSegment++) + lSumPBTimes[iSegment] = 0; + //mut.ReleaseMutex(); + + //for(int iStep = 1; iStep <= (bRndInformationActive || bCheckUpdate ? 1 : 1001); iStep++) + //{ + + if (Settings.bDebug) sWriteDebug1 = "\r\n--- First generated Route (" + Settings.SamplesCount + " Routes in total) --- " + watch.ElapsedMilliseconds + "ms\r\n"; + + if (fTotalBestTime + Settings.TimediffCount <= fToBeat) // PB possible + for (i = 0; /*KeepAlive &&*/ (i < Settings.SamplesCount * (iFaster == 0 ? 10 : 1) || watch.ElapsedMilliseconds < iMinCalcTime) && + (fTotalBestTime + Settings.TimediffCount <= fToBeat); i = i + iCheckDistance) + for (k = 0; k < iCheckDistance; k++) + { + if (KeepAlive == false) return 0; // cancel calculation if new thread is requested + fSecMalus = 0; + iCountActMalus = 0; + fSec = 0;// -Settings.TimediffCount; + //Buffer.BlockCopy(lZeroPBTimes, iCurrentSplitIndex, lActPBTimes, iCurrentSplitIndex, iMaxSplit - iCurrentSplitIndex); + //for (int j = 0; j < iMaxSplit; j++) + // lActPBTimes[j] = 0; + //iAttempt = 0; + iMaxAtempts = 100000; // max tries to catch a valid time + + if (Settings.bDebug || Settings.bExpSplitsvalue || Settings.iSplitsvalue != 100) + { + // Add random split times for each remaining segment + for (iSegment = iCurrentSplitIndex; iSegment < iMaxSplit && iCountActMalus <= Settings.iMalusMax; iSegment++) + { + do + { + iMaxAtempts--; + // select newer attempts more often + if (Settings.bExpSplitsvalue) + do // 0 Exp = X^0 (=0 linear = deactivated) 10 Exponential = X^0.5, 20 Exp = X^1 (=100 linear), 40 Exp = X^2, 60 Exp = X^3, 80 Exp = X^4, 100 Exp = X^5 + iAttempt = rand.Next(splits[iSegment].Count); + while (Math.Pow((splits[iSegment].Count - iAttempt) / (splits[iSegment].Count * 1.0), Settings.iSplitsvalue * .05) < rand.Next(100) * .01); // exponential, this is slower + else + do + iAttempt = rand.Next(splits[iSegment].Count); + while (100 - Settings.iSplitsvalue + (Settings.iSplitsvalue) * (splits[iSegment].Count - iAttempt) / (splits[iSegment].Count * 1.0) < rand.Next(100)); // linear + //while (iAttempt / (splits[iSegment].Count * 1.0) < rand.Next(Settings.iSplitsvalue) * .01) ; // linear + split = splits[iSegment][iAttempt]; + + if (split == null) // split is a failure, add a malus + if ((iPseudoRnd++ % splits[iSegment].Count) > lCountSkippedSplits[iSegment]) + //if (rand.Next(lCountTimedSplits[iSegment] + lCountSkippedSplits[iSegment]) >= lCountSkippedSplits[iSegment]) + { + iCountActMalus++; + fSecMalus += rand.Next(2 * Settings.MalusCount + 1); //fSecMalus += Settings.MalusCount; + if (Settings.bDebug && iFaster == 0 && iSlower == 0) sWriteDebug1 += "Segment: " + iSegment.ToString("00") + " Attempt: " + iAttempt.ToString("0000") + " Route: " + i + " Name: " + State.Run[iSegment].Name + " Failure " + iCountMalus + " add " + Settings.MalusCount + "s\r\n"; + } + } while (split == null && iMaxAtempts > 0 && iCountActMalus <= Settings.iMalusMax); + + if (split != null) // found split times + { + if (split.Value[tmTimingMethod].HasValue) + { // add the time + fSec += split.Value[tmTimingMethod].Value.TotalMilliseconds * .001; + lActPBTimes[iSegment] = split.Value[tmTimingMethod].Value.TotalMilliseconds; + if (Settings.bDebug && iFaster == 0 && iSlower == 0) sWriteDebug1 += "Segment: " + iSegment.ToString("00") + " Attempt: " + iAttempt.ToString("0000") + " Route: " + i + " Duration: " + split.Value[tmTimingMethod].ToString() + " = " + (split.Value[tmTimingMethod].Value.TotalMilliseconds * .001).ToString("000.000") + "ms" + " --- BestTime=" + State.Run[iSegment].BestSegmentTime[tmTimingMethod].Value.TotalSeconds.ToString("000.000") + " Name: " + State.Run[iSegment].Name + "\r\n"; + } + else + { // should never happen + if (State.Run[iSegment].BestSegmentTime[tmTimingMethod].HasValue) + { + InternalComponent.InformationValue = "W4 no time found in A" + iAttempt + " S" + (1 + iSegment) + " " + State.Run[iSegment].Name; + if (Settings.bDebug) sWriteDebug1 += "Segment: " + iSegment.ToString("00") + " Atempt: " + iAttempt + " Name: " + State.Run[iSegment].Name + " (Warning 3: no time found)\r\n"; + fSec += State.Run[iSegment].BestSegmentTime[tmTimingMethod].Value.TotalMilliseconds * .001; + } + else + { + InternalComponent.InformationValue = "E4 no (best) time found in A" + iAttempt + " S" + (1 + iSegment) + " " + State.Run[iSegment].Name; + return 4; + } + } + } + else if(iCountActMalus <= Settings.iMalusMax) + { + InternalComponent.InformationValue = "E5 too many failure attempts S" + (1 + iSegment) + " " + State.Run[iSegment].Name; // + " split contains no times" + return 5; + } + } + if (Settings.bDebug && iFaster == 0 && iSlower == 0) { System.IO.File.AppendAllText(@"pbchance_debug.txt", sWriteDebug1); sWriteDebug1 = "\r\n--- Results of 10 successfully runs and 10 failures if possible --- " + watch.ElapsedMilliseconds + "ms\r\n"; } + + // Check if the time is faster than pb + if (fSec + iCountActMalus * Settings.MalusCount <= fToBeat && iCountActMalus <= Settings.iMalusMax) // equals to: (fSec + fSecStart + iCountActMalus * Settings.MalusCount <= pb[tmTimingMethod].Value.TotalMilliseconds * .001 + Settings.TimediffCount && iCountActMalus <= Settings.iMalusMax) + //if (fSec + fSecMalus <= fToBeat && iCountActMalus <= Settings.iMalusMax) + { + iFaster++; + if (Settings.bDebug && iFaster <= 10) // write first ten faster times + sWriteDebug1 += "Run: " + i.ToString("00000") + " Total Time: (" + fSec.ToString("0000.000") + "+" + fSecStart.ToString() + "+" + (iCountMalus * Settings.MalusCount).ToString("0000.000") + ") = " + (fSec + fSecStart + (iCountMalus * Settings.MalusCount)).ToString("0.000") + " < " + (pb[tmTimingMethod].Value.TotalMilliseconds * .001 + Settings.TimediffCount * fSec / (fSec + fSecStart)).ToString("0.00") + " = (" + pb[tmTimingMethod].Value.TotalMilliseconds * .001 + " + " + (Settings.TimediffCount * fSec / (fSec + fSecStart)).ToString("0.00") + ") success" + (Settings.iOptimistic == 0 ? "\r\n" : ""); + //if (fSec + fSecStart + fSecMalus <= pb[tmTimingMethod].Value.TotalMilliseconds / 1000 + Settings.TimediffCount - Settings.iPaceExtraGoalMS / 1000.0) + if (fSec + fSecMalus <= fToBeatGoal) + { + iFasterPace++; + for (iSegment = iCurrentSplitIndex; iSegment < iMaxSplit; iSegment++) + { + lSumPBTimes[iSegment] += lActPBTimes[iSegment]; + if (lWorstPBTimes[iSegment] < lActPBTimes[iSegment]) + lWorstPBTimes[iSegment] = lActPBTimes[iSegment]; + } + } + } + else + { + iSlower++; + if (Settings.bDebug && iSlower <= 10) // write first ten slower times + sWriteDebug1 += "Run: " + i.ToString("00000") + " Total Time: (" + fSec.ToString("0000.000") + "+" + fSecStart.ToString() + "+" + (iCountMalus * Settings.MalusCount).ToString("0000.000") + ") = " + (fSec + fSecStart + (iCountMalus * Settings.MalusCount)).ToString("0.000") + " > " + (pb[tmTimingMethod].Value.TotalMilliseconds * .001 + Settings.TimediffCount * fSec / (fSec + fSecStart)).ToString("0.00") + " = (" + pb[tmTimingMethod].Value.TotalMilliseconds * .001 + " + " + (Settings.TimediffCount * fSec / (fSec + fSecStart)).ToString("0.00") + ") failure" + (Settings.iOptimistic == 0 ? "\r\n" : ""); + } + } + + + else // no debug, optimized fast version + { + for (iSegment = iCurrentSplitIndex; iSegment < iMaxSplit; iSegment++) + { + { +newTryBecauseThisIsFaster: + iAttempt = rand.Next(splitsExt[iSegment].Count); + //iAttempt = iPseudoRnd++ % splitsExt[iSegment].Count; + split = splitsExt[iSegment][iAttempt]; + + if (split == null) + {// split is a failure, add a malus-penality + if ((iPseudoRnd++ % splits[iSegment].Count) > lCountSkippedSplits[iSegment]) // skipped splits should not increase the chance to fail a segment, this IF neutralize it + { + iCountActMalus++; + fSecMalus += iPseudoRnd % iMalusRange; //rand.Next(iMalusRange); + if (iCountActMalus > Settings.iMalusMax) + { + iSlower++; + goto InterruptedRunBecauseToMuchFailures; + } + } + goto newTryBecauseThisIsFaster; + } + } //while (split == null /*&& iMaxAtempts > 0*/); + fSec += split.Value[tmTimingMethod].Value.TotalMilliseconds * .001; // add the time + lActPBTimes[iSegment] = split.Value[tmTimingMethod].Value.TotalMilliseconds; + } + // Check if the time is faster than pb + if (fSec + fSecMalus <= fToBeat) // equals to: (fSec + fSecStart + fSecMalus <= pb[tmTimingMethod].Value.TotalMilliseconds / 1000 + Settings.TimediffCount) + { + iFaster++; + if (fSec + fSecMalus <= fToBeatGoal) // equals to: (fSec + fSecStart + fSecMalus <= pb[tmTimingMethod].Value.TotalMilliseconds / 1000 + Settings.TimediffCount - Settings.iPaceExtraGoalMS / 1000.0) + { + iFasterPace++; + for (iSegment = iCurrentSplitIndex; iSegment < iMaxSplit; iSegment++) + { + lSumPBTimes[iSegment] += lActPBTimes[iSegment]; + if (lWorstPBTimes[iSegment] < lActPBTimes[iSegment]) + lWorstPBTimes[iSegment] = lActPBTimes[iSegment]; + } + } + } + else + iSlower++; + } +InterruptedRunBecauseToMuchFailures: + iCountMalus += iCountActMalus; + } + else + { + iFaster = 0; + iSlower = Settings.SamplesCount; + //InternalComponent.InformationValue = fTotalBestTime + " + " + State.CurrentTime[tmTimingMethod].Value.TotalMilliseconds *.001 + " <= " + -fSecStart + " + " + pb[tmTimingMethod].Value.TotalMilliseconds * .001 + " = " + fToBeat; + } + + if (Settings.bDebug) System.IO.File.AppendAllText(@"pbchance_Debug.txt", sWriteDebug1); + + bCalcComplete = true; + return 0; } protected void Recalculate() { + int i, iAttempt, iSegment; + double /*fDeviation = 0,*/ iSumMsActSplit = 0; + //string text = ""; + bCalcComplete = false; + watch = System.Diagnostics.Stopwatch.StartNew(); + System.String sWriteDebug1 = "", sWriteDebug2 = "", sWriteDebug3 = ""; + iSurvivalFailure = 0; iSurvivalSuccess = 0; iSurvivalFailurePast = 0; iNextSurvSuc = 0; iNextSurvFail = 0;iSurvToHereAttempt = 0; iSurvToHereCount = 0; + tmTimingMethod = State.CurrentTimingMethod; + //Random random = new Random(); InternalComponent.InformationValue = random.Next(1, 10000) + ""; + if (Settings.sVersion != "1.4.5") + { + Settings.iCalctime = 750; + Settings.bDispGoodPace = true; + Settings.bGoodPaceTotal = true; + Settings.iMalusMax = 1; + Settings.iPaceExtraGoalMS = 0; + Settings.iPaceDigits = 0; + Settings.iRndInfoFor = 12; + Settings.bPaceWorst = false; + Settings.bSkipSplitStroke = true; + Settings.sVersion = "1.4.5"; + InternalComponent.InformationValue = "Welcome to V" + Settings.sVersion; + } + + iCurrentSplitIndex = (State.CurrentSplitIndex < 0 ? 0 : State.CurrentSplitIndex) + (bCheckUpdate ? 1 : 0); + if (Settings.iCalcToSplit > State.Run.Count) Settings.iCalcToSplit = State.Run.Count; + iMaxSplit = (Settings.iCalcToSplit == 0) ? State.Run.Count : Settings.iCalcToSplit; + //if (iCurrentSplitIndex > iMaxSplit) return; // Last split do no check for an update + + // Array of the count of valid split times per split (without failing attemps) + lCountSplits = new int[iMaxSplit + 1]; + lCountTimedSplits = new int[iMaxSplit + 1]; + lCountSkippedSplits = new int[iMaxSplit + 1]; + lOldestAttempt = new int[iMaxSplit + 1]; + + // Sum the Times, if this route is a PB + lActPBTimes = new double[iMaxSplit + 1]; + lSumPBTimes = new double[iMaxSplit + 1]; + lWorstPBTimes = new double[iMaxSplit + 1]; + + // Initialize Arrays + for (iSegment = iCurrentSplitIndex; iSegment < iMaxSplit; iSegment++) + { + lSumPBTimes[iSegment] = 0; + lWorstPBTimes[iSegment] = 0;// Int32.MaxValue; + } + // Get the current Personal Best, if it exists - Time pb = State.Run.Last().PersonalBestSplitTime; - - if(pb[State.CurrentTimingMethod] == TimeSpan.Zero) + pb = State.Run.Last().PersonalBestSplitTime; + + if (pb[tmTimingMethod] == TimeSpan.Zero || !pb[tmTimingMethod].HasValue) { // No personal best, so any run will PB InternalComponent.InformationValue = "100%"; @@ -122,126 +675,545 @@ protected void Recalculate() } // Create the lists of split times - List[] splits = new List[State.Run.Count]; - for(int i=0; i[iMaxSplit]; + for (i = 0; i < iMaxSplit; i++) splits[i] = new List(); - } // Find the range of attempts to gather times from - int lastAttempt = State.Run.AttemptHistory.Count; - int runCount = State.Run.AttemptHistory.Count; + iLastAttempt = State.Run.AttemptHistory.Count - Settings.iSkipNewest; if (!Settings.IgnoreRunCount) + iFirstAttempt = iLastAttempt - (Settings.UseFixedAttempts ? Settings.AttemptCount - 1 : iLastAttempt * (Settings.AttemptCount - 1 - Settings.iSkipNewest) / 100); + if (iFirstAttempt < 1) iFirstAttempt = 1; + iSurvToHereAttempt = iLastAttempt; + + if (Settings.bDebug) + System.IO.File.WriteAllText(@"pbchance_Debug.txt", "AdjustedStartTime: " + State.AdjustedStartTime + " AttemptEnded: " + State.AttemptEnded + " AttemptStarted: " + State.AttemptStarted + " \r\nCurrentAttemptDuration: " + State.CurrentAttemptDuration + " CurrentComparison: " + State.CurrentComparison + " CurrentPhase: " + State.CurrentPhase + "\r\n" //" CurrentHotkeyProfile: " + State.CurrentHotkeyProfile.ToString() + + "CurrentSplit: " + State.CurrentSplit + " CurrentSplitIndex: " + State.CurrentSplitIndex + " CurrentTime: " + State.CurrentTime + + "\r\nCurrentTimingMethod: " + tmTimingMethod + " GameTimePauseTime: " + State.GameTimePauseTime + " IsGameTimeInitialized: " + State.IsGameTimeInitialized + + "\r\nIsGameTimePaused: " + State.IsGameTimePaused + " Layout: " + State.Layout + " LayoutSettings: " + State.LayoutSettings + + "\r\nLoadingTimes: " + State.LoadingTimes + " PauseTime: " + State.PauseTime + " Run: " + State.Run + " Settings: " + State.Settings + + "\r\nStartTime: " + State.StartTime + " StartTimeWithOffset: " + State.StartTimeWithOffset + " TimePausedAt: " + State.TimePausedAt + + "\r\nAttempts: " + iFirstAttempt + " to " + iLastAttempt + " Malus: " + Settings.MalusCount + " Splitclip: " + Settings.SplitclipCount + " Timediff: " + Settings.TimediffCount + " Samples: " + Settings.SamplesCount + " Calctime: " + Settings.iCalctime + " Survival: " + Settings.bSurvival + " Rebalancing: " + Settings.iOptimistic + + "\r\nValueRuns: " + Settings.bValueRuns + " Min Times per Segment: " + Settings.iMinTimes + " Automatic Update every: " + Settings.iUpdate + "s More Value on newer Splits: " + Settings.iSplitsvalue + " Skip newest Splits: " + Settings.iSkipNewest + + "\r\nPersonal Best Time to beat: " + pb[tmTimingMethod].ToString() + " CalcToSplit: " + Settings.iCalcToSplit + + "\r\nConsider also fails: " + Settings.bConsiderFails + " Random Information every: " + Settings.iRndInfoEvery + " Random Information for: " + Settings.iRndInfoFor + "\r\n\r\n--- Failed Runs --- " + watch.ElapsedMilliseconds + "ms\r\n"); + + //if (Settings.bDebug) // alle Daten in Datei schreiben + //{ + // sWriteDebug1 = "Segment Attempt Time\r\n"; + // for (iAttempt = iFirstAttempt; iAttempt <= iLastAttempt; iAttempt++) + // for (iSegment = 0; iSegment < iMaxSplit; iSegment++) + // { + // if (State.Run[iSegment].SegmentHistory.ContainsKey(iAttempt) && State.Run[iSegment].SegmentHistory[iAttempt][tmTimingMethod] > TimeSpan.Zero) + // sWriteDebug1 += iSegment + " " + iAttempt + " " + State.Run[iSegment].SegmentHistory[iAttempt][tmTimingMethod].Value.TotalMilliseconds + "\r\n"; + // } + // System.IO.File.AppendAllText(@"pbchance_Debug.txt", sWriteDebug1); + // sWriteDebug1 = ""; + //} + + PrepareSplits(); + + if (Settings.bDebug) { - runCount = State.Run.AttemptCount; - if (runCount > State.Run.AttemptHistory.Count) + System.IO.File.AppendAllText(@"pbchance_Debug.txt", sWriteDebug1 + "\r\n--- Clipping segments --- " + watch.ElapsedMilliseconds + "ms\r\n" + sWriteDebug2); + sWriteDebug1 = "\r\n--- Added times --- " + watch.ElapsedMilliseconds + "ms\r\n" + sWriteDebug3; + for (iSegment = 0; iSegment < iMaxSplit; iSegment++) // Count Skipped Splits + sWriteDebug1 += "Segm: " + iSegment.ToString("00") + " Skipped: " + lCountSkippedSplits[iSegment].ToString("0000") + " Timed: " + lCountTimedSplits[iSegment].ToString("0000") + " Fails: " + (splits[iSegment].Count - lCountTimedSplits[iSegment]).ToString("0000") + " Count: " + splits[iSegment].Count.ToString("0000") + " lOldestAttempt: " + lOldestAttempt[iSegment].ToString("0000") + " AttemptDifference: " + (iLastAttempt - lOldestAttempt[iSegment]).ToString("0000") + "\n"; + } + + if (KeepAlive == false) return; // cancel calculation if new thread is requested + + fNumberOfCombinations = 1; // calculate number of active combinations + for (iSegment = iCurrentSplitIndex; iSegment < iMaxSplit; iSegment++) + if (splits[iSegment].Count == 0) // This split contains no split times, so we cannot calculate a probability { - runCount = State.Run.AttemptHistory.Count; + if (State.Run.Count > iSegment) + InternalComponent.InformationValue = "E3 no times found in S" + (1 + iSegment) + " " + State.Run[iSegment].Name; // + " split contains no times" + else + InternalComponent.InformationValue = "E6 Segment " + (1 + iSegment) + " not found."; + if (Settings.bDebug) System.IO.File.AppendAllText(@"pbchance_Debug.txt", sWriteDebug1); + return; } - } - int firstAttempt = lastAttempt / 2; - if(Settings.UseFixedAttempts) + else fNumberOfCombinations *= (splits[iSegment].Count + lCountSkippedSplits[iSegment]); + + if (Settings.bDebug) // Count of Times per Segment { - // Fixed number of attempts - firstAttempt = lastAttempt - Settings.AttemptCount; - - if (firstAttempt < State.Run.GetMinSegmentHistoryIndex()) + //System.IO.File.AppendAllText(@"pbchance_Debug.txt", sWriteDebug3); + sWriteDebug1 += "\r\n--- Count of Times per Segment --- " + watch.ElapsedMilliseconds + "ms\r\n"; + for (iSegment = iCurrentSplitIndex; iSegment < iMaxSplit; iSegment++) { - firstAttempt = State.Run.GetMinSegmentHistoryIndex(); + double fAvg = 0; + if (iSegment < iMaxSplit) + { + fAvg = 0; + i = 0; + for (iAttempt = 0; iAttempt < splits[iSegment].Count; iAttempt++) + if (splits[iSegment][iAttempt].HasValue) + { + i++; + fAvg += splits[iSegment][iAttempt].Value[tmTimingMethod].Value.TotalMilliseconds; + } + fAvg = fAvg / i; + } + sWriteDebug1 += "Segment: " + iSegment.ToString("00") + " Count of Valid/Total Times: " + lCountSplits[iSegment].ToString("0000") + "/" + splits[iSegment].Count.ToString("0000") + + " Best: " + State.Run[iSegment].BestSegmentTime[tmTimingMethod].Value.TotalSeconds.ToString("000.000") + + " Avg To Best: " + (fAvg * .001 - State.Run[iSegment].BestSegmentTime[tmTimingMethod].Value.TotalMilliseconds * .001).ToString("00.0s") + + " Name: " + State.Run[iSegment].Name + "\r\n"; } + System.IO.File.AppendAllText(@"pbchance_Debug.txt", sWriteDebug1); + + //Write all Segment Times + sWriteDebug2 = "\r\n\r\n\r\n--- Detailed Segment Times ---\r\n"; + for (iSegment = iCurrentSplitIndex; iSegment < iMaxSplit; iSegment++) + { + sWriteDebug2 += " - " + State.Run[iSegment].Name + " -\r\n"; + for (iAttempt = 0; iAttempt < splits[iSegment].Count; iAttempt++) + { + sWriteDebug2 += "Segment: " + iSegment + " Attempt:" + iAttempt.ToString("000") + " Chance: "; + sWriteDebug2 += ((100 - Settings.iSplitsvalue + Settings.iSplitsvalue * (splits[iSegment].Count - iAttempt) / (splits[iSegment].Count + 1.0)) / splits[iSegment].Count / (100 - Settings.iSplitsvalue * .5) * 100.0).ToString("00.0") + "% "; // linear + //sWriteDebug2 += (100 * (iAttempt + 1) / summ(splits[iSegment].Count)).ToString("00.0") + "% "; + if (splits[iSegment][iAttempt].HasValue) + sWriteDebug2 += "Time:" + splits[iSegment][iAttempt].Value[tmTimingMethod].Value + "/" + splits[iSegment][iAttempt].Value[tmTimingMethod].Value.TotalMilliseconds + " Factor: " + Math.Round(splits[iSegment][iAttempt].Value[tmTimingMethod].Value.TotalSeconds / (State.Run[iSegment].BestSegmentTime[tmTimingMethod].Value.TotalSeconds + .0001), 2).ToString("0.00\r\n"); + else + sWriteDebug2 += "Failed\r\n"; + //while (iAttempt / (splits[iSegment].Count * 1.0) < rand.Next(Settings.iSplitsvalue) * .01) ; + } + } + sWriteDebug2 += "\r\nNumber of combinations = " + fNumberOfCombinations + " = " + fNumberOfCombinations.ToString($"F{0}"); + //sWriteDebug1 = "\r\n--- First generated Route (" + Settings.SamplesCount + " Routes in total) --- " + watch.ElapsedMilliseconds + "ms\r\n"; } - else + + /*double*/ fAvgTime = 0; // Calc next average Split Time + if (Settings.bInfoNext || bRndInformationActive) + if (iCurrentSplitIndex < iMaxSplit) + { + i = 0; + for (iAttempt = 0; iAttempt < splits[iCurrentSplitIndex].Count; iAttempt++) + if (splits[iCurrentSplitIndex][iAttempt].HasValue) + { + i++; + fAvgTime += splits[iCurrentSplitIndex][iAttempt].Value[tmTimingMethod].Value.TotalMilliseconds; + } + fAvgTime = fAvgTime / i; + } + + if ((Settings.bDeviation || bRndInformationActive) && iCurrentSplitIndex < iMaxSplit) // Calc Standard Deviation { - // Percentage of attempts - firstAttempt = lastAttempt - runCount * Settings.AttemptCount / 100; - if(firstAttempt < State.Run.GetMinSegmentHistoryIndex()) + double fMean; + if (Settings.bDebug) sWriteDebug2 += "\r\n\r\n--- Standard Deviation ---\r\n"; + for (iSegment = Settings.bDebug ? iMaxSplit - 1 : iCurrentSplitIndex; iSegment >= iCurrentSplitIndex; iSegment--) + //for (iSegment = iCurrentSplitIndex; iSegment >= iCurrentSplitIndex; iSegment--) { - firstAttempt = State.Run.GetMinSegmentHistoryIndex(); + i = 0; + fDeviation = 0; + iSumMsActSplit = 0; + for (iAttempt = 0; iAttempt < splits[iSegment].Count; iAttempt++) + if (splits[iSegment][iAttempt].HasValue) + { + i++; + iSumMsActSplit += splits[iSegment][iAttempt].Value[tmTimingMethod].Value.TotalMilliseconds; + //if(Settings.bDebug) System.IO.File.AppendAllText(@"pbchance_Debug.txt", "+"+ splits[iSegment][iAttempt].Value[tmTimingMethod].Value.TotalMilliseconds+","); + } + fMean = iSumMsActSplit / i; + //if (Settings.bDebug) System.IO.File.AppendAllText(@"pbchance_Debug.txt", " MEAN=" + fMean + " iSumMs=" + iSumMsActSplit + " /i= "+ i); + for (iAttempt = 0; iAttempt < splits[iSegment].Count; iAttempt++) + { + if (splits[iSegment][iAttempt].HasValue) + fDeviation += (splits[iSegment][iAttempt].Value[tmTimingMethod].Value.TotalMilliseconds - fMean) + * (splits[iSegment][iAttempt].Value[tmTimingMethod].Value.TotalMilliseconds - fMean); + //if (Settings.bDebug) System.IO.File.AppendAllText(@"pbchance_Debug.txt", " fDeviation=" + fDeviation); + } + fDeviation = Math.Pow(fDeviation / i, .5) * 0.001; // 0.5 Deviation / 1.0 Variation / Version 2 = fDeviation / (i-1) + //if (Settings.bDebug) System.IO.File.AppendAllText(@"pbchance_Debug.txt", " Wurzel fDeviation /1000 =" + fDeviation); + if (Settings.bDebug) sWriteDebug2 += "Segment: " + iSegment.ToString("00") + " Deviation: " + fDeviation.ToString("0.00") + "\r\n"; } } - // Gather split times - for (int a = firstAttempt; a < lastAttempt; a++) - { - int lastSegment = -1; + // Total Best Time + fTotalBestTime = 0; + for (iSegment = State.CurrentSplitIndex + 1; iSegment < iMaxSplit && State.Run.Count > iSegment; iSegment++) + fTotalBestTime += State.Run[iSegment].BestSegmentTime[tmTimingMethod].Value.TotalMilliseconds * .001; + fTotalBestTime -= Settings.TimediffCount; - // Get split times from a single attempt - for (int segment = 0; segment < State.Run.Count; segment++) + // Get current time as a baseline + Time test = State.CurrentTime; + if (State.CurrentSplitIndex > 0) + { + if (test[tmTimingMethod] == null) test = State.CurrentTime; + test = State.Run[iCurrentSplitIndex - 1].SplitTime; + } + else + test[tmTimingMethod] = TimeSpan.Zero; + if (!bCheckUpdate) + if (test[tmTimingMethod].HasValue) // split hasn't skipped + fSecStart = test[tmTimingMethod].Value.TotalMilliseconds * .001; + else { - if (State.Run[segment].SegmentHistory == null || State.Run[segment].SegmentHistory.Count == 0) - { - InternalComponent.InformationValue = "-"; + if (Settings.bSkipSplitStroke) { InternalComponent.InformationValue = "-"; return; } + if (Settings.bIgnoreSkipClip) return; - } + else // use the actual time, possible to read the skipping time? + fSecStart = State.CurrentTime[tmTimingMethod].Value.TotalMilliseconds * .001; + } + else + fSecStart = State.CurrentTime[tmTimingMethod].Value.TotalMilliseconds * .001; - if (State.Run[segment].SegmentHistory.ContainsKey(a) && State.Run[segment].SegmentHistory[a][State.CurrentTimingMethod] > TimeSpan.Zero) + // Create extended split times for faster calculation + splitsExt = new List[iMaxSplit]; + { + int j, iCount; + for (iSegment = iCurrentSplitIndex; iSegment < iMaxSplit; iSegment++) + { + splitsExt[iSegment] = new List(); + iCount = 0; + for (i = 0; i < splits[iSegment].Count; i++) { - splits[segment].Add(State.Run[segment].SegmentHistory[a]); - lastSegment = segment; + iCount++; + for (j = 0; j < iCount; j++) + splitsExt[iSegment].Add(splits[iSegment][splits[iSegment].Count - i - 1]); } } + } - if (lastSegment < State.Run.Count - 1) + //thread1 = new Thread(new ThreadStart(CheckForPB)); + //thread1.Start(); + + //thread2 = new Thread(new ThreadStart(CheckForPB)); + //thread2.Start(); + + //if (thread1 != null) + // if ((thread.ThreadState & (System.Threading.ThreadState.Stopped | System.Threading.ThreadState.Unstarted)) == 0) + // if (thread1.IsAlive) + // thread1.Join(); + + ////thread2 = new Thread(new ThreadStart(CheckForPB)); + ////thread2.Start(); + + //if (thread2 != null) + // if ((thread2.ThreadState & (System.Threading.ThreadState.Stopped | System.Threading.ThreadState.Unstarted)) == 0) + // if (thread2.IsAlive) + // thread2.Join(); + + //InternalComponent.InformationValue = "H"; + CheckForPB();//return; + //InternalComponent.InformationValue = "I"; + bCalcComplete = true; + DisplayResults(); + } + + + protected void DisplayResults() + { + int iSegment; + + if (iFasterPace > 0) + for (iSegment = 0; iSegment < iMaxSplit; iSegment++) { - // Run didn't finish, add "reset" for the last known split - splits[lastSegment + 1].Add(null); + lSumPBTimes[iSegment] /= 1000.0 * iFasterPace; + lWorstPBTimes[iSegment] /= 1000.0; } - } - // Calculate probability of PB - int success = 0; - for (int i = 0; i < 10000; i++) + if (iCurrentSplitIndex == iMaxSplit) // no more remaining times, check for a new pb + { + InternalComponent.InformationName = "PB Chance"; + InternalComponent.InformationValue = (fSecStart < pb[tmTimingMethod].Value.TotalMilliseconds * .001) ? bCheckUpdate ? InternalComponent.InformationValue : "100% PB" : (fSecStart == pb[tmTimingMethod].Value.TotalMilliseconds * .001) ? "50% PB" : "0%"; + } + else // display results { - // Get current time as a baseline - Time test = State.CurrentTime; - if (test[State.CurrentTimingMethod] < TimeSpan.Zero) + double fProb = iFaster / (iFaster + iSlower + 0.0); + if (State.CurrentSplitIndex == 0 && !bCheckUpdate) // memorize Startingchance + fProbStart = fProb; + + if (bRndInformationActive) { - test[State.CurrentTimingMethod] = TimeSpan.Zero; + displayRndInformation(); + bRndInformationActive = false; + return; } - // Add random split times for each remaining segment - for (int segment = 0; segment < State.Run.Count; segment++) - { - if (segment < State.CurrentSplitIndex) - { - continue; - } + if (bCheckUpdate) + { // background calculation + fLiveChanceAvg = (fLiveChanceAvg > 0) ? (fLiveChanceAvg + fProb) * .5 : fProb; - if(splits[segment].Count == 0) - { - // This split contains no split times, so we cannot calculate a probability - InternalComponent.InformationValue = "-"; + if (fProb > fLiveChanceAvg || fLiveChanceAvg > fLiveChanceAct) // do not display, if chance is higher than the displaying chance //&& !(fProb==0 && fLiveChanceAvg==0 && fLiveChanceAct>0) return; - } - int attempt = rand.Next(splits[segment].Count); - Time? split = splits[segment][attempt]; - if (split == null) - { - // Split is a reset, so count it as a failure - test += pb; - break; - } + if (fProb > 0) + fProb = (fLiveChanceAvg > .1 && fLiveChanceAvg < .9) ? Math.Round(fLiveChanceAvg, 3) : fLiveChanceAvg; // round a place behind the comma, in the range of 10%-90% + } + fLiveChanceAct = fProb; + + // Display additional informations + if (!bCheckUpdate || iFaster == 0 || InternalComponent.InformationName.Remove(2, InternalComponent.InformationName.Length - 2) != "PB") + { + if (Settings.bSurvival && iCurrentSplitIndex < iMaxSplit) // Calculate survival chance + InternalComponent.InformationName = "PB Chance (" + Math.Round(iNextSurvSuc / (iNextSurvSuc + iNextSurvFail + .0) * 100, 0).ToString() + "%/" + + Math.Round(iSurvivalSuccess / (iSurvivalSuccess + iSurvivalFailure + .0) * 100, 0).ToString() + "%)"; + else if (InternalComponent.InformationName != "PB Chance") + InternalComponent.InformationName = "PB Chance"; + if (Settings.bDeviation) // Displaying Deviation + InternalComponent.InformationName += " (" + Math.Round(fDeviation, 2).ToString() + ")"; + if (Settings.bInfoNext && iCurrentSplitIndex < iMaxSplit) + if (State.Run[iCurrentSplitIndex].BestSegmentTime[tmTimingMethod].HasValue) + InternalComponent.InformationName += " (" + (int)(fAvgTime * .001 - State.Run[iCurrentSplitIndex].BestSegmentTime[tmTimingMethod].Value.TotalMilliseconds * .001) + "s " + (iNextSurvFail / (iNextSurvSuc + iNextSurvFail + .0) * 100).ToString("0") + "%)"; + if (Settings.bDispGoodPace && iFasterPace > 0) + if (!Settings.bGoodPaceTotal || iCurrentSplitIndex < 1) + InternalComponent.InformationName += ", " + secondsToTime(lSumPBTimes[iCurrentSplitIndex], Settings.iPaceDigits, true); + else + if (State.Run[iCurrentSplitIndex - 1].SplitTime[tmTimingMethod].HasValue) + InternalComponent.InformationName += ", " + secondsToTime(lSumPBTimes[iCurrentSplitIndex] + State.Run[iCurrentSplitIndex - 1].SplitTime[tmTimingMethod].Value.TotalMilliseconds * .001, Settings.iPaceDigits, true); + if (Settings.bPaceWorst && iFasterPace > 0) + if (!Settings.bGoodPaceTotal || iCurrentSplitIndex < 1) + InternalComponent.InformationName += ", " + secondsToTime(Settings.bPaceWorst ? lWorstPBTimes[iCurrentSplitIndex] : lSumPBTimes[iCurrentSplitIndex], Settings.iPaceDigits, true); + else + if (State.Run[iCurrentSplitIndex - 1].SplitTime[tmTimingMethod].HasValue) + InternalComponent.InformationName += ", " + secondsToTime((Settings.bPaceWorst ? lWorstPBTimes[iCurrentSplitIndex] : lSumPBTimes[iCurrentSplitIndex]) + State.Run[iCurrentSplitIndex - 1].SplitTime[tmTimingMethod].Value.TotalMilliseconds * .001, Settings.iPaceDigits, true); + } + + // Zero success, display 0% instead of 0.00%. If it's <0.01%, it will display the number of success runs and total runs + string text = Settings.DisplayOdds && fProb < .0000100055 && fProb > 0 ? "" : (fProb > 0 && fProb < .0001 && !bCheckUpdate && !Settings.DisplayOdds) ? iFaster + " in " + (iFaster + iSlower) : fProb == 0 ? "0%" : (fProb * 100).ToString("0.00") + "%"; + + if (Settings.DisplayOdds && fProb > 0 && (fProb >= 0.00000001 || bCheckUpdate)) // Displaying odds + if (bCheckUpdate) + text = "1 : " + RoundExtended(1 / fProb, fProb > 0.000001 ? fProb > 0.00001 ? fProb > 0.0001 ? fProb > 0.001 ? fProb > 0.01 ? fProb > .05 ? fProb > .25 ? 2 : 1 : 0 : -1 : -2 : -3 : -4 : -5).ToString(fProb > .000100055 ? fProb > .00100055 ? fProb > .010055 ? fProb > .100055 ? fProb > .91 ? fProb > .9999 ? "0 " : "0.00 " : "0.00 " : "0.0 " : "0 " : "0 " : "0") + (fProb > .00000100055 ? fProb > .0000100055 ? "" : " 0%" : " 0%") + (fProb >= .1 ? fProb == 1 ? "" : "" : " ") + text; + // text = "1 in " + RoundExtended(1 / fProb, fProb > 0.0000002 ? fProb > 0.000002 ? fProb > 0.00002 ? fProb > 0.0002 ? fProb > 0.002 ? fProb > .02 ? fProb > .2 ? 3 : 1 : 0 : -1 : -2 : -3 : -4 : -5).ToString(fProb > .0100055 ? fProb > .100055 ? fProb > .91 ? fProb == 1 ? "0 " : "0.00 " : "0.00" : "0.0" : "0") + (fProb > .000100055 ? fProb > .00100055 ? fProb > .0100055 ? fProb > .100055 ? fProb > .91 ? fProb == 1 ? " " : "" : " " : " " : " " : " " : "") + "" + (fProb >= .1 ? fProb == 1 ? "" : "" : " ") + text; //.ToString(fProb > .0100055 ? fProb > .100055 ? fProb > .91 ? fProb == 1 ? "0" : "0.000" : "0.00" : "0.0" : "0") + " | " + text; else - { - // Add the split time - test += split.Value; - } + text = "1 in " + (1 / fProb).ToString(fProb > .000100055 ? fProb > .00100055 ? fProb > .0100055 ? fProb > .100055 ? fProb > .91 ? fProb > .9999 ? "0 " : "0.00 " : "0.00 " : "0.0 " : "0 " : "0 " : "0") + (fProb > .00000100055 ? fProb > .0000100055 ? "" : " 0%" : " 0%") + (fProb >= .1 ? fProb == 1 ? "" : "" : " ") + text; + + /* + if (Settings.bSurvival && iCurrentSplitIndex < iMaxSplit) // Calculate survival chance + { + //text += " / " + Math.Round(iSurvivalSuccess / (iSurvivalSuccess + iSurvivalFailure + .0) * 100, 0).ToString() + "%"; // Chance to finish the run + text += " / " + iSurvivalSuccess + "*" + iSurvivalFailure + "*" + iNextSurvSuc + "*" + iNextSurvFail; // Chance to finish the run + //+ (iCurrentSplitIndex+1 < iMaxSplit ? "|" + lCountSplits[iCurrentSplitIndex + 1] + "-" + splits[iCurrentSplitIndex + 1].Count + "-" + Math.Round(lCountSplits[iCurrentSplitIndex+1] / (splits[iCurrentSplitIndex+1].Count + .0) * 100, 0).ToString() :"") + ")%"; // next Split Chance + //if (InternalComponent.InformationName != "PB / Survival Chance") InternalComponent.InformationName = "PB / Survival Chance"; + }*/ + if (Settings.bDebug) + { + sWriteDebug1 += "\r\n\r\n" + InternalComponent.InformationName + ": " + text + " SuccessCount: " + iFaster + " FailCount: " + iSlower + " MalusCount: " + iCountMalus + "\r\n\r\nExecution time: " + watch.ElapsedMilliseconds + "ms"; + System.IO.File.AppendAllText(@"pbchance_Debug.txt", sWriteDebug1 + sWriteDebug2); + Settings.bDebug = false; } - if (test[State.CurrentTimingMethod] < pb[State.CurrentTimingMethod]) + //InternalComponent.InformationName = fTotalBestTime + " + " + Settings.TimediffCount /*+ " + " + State.CurrentTime[tmTimingMethod].Value.TotalMilliseconds * .001*/ + " <= " + -fSecStart + " + " + pb[tmTimingMethod].Value.TotalMilliseconds * .001 + " + " + Settings.TimediffCount; + //text += "\t"; + InternalComponent.InformationValue = text; + + sInformationAlternative = new string[] + { + "PB Ch." + InternalComponent.InformationName.Remove(0, InternalComponent.InformationName.Length > 9 ? 9 : InternalComponent.InformationName.Length), + "PB" + InternalComponent.InformationName.Remove(0, InternalComponent.InformationName.Length > 9 ? 9 : InternalComponent.InformationName.Length), + "PB Chance", + "PB Ch.", + "PB" + }; + InternalComponent.AlternateNameText = sInformationAlternative; + + updateDataTable(); + } + + sInformationName = InternalComponent.InformationName; + sInformationValue = InternalComponent.InformationValue; + bCalcComplete = false; + } + + private void updateDataTable() + { + double fSum = State.CurrentTime[tmTimingMethod].Value.TotalMilliseconds * .001, + fSumWorst = State.CurrentTime[tmTimingMethod].Value.TotalMilliseconds * .001, + fActSum=State.CurrentTime[tmTimingMethod].Value.TotalMilliseconds * .001; + int iSegment; + System.Data.DataTable dataTable1 = new System.Data.DataTable(); + + dataTable1.Rows.Clear(); + dataTable1.Columns.Clear(); + dataTable1.Columns.Add("Segment Name", typeof(string), null); + dataTable1.Columns.Add("Split Time", typeof(string), null); + dataTable1.Columns.Add("Avg Pace", typeof(string), null); + dataTable1.Columns.Add("Worst Pace", typeof(string), null); + dataTable1.Columns.Add("Best Segment", typeof(string), null); + //dataTable1.Rows.Add(new string[] { "PB chance", (100 * fProb).ToString("0.00") + "%" }); + + if (iFasterPace > 0) + { + //for (iSegment = iMaxSplit; iSegment > iCurrentSplitIndex && iSegment > 0; iSegment--) + // lSumPBTimes[iSegment] -= lSumPBTimes[iSegment - 1]; + iMaxSplit = (Settings.iCalcToSplit == 0 || Settings.iCalcToSplit > State.Run.Count) ? State.Run.Count : Settings.iCalcToSplit; + for (iSegment = iCurrentSplitIndex; iSegment < iMaxSplit; iSegment++) { - success++; + if(lSumPBTimes.Length>iSegment) fSum += lSumPBTimes[iSegment]; + if(lWorstPBTimes.Length > iSegment) fSumWorst += lWorstPBTimes[iSegment]; } + dataTable1.Rows.Add(new string[] { "Faster/Extra Goal/Total", iFaster.ToString("#,##0"), iFasterPace.ToString("#,##0"), (iFaster+iSlower).ToString("#,##0") }); + dataTable1.Rows.Add(new string[] { "PB Regular/Extra Goal", (1.0*iFaster / (iFaster + iSlower)).ToString("0.00%"), (iFasterPace / (iFaster + iSlower * 1.0)).ToString("0.00%") }); + dataTable1.Rows.Add(new string[] { "Total Time", secondsToTime(fSum, 3, false), secondsToTime(fSum, 3, false), secondsToTime(fSumWorst, 3, false), secondsToTime(fTotalBestTime, 3, false) }); + for (iSegment = iCurrentSplitIndex; iSegment < iMaxSplit && iSegment < State.Run.Count; iSegment++) + if (State.Run[iSegment].BestSegmentTime[tmTimingMethod].HasValue && lSumPBTimes.Length > iSegment && lWorstPBTimes.Length > iSegment) + { + fActSum += lSumPBTimes[iSegment]; + dataTable1.Rows.Add(new string[] { State.Run[iSegment].Name, + secondsToTime(fActSum, 1, false), + secondsToTime(lSumPBTimes[iSegment], 1, false), + secondsToTime(lWorstPBTimes[iSegment], 1, false), + secondsToTime(State.Run[iSegment].BestSegmentTime[tmTimingMethod].Value.TotalMilliseconds*.001,1, false) }); + } + } + else + dataTable1.Rows.Add(new string[] { "No PB found", "0", (iFaster + iSlower).ToString("#,##0"), secondsToTime(fTotalBestTime, 3, false) }); + + Settings.DataGridViewV = dataTable1; + Settings.viewUpdateDisplay(); + } + + void displayRndInformation() + { + double fProb = iFaster / (iFaster + iSlower + 0.0); + string[] sBaseText = new string[] { "PB Chance" }; + Random random = new Random(); + int iRandom; + + TryAgain: + { + iRandom = random.Next(1, 17); + if (random.Next(1, 4) == 1 && !Settings.bDispGoodPace) + iRandom = 11; // 25% chance Pace to PB, if it isn't displayed } + //iRandom = 6; - double prob = success / 10000.0; - string text = (prob * 100.0).ToString() + "%"; - if (Settings.DisplayOdds && prob > 0) + switch (iRandom) { - text += " (1 in " + Math.Round(1 / prob, 2).ToString() + ")"; + case 1: + if (random.Next(0, 100) < 50) goto TryAgain; // half chance + sBaseText = new string[] { "Remaining Combinations", "Remaining Comb.", "Combinations", "Comb." }; + InternalComponent.InformationValue = getLargeNumber(fNumberOfCombinations); + break; + case 2: + sBaseText = new string[] { "Sample Size", "Sample", "Size" }; + InternalComponent.InformationValue = (iFaster + iSlower).ToString("#,##0") + " in " + (((double)watch.ElapsedMilliseconds) * .001).ToString("0.00s"); + break; + case 3: + sBaseText = new string[] { "Survival in this Segment", "Survival this Segment", "Survival here", "Surv. here" }; + InternalComponent.InformationValue = /*iNextSurvSuc + " of " + (iNextSurvSuc + iNextSurvFail) + " = " +*/ (iNextSurvSuc / (iNextSurvSuc + iNextSurvFail + 0.0)).ToString("0.00%"); + break; + case 4: + if (random.Next(0, 100) < 66) goto TryAgain; // 2/3 chance + sBaseText = new string[] { "Survival to the End", "Survival to End", "Survival End", "Surv. End" }; + InternalComponent.InformationValue = /*iSurvivalSuccess + "/" + (iSurvivalSuccess + iSurvivalFailure + iSurvivalFailurePast) + " = " +*/ (iSurvivalSuccess / (iSurvivalSuccess + iSurvivalFailure + 0.0)).ToString("0.00%"); + break; + case 5: + if (random.Next(0, 100) < 33) goto TryAgain; // 1/3 chance + sBaseText = new string[] { "Standard Deviation", "Std Deviation", "Std Dev." }; + InternalComponent.InformationValue = fDeviation.ToString("0.00s"); + break; + case 6: + if (random.Next(0, 100) < 50) goto TryAgain; // 1/2 chance + sBaseText = new string[] { "Average Difference to Best", "Avg Difference to Best", "Avg Difference Best", "Avg Dif. to Best", "Avg Dif. Best" }; + InternalComponent.InformationValue = (fAvgTime * .001 - State.Run[iCurrentSplitIndex].BestSegmentTime[tmTimingMethod].Value.TotalMilliseconds * .001).ToString("0.0s"); + break; + case 7: + if (iCurrentSplitIndex == 0) + goto TryAgain; + sBaseText = new string[] { "Until here has Survived", "Until here Survived", "Until here Surv." }; + InternalComponent.InformationValue = /*iSurvToHereCount + " of " + (iLastAttempt - iSurvToHereAttempt + 1) + " = " +*/ (iSurvToHereCount / (iLastAttempt - iSurvToHereAttempt + 1.0)).ToString("0.00%"); + break; + case 8: + if (watch.ElapsedMilliseconds == 0) goto TryAgain; + if (random.Next(0, 100) < 10) goto TryAgain; // 1/10 chance, case 2 doing similar + sBaseText = new string[] { "Combinations per Second", "Comb. per Second", "Comb. / Second", "Comb. / Sec", "Comb./s" }; + InternalComponent.InformationValue = ((double)(1000 * (iFaster + iSlower + 0.0) / watch.ElapsedMilliseconds)).ToString("#,##0") /*+ "*" + iFaster + "*" + iSlower + "*" + watch.ElapsedMilliseconds*/; + break; + case 9: + if (fProbStart == 0 || iFaster == 0) goto TryAgain; + double f = fProb / fProbStart * pb[tmTimingMethod].Value.TotalMilliseconds / (pb[tmTimingMethod].Value.TotalMilliseconds - State.CurrentTime[tmTimingMethod].Value.TotalMilliseconds); + sBaseText = new string[] { "Worth to continue", "Continue" }; + InternalComponent.InformationValue = (f > 2 ? "sure" : f > 1.5 ? "yes" : f > 1.0 ? "think so" : f > 0.75 ? "equal" : f > .5 ? "maybe not" : "no") + " " + f.ToString("[x0.0]"); + //InternalComponent.InformationValue = f.ToString(", x0.0 - ") + pb[tmTimingMethod].Value.TotalMilliseconds.ToString("0 - ") + State.CurrentTime[tmTimingMethod].Value.TotalMilliseconds.ToString("0 - ") + (fProb / fProbStart).ToString("0"); + break; + case 10: + if (fProbStart == 0 || fProbStart == 0) goto TryAgain; + if (random.Next(0, 100) < 75) goto TryAgain; // 3/4 chance + double fFact = Math.Pow(10, Math.Log10(25 / fProbStart) / iMaxSplit); // 25% goal + fFact = Math.Pow(fFact, iCurrentSplitIndex); + f = fProb / fFact / fProbStart * pb[tmTimingMethod].Value.TotalMilliseconds / (pb[tmTimingMethod].Value.TotalMilliseconds - fSecStart); + sBaseText = new string[] { "Health Status", "Health" }; // Run is currently + InternalComponent.InformationValue = f > 1 ? (f > 2 ? "very good" : f > 1.5 ? "good" : f > 1 ? "above average" : f > 0.5 ? "average" : f > .25 ? "below average" : "bad") + " " + f.ToString("[x0.0]") : f.ToString("0.00%"); + //InternalComponent.InformationValue = f1.ToString("x0.0 ") + fFact.ToString("x0.0 ") + f.ToString(", x0.0"); + break; + case 11: + if (iFasterPace == 0) goto TryAgain; + if (Settings.iPaceExtraGoalMS == 0) + sBaseText = new string[] { "Pace to PB", "PB Pace", "Pace" }; + else + sBaseText = new string[] { "Pace to PB (" + secondsToTime((pb[tmTimingMethod].Value.TotalMilliseconds - Settings.iPaceExtraGoalMS) * .001, 0, true) + ")", + "PB Pace (" + secondsToTime((pb[tmTimingMethod].Value.TotalMilliseconds - Settings.iPaceExtraGoalMS) * .001, 0, true) + ")", + "Pace (" + secondsToTime((pb[tmTimingMethod].Value.TotalMilliseconds - Settings.iPaceExtraGoalMS) * .001, 0, true) + ")", "Pace to PB", "PB Pace", "Pace" }; + if (iCurrentSplitIndex > 0) + { + if(State.Run[iCurrentSplitIndex - 1].SplitTime[tmTimingMethod].HasValue) + InternalComponent.InformationValue = secondsToTime(lSumPBTimes[iCurrentSplitIndex], 0, true) + " / " + secondsToTime(lSumPBTimes[iCurrentSplitIndex] + State.Run[iCurrentSplitIndex - 1].SplitTime[tmTimingMethod].Value.TotalMilliseconds * .001, 0, true); + else + goto TryAgain; + } + else + InternalComponent.InformationValue = secondsToTime(lSumPBTimes[0], 0, true) + " / " + secondsToTime((lSumPBTimes[0]), 0, true); + break; + case 12: + if (iFasterPace == 0) goto TryAgain; + if (random.Next(0, 100) < 25) goto TryAgain; // 1/4 chance + sBaseText = new string[] { "Average Difference to Best (All/Suc)", "Avg Difference to Best (All/Suc)", "Avg Dif to Best (All/Suc)", "Avg Dif to Best", "Avg Dif Best" }; + InternalComponent.InformationValue = (fAvgTime * .001 - State.Run[iCurrentSplitIndex].BestSegmentTime[tmTimingMethod].Value.TotalMilliseconds * .001).ToString("0.0s") + + " / " + (lSumPBTimes[iCurrentSplitIndex] - State.Run[iCurrentSplitIndex].BestSegmentTime[tmTimingMethod].Value.TotalMilliseconds * .001).ToString("0.0s"); + break; + case 13: + if (iFasterPace == 0) goto TryAgain; + if (random.Next(0, 100) < 10) goto TryAgain; // 1/10 chance + sBaseText = new string[] { "Worst Pace to PB", "Worst PB Pace", "Worst Pace" }; + if (iCurrentSplitIndex > 0) + { + if (State.Run[iCurrentSplitIndex - 1].SplitTime[tmTimingMethod].HasValue) + InternalComponent.InformationValue = secondsToTime(lWorstPBTimes[iCurrentSplitIndex], 0, true) + " / " + secondsToTime(lWorstPBTimes[iCurrentSplitIndex] + State.Run[iCurrentSplitIndex - 1].SplitTime[tmTimingMethod].Value.TotalMilliseconds * .001, 0, true); + else + goto TryAgain; + } + else + InternalComponent.InformationValue = secondsToTime(lWorstPBTimes[0], 0, true) + " / " + secondsToTime((lWorstPBTimes[0]), 0, true); + break; + case 14: + if (iFasterPace == 0) goto TryAgain; + if (random.Next(0, 100) < 25) goto TryAgain; // 1/4 chance + sBaseText = new string[] { "Average/Worst Pace to PB", "Avg/Worst Pace to PB", "Avg/Worst PB Pace", "Avg/Worst Pace" }; + if(iCurrentSplitIndex>0) + if (State.Run[iCurrentSplitIndex - 1].SplitTime[tmTimingMethod].HasValue) + InternalComponent.InformationValue = secondsToTime( lSumPBTimes[iCurrentSplitIndex] + State.Run[iCurrentSplitIndex - 1].SplitTime[tmTimingMethod].Value.TotalMilliseconds * .001, 0, true) + + " / " + secondsToTime(lWorstPBTimes[iCurrentSplitIndex] + State.Run[iCurrentSplitIndex - 1].SplitTime[tmTimingMethod].Value.TotalMilliseconds * .001, 0, true); + else + goto TryAgain; + else + InternalComponent.InformationValue = secondsToTime(lSumPBTimes[iCurrentSplitIndex], 0, true) + " / " + secondsToTime(lWorstPBTimes[iCurrentSplitIndex], 0, true); + break; + case 15: + if (iCurrentSplitIndex == 0) goto TryAgain; // 1/2 chance + sBaseText = new string[] { "Considered Runs (here/end)", "Consid. Runs (here/end)", "Considered Runs", "Consid. Runs", "Cons. Runs" }; + InternalComponent.InformationValue = (iLastAttempt - iSurvToHereAttempt + 1) + "/" + (iSurvivalSuccess + iSurvivalFailure + iSurvivalFailurePast) + " of " + State.Run.AttemptHistory.Count; + //InternalComponent.InformationValue = (iLastAttempt-lOldestAttempt[iCurrentSplitIndex]) + " Ö " + (iLastAttempt - lOldestAttempt[iMaxSplit-1]) + " Ö " + (iLastAttempt - iSurvToHereAttempt + 1) + "/" + (iSurvivalSuccess + iSurvivalFailure + iSurvivalFailurePast) + " of " + State.Run.AttemptHistory.Count; + //lOldestAttempt[iSegment] + break; + case 16: + if (random.Next(0, 100) < 20) goto TryAgain; // 1/5 chance + sBaseText = new string[] { "Github.com/kasi777/PBChance" }; + InternalComponent.InformationValue = ""; + break; + case 17: + if (Settings.iPaceExtraGoalMS==0) goto TryAgain; + sBaseText = new string[] { "PB Chance Extra Goal (" + secondsToTime((pb[tmTimingMethod].Value.TotalMilliseconds - Settings.iPaceExtraGoalMS) * .001, 0, true) + ")", + "Chance Extra Goal (" + secondsToTime((pb[tmTimingMethod].Value.TotalMilliseconds - Settings.iPaceExtraGoalMS) * .001, 0, true) + ")", + "Chance Goal (" + secondsToTime((pb[tmTimingMethod].Value.TotalMilliseconds - Settings.iPaceExtraGoalMS) * .001, 0, true) + ")", + "Goal (" + secondsToTime((pb[tmTimingMethod].Value.TotalMilliseconds - Settings.iPaceExtraGoalMS) * .001, 0, true) + ")" }; + InternalComponent.InformationValue = (iFasterPace/(iFaster+iSlower)).ToString("0.00%"); + break; } - InternalComponent.InformationValue = text; + InternalComponent.AlternateNameText = sBaseText; + InternalComponent.InformationName = sBaseText[0]; } void IComponent.DrawHorizontal(Graphics g, LiveSplitState state, float height, Region clipRegion) @@ -269,16 +1241,120 @@ void IComponent.Update(IInvalidator invalidator, LiveSplitState state, float wid string newCategory = State.Run.GameName + State.Run.CategoryName; if (newCategory != category) { - Recalculate(); + StartRecalculate(true); category = newCategory; } - + + //InternalComponent.InformationName = State.CurrentTime[tmTimingMethod].Value.TotalMilliseconds*.001 + "s"; + // check the update frequency + /*if (bCalcComplete) + DisplayResults(); + else*/ + if (Math.Abs(fLastUpdate - State.CurrentTime[tmTimingMethod].Value.TotalMilliseconds) >= Settings.iUpdate * 1000) + { + double fTimer = 0, fBestSegmentTime = 0, fSplitTime = 0; + int iCurrentSplitIndex = State.CurrentSplitIndex; + fLastUpdate = State.CurrentTime[tmTimingMethod].Value.TotalMilliseconds; + + if (iCurrentSplitIndex >= 1) // calculate the actual split time + if (State.Run[iCurrentSplitIndex - 1].SplitTime[tmTimingMethod].HasValue) + //if (State.CurrentTime[tmTimingMethod].HasValue) // seems this is not necessary + { + fSplitTime = State.Run[iCurrentSplitIndex - 1].SplitTime[tmTimingMethod].Value.TotalMilliseconds; + fTimer = State.CurrentTime[tmTimingMethod].Value.TotalMilliseconds - fSplitTime; + } + else fTimer = State.CurrentTime[tmTimingMethod].Value.TotalMilliseconds; // determination of split time isn't possible now + else fTimer = State.CurrentTime[tmTimingMethod].Value.TotalMilliseconds; + + //InternalComponent.InformationName = secondsToTime(fTimer/1000,3); // Test actual Timer + + // background calculation, if actual split time is slower than best split time, and the actual chance is > 0 + if (iCurrentSplitIndex > -1) + + if (State.Run[iCurrentSplitIndex].BestSegmentTime[tmTimingMethod].HasValue) + { + if (thread == null || thread.ThreadState != System.Threading.ThreadState.Running) // do it if the thread isn't running + //if(bCalcComplete) + { + fBestSegmentTime = State.Run[iCurrentSplitIndex].BestSegmentTime[tmTimingMethod].Value.TotalMilliseconds; + if (fTimer > fBestSegmentTime && fLiveChanceAct > 0) + { + KeepAlive = true; + bCheckUpdate = true; // tell Recalculate(), that's a background calculation + bRndInformationOn = false; + thread = new Thread(new ThreadStart(Recalculate)); + thread.Start(); + //Recalculate(); + } + else if (Settings.iRndInfoEvery > 0) + { + if (fTimer > 10000 && (fTimer < fBestSegmentTime - 11000 || fLiveChanceAct == 0) && !bRndInformationOn && + (fLastUpdate * .001 - Settings.iRndInfoFor + Settings.iRndInfoEvery / 2) % Settings.iRndInfoEvery > Settings.iRndInfoEvery - Settings.iRndInfoFor) + { // display a random information + if (InternalComponent.InformationName.Remove(2, InternalComponent.InformationName.Length - 2) == "PB") + { + bRndInformationOn = true; + KeepAlive = true; + bRndInformationActive = true; + thread = new Thread(new ThreadStart(Recalculate)); + thread.Start(); + //Recalculate(); + } + else + { + sInformationName = InternalComponent.InformationName; + sInformationValue = InternalComponent.InformationValue; + StartRecalculate(true); + } + } + else if (bRndInformationOn && ((fLastUpdate * .001 - Settings.iRndInfoEvery / 2) % Settings.iRndInfoEvery > Settings.iRndInfoFor + || (fTimer > fBestSegmentTime - 10000 && fLiveChanceAct > 0))) + { + InternalComponent.InformationName = sInformationName; + InternalComponent.InformationValue = sInformationValue; + InternalComponent.AlternateNameText = sInformationAlternative; + bRndInformationOn = false; + } + } + else + { + if (fTimer > fBestSegmentTime / 2 - 1000 * Settings.iRndInfoFor / 2 && fTimer > 10000 && fTimer < fBestSegmentTime - 10000 && + fTimer < fBestSegmentTime / 2 + 1000 * Settings.iRndInfoFor / 2 && !bRndInformationOn) + { // display a random information + if (InternalComponent.InformationName.Remove(2, InternalComponent.InformationName.Length - 2) == "PB") + { + bRndInformationOn = true; + KeepAlive = true; + bRndInformationActive = true; + thread = new Thread(new ThreadStart(Recalculate)); + thread.Start(); + //Recalculate(); + } + else + { + sInformationName = InternalComponent.InformationName; + sInformationValue = InternalComponent.InformationValue; + StartRecalculate(true); + } + } + else if ((fTimer > fBestSegmentTime / 2 + 1000 * Settings.iRndInfoFor / 2 || fTimer > fBestSegmentTime - 10000) && bRndInformationOn) + { + InternalComponent.InformationName = sInformationName; + InternalComponent.InformationValue = sInformationValue; + InternalComponent.AlternateNameText = sInformationAlternative; + bRndInformationOn = false; + } + } + } + } + } + InternalComponent.Update(invalidator, state, width, height, mode); } void IDisposable.Dispose() { - + } } } diff --git a/PBChance/UI/Components/PBChanceFactory.cs b/PBChance/UI/Components/PBChanceFactory.cs index c27da42..47b7fe0 100644 --- a/PBChance/UI/Components/PBChanceFactory.cs +++ b/PBChance/UI/Components/PBChanceFactory.cs @@ -22,6 +22,6 @@ class PBChanceFactory : IComponentFactory public string UpdateURL => "http://livesplit.org/update/"; - public Version Version => Version.Parse("0.1.1"); + public Version Version => Version.Parse("1.4.3"); } } diff --git a/PBChance/UI/Components/PBChanceSettings.Designer.cs b/PBChance/UI/Components/PBChanceSettings.Designer.cs index 8b0c2b5..7de9d1f 100644 --- a/PBChance/UI/Components/PBChanceSettings.Designer.cs +++ b/PBChance/UI/Components/PBChanceSettings.Designer.cs @@ -29,52 +29,146 @@ protected override void Dispose(bool disposing) private void InitializeComponent() { this.RecentLabel = new System.Windows.Forms.Label(); - this.PercentOfAttempts = new System.Windows.Forms.RadioButton(); - this.FixedAttempts = new System.Windows.Forms.RadioButton(); this.AttemptCountBox = new System.Windows.Forms.NumericUpDown(); - this.CreditsLabel = new System.Windows.Forms.Label(); this.DisplayOddsCheckbox = new System.Windows.Forms.CheckBox(); this.IgnoreRunCountBox = new System.Windows.Forms.CheckBox(); + this.MalusCountBox = new System.Windows.Forms.NumericUpDown(); + this.SplitclipCountBox = new System.Windows.Forms.NumericUpDown(); + this.label3 = new System.Windows.Forms.Label(); + this.label4 = new System.Windows.Forms.Label(); + this.label5 = new System.Windows.Forms.Label(); + this.label6 = new System.Windows.Forms.Label(); + this.label7 = new System.Windows.Forms.Label(); + this.TimediffCountBox = new System.Windows.Forms.NumericUpDown(); + this.label8 = new System.Windows.Forms.Label(); + this.label9 = new System.Windows.Forms.Label(); + this.label11 = new System.Windows.Forms.Label(); + this.label14 = new System.Windows.Forms.Label(); + this.btnDebug = new System.Windows.Forms.Button(); + this.label17 = new System.Windows.Forms.Label(); + this.label18 = new System.Windows.Forms.Label(); + this.label19 = new System.Windows.Forms.Label(); + this.label30 = new System.Windows.Forms.Label(); + this.SkipNewestCountBox = new System.Windows.Forms.NumericUpDown(); + this.label2 = new System.Windows.Forms.Label(); + this.label32 = new System.Windows.Forms.Label(); + this.CalcToSplitUpDown = new System.Windows.Forms.NumericUpDown(); + this.label34 = new System.Windows.Forms.Label(); + this.label35 = new System.Windows.Forms.Label(); + this.label10 = new System.Windows.Forms.Label(); + this.label13 = new System.Windows.Forms.Label(); + this.SamplesCountBox = new System.Windows.Forms.NumericUpDown(); + this.label15 = new System.Windows.Forms.Label(); + this.chkSurvival = new System.Windows.Forms.CheckBox(); + this.chkExpSplitsvalue = new System.Windows.Forms.CheckBox(); + this.MinTimesCountBox = new System.Windows.Forms.NumericUpDown(); + this.label24 = new System.Windows.Forms.Label(); + this.label25 = new System.Windows.Forms.Label(); + this.SplitsvalueCountBox = new System.Windows.Forms.NumericUpDown(); + this.label26 = new System.Windows.Forms.Label(); + this.UpdateCountBox = new System.Windows.Forms.NumericUpDown(); + this.label27 = new System.Windows.Forms.Label(); + this.label28 = new System.Windows.Forms.Label(); + this.label29 = new System.Windows.Forms.Label(); + this.label33 = new System.Windows.Forms.Label(); + this.rdoAbsAttempt = new System.Windows.Forms.RadioButton(); + this.rdoPercentAttempt = new System.Windows.Forms.RadioButton(); + this.CalctimeCountBox = new System.Windows.Forms.NumericUpDown(); + this.lblCalctime2 = new System.Windows.Forms.Label(); + this.lblCalctime1 = new System.Windows.Forms.Label(); + this.chkIgnoreSkipClip = new System.Windows.Forms.CheckBox(); + this.chkDeviation = new System.Windows.Forms.CheckBox(); + this.chkInfoNext = new System.Windows.Forms.CheckBox(); + this.label37 = new System.Windows.Forms.Label(); + this.label16 = new System.Windows.Forms.Label(); + this.chkConsiderFails = new System.Windows.Forms.CheckBox(); + this.label20 = new System.Windows.Forms.Label(); + this.RndInfoEveryCountBox = new System.Windows.Forms.NumericUpDown(); + this.label21 = new System.Windows.Forms.Label(); + this.RndInfoForCountBox = new System.Windows.Forms.NumericUpDown(); + this.label22 = new System.Windows.Forms.Label(); + this.btnNewVersion = new System.Windows.Forms.Button(); + this.label23 = new System.Windows.Forms.Label(); + this.AddBestCountBox = new System.Windows.Forms.NumericUpDown(); + this.label38 = new System.Windows.Forms.Label(); + this.label40 = new System.Windows.Forms.Label(); + this.btnUpdList = new System.Windows.Forms.Button(); + this.dataGridView1 = new System.Windows.Forms.DataGridView(); + this.chkDispGoodPace = new System.Windows.Forms.CheckBox(); + this.chkGoodPaceTotal = new System.Windows.Forms.CheckBox(); + this.label39 = new System.Windows.Forms.Label(); + this.chkPaceWorst = new System.Windows.Forms.CheckBox(); + this.label41 = new System.Windows.Forms.Label(); + this.label42 = new System.Windows.Forms.Label(); + this.PaceExtraGoalMSCountBox = new System.Windows.Forms.NumericUpDown(); + this.label43 = new System.Windows.Forms.Label(); + this.MalusMaxCountBox = new System.Windows.Forms.NumericUpDown(); + this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.label12 = new System.Windows.Forms.Label(); + this.label1 = new System.Windows.Forms.Label(); + this.PaceDigitsCountBox = new System.Windows.Forms.NumericUpDown(); + this.groupBox2 = new System.Windows.Forms.GroupBox(); + this.label44 = new System.Windows.Forms.Label(); + this.groupBox3 = new System.Windows.Forms.GroupBox(); + this.groupBox4 = new System.Windows.Forms.GroupBox(); + this.label31 = new System.Windows.Forms.Label(); + this.groupBox5 = new System.Windows.Forms.GroupBox(); + this.chkSkipSplitStroke = new System.Windows.Forms.CheckBox(); + this.tabPages = new System.Windows.Forms.TabControl(); + this.tabPage1 = new System.Windows.Forms.TabPage(); + this.groupBox6 = new System.Windows.Forms.GroupBox(); + this.tabPage2 = new System.Windows.Forms.TabPage(); + this.tabPage3 = new System.Windows.Forms.TabPage(); + this.label46 = new System.Windows.Forms.Label(); + this.label45 = new System.Windows.Forms.Label(); + this.label36 = new System.Windows.Forms.Label(); + this.lblFaster = new System.Windows.Forms.Label(); + this.lblSampleSize = new System.Windows.Forms.Label(); + this.lblChance = new System.Windows.Forms.Label(); ((System.ComponentModel.ISupportInitialize)(this.AttemptCountBox)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.MalusCountBox)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.SplitclipCountBox)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.TimediffCountBox)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.SkipNewestCountBox)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.CalcToSplitUpDown)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.SamplesCountBox)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.MinTimesCountBox)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.SplitsvalueCountBox)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.UpdateCountBox)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.CalctimeCountBox)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.RndInfoEveryCountBox)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.RndInfoForCountBox)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.AddBestCountBox)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.dataGridView1)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.PaceExtraGoalMSCountBox)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.MalusMaxCountBox)).BeginInit(); + this.groupBox1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.PaceDigitsCountBox)).BeginInit(); + this.groupBox2.SuspendLayout(); + this.groupBox3.SuspendLayout(); + this.groupBox4.SuspendLayout(); + this.groupBox5.SuspendLayout(); + this.tabPages.SuspendLayout(); + this.tabPage1.SuspendLayout(); + this.groupBox6.SuspendLayout(); + this.tabPage2.SuspendLayout(); + this.tabPage3.SuspendLayout(); this.SuspendLayout(); // // RecentLabel // this.RecentLabel.AutoSize = true; - this.RecentLabel.Location = new System.Drawing.Point(3, 41); + this.RecentLabel.Location = new System.Drawing.Point(6, 35); this.RecentLabel.Name = "RecentLabel"; this.RecentLabel.Size = new System.Drawing.Size(87, 13); this.RecentLabel.TabIndex = 1; this.RecentLabel.Text = "Use most recent:"; // - // PercentOfAttempts - // - this.PercentOfAttempts.AutoSize = true; - this.PercentOfAttempts.Checked = true; - this.PercentOfAttempts.Location = new System.Drawing.Point(150, 32); - this.PercentOfAttempts.Name = "PercentOfAttempts"; - this.PercentOfAttempts.Size = new System.Drawing.Size(118, 17); - this.PercentOfAttempts.TabIndex = 2; - this.PercentOfAttempts.TabStop = true; - this.PercentOfAttempts.Text = "Percent of Attempts"; - this.PercentOfAttempts.UseVisualStyleBackColor = true; - // - // FixedAttempts - // - this.FixedAttempts.AutoSize = true; - this.FixedAttempts.Location = new System.Drawing.Point(150, 55); - this.FixedAttempts.Name = "FixedAttempts"; - this.FixedAttempts.Size = new System.Drawing.Size(66, 17); - this.FixedAttempts.TabIndex = 3; - this.FixedAttempts.TabStop = true; - this.FixedAttempts.Text = "Attempts"; - this.FixedAttempts.UseVisualStyleBackColor = true; - // // AttemptCountBox // - this.AttemptCountBox.Location = new System.Drawing.Point(93, 39); + this.AttemptCountBox.Location = new System.Drawing.Point(94, 28); this.AttemptCountBox.Maximum = new decimal(new int[] { - 999999, + 99999, 0, 0, 0}); @@ -84,7 +178,7 @@ private void InitializeComponent() 0, 0}); this.AttemptCountBox.Name = "AttemptCountBox"; - this.AttemptCountBox.Size = new System.Drawing.Size(51, 20); + this.AttemptCountBox.Size = new System.Drawing.Size(52, 20); this.AttemptCountBox.TabIndex = 1; this.AttemptCountBox.Value = new decimal(new int[] { 50, @@ -92,50 +186,1181 @@ private void InitializeComponent() 0, 0}); // - // CreditsLabel - // - this.CreditsLabel.AutoSize = true; - this.CreditsLabel.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.CreditsLabel.Location = new System.Drawing.Point(3, 13); - this.CreditsLabel.Name = "CreditsLabel"; - this.CreditsLabel.Size = new System.Drawing.Size(141, 13); - this.CreditsLabel.TabIndex = 4; - this.CreditsLabel.Text = "PBChance by SethBling"; - // // DisplayOddsCheckbox // this.DisplayOddsCheckbox.AutoSize = true; - this.DisplayOddsCheckbox.Location = new System.Drawing.Point(6, 72); + this.DisplayOddsCheckbox.Location = new System.Drawing.Point(277, 24); this.DisplayOddsCheckbox.Name = "DisplayOddsCheckbox"; - this.DisplayOddsCheckbox.Size = new System.Drawing.Size(125, 17); + this.DisplayOddsCheckbox.Size = new System.Drawing.Size(123, 17); this.DisplayOddsCheckbox.TabIndex = 5; - this.DisplayOddsCheckbox.Text = "Display Odds (1 in N)"; + this.DisplayOddsCheckbox.Text = "Display odds (1 in N)"; this.DisplayOddsCheckbox.UseVisualStyleBackColor = true; // // IgnoreRunCountBox // this.IgnoreRunCountBox.AutoSize = true; - this.IgnoreRunCountBox.Location = new System.Drawing.Point(6, 95); + this.IgnoreRunCountBox.Location = new System.Drawing.Point(277, 42); this.IgnoreRunCountBox.Name = "IgnoreRunCountBox"; - this.IgnoreRunCountBox.Size = new System.Drawing.Size(205, 17); + this.IgnoreRunCountBox.Size = new System.Drawing.Size(81, 17); this.IgnoreRunCountBox.TabIndex = 6; - this.IgnoreRunCountBox.Text = "Use All Runs (Ignore Attempt Counter)"; + this.IgnoreRunCountBox.Text = "Use all runs"; this.IgnoreRunCountBox.UseVisualStyleBackColor = true; // + // MalusCountBox + // + this.MalusCountBox.Location = new System.Drawing.Point(105, 27); + this.MalusCountBox.Maximum = new decimal(new int[] { + 999, + 0, + 0, + 0}); + this.MalusCountBox.Name = "MalusCountBox"; + this.MalusCountBox.Size = new System.Drawing.Size(40, 20); + this.MalusCountBox.TabIndex = 7; + this.MalusCountBox.Value = new decimal(new int[] { + 30, + 0, + 0, + 0}); + // + // SplitclipCountBox + // + this.SplitclipCountBox.Increment = new decimal(new int[] { + 5, + 0, + 0, + 0}); + this.SplitclipCountBox.Location = new System.Drawing.Point(306, 75); + this.SplitclipCountBox.Maximum = new decimal(new int[] { + 999, + 0, + 0, + 0}); + this.SplitclipCountBox.Minimum = new decimal(new int[] { + 100, + 0, + 0, + 0}); + this.SplitclipCountBox.Name = "SplitclipCountBox"; + this.SplitclipCountBox.Size = new System.Drawing.Size(40, 20); + this.SplitclipCountBox.TabIndex = 8; + this.SplitclipCountBox.Value = new decimal(new int[] { + 200, + 0, + 0, + 0}); + // + // label3 + // + this.label3.AutoSize = true; + this.label3.Location = new System.Drawing.Point(6, 34); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size(93, 13); + this.label3.TabIndex = 11; + this.label3.Text = "Penalty on failures"; + // + // label4 + // + this.label4.AutoSize = true; + this.label4.Location = new System.Drawing.Point(151, 34); + this.label4.Name = "label4"; + this.label4.Size = new System.Drawing.Size(47, 13); + this.label4.TabIndex = 12; + this.label4.Text = "seconds"; + // + // label5 + // + this.label5.AutoSize = true; + this.label5.Location = new System.Drawing.Point(6, 82); + this.label5.Name = "label5"; + this.label5.Size = new System.Drawing.Size(300, 13); + this.label5.TabIndex = 13; + this.label5.Text = "Only consider segments, which are faster than {bestSegm[s] x"; + // + // label6 + // + this.label6.AutoSize = true; + this.label6.Location = new System.Drawing.Point(352, 82); + this.label6.Name = "label6"; + this.label6.Size = new System.Drawing.Size(47, 13); + this.label6.TabIndex = 14; + this.label6.Text = "percent}"; + // + // label7 + // + this.label7.AutoSize = true; + this.label7.Location = new System.Drawing.Point(10, 28); + this.label7.Name = "label7"; + this.label7.Size = new System.Drawing.Size(80, 13); + this.label7.TabIndex = 15; + this.label7.Text = "Time difference"; + // + // TimediffCountBox + // + this.TimediffCountBox.Location = new System.Drawing.Point(91, 21); + this.TimediffCountBox.Maximum = new decimal(new int[] { + 86400, + 0, + 0, + 0}); + this.TimediffCountBox.Minimum = new decimal(new int[] { + 86400, + 0, + 0, + -2147483648}); + this.TimediffCountBox.Name = "TimediffCountBox"; + this.TimediffCountBox.Size = new System.Drawing.Size(60, 20); + this.TimediffCountBox.TabIndex = 9; + // + // label8 + // + this.label8.AutoSize = true; + this.label8.Location = new System.Drawing.Point(154, 28); + this.label8.Name = "label8"; + this.label8.Size = new System.Drawing.Size(47, 13); + this.label8.TabIndex = 17; + this.label8.Text = "seconds"; + // + // label9 + // + this.label9.AutoSize = true; + this.label9.ForeColor = System.Drawing.SystemColors.AppWorkspace; + this.label9.Location = new System.Drawing.Point(202, 18); + this.label9.Name = "label9"; + this.label9.Size = new System.Drawing.Size(244, 13); + this.label9.TabIndex = 18; + this.label9.Text = "higher number -> higher chance. Can be negative."; + // + // label11 + // + this.label11.AutoSize = true; + this.label11.ForeColor = System.Drawing.SystemColors.AppWorkspace; + this.label11.Location = new System.Drawing.Point(6, 95); + this.label11.Name = "label11"; + this.label11.Size = new System.Drawing.Size(156, 13); + this.label11.TabIndex = 20; + this.label11.Text = "higher number -> lower chance."; + // + // label14 + // + this.label14.AutoSize = true; + this.label14.ForeColor = System.Drawing.SystemColors.AppWorkspace; + this.label14.Location = new System.Drawing.Point(6, 61); + this.label14.Name = "label14"; + this.label14.Size = new System.Drawing.Size(337, 13); + this.label14.TabIndex = 23; + this.label14.Text = "It\'s added every time to a simulated run, if a failed segment is selected."; + // + // btnDebug + // + this.btnDebug.Location = new System.Drawing.Point(11, 50); + this.btnDebug.Name = "btnDebug"; + this.btnDebug.Size = new System.Drawing.Size(66, 45); + this.btnDebug.TabIndex = 29; + this.btnDebug.Text = "Generate Debug File"; + this.btnDebug.UseVisualStyleBackColor = true; + this.btnDebug.Click += new System.EventHandler(this.btnDebug_Click); + // + // label17 + // + this.label17.AutoSize = true; + this.label17.Location = new System.Drawing.Point(78, 53); + this.label17.Name = "label17"; + this.label17.Size = new System.Drawing.Size(131, 13); + this.label17.TabIndex = 30; + this.label17.Text = "To retrace the calculation."; + // + // label18 + // + this.label18.AutoSize = true; + this.label18.Location = new System.Drawing.Point(78, 66); + this.label18.Name = "label18"; + this.label18.Size = new System.Drawing.Size(127, 13); + this.label18.TabIndex = 31; + this.label18.Text = "See pbchance_debug.txt"; + // + // label19 + // + this.label19.AutoSize = true; + this.label19.ForeColor = System.Drawing.SystemColors.AppWorkspace; + this.label19.Location = new System.Drawing.Point(200, 31); + this.label19.Name = "label19"; + this.label19.Size = new System.Drawing.Size(242, 13); + this.label19.TabIndex = 39; + this.label19.Text = "Use it for building scenarios or to shift the PB-time."; + // + // label30 + // + this.label30.AutoSize = true; + this.label30.ForeColor = System.Drawing.SystemColors.AppWorkspace; + this.label30.Location = new System.Drawing.Point(6, 48); + this.label30.Name = "label30"; + this.label30.Size = new System.Drawing.Size(311, 13); + this.label30.TabIndex = 53; + this.label30.Text = "For each discontinued run, one failed segment will be generated."; + // + // SkipNewestCountBox + // + this.SkipNewestCountBox.Location = new System.Drawing.Point(355, 50); + this.SkipNewestCountBox.Maximum = new decimal(new int[] { + 99999, + 0, + 0, + 0}); + this.SkipNewestCountBox.Name = "SkipNewestCountBox"; + this.SkipNewestCountBox.Size = new System.Drawing.Size(40, 20); + this.SkipNewestCountBox.TabIndex = 54; + // + // label2 + // + this.label2.AutoSize = true; + this.label2.Location = new System.Drawing.Point(219, 57); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(129, 13); + this.label2.TabIndex = 55; + this.label2.Text = "Skip the newest attempts:"; + // + // label32 + // + this.label32.AutoSize = true; + this.label32.Location = new System.Drawing.Point(238, 78); + this.label32.Name = "label32"; + this.label32.Size = new System.Drawing.Size(111, 13); + this.label32.TabIndex = 58; + this.label32.Text = "Only calc to Segment:"; + // + // CalcToSplitUpDown + // + this.CalcToSplitUpDown.Location = new System.Drawing.Point(355, 76); + this.CalcToSplitUpDown.Maximum = new decimal(new int[] { + 99999, + 0, + 0, + 0}); + this.CalcToSplitUpDown.Name = "CalcToSplitUpDown"; + this.CalcToSplitUpDown.Size = new System.Drawing.Size(40, 20); + this.CalcToSplitUpDown.TabIndex = 57; + // + // label34 + // + this.label34.AutoSize = true; + this.label34.Location = new System.Drawing.Point(83, 80); + this.label34.Name = "label34"; + this.label34.Size = new System.Drawing.Size(113, 13); + this.label34.TabIndex = 60; + this.label34.Text = "in your LiveSplit folder."; + // + // label35 + // + this.label35.AutoSize = true; + this.label35.BackColor = System.Drawing.Color.Transparent; + this.label35.ForeColor = System.Drawing.SystemColors.AppWorkspace; + this.label35.Location = new System.Drawing.Point(399, 76); + this.label35.Name = "label35"; + this.label35.Size = new System.Drawing.Size(35, 13); + this.label35.TabIndex = 61; + this.label35.Text = "0 = all"; + // + // label10 + // + this.label10.AutoSize = true; + this.label10.ForeColor = System.Drawing.SystemColors.AppWorkspace; + this.label10.Location = new System.Drawing.Point(6, 41); + this.label10.Name = "label10"; + this.label10.Size = new System.Drawing.Size(174, 13); + this.label10.TabIndex = 19; + this.label10.Text = "higher number -> more stable result."; + // + // label13 + // + this.label13.AutoSize = true; + this.label13.Location = new System.Drawing.Point(6, 27); + this.label13.Name = "label13"; + this.label13.Size = new System.Drawing.Size(117, 13); + this.label13.TabIndex = 22; + this.label13.Text = "Random sample survey"; + // + // SamplesCountBox + // + this.SamplesCountBox.Increment = new decimal(new int[] { + 1000, + 0, + 0, + 0}); + this.SamplesCountBox.Location = new System.Drawing.Point(129, 20); + this.SamplesCountBox.Maximum = new decimal(new int[] { + 9999999, + 0, + 0, + 0}); + this.SamplesCountBox.Minimum = new decimal(new int[] { + 1, + 0, + 0, + 0}); + this.SamplesCountBox.Name = "SamplesCountBox"; + this.SamplesCountBox.Size = new System.Drawing.Size(63, 20); + this.SamplesCountBox.TabIndex = 10; + this.SamplesCountBox.Value = new decimal(new int[] { + 250000, + 0, + 0, + 0}); + // + // label15 + // + this.label15.AutoSize = true; + this.label15.Location = new System.Drawing.Point(195, 27); + this.label15.Name = "label15"; + this.label15.Size = new System.Drawing.Size(72, 13); + this.label15.TabIndex = 25; + this.label15.Text = "combinations."; + this.label15.DoubleClick += new System.EventHandler(this.label15_DoubleClick); + // + // chkSurvival + // + this.chkSurvival.AutoSize = true; + this.chkSurvival.Location = new System.Drawing.Point(9, 96); + this.chkSurvival.Name = "chkSurvival"; + this.chkSurvival.Size = new System.Drawing.Size(138, 17); + this.chkSurvival.TabIndex = 27; + this.chkSurvival.Text = "Display survival chance"; + this.chkSurvival.UseVisualStyleBackColor = true; + // + // chkExpSplitsvalue + // + this.chkExpSplitsvalue.AutoSize = true; + this.chkExpSplitsvalue.Location = new System.Drawing.Point(285, 129); + this.chkExpSplitsvalue.Name = "chkExpSplitsvalue"; + this.chkExpSplitsvalue.Size = new System.Drawing.Size(158, 17); + this.chkExpSplitsvalue.TabIndex = 38; + this.chkExpSplitsvalue.Text = "Exponential instead of linear"; + this.chkExpSplitsvalue.UseVisualStyleBackColor = true; + this.chkExpSplitsvalue.Visible = false; + // + // MinTimesCountBox + // + this.MinTimesCountBox.Location = new System.Drawing.Point(94, 70); + this.MinTimesCountBox.Maximum = new decimal(new int[] { + 99999, + 0, + 0, + 0}); + this.MinTimesCountBox.Minimum = new decimal(new int[] { + 1, + 0, + 0, + 0}); + this.MinTimesCountBox.Name = "MinTimesCountBox"; + this.MinTimesCountBox.Size = new System.Drawing.Size(52, 20); + this.MinTimesCountBox.TabIndex = 40; + this.MinTimesCountBox.Value = new decimal(new int[] { + 10, + 0, + 0, + 0}); + // + // label24 + // + this.label24.AutoSize = true; + this.label24.Location = new System.Drawing.Point(7, 77); + this.label24.Name = "label24"; + this.label24.Size = new System.Drawing.Size(85, 13); + this.label24.TabIndex = 41; + this.label24.Text = "Consider at least"; + // + // label25 + // + this.label25.AutoSize = true; + this.label25.Location = new System.Drawing.Point(149, 77); + this.label25.Name = "label25"; + this.label25.Size = new System.Drawing.Size(95, 13); + this.label25.TabIndex = 42; + this.label25.Text = "times per segment."; + // + // SplitsvalueCountBox + // + this.SplitsvalueCountBox.Location = new System.Drawing.Point(8, 117); + this.SplitsvalueCountBox.Name = "SplitsvalueCountBox"; + this.SplitsvalueCountBox.Size = new System.Drawing.Size(40, 20); + this.SplitsvalueCountBox.TabIndex = 43; + this.SplitsvalueCountBox.Value = new decimal(new int[] { + 100, + 0, + 0, + 0}); + // + // label26 + // + this.label26.AutoSize = true; + this.label26.Location = new System.Drawing.Point(54, 117); + this.label26.Name = "label26"; + this.label26.Size = new System.Drawing.Size(268, 13); + this.label26.TabIndex = 44; + this.label26.Text = "Newer segment times are more important than old ones."; + this.label26.DoubleClick += new System.EventHandler(this.label26_DoubleClick); + // + // UpdateCountBox + // + this.UpdateCountBox.Location = new System.Drawing.Point(143, 15); + this.UpdateCountBox.Maximum = new decimal(new int[] { + 999, + 0, + 0, + 0}); + this.UpdateCountBox.Name = "UpdateCountBox"; + this.UpdateCountBox.Size = new System.Drawing.Size(40, 20); + this.UpdateCountBox.TabIndex = 46; + this.UpdateCountBox.Value = new decimal(new int[] { + 5, + 0, + 0, + 0}); + // + // label27 + // + this.label27.AutoSize = true; + this.label27.Location = new System.Drawing.Point(6, 22); + this.label27.Name = "label27"; + this.label27.Size = new System.Drawing.Size(135, 13); + this.label27.TabIndex = 47; + this.label27.Text = "Update automatically every"; + // + // label28 + // + this.label28.AutoSize = true; + this.label28.Location = new System.Drawing.Point(189, 22); + this.label28.Name = "label28"; + this.label28.Size = new System.Drawing.Size(165, 13); + this.label28.TabIndex = 48; + this.label28.Text = "seconds when the chance drops."; + // + // label29 + // + this.label29.AutoSize = true; + this.label29.ForeColor = System.Drawing.SystemColors.AppWorkspace; + this.label29.Location = new System.Drawing.Point(54, 130); + this.label29.Name = "label29"; + this.label29.Size = new System.Drawing.Size(318, 13); + this.label29.TabIndex = 52; + this.label29.Text = "Newer attempts will be selected more often during a simulated run."; + // + // label33 + // + this.label33.AutoSize = true; + this.label33.ForeColor = System.Drawing.SystemColors.AppWorkspace; + this.label33.Location = new System.Drawing.Point(7, 91); + this.label33.Name = "label33"; + this.label33.Size = new System.Drawing.Size(202, 13); + this.label33.TabIndex = 59; + this.label33.Text = "Missing times will be filled with older ones."; + // + // rdoAbsAttempt + // + this.rdoAbsAttempt.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); + this.rdoAbsAttempt.AutoSize = true; + this.rdoAbsAttempt.Location = new System.Drawing.Point(152, 23); + this.rdoAbsAttempt.Name = "rdoAbsAttempt"; + this.rdoAbsAttempt.Size = new System.Drawing.Size(66, 17); + this.rdoAbsAttempt.TabIndex = 62; + this.rdoAbsAttempt.TabStop = true; + this.rdoAbsAttempt.Text = "Attempts"; + this.rdoAbsAttempt.UseVisualStyleBackColor = true; + // + // rdoPercentAttempt + // + this.rdoPercentAttempt.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); + this.rdoPercentAttempt.AutoSize = true; + this.rdoPercentAttempt.Location = new System.Drawing.Point(152, 41); + this.rdoPercentAttempt.Name = "rdoPercentAttempt"; + this.rdoPercentAttempt.Size = new System.Drawing.Size(117, 17); + this.rdoPercentAttempt.TabIndex = 63; + this.rdoPercentAttempt.TabStop = true; + this.rdoPercentAttempt.Text = "Percent of attempts"; + this.rdoPercentAttempt.UseVisualStyleBackColor = true; + // + // CalctimeCountBox + // + this.CalctimeCountBox.Increment = new decimal(new int[] { + 100, + 0, + 0, + 0}); + this.CalctimeCountBox.Location = new System.Drawing.Point(321, 20); + this.CalctimeCountBox.Maximum = new decimal(new int[] { + 9999, + 0, + 0, + 0}); + this.CalctimeCountBox.Name = "CalctimeCountBox"; + this.CalctimeCountBox.Size = new System.Drawing.Size(50, 20); + this.CalctimeCountBox.TabIndex = 64; + this.CalctimeCountBox.Value = new decimal(new int[] { + 500, + 0, + 0, + 0}); + // + // lblCalctime2 + // + this.lblCalctime2.AutoSize = true; + this.lblCalctime2.Location = new System.Drawing.Point(377, 27); + this.lblCalctime2.Name = "lblCalctime2"; + this.lblCalctime2.Size = new System.Drawing.Size(66, 13); + this.lblCalctime2.TabIndex = 65; + this.lblCalctime2.Text = "milliseconds."; + // + // lblCalctime1 + // + this.lblCalctime1.AutoSize = true; + this.lblCalctime1.Location = new System.Drawing.Point(273, 27); + this.lblCalctime1.Name = "lblCalctime1"; + this.lblCalctime1.Size = new System.Drawing.Size(42, 13); + this.lblCalctime1.TabIndex = 66; + this.lblCalctime1.Text = "At least"; + // + // chkIgnoreSkipClip + // + this.chkIgnoreSkipClip.AutoSize = true; + this.chkIgnoreSkipClip.Location = new System.Drawing.Point(9, 42); + this.chkIgnoreSkipClip.Name = "chkIgnoreSkipClip"; + this.chkIgnoreSkipClip.Size = new System.Drawing.Size(212, 17); + this.chkIgnoreSkipClip.TabIndex = 67; + this.chkIgnoreSkipClip.Text = "Do not increase chance on \"Skip Split\""; + this.chkIgnoreSkipClip.UseVisualStyleBackColor = true; + // + // chkDeviation + // + this.chkDeviation.AutoSize = true; + this.chkDeviation.Location = new System.Drawing.Point(9, 114); + this.chkDeviation.Name = "chkDeviation"; + this.chkDeviation.Size = new System.Drawing.Size(150, 17); + this.chkDeviation.TabIndex = 69; + this.chkDeviation.Text = "Display standard deviation"; + this.chkDeviation.UseVisualStyleBackColor = true; + // + // chkInfoNext + // + this.chkInfoNext.AutoSize = true; + this.chkInfoNext.Location = new System.Drawing.Point(9, 78); + this.chkInfoNext.Name = "chkInfoNext"; + this.chkInfoNext.Size = new System.Drawing.Size(128, 17); + this.chkInfoNext.TabIndex = 70; + this.chkInfoNext.Text = "Display additional info"; + this.chkInfoNext.UseVisualStyleBackColor = true; + // + // label37 + // + this.label37.AutoSize = true; + this.label37.ForeColor = System.Drawing.SystemColors.AppWorkspace; + this.label37.Location = new System.Drawing.Point(140, 79); + this.label37.Name = "label37"; + this.label37.Size = new System.Drawing.Size(152, 13); + this.label37.TabIndex = 71; + this.label37.Text = "Avg-Best Time / Chance to fail"; + // + // label16 + // + this.label16.AutoSize = true; + this.label16.ForeColor = System.Drawing.SystemColors.AppWorkspace; + this.label16.Location = new System.Drawing.Point(149, 97); + this.label16.Name = "label16"; + this.label16.Size = new System.Drawing.Size(148, 13); + this.label16.TabIndex = 72; + this.label16.Text = "This Segment / Up to the end"; + // + // chkConsiderFails + // + this.chkConsiderFails.AutoSize = true; + this.chkConsiderFails.Location = new System.Drawing.Point(277, 76); + this.chkConsiderFails.Name = "chkConsiderFails"; + this.chkConsiderFails.Size = new System.Drawing.Size(158, 17); + this.chkConsiderFails.TabIndex = 73; + this.chkConsiderFails.Text = "also include failed segments"; + this.chkConsiderFails.UseVisualStyleBackColor = true; + // + // label20 + // + this.label20.AutoSize = true; + this.label20.Location = new System.Drawing.Point(6, 141); + this.label20.Name = "label20"; + this.label20.Size = new System.Drawing.Size(70, 13); + this.label20.TabIndex = 74; + this.label20.Text = "Display every"; + // + // RndInfoEveryCountBox + // + this.RndInfoEveryCountBox.Location = new System.Drawing.Point(82, 136); + this.RndInfoEveryCountBox.Maximum = new decimal(new int[] { + 999, + 0, + 0, + 0}); + this.RndInfoEveryCountBox.Name = "RndInfoEveryCountBox"; + this.RndInfoEveryCountBox.Size = new System.Drawing.Size(40, 20); + this.RndInfoEveryCountBox.TabIndex = 75; + this.RndInfoEveryCountBox.Value = new decimal(new int[] { + 30, + 0, + 0, + 0}); + // + // label21 + // + this.label21.AutoSize = true; + this.label21.Location = new System.Drawing.Point(128, 141); + this.label21.Name = "label21"; + this.label21.Size = new System.Drawing.Size(163, 13); + this.label21.TabIndex = 76; + this.label21.Text = "seconds a random information for"; + // + // RndInfoForCountBox + // + this.RndInfoForCountBox.Location = new System.Drawing.Point(297, 136); + this.RndInfoForCountBox.Maximum = new decimal(new int[] { + 999, + 0, + 0, + 0}); + this.RndInfoForCountBox.Name = "RndInfoForCountBox"; + this.RndInfoForCountBox.Size = new System.Drawing.Size(40, 20); + this.RndInfoForCountBox.TabIndex = 77; + this.RndInfoForCountBox.Value = new decimal(new int[] { + 30, + 0, + 0, + 0}); + // + // label22 + // + this.label22.AutoSize = true; + this.label22.Location = new System.Drawing.Point(343, 141); + this.label22.Name = "label22"; + this.label22.Size = new System.Drawing.Size(50, 13); + this.label22.TabIndex = 78; + this.label22.Text = "seconds."; + // + // btnNewVersion + // + this.btnNewVersion.Location = new System.Drawing.Point(353, 16); + this.btnNewVersion.Name = "btnNewVersion"; + this.btnNewVersion.Size = new System.Drawing.Size(115, 24); + this.btnNewVersion.TabIndex = 79; + this.btnNewVersion.Text = "Check New Version"; + this.btnNewVersion.UseVisualStyleBackColor = true; + this.btnNewVersion.Click += new System.EventHandler(this.btnNewVersion_Click); + // + // label23 + // + this.label23.AutoSize = true; + this.label23.Location = new System.Drawing.Point(54, 147); + this.label23.Name = "label23"; + this.label23.Size = new System.Drawing.Size(204, 13); + this.label23.TabIndex = 81; + this.label23.Text = "Add the best time once for each segment."; + // + // AddBestCountBox + // + this.AddBestCountBox.Location = new System.Drawing.Point(8, 147); + this.AddBestCountBox.Name = "AddBestCountBox"; + this.AddBestCountBox.Size = new System.Drawing.Size(40, 20); + this.AddBestCountBox.TabIndex = 80; + this.AddBestCountBox.Value = new decimal(new int[] { + 100, + 0, + 0, + 0}); + // + // label38 + // + this.label38.AutoSize = true; + this.label38.ForeColor = System.Drawing.SystemColors.AppWorkspace; + this.label38.Location = new System.Drawing.Point(54, 160); + this.label38.Name = "label38"; + this.label38.Size = new System.Drawing.Size(241, 13); + this.label38.TabIndex = 82; + this.label38.Text = "Higher Number -> Higher Chance. 0 to deactivate"; + // + // label40 + // + this.label40.AutoSize = true; + this.label40.ForeColor = System.Drawing.SystemColors.AppWorkspace; + this.label40.Location = new System.Drawing.Point(8, 156); + this.label40.Name = "label40"; + this.label40.Size = new System.Drawing.Size(285, 13); + this.label40.TabIndex = 85; + this.label40.Text = "If it\'s set to 0, it will display once per segment (in the middle)"; + // + // btnUpdList + // + this.btnUpdList.Location = new System.Drawing.Point(9, 132); + this.btnUpdList.Name = "btnUpdList"; + this.btnUpdList.Size = new System.Drawing.Size(115, 24); + this.btnUpdList.TabIndex = 87; + this.btnUpdList.Text = "Refresh List"; + this.btnUpdList.UseVisualStyleBackColor = true; + this.btnUpdList.Click += new System.EventHandler(this.btnUpdList_Click); + // + // dataGridView1 + // + this.dataGridView1.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize; + this.dataGridView1.Location = new System.Drawing.Point(9, 162); + this.dataGridView1.Name = "dataGridView1"; + this.dataGridView1.Size = new System.Drawing.Size(451, 269); + this.dataGridView1.TabIndex = 86; + // + // chkDispGoodPace + // + this.chkDispGoodPace.AutoSize = true; + this.chkDispGoodPace.Location = new System.Drawing.Point(16, 19); + this.chkDispGoodPace.Name = "chkDispGoodPace"; + this.chkDispGoodPace.Size = new System.Drawing.Size(139, 17); + this.chkDispGoodPace.TabIndex = 88; + this.chkDispGoodPace.Text = "Display Avg Pace to PB"; + this.chkDispGoodPace.UseVisualStyleBackColor = true; + // + // chkGoodPaceTotal + // + this.chkGoodPaceTotal.AutoSize = true; + this.chkGoodPaceTotal.Location = new System.Drawing.Point(161, 19); + this.chkGoodPaceTotal.Name = "chkGoodPaceTotal"; + this.chkGoodPaceTotal.Size = new System.Drawing.Size(182, 17); + this.chkGoodPaceTotal.TabIndex = 89; + this.chkGoodPaceTotal.Text = "Split time instead of segment time"; + this.chkGoodPaceTotal.UseVisualStyleBackColor = true; + // + // label39 + // + this.label39.AutoSize = true; + this.label39.Location = new System.Drawing.Point(130, 138); + this.label39.Name = "label39"; + this.label39.Size = new System.Drawing.Size(247, 13); + this.label39.TabIndex = 90; + this.label39.Text = "See \"Pace to PB\" for live calculation next segment"; + // + // chkPaceWorst + // + this.chkPaceWorst.AutoSize = true; + this.chkPaceWorst.Location = new System.Drawing.Point(161, 38); + this.chkPaceWorst.Name = "chkPaceWorst"; + this.chkPaceWorst.Size = new System.Drawing.Size(148, 17); + this.chkPaceWorst.TabIndex = 91; + this.chkPaceWorst.Text = "Display Worst Pace to PB"; + this.chkPaceWorst.UseVisualStyleBackColor = true; + // + // label41 + // + this.label41.AutoSize = true; + this.label41.Location = new System.Drawing.Point(243, 59); + this.label41.Name = "label41"; + this.label41.Size = new System.Drawing.Size(134, 13); + this.label41.TabIndex = 94; + this.label41.Text = "Milliseconds faster then PB"; + // + // label42 + // + this.label42.AutoSize = true; + this.label42.Location = new System.Drawing.Point(100, 59); + this.label42.Name = "label42"; + this.label42.Size = new System.Drawing.Size(57, 13); + this.label42.TabIndex = 93; + this.label42.Text = "Extra goal:"; + // + // PaceExtraGoalMSCountBox + // + this.PaceExtraGoalMSCountBox.Increment = new decimal(new int[] { + 100, + 0, + 0, + 0}); + this.PaceExtraGoalMSCountBox.Location = new System.Drawing.Point(161, 57); + this.PaceExtraGoalMSCountBox.Maximum = new decimal(new int[] { + 9999999, + 0, + 0, + 0}); + this.PaceExtraGoalMSCountBox.Name = "PaceExtraGoalMSCountBox"; + this.PaceExtraGoalMSCountBox.Size = new System.Drawing.Size(76, 20); + this.PaceExtraGoalMSCountBox.TabIndex = 92; + // + // label43 + // + this.label43.AutoSize = true; + this.label43.Location = new System.Drawing.Point(210, 34); + this.label43.Name = "label43"; + this.label43.Size = new System.Drawing.Size(48, 13); + this.label43.TabIndex = 96; + this.label43.Text = "Max fails"; + // + // MalusMaxCountBox + // + this.MalusMaxCountBox.Location = new System.Drawing.Point(258, 27); + this.MalusMaxCountBox.Maximum = new decimal(new int[] { + 999, + 0, + 0, + 0}); + this.MalusMaxCountBox.Name = "MalusMaxCountBox"; + this.MalusMaxCountBox.Size = new System.Drawing.Size(40, 20); + this.MalusMaxCountBox.TabIndex = 95; + this.MalusMaxCountBox.Value = new decimal(new int[] { + 1, + 0, + 0, + 0}); + // + // groupBox1 + // + this.groupBox1.Controls.Add(this.label12); + this.groupBox1.Controls.Add(this.label1); + this.groupBox1.Controls.Add(this.PaceDigitsCountBox); + this.groupBox1.Controls.Add(this.chkDispGoodPace); + this.groupBox1.Controls.Add(this.chkGoodPaceTotal); + this.groupBox1.Controls.Add(this.chkPaceWorst); + this.groupBox1.Controls.Add(this.label41); + this.groupBox1.Controls.Add(this.PaceExtraGoalMSCountBox); + this.groupBox1.Controls.Add(this.label42); + this.groupBox1.Location = new System.Drawing.Point(10, 16); + this.groupBox1.Name = "groupBox1"; + this.groupBox1.Size = new System.Drawing.Size(451, 106); + this.groupBox1.TabIndex = 97; + this.groupBox1.TabStop = false; + this.groupBox1.Text = "Pace to PB"; + // + // label12 + // + this.label12.AutoSize = true; + this.label12.Location = new System.Drawing.Point(102, 82); + this.label12.Name = "label12"; + this.label12.Size = new System.Drawing.Size(55, 13); + this.label12.TabIndex = 97; + this.label12.Text = "Accuracy:"; + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(200, 82); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(104, 13); + this.label1.TabIndex = 96; + this.label1.Text = "Digits of milliseconds"; + // + // PaceDigitsCountBox + // + this.PaceDigitsCountBox.Location = new System.Drawing.Point(161, 80); + this.PaceDigitsCountBox.Maximum = new decimal(new int[] { + 3, + 0, + 0, + 0}); + this.PaceDigitsCountBox.Name = "PaceDigitsCountBox"; + this.PaceDigitsCountBox.Size = new System.Drawing.Size(33, 20); + this.PaceDigitsCountBox.TabIndex = 95; + // + // groupBox2 + // + this.groupBox2.Controls.Add(this.RecentLabel); + this.groupBox2.Controls.Add(this.label24); + this.groupBox2.Controls.Add(this.AttemptCountBox); + this.groupBox2.Controls.Add(this.DisplayOddsCheckbox); + this.groupBox2.Controls.Add(this.IgnoreRunCountBox); + this.groupBox2.Controls.Add(this.rdoPercentAttempt); + this.groupBox2.Controls.Add(this.rdoAbsAttempt); + this.groupBox2.Controls.Add(this.MinTimesCountBox); + this.groupBox2.Controls.Add(this.chkConsiderFails); + this.groupBox2.Controls.Add(this.label33); + this.groupBox2.Controls.Add(this.label25); + this.groupBox2.Location = new System.Drawing.Point(10, 16); + this.groupBox2.Name = "groupBox2"; + this.groupBox2.Size = new System.Drawing.Size(451, 116); + this.groupBox2.TabIndex = 98; + this.groupBox2.TabStop = false; + this.groupBox2.Text = "Number of attempts used"; + // + // label44 + // + this.label44.AutoSize = true; + this.label44.Font = new System.Drawing.Font("Microsoft Sans Serif", 14.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.label44.Location = new System.Drawing.Point(11, 13); + this.label44.Name = "label44"; + this.label44.Size = new System.Drawing.Size(179, 24); + this.label44.TabIndex = 99; + this.label44.Text = "PB Chance V1.4.5"; + // + // groupBox3 + // + this.groupBox3.Controls.Add(this.label7); + this.groupBox3.Controls.Add(this.TimediffCountBox); + this.groupBox3.Controls.Add(this.label8); + this.groupBox3.Controls.Add(this.label9); + this.groupBox3.Controls.Add(this.btnDebug); + this.groupBox3.Controls.Add(this.label17); + this.groupBox3.Controls.Add(this.label18); + this.groupBox3.Controls.Add(this.label19); + this.groupBox3.Controls.Add(this.SkipNewestCountBox); + this.groupBox3.Controls.Add(this.label2); + this.groupBox3.Controls.Add(this.CalcToSplitUpDown); + this.groupBox3.Controls.Add(this.label32); + this.groupBox3.Controls.Add(this.label34); + this.groupBox3.Controls.Add(this.label35); + this.groupBox3.Location = new System.Drawing.Point(10, 249); + this.groupBox3.Name = "groupBox3"; + this.groupBox3.Size = new System.Drawing.Size(451, 100); + this.groupBox3.TabIndex = 100; + this.groupBox3.TabStop = false; + this.groupBox3.Text = "Debugging settings, should be 0 during regular runs"; + // + // groupBox4 + // + this.groupBox4.Controls.Add(this.label31); + this.groupBox4.Controls.Add(this.MalusCountBox); + this.groupBox4.Controls.Add(this.SplitclipCountBox); + this.groupBox4.Controls.Add(this.label3); + this.groupBox4.Controls.Add(this.label4); + this.groupBox4.Controls.Add(this.label43); + this.groupBox4.Controls.Add(this.label5); + this.groupBox4.Controls.Add(this.MalusMaxCountBox); + this.groupBox4.Controls.Add(this.label6); + this.groupBox4.Controls.Add(this.chkExpSplitsvalue); + this.groupBox4.Controls.Add(this.label11); + this.groupBox4.Controls.Add(this.label14); + this.groupBox4.Controls.Add(this.label38); + this.groupBox4.Controls.Add(this.label30); + this.groupBox4.Controls.Add(this.label23); + this.groupBox4.Controls.Add(this.SplitsvalueCountBox); + this.groupBox4.Controls.Add(this.label26); + this.groupBox4.Controls.Add(this.AddBestCountBox); + this.groupBox4.Controls.Add(this.label29); + this.groupBox4.Location = new System.Drawing.Point(8, 224); + this.groupBox4.Name = "groupBox4"; + this.groupBox4.Size = new System.Drawing.Size(453, 182); + this.groupBox4.TabIndex = 101; + this.groupBox4.TabStop = false; + this.groupBox4.Text = "Settings affect the PB Chance"; + // + // label31 + // + this.label31.AutoSize = true; + this.label31.ForeColor = System.Drawing.SystemColors.AppWorkspace; + this.label31.Location = new System.Drawing.Point(303, 34); + this.label31.Name = "label31"; + this.label31.Size = new System.Drawing.Size(126, 13); + this.label31.TabIndex = 97; + this.label31.Text = "then the penalty is infinite"; + // + // groupBox5 + // + this.groupBox5.Controls.Add(this.chkSkipSplitStroke); + this.groupBox5.Controls.Add(this.label27); + this.groupBox5.Controls.Add(this.UpdateCountBox); + this.groupBox5.Controls.Add(this.label28); + this.groupBox5.Controls.Add(this.chkIgnoreSkipClip); + this.groupBox5.Controls.Add(this.chkSurvival); + this.groupBox5.Controls.Add(this.chkDeviation); + this.groupBox5.Controls.Add(this.chkInfoNext); + this.groupBox5.Controls.Add(this.label37); + this.groupBox5.Controls.Add(this.label40); + this.groupBox5.Controls.Add(this.label16); + this.groupBox5.Controls.Add(this.label20); + this.groupBox5.Controls.Add(this.label22); + this.groupBox5.Controls.Add(this.RndInfoEveryCountBox); + this.groupBox5.Controls.Add(this.RndInfoForCountBox); + this.groupBox5.Controls.Add(this.label21); + this.groupBox5.Location = new System.Drawing.Point(10, 16); + this.groupBox5.Name = "groupBox5"; + this.groupBox5.Size = new System.Drawing.Size(451, 178); + this.groupBox5.TabIndex = 102; + this.groupBox5.TabStop = false; + this.groupBox5.Text = "Display Options"; + // + // chkSkipSplitStroke + // + this.chkSkipSplitStroke.AutoSize = true; + this.chkSkipSplitStroke.Location = new System.Drawing.Point(9, 60); + this.chkSkipSplitStroke.Name = "chkSkipSplitStroke"; + this.chkSkipSplitStroke.Size = new System.Drawing.Size(299, 17); + this.chkSkipSplitStroke.TabIndex = 86; + this.chkSkipSplitStroke.Text = "On \"Skip Split\" display \"-\" only, else old value will be hold."; + this.chkSkipSplitStroke.UseVisualStyleBackColor = true; + // + // tabPages + // + this.tabPages.Controls.Add(this.tabPage1); + this.tabPages.Controls.Add(this.tabPage2); + this.tabPages.Controls.Add(this.tabPage3); + this.tabPages.Location = new System.Drawing.Point(3, 46); + this.tabPages.Name = "tabPages"; + this.tabPages.SelectedIndex = 0; + this.tabPages.Size = new System.Drawing.Size(471, 463); + this.tabPages.TabIndex = 103; + // + // tabPage1 + // + this.tabPage1.Controls.Add(this.groupBox6); + this.tabPage1.Controls.Add(this.groupBox2); + this.tabPage1.Controls.Add(this.groupBox4); + this.tabPage1.Location = new System.Drawing.Point(4, 22); + this.tabPage1.Name = "tabPage1"; + this.tabPage1.Padding = new System.Windows.Forms.Padding(3); + this.tabPage1.Size = new System.Drawing.Size(463, 437); + this.tabPage1.TabIndex = 0; + this.tabPage1.Text = "General"; + this.tabPage1.UseVisualStyleBackColor = true; + // + // groupBox6 + // + this.groupBox6.Controls.Add(this.label13); + this.groupBox6.Controls.Add(this.lblCalctime1); + this.groupBox6.Controls.Add(this.lblCalctime2); + this.groupBox6.Controls.Add(this.CalctimeCountBox); + this.groupBox6.Controls.Add(this.label15); + this.groupBox6.Controls.Add(this.label10); + this.groupBox6.Controls.Add(this.SamplesCountBox); + this.groupBox6.Location = new System.Drawing.Point(8, 143); + this.groupBox6.Name = "groupBox6"; + this.groupBox6.Size = new System.Drawing.Size(451, 70); + this.groupBox6.TabIndex = 104; + this.groupBox6.TabStop = false; + this.groupBox6.Text = "Sample size"; + // + // tabPage2 + // + this.tabPage2.Controls.Add(this.groupBox1); + this.tabPage2.Controls.Add(this.dataGridView1); + this.tabPage2.Controls.Add(this.btnUpdList); + this.tabPage2.Controls.Add(this.label39); + this.tabPage2.Location = new System.Drawing.Point(4, 22); + this.tabPage2.Name = "tabPage2"; + this.tabPage2.Padding = new System.Windows.Forms.Padding(3); + this.tabPage2.Size = new System.Drawing.Size(467, 437); + this.tabPage2.TabIndex = 1; + this.tabPage2.Text = "PB Pace"; + this.tabPage2.UseVisualStyleBackColor = true; + this.tabPage2.Enter += new System.EventHandler(this.tabHistory_Enter); + // + // tabPage3 + // + this.tabPage3.Controls.Add(this.label46); + this.tabPage3.Controls.Add(this.groupBox5); + this.tabPage3.Controls.Add(this.label45); + this.tabPage3.Controls.Add(this.groupBox3); + this.tabPage3.Controls.Add(this.label36); + this.tabPage3.Location = new System.Drawing.Point(4, 22); + this.tabPage3.Name = "tabPage3"; + this.tabPage3.Padding = new System.Windows.Forms.Padding(3); + this.tabPage3.Size = new System.Drawing.Size(467, 437); + this.tabPage3.TabIndex = 2; + this.tabPage3.Text = "Display Options"; + this.tabPage3.UseVisualStyleBackColor = true; + // + // label46 + // + this.label46.AutoSize = true; + this.label46.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.label46.ForeColor = System.Drawing.SystemColors.ActiveCaption; + this.label46.Location = new System.Drawing.Point(150, 414); + this.label46.Name = "label46"; + this.label46.Size = new System.Drawing.Size(184, 13); + this.label46.TabIndex = 104; + this.label46.Text = "www.github.com/kasi777/PBChance"; + // + // label45 + // + this.label45.AutoSize = true; + this.label45.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.label45.ForeColor = System.Drawing.SystemColors.ActiveCaption; + this.label45.Location = new System.Drawing.Point(134, 401); + this.label45.Name = "label45"; + this.label45.Size = new System.Drawing.Size(213, 13); + this.label45.TabIndex = 103; + this.label45.Text = "Advanced settings and rewritten by kasi777"; + // + // label36 + // + this.label36.AutoSize = true; + this.label36.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.label36.ForeColor = System.Drawing.SystemColors.ActiveCaption; + this.label36.Location = new System.Drawing.Point(152, 388); + this.label36.Name = "label36"; + this.label36.Size = new System.Drawing.Size(175, 13); + this.label36.TabIndex = 102; + this.label36.Text = "Idea and initial Version by SethBling"; + // + // lblFaster + // + this.lblFaster.AutoSize = true; + this.lblFaster.Location = new System.Drawing.Point(196, 514); + this.lblFaster.Name = "lblFaster"; + this.lblFaster.Size = new System.Drawing.Size(39, 13); + this.lblFaster.TabIndex = 105; + this.lblFaster.Text = "Faster:"; + // + // lblSampleSize + // + this.lblSampleSize.AutoSize = true; + this.lblSampleSize.Location = new System.Drawing.Point(10, 514); + this.lblSampleSize.Name = "lblSampleSize"; + this.lblSampleSize.Size = new System.Drawing.Size(99, 13); + this.lblSampleSize.TabIndex = 74; + this.lblSampleSize.Text = "Actual Sample size:"; + // + // lblChance + // + this.lblChance.AutoSize = true; + this.lblChance.Location = new System.Drawing.Point(326, 514); + this.lblChance.Name = "lblChance"; + this.lblChance.Size = new System.Drawing.Size(47, 13); + this.lblChance.TabIndex = 106; + this.lblChance.Text = "Chance:"; + // // PBChanceSettings // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.Controls.Add(this.IgnoreRunCountBox); - this.Controls.Add(this.DisplayOddsCheckbox); - this.Controls.Add(this.CreditsLabel); - this.Controls.Add(this.AttemptCountBox); - this.Controls.Add(this.FixedAttempts); - this.Controls.Add(this.PercentOfAttempts); - this.Controls.Add(this.RecentLabel); + this.Controls.Add(this.lblChance); + this.Controls.Add(this.lblFaster); + this.Controls.Add(this.tabPages); + this.Controls.Add(this.lblSampleSize); + this.Controls.Add(this.label44); + this.Controls.Add(this.btnNewVersion); this.Name = "PBChanceSettings"; - this.Size = new System.Drawing.Size(289, 121); + this.Size = new System.Drawing.Size(475, 530); ((System.ComponentModel.ISupportInitialize)(this.AttemptCountBox)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.MalusCountBox)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.SplitclipCountBox)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.TimediffCountBox)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.SkipNewestCountBox)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.CalcToSplitUpDown)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.SamplesCountBox)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.MinTimesCountBox)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.SplitsvalueCountBox)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.UpdateCountBox)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.CalctimeCountBox)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.RndInfoEveryCountBox)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.RndInfoForCountBox)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.AddBestCountBox)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.dataGridView1)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.PaceExtraGoalMSCountBox)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.MalusMaxCountBox)).EndInit(); + this.groupBox1.ResumeLayout(false); + this.groupBox1.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.PaceDigitsCountBox)).EndInit(); + this.groupBox2.ResumeLayout(false); + this.groupBox2.PerformLayout(); + this.groupBox3.ResumeLayout(false); + this.groupBox3.PerformLayout(); + this.groupBox4.ResumeLayout(false); + this.groupBox4.PerformLayout(); + this.groupBox5.ResumeLayout(false); + this.groupBox5.PerformLayout(); + this.tabPages.ResumeLayout(false); + this.tabPage1.ResumeLayout(false); + this.groupBox6.ResumeLayout(false); + this.groupBox6.PerformLayout(); + this.tabPage2.ResumeLayout(false); + this.tabPage2.PerformLayout(); + this.tabPage3.ResumeLayout(false); + this.tabPage3.PerformLayout(); this.ResumeLayout(false); this.PerformLayout(); @@ -143,11 +1368,101 @@ private void InitializeComponent() #endregion private System.Windows.Forms.Label RecentLabel; - private System.Windows.Forms.RadioButton PercentOfAttempts; - private System.Windows.Forms.RadioButton FixedAttempts; private System.Windows.Forms.NumericUpDown AttemptCountBox; - private System.Windows.Forms.Label CreditsLabel; private System.Windows.Forms.CheckBox DisplayOddsCheckbox; private System.Windows.Forms.CheckBox IgnoreRunCountBox; + private System.Windows.Forms.NumericUpDown MalusCountBox; + private System.Windows.Forms.NumericUpDown SplitclipCountBox; + private System.Windows.Forms.Label label3; + private System.Windows.Forms.Label label4; + private System.Windows.Forms.Label label5; + private System.Windows.Forms.Label label6; + private System.Windows.Forms.Label label7; + private System.Windows.Forms.NumericUpDown TimediffCountBox; + private System.Windows.Forms.Label label8; + private System.Windows.Forms.Label label9; + private System.Windows.Forms.Label label11; + private System.Windows.Forms.Label label14; + private System.Windows.Forms.Button btnDebug; + private System.Windows.Forms.Label label17; + private System.Windows.Forms.Label label18; + private System.Windows.Forms.Label label19; + private System.Windows.Forms.Label label30; + private System.Windows.Forms.NumericUpDown SkipNewestCountBox; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.Label label32; + private System.Windows.Forms.NumericUpDown CalcToSplitUpDown; + private System.Windows.Forms.Label label34; + private System.Windows.Forms.Label label35; + private System.Windows.Forms.Label label10; + private System.Windows.Forms.Label label13; + private System.Windows.Forms.NumericUpDown SamplesCountBox; + private System.Windows.Forms.Label label15; + private System.Windows.Forms.CheckBox chkSurvival; + private System.Windows.Forms.CheckBox chkExpSplitsvalue; + private System.Windows.Forms.NumericUpDown MinTimesCountBox; + private System.Windows.Forms.Label label24; + private System.Windows.Forms.Label label25; + private System.Windows.Forms.NumericUpDown SplitsvalueCountBox; + private System.Windows.Forms.Label label26; + private System.Windows.Forms.NumericUpDown UpdateCountBox; + private System.Windows.Forms.Label label27; + private System.Windows.Forms.Label label28; + private System.Windows.Forms.Label label29; + private System.Windows.Forms.Label label33; + private System.Windows.Forms.RadioButton rdoAbsAttempt; + private System.Windows.Forms.RadioButton rdoPercentAttempt; + private System.Windows.Forms.NumericUpDown CalctimeCountBox; + private System.Windows.Forms.Label lblCalctime2; + private System.Windows.Forms.Label lblCalctime1; + private System.Windows.Forms.CheckBox chkIgnoreSkipClip; + private System.Windows.Forms.CheckBox chkDeviation; + private System.Windows.Forms.CheckBox chkInfoNext; + private System.Windows.Forms.Label label37; + private System.Windows.Forms.Label label16; + private System.Windows.Forms.CheckBox chkConsiderFails; + private System.Windows.Forms.Label label20; + private System.Windows.Forms.NumericUpDown RndInfoEveryCountBox; + private System.Windows.Forms.Label label21; + private System.Windows.Forms.NumericUpDown RndInfoForCountBox; + private System.Windows.Forms.Label label22; + private System.Windows.Forms.Button btnNewVersion; + private System.Windows.Forms.Label label23; + private System.Windows.Forms.NumericUpDown AddBestCountBox; + private System.Windows.Forms.Label label38; + private System.Windows.Forms.Label label40; + private System.Windows.Forms.Button btnUpdList; + private System.Windows.Forms.DataGridView dataGridView1; + private System.Windows.Forms.CheckBox chkDispGoodPace; + private System.Windows.Forms.CheckBox chkGoodPaceTotal; + private System.Windows.Forms.Label label39; + private System.Windows.Forms.CheckBox chkPaceWorst; + private System.Windows.Forms.Label label41; + private System.Windows.Forms.Label label42; + private System.Windows.Forms.NumericUpDown PaceExtraGoalMSCountBox; + private System.Windows.Forms.Label label43; + private System.Windows.Forms.NumericUpDown MalusMaxCountBox; + private System.Windows.Forms.GroupBox groupBox1; + private System.Windows.Forms.GroupBox groupBox2; + private System.Windows.Forms.Label label44; + private System.Windows.Forms.GroupBox groupBox3; + private System.Windows.Forms.GroupBox groupBox4; + private System.Windows.Forms.GroupBox groupBox5; + private System.Windows.Forms.Label label31; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.NumericUpDown PaceDigitsCountBox; + private System.Windows.Forms.TabControl tabPages; + private System.Windows.Forms.TabPage tabPage1; + private System.Windows.Forms.TabPage tabPage2; + private System.Windows.Forms.TabPage tabPage3; + private System.Windows.Forms.GroupBox groupBox6; + private System.Windows.Forms.Label label45; + private System.Windows.Forms.Label label36; + private System.Windows.Forms.Label lblFaster; + private System.Windows.Forms.Label lblSampleSize; + private System.Windows.Forms.Label lblChance; + private System.Windows.Forms.Label label12; + private System.Windows.Forms.CheckBox chkSkipSplitStroke; + private System.Windows.Forms.Label label46; } } diff --git a/PBChance/UI/Components/PBChanceSettings.cs b/PBChance/UI/Components/PBChanceSettings.cs index 2004488..85f830e 100644 --- a/PBChance/UI/Components/PBChanceSettings.cs +++ b/PBChance/UI/Components/PBChanceSettings.cs @@ -9,37 +9,139 @@ using System.Windows.Forms; using System.Xml; using LiveSplit.UI; +using System.Net; //because WebClient namespace PBChance.UI.Components { public partial class PBChanceSettings : UserControl { + public string sVersion { get; set; } public Boolean UsePercentOfAttempts { get; set; } public Boolean UseFixedAttempts { get; set; } public int AttemptCount { get; set; } + public int MalusCount { get; set; } + public int SplitclipCount { get; set; } + public int TimediffCount { get; set; } + public int SamplesCount { get; set; } public bool DisplayOdds { get; set; } public bool IgnoreRunCount { get; set; } + public bool bDebug { get; set; } + public int iOptimistic { get; set; } + public bool bRebalance { get; set; } + public bool bValueRuns { get; set; } + public bool bExpSplitsvalue { get; set; } + public int iMinTimes { get; set; } + public int iUpdate { get; set; } + public int iSplitsvalue { get; set; } + public bool bInfoNext { get; set; } + public bool bConsiderFails { get; set; } + + public bool bDispGoodPace { get; set; } + public bool bGoodPaceTotal { get; set; } + public bool bPaceWorst { get; set; } + public int iMalusMax { get; set; } + public int iPaceExtraGoalMS { get; set; } + public int iPaceDigits { get; set; } + + public System.Data.DataTable DataGridViewV { get; set; } + + public Boolean bSurvival { get; set; } + public Boolean bIgnoreSkipClip { get; set; } + public Boolean bSkipSplitStroke { get; set; } + public Boolean bDeviation { get; set; } + + public int iSkipNewest { get; set; } + public int iCalcToSplit { get; set; } + public int iCalctime { get; set; } + public int iRndInfoEvery { get; set; } + public int iRndInfoFor { get; set; } + + public int iAddBest { get; set; } public event EventHandler SettingChanged; public PBChanceSettings() { + //bool bFixedAttempts; InitializeComponent(); - UsePercentOfAttempts = true; - UseFixedAttempts = false; + UsePercentOfAttempts = false; + UseFixedAttempts = true; + IgnoreRunCount = false; AttemptCount = 50; + MalusCount = 30; + SplitclipCount = 150; + TimediffCount = 0; + SamplesCount = 250000; + iCalctime = 900; + bSurvival = false; + bDebug = false; + iOptimistic = 0; + bRebalance = false; + bValueRuns = false; + iMinTimes = 20; + iUpdate = 1; + iSplitsvalue = 100; + iSkipNewest = 0; + iCalcToSplit = 0; + bExpSplitsvalue = false; + bConsiderFails = true; + bIgnoreSkipClip = true; + iRndInfoEvery = 0; // once per segment, in the middle (e.g. Best Segment Time=2:00, for 10 seconds, it will display between 0:55-1:05) + iRndInfoFor = 12; + iAddBest = 25; + bDispGoodPace = true; + bGoodPaceTotal = false; + iMalusMax = 1; + iPaceExtraGoalMS = 0; + bPaceWorst = false; + iPaceDigits = 0; + + rdoPercentAttempt.DataBindings.Add("Checked", this, "UsePercentOfAttempts", false, DataSourceUpdateMode.OnPropertyChanged).BindingComplete += OnSettingChanged; + rdoAbsAttempt.DataBindings.Add("Checked", this, "UseFixedAttempts", false, DataSourceUpdateMode.OnPropertyChanged).BindingComplete += OnSettingChanged; + AttemptCountBox.DataBindings.Add("Value", this, "AttemptCount", false, DataSourceUpdateMode.OnPropertyChanged).BindingComplete += OnSettingChanged; + DisplayOddsCheckbox.DataBindings.Add("Checked", this, "DisplayOdds", false, DataSourceUpdateMode.OnPropertyChanged).BindingComplete += OnSettingChanged; + IgnoreRunCountBox.DataBindings.Add("Checked", this, "IgnoreRunCount", false, DataSourceUpdateMode.OnPropertyChanged).BindingComplete += OnSettingChanged; + MalusCountBox.DataBindings.Add("Value", this, "MalusCount", false, DataSourceUpdateMode.OnPropertyChanged).BindingComplete += OnSettingChanged; + SplitclipCountBox.DataBindings.Add("Value", this, "SplitclipCount", true, DataSourceUpdateMode.OnPropertyChanged).BindingComplete += OnSettingChanged; + SamplesCountBox.DataBindings.Add("Value", this, "SamplesCount", false, DataSourceUpdateMode.OnPropertyChanged).BindingComplete += OnSettingChanged; + TimediffCountBox.DataBindings.Add("Value", this, "TimediffCount", false, DataSourceUpdateMode.OnPropertyChanged).BindingComplete += OnSettingChanged; + CalctimeCountBox.DataBindings.Add("Value", this, "iCalctime", false, DataSourceUpdateMode.OnPropertyChanged).BindingComplete += OnSettingChanged; + chkSurvival.DataBindings.Add("Checked", this, "bSurvival", false, DataSourceUpdateMode.OnPropertyChanged).BindingComplete += OnSettingChanged; + chkIgnoreSkipClip.DataBindings.Add("Checked", this, "bIgnoreSkipClip", false, DataSourceUpdateMode.OnPropertyChanged).BindingComplete += OnSettingChanged; + chkSkipSplitStroke.DataBindings.Add("Checked", this, "bSkipSplitStroke", false, DataSourceUpdateMode.OnPropertyChanged).BindingComplete += OnSettingChanged; + chkDeviation.DataBindings.Add("Checked", this, "bDeviation", false, DataSourceUpdateMode.OnPropertyChanged).BindingComplete += OnSettingChanged; + + MinTimesCountBox.DataBindings.Add("Value", this, "iMinTimes", false, DataSourceUpdateMode.OnPropertyChanged).BindingComplete += OnSettingChanged; + UpdateCountBox.DataBindings.Add("Value", this, "iUpdate", false, DataSourceUpdateMode.OnPropertyChanged).BindingComplete += OnSettingChanged; + SplitsvalueCountBox.DataBindings.Add("Value", this, "iSplitsvalue", false, DataSourceUpdateMode.OnPropertyChanged).BindingComplete += OnSettingChanged; + + SkipNewestCountBox.DataBindings.Add("Value", this, "iSkipNewest", false, DataSourceUpdateMode.OnPropertyChanged).BindingComplete += OnSettingChanged; + CalcToSplitUpDown.DataBindings.Add("Value", this, "iCalcToSplit", false, DataSourceUpdateMode.OnPropertyChanged).BindingComplete += OnSettingChanged; + chkExpSplitsvalue.DataBindings.Add("Checked", this, "bExpSplitsvalue", false, DataSourceUpdateMode.OnPropertyChanged).BindingComplete += OnSettingChanged; + chkInfoNext.DataBindings.Add("Checked", this, "bInfoNext", false, DataSourceUpdateMode.OnPropertyChanged).BindingComplete += OnSettingChanged; - PercentOfAttempts.DataBindings.Add("Checked", this, "UsePercentOfAttempts", true, DataSourceUpdateMode.OnPropertyChanged).BindingComplete += OnSettingChanged; - FixedAttempts.DataBindings.Add("Checked", this, "UseFixedAttempts", true, DataSourceUpdateMode.OnPropertyChanged).BindingComplete += OnSettingChanged; - AttemptCountBox.DataBindings.Add("Value", this, "AttemptCount", true, DataSourceUpdateMode.OnPropertyChanged).BindingComplete += OnSettingChanged; - DisplayOddsCheckbox.DataBindings.Add("Checked", this, "DisplayOdds", true, DataSourceUpdateMode.OnPropertyChanged).BindingComplete += OnSettingChanged; - IgnoreRunCountBox.DataBindings.Add("Checked", this, "IgnoreRunCount", true, DataSourceUpdateMode.OnPropertyChanged).BindingComplete += OnSettingChanged; + RndInfoEveryCountBox.DataBindings.Add("Value", this, "iRndInfoEvery", false, DataSourceUpdateMode.OnPropertyChanged).BindingComplete += OnSettingChanged; + RndInfoForCountBox.DataBindings.Add("Value", this, "iRndInfoFor", false, DataSourceUpdateMode.OnPropertyChanged).BindingComplete += OnSettingChanged; + chkConsiderFails.DataBindings.Add("Checked", this, "bConsiderFails", false, DataSourceUpdateMode.OnPropertyChanged).BindingComplete += OnSettingChanged; + + AddBestCountBox.DataBindings.Add("Value", this, "iAddBest", false, DataSourceUpdateMode.OnPropertyChanged).BindingComplete += OnSettingChanged; + chkDispGoodPace.DataBindings.Add("Checked", this, "bDispGoodPace", false, DataSourceUpdateMode.OnPropertyChanged).BindingComplete += OnSettingChanged; + chkGoodPaceTotal.DataBindings.Add("Checked", this, "bGoodPaceTotal", false, DataSourceUpdateMode.OnPropertyChanged).BindingComplete += OnSettingChanged; + + chkPaceWorst.DataBindings.Add("Checked", this, "bPaceWorst", false, DataSourceUpdateMode.OnPropertyChanged).BindingComplete += OnSettingChanged; + PaceExtraGoalMSCountBox.DataBindings.Add("Value", this, "iPaceExtraGoalMS", false, DataSourceUpdateMode.OnPropertyChanged).BindingComplete += OnSettingChanged; + PaceDigitsCountBox.DataBindings.Add("Value", this, "iPaceDigits", false, DataSourceUpdateMode.OnPropertyChanged).BindingComplete += OnSettingChanged; + MalusMaxCountBox.DataBindings.Add("Value", this, "iMalusMax", false, DataSourceUpdateMode.OnPropertyChanged).BindingComplete += OnSettingChanged; + + UseFixedAttempts = !UsePercentOfAttempts; + UsePercentOfAttempts = !UseFixedAttempts; } private void OnSettingChanged(object sender, BindingCompleteEventArgs e) { SettingChanged?.Invoke(this, e); + updateDataTable_Core2(dataGridView1, true); } public LayoutMode Mode { get; internal set; } @@ -53,21 +155,395 @@ internal XmlNode GetSettings(XmlDocument document) private int CreateSettingsNode(XmlDocument document, XmlElement parent) { - return SettingsHelper.CreateSetting(document, parent, "Version", "0.1") ^ + return SettingsHelper.CreateSetting(document, parent, "Version", sVersion) ^ SettingsHelper.CreateSetting(document, parent, "AttemptCount", AttemptCount) ^ SettingsHelper.CreateSetting(document, parent, "UsePercentOfAttempts", UsePercentOfAttempts) ^ SettingsHelper.CreateSetting(document, parent, "UseFixedAttempts", UseFixedAttempts) ^ SettingsHelper.CreateSetting(document, parent, "DisplayOdds", DisplayOdds) ^ - SettingsHelper.CreateSetting(document, parent, "IgnoreRunCount", IgnoreRunCount); + SettingsHelper.CreateSetting(document, parent, "IgnoreRunCount", IgnoreRunCount) ^ + SettingsHelper.CreateSetting(document, parent, "MalusCount", MalusCount) ^ + SettingsHelper.CreateSetting(document, parent, "SplitclipCount", SplitclipCount) ^ + SettingsHelper.CreateSetting(document, parent, "TimediffCount", TimediffCount) ^ + SettingsHelper.CreateSetting(document, parent, "SamplesCount", SamplesCount) ^ + SettingsHelper.CreateSetting(document, parent, "iCalctime", iCalctime) ^ + SettingsHelper.CreateSetting(document, parent, "iOptimistic", iOptimistic) ^ + SettingsHelper.CreateSetting(document, parent, "chkRebalance", bRebalance) ^ + SettingsHelper.CreateSetting(document, parent, "chkSurvival", bSurvival) ^ + SettingsHelper.CreateSetting(document, parent, "chkInfoNext", bInfoNext) ^ + SettingsHelper.CreateSetting(document, parent, "bValueRuns", bValueRuns) ^ + SettingsHelper.CreateSetting(document, parent, "IgnoreSkipClip", bIgnoreSkipClip) ^ + SettingsHelper.CreateSetting(document, parent, "bSkipSplitStroke", bSkipSplitStroke) ^ + SettingsHelper.CreateSetting(document, parent, "Deviation", bDeviation) ^ + SettingsHelper.CreateSetting(document, parent, "iMinTimes", iMinTimes) ^ + SettingsHelper.CreateSetting(document, parent, "iUpdate", iUpdate) ^ + SettingsHelper.CreateSetting(document, parent, "iAddBest", iAddBest) ^ + SettingsHelper.CreateSetting(document, parent, "RndInfoEveryCountBox", iRndInfoEvery) ^ + SettingsHelper.CreateSetting(document, parent, "RndInfoForCountBox", iRndInfoFor) ^ + SettingsHelper.CreateSetting(document, parent, "chkConsiderFails", bConsiderFails) ^ + SettingsHelper.CreateSetting(document, parent, "bDispGoodPace", bDispGoodPace) ^ + SettingsHelper.CreateSetting(document, parent, "bGoodPaceTotal", bGoodPaceTotal) ^ + SettingsHelper.CreateSetting(document, parent, "chkPaceWorst", bPaceWorst) ^ + SettingsHelper.CreateSetting(document, parent, "PaceExtraGoalMSCountBox", iPaceExtraGoalMS) ^ + SettingsHelper.CreateSetting(document, parent, "MalusMaxCountBox", iMalusMax) ^ + SettingsHelper.CreateSetting(document, parent, "PaceDigitsCountBox", iPaceDigits) ^ + SettingsHelper.CreateSetting(document, parent, "iSplitsvalue", iSplitsvalue); } + public void SetSettings(XmlNode settings) { SetSettingsCore(dataGridView1, settings); } + public delegate void SetSettingsDelegate(DataGridView control, XmlNode settings); // defines a delegate type + public void SetSettingsCore(DataGridView control, XmlNode settings) + { + if (this.InvokeRequired) + this.Invoke(new SetSettingsDelegate(SetSettingsCore), new object[] { control, settings }); // invoking itself + else // the "functional part", executing only on the main thread + { + sVersion = SettingsHelper.ParseString(settings["Version"]); + AttemptCount = SettingsHelper.ParseInt(settings["AttemptCount"]); + UsePercentOfAttempts = SettingsHelper.ParseBool(settings["UsePercentOfAttempts"]); + UseFixedAttempts = SettingsHelper.ParseBool(settings["UseFixedAttempts"]); + DisplayOdds = SettingsHelper.ParseBool(settings["DisplayOdds"]); + IgnoreRunCount = SettingsHelper.ParseBool(settings["IgnoreRunCount"]); + MalusCount = SettingsHelper.ParseInt(settings["MalusCount"]); + SplitclipCount = SettingsHelper.ParseInt(settings["SplitclipCount"]); + TimediffCount = SettingsHelper.ParseInt(settings["TimediffCount"]); + SamplesCount = SettingsHelper.ParseInt(settings["SamplesCount"]); + iCalctime = SettingsHelper.ParseInt(settings["iCalctime"]); + iOptimistic = SettingsHelper.ParseInt(settings["iOptimistic"]); + bSurvival = SettingsHelper.ParseBool(settings["chkSurvival"]); + bRebalance = SettingsHelper.ParseBool(settings["chkRebalance"]); + bIgnoreSkipClip = SettingsHelper.ParseBool(settings["IgnoreSkipClip"]); + bSkipSplitStroke = SettingsHelper.ParseBool(settings["bSkipSplitStroke"]); + bDeviation = SettingsHelper.ParseBool(settings["Deviation"]); + bValueRuns = SettingsHelper.ParseBool(settings["bValueRuns"]); + bInfoNext = SettingsHelper.ParseBool(settings["chkInfoNext"]); + iMinTimes = SettingsHelper.ParseInt(settings["iMinTimes"]); + iUpdate = SettingsHelper.ParseInt(settings["iUpdate"]); + iAddBest = SettingsHelper.ParseInt(settings["iAddBest"]); + iSplitsvalue = SettingsHelper.ParseInt(settings["iSplitsvalue"]); + bExpSplitsvalue = SettingsHelper.ParseBool(settings["bExpSplitsvalue"]); + iRndInfoEvery = SettingsHelper.ParseInt(settings["RndInfoEveryCountBox"]); + iRndInfoFor = SettingsHelper.ParseInt(settings["RndInfoForCountBox"]); + bConsiderFails = SettingsHelper.ParseBool(settings["chkConsiderFails"]); + iPaceExtraGoalMS = SettingsHelper.ParseInt(settings["PaceExtraGoalMSCountBox"]); + iMalusMax = SettingsHelper.ParseInt(settings["MalusMaxCountBox"]); + iPaceDigits = SettingsHelper.ParseInt(settings["PaceDigitsCountBox"]); + bPaceWorst = SettingsHelper.ParseBool(settings["chkPaceWorst"]); + bDispGoodPace = SettingsHelper.ParseBool(settings["bDispGoodPace"]); + bGoodPaceTotal = SettingsHelper.ParseBool(settings["bGoodPaceTotal"]); + } + } + /* internal void SetSettings(XmlNode settings) { + sVersion = SettingsHelper.ParseString(settings["Version"]); AttemptCount = SettingsHelper.ParseInt(settings["AttemptCount"]); UsePercentOfAttempts = SettingsHelper.ParseBool(settings["UsePercentOfAttempts"]); UseFixedAttempts = SettingsHelper.ParseBool(settings["UseFixedAttempts"]); DisplayOdds = SettingsHelper.ParseBool(settings["DisplayOdds"]); IgnoreRunCount = SettingsHelper.ParseBool(settings["IgnoreRunCount"]); + MalusCount = SettingsHelper.ParseInt(settings["MalusCount"]); + SplitclipCount = SettingsHelper.ParseInt(settings["SplitclipCount"]); + TimediffCount = SettingsHelper.ParseInt(settings["TimediffCount"]); + SamplesCount = SettingsHelper.ParseInt(settings["SamplesCount"]); + iCalctime = SettingsHelper.ParseInt(settings["iCalctime"]); + iOptimistic = SettingsHelper.ParseInt(settings["iOptimistic"]); + bSurvival = SettingsHelper.ParseBool(settings["chkSurvival"]); + bRebalance = SettingsHelper.ParseBool(settings["chkRebalance"]); + bIgnoreSkipClip = SettingsHelper.ParseBool(settings["IgnoreSkipClip"]); + bDeviation = SettingsHelper.ParseBool(settings["Deviation"]); + bValueRuns = SettingsHelper.ParseBool(settings["bValueRuns"]); + bInfoNext = SettingsHelper.ParseBool(settings["chkInfoNext"]); + iMinTimes = SettingsHelper.ParseInt(settings["iMinTimes"]); + iUpdate = SettingsHelper.ParseInt(settings["iUpdate"]); + iAddBest = SettingsHelper.ParseInt(settings["iAddBest"]); + iSplitsvalue = SettingsHelper.ParseInt(settings["iSplitsvalue"]); + bExpSplitsvalue = SettingsHelper.ParseBool(settings["bExpSplitsvalue"]); + iRndInfoEvery = SettingsHelper.ParseInt(settings["RndInfoEveryCountBox"]); + iRndInfoFor = SettingsHelper.ParseInt(settings["RndInfoForCountBox"]); + bConsiderFails = SettingsHelper.ParseBool(settings["chkConsiderFails"]); + iPaceExtraGoalMS = SettingsHelper.ParseInt(settings["PaceExtraGoalMSCountBox"]); + iMalusMax = SettingsHelper.ParseInt(settings["MalusMaxCountBox"]); + iPaceDigits = SettingsHelper.ParseInt(settings["PaceDigitsCountBox"]); + bPaceWorst = SettingsHelper.ParseBool(settings["chkPaceWorst"]); + bDispGoodPace = SettingsHelper.ParseBool(settings["bDispGoodPace"]); + bGoodPaceTotal = SettingsHelper.ParseBool(settings["bGoodPaceTotal"]); + } + */ + private void btnDebug_Click(object sender, EventArgs e) + { + bDebug = true; + SettingChanged?.Invoke(this, e); + } + + private void label26_DoubleClick(object sender, EventArgs e) + { + if (!bExpSplitsvalue) + chkExpSplitsvalue.Visible = !chkExpSplitsvalue.Visible; } + + private void label15_DoubleClick(object sender, EventArgs e) + { + CalctimeCountBox.Visible = !CalctimeCountBox.Visible; + lblCalctime1.Visible = !lblCalctime1.Visible; + lblCalctime2.Visible = !lblCalctime2.Visible; + } + + private void btnNewVersion_Click(object sender, EventArgs e) + { + ServicePointManager.Expect100Continue = true; + ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12; + WebClient wc = new WebClient(); + try + { + string sVersion = wc.DownloadString("https://github.com/kasi777/PBChance/raw/master/PBChance/Version.txt"); + + if (sVersion.Remove(10, sVersion.Length - 10) != "1.4.5 ")//sVersion + " ") + { + wc.DownloadFile("https://github.com/kasi777/PBChance/raw/master/PBChance.dll", "PBChance.dll"); + MessageBox.Show("New Version available: Installed: " + sVersion + ", Available: " + sVersion.Remove(10, sVersion.Length - 10) + + "\n\r\n\rPBChance.dll is already downloaded into your LiveSplit directory. Move it into the Components directory to install it.\n\r\n\r" + + sVersion.Remove(0, 10) + "\n\r\n\rhttps://github.com/kasi777/PBChance"); + } + else + MessageBox.Show("PBChance is already up to date. \n\r\n\rhttps://github.com/kasi777/PBChance"); + } + catch + { + MessageBox.Show("Can't connect to https://github.com/kasi777/PBChance"); + } + } + + private void btnUpdList_Click(object sender, EventArgs e) { updateDataTable_Core2(dataGridView1, true); } + public delegate void updateDataTable_Delegate(DataGridView control, bool bStar); // defines a delegate type + public void updateDataTable_Core(DataGridView control, bool bStar) + { + if (this.InvokeRequired) + this.Invoke(new updateDataTable_Delegate(updateDataTable_Core), new object[] { control, bStar }); // invoking itself + else // the "functional part", executing only on the main thread + { + control.DataSource = DataGridViewV; + control.Columns[0].Width = 143; + control.Columns[1].Width = 80; // 77 min + control.Columns[2].Width = 87; // 87 min + control.Columns[3].Width = 80; // 73 min + if (DataGridViewV.Rows.Count > 2) + { + if (bStar) //(DataGridViewV.Rows[0][3].ToString() != this.lblSampleSize.Text.Remove(0, 13)) + { + this.lblSampleSize.Text = "Sample size: " + DataGridViewV.Rows[0][3] + " * "; + this.lblFaster.Text = "Faster: " + DataGridViewV.Rows[0][1] + " * "; + this.lblChance.Text = "Chance: " + (Convert.ToDouble(DataGridViewV.Rows[0][1]) / Convert.ToDouble(DataGridViewV.Rows[0][3])).ToString("0.000%") + "*"; + } + } + else if (DataGridViewV.Rows.Count <= 2) + { + if (bStar) + { + this.lblSampleSize.Text = "Sample size:" + DataGridViewV.Rows[0][1] + " * "; + this.lblFaster.Text = "Faster: " + "0*"; + this.lblChance.Text = "Chance: " + "0%*"; + } + } + } + + } + public void updateDataTable_Core2(DataGridView control, bool bStar) // this.UIThreadSync(() => X) this.Invoke(new MethodInvoker( X )) + { + /* + Random random = new Random(); + for (int i = 0; i < 10000; i++) + { + UsePercentOfAttempts = random.Next(0, 1) == 1 ? true : false; + UseFixedAttempts = random.Next(0, 1) == 1 ? true : false; + IgnoreRunCount = random.Next(0, 1) == 1 ? true : false; + AttemptCount = random.Next(1, 999); + MalusCount = random.Next(0, 999); + SplitclipCount = random.Next(1, 999); + TimediffCount = random.Next(0, 999); + SamplesCount = random.Next(1, 999999); + iCalctime = random.Next(0, 999); + bSurvival = random.Next(0, 1) == 1 ? true : false; + bDebug = random.Next(0, 1) == 1 ? true : false; + iOptimistic = random.Next(0, 999); + bRebalance = random.Next(0, 1) == 1 ? true : false; + bValueRuns = random.Next(0, 1) == 1 ? true : false; + iMinTimes = random.Next(1, 999); + iUpdate = random.Next(0, 999); + iSplitsvalue = random.Next(0, 100); + iSkipNewest = random.Next(0, 99); + iCalcToSplit = random.Next(0, 99); + bExpSplitsvalue = random.Next(0, 1) == 1 ? true : false; + bConsiderFails = random.Next(0, 1) == 1 ? true : false; + bIgnoreSkipClip = random.Next(0, 1) == 1 ? true : false; + iRndInfoEvery = random.Next(1, 999); // once per segment, in the middle (e.g. Best Segment Time=2:00, for 10 seconds, it will display between 0:55-1:05) + iRndInfoFor = random.Next(1, 999); + iAddBest = random.Next(0, 100); + bDispGoodPace = random.Next(0, 1) == 1 ? true : false; + bGoodPaceTotal = random.Next(0, 1) == 1 ? true : false; + iMalusMax = random.Next(1, 999); + iPaceExtraGoalMS = random.Next(1, 9999); + bPaceWorst = random.Next(0, 1) == 1 ? true : false; + iPaceDigits = random.Next(1, 3); + DisplayOdds = random.Next(0, 1) == 1 ? true : false; + IgnoreRunCount = random.Next(0, 1) == 1 ? true : false; + bInfoNext = random.Next(0, 1) == 1 ? true : false; + bSkipSplitStroke = random.Next(0, 1) == 1 ? true : false; + bDeviation = random.Next(0, 1) == 1 ? true : false; + } + */ + + this.UIThreadSync(() => control.DataSource = DataGridViewV); + this.UIThreadSync(() => control.Columns[0].Width = 130); + this.UIThreadSync(() => control.Columns[1].Width = 65); + this.UIThreadSync(() => control.Columns[2].Width = 65); + this.UIThreadSync(() => control.Columns[3].Width = 65); + this.UIThreadSync(() => control.Columns[4].Width = 65); + + if (DataGridViewV.Rows.Count > 2) + { + if (bStar) //(DataGridViewV.Rows[0][3].ToString() != this.lblSampleSize.Text.Remove(0, 13)) + { + this.lblSampleSize.Text = "Sample size: " + DataGridViewV.Rows[0][3] + " * "; + this.lblFaster.Text = "Faster: " + DataGridViewV.Rows[0][1] + " * "; + this.lblChance.Text = "Chance: " + (Convert.ToDouble(DataGridViewV.Rows[0][1]) / Convert.ToDouble(DataGridViewV.Rows[0][3])).ToString("0.000%") + "*"; + } + } + else if (DataGridViewV.Rows.Count <= 2) + { + if (bStar) + { + this.lblSampleSize.Text = "Sample size:" + DataGridViewV.Rows[0][1] + " * "; + this.lblFaster.Text = "Faster: " + "0*"; + this.lblChance.Text = "Chance: " + "0%*"; + } + } + } + /* + private void updateDataTable(bool bStar) + { + dataGridView1.DataSource = DataGridViewV; + dataGridView1.Columns[0].Width = 143; + dataGridView1.Columns[1].Width = 80; // 77 min + dataGridView1.Columns[2].Width = 87; // 87 min + dataGridView1.Columns[3].Width = 80; // 73 min + if (DataGridViewV.Rows.Count > 2) + { + if (bStar) //(DataGridViewV.Rows[0][3].ToString() != this.lblSampleSize.Text.Remove(0, 13)) + { + this.lblSampleSize.Text = "Sample size: " + DataGridViewV.Rows[0][3] + " * "; + this.lblFaster.Text = "Faster: " + DataGridViewV.Rows[0][1] + " * "; + this.lblChance.Text = "Chance: " + (Convert.ToDouble(DataGridViewV.Rows[0][1]) / Convert.ToDouble(DataGridViewV.Rows[0][3])).ToString("0.000%") + "*"; + } + } + else if (DataGridViewV.Rows.Count <= 2) + { + if (bStar) + { + this.lblSampleSize.Text = "Sample size:" + DataGridViewV.Rows[0][1] + " * "; + this.lblFaster.Text = "Faster: " + "0*"; + this.lblChance.Text = "Chance: " + "0%*"; + } + } + } + */ + /* + public delegate void viewUpdateDisplayDelegate(); // defines a delegate type + public void viewUpdateDisplay2() + { + if (this.InvokeRequired) + { + this.Invoke(new viewUpdateDisplayDelegate(viewUpdateDisplay2), new object[] { }); // invoking itself + } + else // the "functional part", executing only on the main thread + { + if (DataGridViewV.Rows.Count > 2) + { + this.lblSampleSize.Text = "Sample size: " + DataGridViewV.Rows[0][3]; + this.lblFaster.Text = "Faster: " + DataGridViewV.Rows[0][1]; + this.lblChance.Text = "Chance: " + (Convert.ToDouble(DataGridViewV.Rows[0][1]) / Convert.ToDouble(DataGridViewV.Rows[0][3])).ToString("0.000%"); + } + else + { + this.lblSampleSize.Text = "Sample size:" + DataGridViewV.Rows[0][1]; + this.lblFaster.Text = "Faster: " + "0"; + this.lblChance.Text = "Chance: " + "0%"; + } + } + }*/ + + public void viewUpdateDisplay() + { + try + { + if (DataGridViewV.Rows.Count > 2) + { + //this.UIThreadSync(() => lblSampleSize.Text = "Sample size:" + DataGridViewV.Rows[0][3]); + //this.UIThreadSync(() => lblFaster.Text = "Faster: " + DataGridViewV.Rows[0][1]); + //this.UIThreadSync(() => lblChance.Text = "Chance: " + (Convert.ToDouble(DataGridViewV.Rows[0][1]) / Convert.ToDouble(DataGridViewV.Rows[0][3])).ToString("0.000%")); + + this.lblSampleSize.Text = "Sample size: " + DataGridViewV.Rows[0][3]; + this.lblFaster.Text = "Faster: " + DataGridViewV.Rows[0][1]; + this.lblChance.Text = "Chance: " + (Convert.ToDouble(DataGridViewV.Rows[0][1]) / Convert.ToDouble(DataGridViewV.Rows[0][3])).ToString("0.000%"); + } + else + { + //this.UIThreadSync(() => lblSampleSize.Text = "Sample size:" + DataGridViewV.Rows[0][1]); + //this.UIThreadSync(() => lblFaster.Text = "Faster: 0"); + //this.UIThreadSync(() => lblChance.Text = "Chance: 0%"); + + this.lblSampleSize.Text = "Sample size:" + DataGridViewV.Rows[0][1]; + this.lblFaster.Text = "Faster: 0"; + this.lblChance.Text = "Chance: 0%"; + } + } + catch (System.ComponentModel.Win32Exception) { } + } + + //private void TabPages_Selected(Object sender, TabControlEventArgs e) + //{ + + // System.Text.StringBuilder messageBoxCS = new System.Text.StringBuilder(); + // messageBoxCS.AppendFormat("{0} = {1}", "TabPage", e.TabPage); + // messageBoxCS.AppendLine(); + // messageBoxCS.AppendFormat("{0} = {1}", "TabPageIndex", e.TabPageIndex); + // messageBoxCS.AppendLine(); + // messageBoxCS.AppendFormat("{0} = {1}", "Action", e.Action); + // messageBoxCS.AppendLine(); + // MessageBox.Show(messageBoxCS.ToString(), "Selected Event"); + //} + + private void tabHistory_Enter(object sender, EventArgs e) { /*dataGridView1.DataSource = DataGridViewV;*/ tabHistory_Enter_Core(dataGridView1); } + public delegate void tabHistory_Enter_Delegate(DataGridView control); // defines a delegate type + public void tabHistory_Enter_Core(DataGridView control) + { + if (this.InvokeRequired) + this.Invoke(new tabHistory_Enter_Delegate(tabHistory_Enter_Core), new object[] { control }); // invoking itself + else // the "functional part", executing only on the main thread + control.DataSource = DataGridViewV; + } + } +} + +public static class FormInvokeExtension +{ + static public void UIThreadAsync(this Control control, Action code) + { + if (control.InvokeRequired) + { + control.BeginInvoke(code); + return; + } + code.Invoke(); + } + + static public void UIThreadSync(this Control control, Action code) + { + if (control.InvokeRequired) + { + control.Invoke(code); + return; + } + code.Invoke(); } } + diff --git a/PBChance/Version 1.3.10.txt b/PBChance/Version 1.3.10.txt new file mode 100644 index 0000000..443ef09 --- /dev/null +++ b/PBChance/Version 1.3.10.txt @@ -0,0 +1,10 @@ +1.3.10 +Update Notes V1.3.10 (2019-04-08) + +1. About two times faster calculation, if the setting "Newer segment times are more important than old ones" is set to 100. + +2. Live views "Survival in this Segment", "Survival to the End", "Until here have Survived" displaying now in following format: "Success / Total = Chance" + +3. Additional display "Considered Runs (here/end)". It shows the number of runs taken into account up to the current segment and to the last segment. In addition, the total number is displayed. + +4. No live calculations in segment two have been fixed. diff --git a/PBChance/Version 1.3.8.txt b/PBChance/Version 1.3.8.txt new file mode 100644 index 0000000..fd64804 --- /dev/null +++ b/PBChance/Version 1.3.8.txt @@ -0,0 +1,16 @@ +1.3.8 +************************************************************* +*** Please download PBChance.dll manually from github.com *** +************************************************************* + +Update Notes V1.3.8 (2019-03-20) + +1. Displaying 1 in x is now better to read (less decimal if not required). + +2. The chance of survival also takes into account the setting "Consider at least X times" now. Thus, the survival chance to the end is definitely greater than 0%. For example, when this setting is 20, it takes into account the last 20 successfully runs (or as many as possible if there aren't 20 successfully runs available). + +3. The setting "display survival chance" now displays a) the chance to survive in the current segment and b) the chance to survive to the end. + +4. Check New Version will download the correct file now. + +5. No more periodicaly displays between splits, with a distance of 10 seconds (before best time and after a split). \ No newline at end of file diff --git a/PBChance/Version 1.3.9.txt b/PBChance/Version 1.3.9.txt new file mode 100644 index 0000000..04b0ae8 --- /dev/null +++ b/PBChance/Version 1.3.9.txt @@ -0,0 +1,19 @@ +1.3.9 +Update Notes V1.3.9 (2019-03-23) + +1. If the Setting "Display every x seconds a random information... is set to 0, PBChance will display a information once per segment (in the middle). +E.G. Display every 0 seconds ... for 10 seconds, and the best segment time is 2:00, then it will display between 0:55 and 1:05 in this segment. + +2. If a chance isn't possible, PBChance will not try to find a success run, and returns a 0% chance instantly. However, if it's possible, and PBChance can't find a success run within the sample size, PBChance will try to find a success run up to ten times longer than usual. + +3. When you split at a chance below 0.01%, the display will be in following format: x in n. "x" is the count of successfully runs, "n" is the count of the sample size. The usual display "x.xx% (1 in n)" will be overridden for this. + +4. The information "Times in this Segment" is changed to "Until here have Survived". It displays the survived runs at least to the last Segment, and how many attempts were necessary for it. + +5. New information "Combinations per Second". It tells how many combinations the computer can check for a PB within a second. The formula is the sample size divided by the elapsed time (the whole function) multiplied by one second. + +Update Notes V1.3.9b (2019-03-31) + +1. Remaining Combinations now displays the result as an advertised number. For example, "1.2 E+057" is now called "1.2 Octodecillion E57". Up to 308 digits are supported. + +2. If "Display odds (1 in N)" is checked, and you have a chance below 0.001% (live or split doesn't matter), the display will be in the following format "1 in n 0%", other than as described in point 3. So the decimal places are deleted in this case. If there aren't any successfully runs found, the display is simply "0%". diff --git a/PBChance/Version 1.4.0.txt b/PBChance/Version 1.4.0.txt new file mode 100644 index 0000000..f62e4ab --- /dev/null +++ b/PBChance/Version 1.4.0.txt @@ -0,0 +1,8 @@ +1.4.0 +Update Notes V1.4.0 (2019-05-14) + +1. About three times faster calculation with the help of a lookup-table, if the setting "Newer segment times are more important than old ones" is set to 100. Roughly 1,000,000 calculations and checks per second, if there are 15 splits left, tested with an average CPU. + +2. Skipped splits will no longer decrease and influence the PB-chance. For example, if one segment contains 8 correct split times, 2 skips and 3 failures, the chance to select a failure is 3/13 instead of 3/11. + +3. No live calculations in segment two have been fixed. diff --git a/PBChance/Version 1.4.1.txt b/PBChance/Version 1.4.1.txt new file mode 100644 index 0000000..8b03d6a --- /dev/null +++ b/PBChance/Version 1.4.1.txt @@ -0,0 +1,14 @@ +1.4.1 +Update Notes V1.4.1 (2019-05-28) + +1. The calculation for a good pace. It calculates the average segment time, for all successfully simulated runs. + +2. "Display Good Pace to PB" will display a good segment time, due to (1.). + It's not a static information, so if a pb isn't possible, it can't display, and if it's only barely possible, the times will be going harder to beat. + If you want to display the total time, check "Total time instead of Segment Time". + +3. You can make a data-table of a complete run based on (1.). Go into the settings and scroll down. The table will be updated automatically, however you can click on "Refresh List" for a more accurate result. + It will display the "Goal Time" (see 1.) in total and separately by the segments. In addition, it displays the best possible time, you can compare to this. + So, if you want to beat a certain pb-time, you can also adjust the setting "Time difference" for this, to shift the Goal PB Time what you want. + +4. New random information "Good pace to PB" and "Worth to continue". diff --git a/PBChance/Version 1.4.2.txt b/PBChance/Version 1.4.2.txt new file mode 100644 index 0000000..ffb55fc --- /dev/null +++ b/PBChance/Version 1.4.2.txt @@ -0,0 +1,21 @@ +1.4.2 +Update Notes V1.4.2 (2019-06-01) + +1. An extra goal can be specified for the PB pace. Use it, if you want to PB a better time, +e.g. your PB is currently 1:30:20 and you want 1:30:00, then you can set the difference time to 20000 milliseconds. +The regular PB Chance remains untouched for this setting, but you can see the chance in the data-list under "PB Regular/Extra Goal". + +2. If a successful run is found, it remembers the worst time per segment. It can display the worst segment, but it was successful in a simulated run. +Use it, if you want to know the slowest time you have to beat to continue. Use the average segment time, if you want to know an average segment time for a run to PB. + +3. A new random information based on (2.). + +4. The number of digits for a pace can be specified between 0-3 (1 second up to 1-millisecond resolution). + +5. A new row in the data list: Faster/Extra Goal/Total. Faster means the number of successful runs, Extra Goal means the same, but considering the setting in (1.), Total is the sample size. This information can be used to know the information in the table is complete. If not, the sample size to low, click on "Refresh List". Every time, you change a setting, the list will be automatically quick-updated, for a fast response, but not the whole sample size. After the calculation is complete - it takes about one second after a change in the settings - the results will no longer be changed when clicking on "refresh list" twice or more. + +6. The number of selecting a failure in a simulated run can be limited now. If it is set to 1 (default), only the first time the penalty time will be added. +If a failed segment will be selected two times, the simulated run will be count as a failure, no matter how good it would be. +In addition, if it's set to a low number, the number of combinations per second will increase significantly by two to three times. + +7. The settings have been rearranged and sorted into groups. diff --git a/PBChance/Version 1.4.3.txt b/PBChance/Version 1.4.3.txt new file mode 100644 index 0000000..305ad3a --- /dev/null +++ b/PBChance/Version 1.4.3.txt @@ -0,0 +1,17 @@ +1.4.3. +Update Notes (2019-06-21) + +New settings +- Sample size: At least x milliseconds. +- Display options: On "Skip Split" display "-", otherwise, the old value is retained. + +PB Pace +- Display worst PB Pace can be combined with average PB Pace. +- New column "Split Time" in the table PB Pace. + +Minor changes +- More alternative (shorter) text, if LiveSplit window is compact. +- New information: Health Status. It tells you are on PB Pace, based on linear chance increases each split. +- New information: PB Chance Extra Goal. If an extra goal is set, the chance to beat it. +- New information: Considered Runs (here/end). It tells the number of runs is considered in the actual segment, on the last segment, and the total number of runs available. +- Fixed several informations (in particular survival chance) diff --git a/PBChance/Version.txt b/PBChance/Version.txt new file mode 100644 index 0000000..fbb11ac --- /dev/null +++ b/PBChance/Version.txt @@ -0,0 +1,72 @@ +1.4.5 +Update Notes V1.4.5 (2020-08-14) +Bug Fix +"Check new version" will no longer cause a lock on opening a Message Box. + +1.4.3 +Update Notes V1.4.3 (2019-06-21) + +New settings +- Sample size: At least x milliseconds. +- Display options: On "Skip Split" display "-", otherwise, the old value is retained. + +PB Pace +- Display worst PB Pace can be combined with average PB Pace. +- New column "Split Time" in the table PB Pace. + +Minor changes +- More alternative (shorter) text, if LiveSplit window is compact. +- New information: Health Status. It tells you are on PB Pace, based on linear chance increases each split. +- New information: PB Chance Extra Goal. If an extra goal is set, the chance to beat it. +- New information: Considered Runs (here/end). It tells the number of runs is considered in the actual segment, on the last segment, and the total number of runs available. +- Fixed several informations (in particular survival chance) + + +1.4.2 +Update Notes V1.4.2 (2019-06-01) + +1. An extra goal can be specified for the PB pace. Use it, if you want to PB a better time, +e.g. your PB is currently 1:30:20 and you want 1:30:00, then you can set the difference time to 20000 milliseconds. +The regular PB Chance remains untouched for this setting, but you can see the chance in the data-list under "PB Regular/Extra Goal". + +2. If a successful run is found, it remembers the worst time per segment. It can display the worst segment, but it was successful in a simulated run. +Use it, if you want to know the slowest time you have to beat to continue. Use the average segment time, if you want to know an average segment time for a run to PB. + +3. A new random information based on (2.). + +4. The number of digits for a pace can be specified between 0-3 (1 second up to 1-millisecond resolution). + +5. A new row in the data list: Faster/Extra Goal/Total. Faster means the number of successful runs, Extra Goal means the same, but considering the setting in (1.), Total is the sample size. This information can be used to know the information in the table is complete. If not, the sample size to low, click on "Refresh List". Every time, you change a setting, the list will be automatically quick-updated, for a fast response, but not the whole sample size. After the calculation is complete - it takes about one second after a change in the settings - the results will no longer be changed when clicking on "refresh list" twice or more. + +6. The number of selecting a failure in a simulated run can be limited now. If it is set to 1 (default), only the first time the penalty time will be added. +If a failed segment will be selected two times, the simulated run will be count as a failure, no matter how good it would be. +In addition, if it's set to a low number, the number of combinations per second will increase significantly by two to three times. + +7. The settings have been rearranged and sorted into groups and tabs "General", "PB Pace" and "Display Options". + + +1.4.1 +Update Notes V1.4.1 (2019-05-28) + +1. The calculation for a good pace. It calculates the average segment time, for all successfully simulated runs. + +2. "Display Good Pace to PB" will display a good segment time, due to (1.). + It's not a static information, so if a pb isn't possible, it can't display, and if it's only barely possible, the times will be going harder to beat. + If you want to display the total time, check "Total time instead of Segment Time". + +3. You can make a data-table of a complete run based on (1.). Go into the settings and scroll down. The table will be updated automatically, however you can click on "Refresh List" for a more accurate result. + It will display the "Goal Time" (see 1.) in total and separately by the segments. In addition, it displays the best possible time, you can compare to this. + So, if you want to beat a certain pb-time, you can also adjust the setting "Time difference" for this, to shift the Goal PB Time what you want. + +4. New random information "Good pace to PB", "Worth to continue" and "Run is currently". + + + +1.4.0 +Update Notes V1.4.0 (2019-05-14) + +1. About three times faster calculation with the help of a lookup-table, if the setting "Newer segment times are more important than old ones" is set to 100. Roughly 1,000,000 calculations and checks per second, if there are 15 splits left, tested with an average CPU. + +2. Skipped splits will no longer decrease and influence the PB-chance. For example, if one segment contains 8 correct split times, 2 skips and 3 failures, the chance to select a failure is 3/13 instead of 3/11. + +3. No live calculations in segment two have been fixed. diff --git a/PBChance/images/PB Chance 1.4.1.gif b/PBChance/images/PB Chance 1.4.1.gif new file mode 100644 index 0000000..08e4816 Binary files /dev/null and b/PBChance/images/PB Chance 1.4.1.gif differ diff --git a/PBChance/images/PB Chance 1.4.2.gif b/PBChance/images/PB Chance 1.4.2.gif new file mode 100644 index 0000000..44a2331 Binary files /dev/null and b/PBChance/images/PB Chance 1.4.2.gif differ diff --git a/PBChance/images/PBChance Settings 1.4.2 P1.png b/PBChance/images/PBChance Settings 1.4.2 P1.png new file mode 100644 index 0000000..e82f347 Binary files /dev/null and b/PBChance/images/PBChance Settings 1.4.2 P1.png differ diff --git a/PBChance/images/PBChance Settings 1.4.2 P2b.png b/PBChance/images/PBChance Settings 1.4.2 P2b.png new file mode 100644 index 0000000..f8c7b92 Binary files /dev/null and b/PBChance/images/PBChance Settings 1.4.2 P2b.png differ diff --git a/PBChance/images/PBChance Settings 1.4.2 P2c.png b/PBChance/images/PBChance Settings 1.4.2 P2c.png new file mode 100644 index 0000000..9527aba Binary files /dev/null and b/PBChance/images/PBChance Settings 1.4.2 P2c.png differ diff --git a/PBChance/images/PBChance Settings 1.4.2 P3.png b/PBChance/images/PBChance Settings 1.4.2 P3.png new file mode 100644 index 0000000..98844f7 Binary files /dev/null and b/PBChance/images/PBChance Settings 1.4.2 P3.png differ diff --git a/PBChance/images/PBChance Title.png b/PBChance/images/PBChance Title.png new file mode 100644 index 0000000..b878a21 Binary files /dev/null and b/PBChance/images/PBChance Title.png differ diff --git a/README.md b/README.md index 6a57fec..6c3df23 100644 --- a/README.md +++ b/README.md @@ -1,25 +1,147 @@ # PBChance -PBChance Component for LiveSplit +PBChance Component for LiveSplit. It displays the chance of obtaining a PB on your current run. Whenever you reset, split or the run becomes slow, it runs a variable number (1,000,000 recommended) of simulations by randomly drawing the remaining splits from your splits in previous attempts and computes how many of those would result in a PB. -## What it is: +![Title](/PBChance/images/PBChance%20Title.png) -PBChance is a LiveSplit component that displays the chance of obtaining a PB on your current run. Whenever you reset or split, it runs 10,000 simulations by randomly drawing the remaining splits from your splits in previous attempts, and computes how many of those would result in a PB. +## Installation -## Installation: - -1. Place PBChance.dll into the Components directory of your LiveSplit installation. +1. Download ![PBChance.dll](/PBChance.dll) and place it into the Components directory of your LiveSplit installation. 2. Open LiveSplit. Right click -> Edit Layout -> [Giant "+" Button] -> Information -> PB Chance -3. You can configure how many of your most recent attempts will be used to calculate the PB chance. Go to Layout Settings and click on the PB Chance tab. You can either have it use a percentage of your most recent attempts, or just a fixed number of your most recent attempts. +3. Read below for general, PB pace and display settings. 4. Speedrun! -## Pictures: +## Features + +1. The calculation will perform in the background in an own thread. Even if the number of calculations is set to a high number, LiveSplit will not be interrupted during the calculation. +2. Autoupdate. The chance will be automatically updated if the chance drops during the run. +3. The calculation of a typical PB pace. +4. Additional informations can be displayed continuously or periodically. +5. Debug file. To retrace the calculation. This includes: Header data, Failed Runs, clipped segment, added times, count of times per segment, first generated route, results of first 10 successfully runs and 10 failures if possible, the results, the detailed segment times/chance of selection, the execution time and the number of possible combinations. +6. Check for the latest version and download it. Directly in the settings window. + +## General Settings (Tab 1) +![Settings1](/PBChance/images/PBChance%20Settings%201.4.2%20P1.png) + +1. Number of attempts used + 1. You can configure how many of your most recent attempts will be used to calculate the PB chance. Go to Layout Settings and click on the PB Chance tab. You can either have it use a percentage of your most recent attempts, or just a fixed number of your most recent attempts. Valid values: 1-99,999 Suggestion: 50 attempts on runs > 2h, 100 attempts on runs < 1h. + 2. Consider at least # times per segment +This will fill up times, if there are not enough because of the Setting "Use the most recent [x] attempts." +Valid values: 1-99,999 Suggestion: about 1/3 of the number of attempts. Checkbox: Also include failed segments. It will consider all intervening failes. Otherwise, only the additional times are considered. The chance is lower when it's activated. Suggestion: activated + +2. Sample Size + 1. Random sample survey # combinations + The minimum number of simulated runs. A lower number will calculate the result faster, a higher number gives a more stable result. However, it will calculate at least 900ms by default, so in most cases, the sample size is already more than a million (check "Actual Sample size"). Valid values: 1-9,999,999 Suggestion: around 1,000,000 + +3. Settings affect the PB Chance + 1. Penalty on failures # seconds + For each discontinued run, a failed segment will be generated. It's added every time to a simulated run, if a failed segment is selected. Valid values: 0-999 Suggestion: Start with 30. Should be set to a higher value if the reason for an interruption is essentially significant errors in a single segment (and lower in the opposite case). Can be also set to 0, if "Display survival chance" is set. In that case, multiply these two numbers will result in a chance, the same as an infinite penalty. + 2. Max fails #, then the penalty is infinite + If a simulated run contains more then # fails, the whole run is considered as a fail. +The number of selecting a failure in a simulated run can be limited now. If it is set to 1, only the first time the penalty time will be added. If a failed segment will be selected two times, the simulated run will be count as a failure, no matter how good it would be. In addition, if it's set to a low number, the number of combinations per second will increase significantly by two to three times. Valid values: 0-999 Suggestion: 1 + 3. Only consider segments, which are faster than {bestSegment[s] x # percent} + Very slow segment times will be eliminated. Should set to a number, which is clearly too slow for a normal run. Should be checked with the debug file (clipped segments), for the correct setting and result. Keep in mind, the failed runs will be kept. +Valid values: 100-999 Suggestion: 150-200 + 4. Newer segment times are more important than old ones + Newer attempts will be selected more often during a simulated run. This calculation is much faster when setting to exactly 100. +Valid values: 0-100 Suggestion: 100 + 5. Add the best time for each segment + Valid values: 0-100. Suggestion: about 25 +If the value is above 0, the best time will be added once for each segment, regardless of other settings. The larger the set value, the more often the best time will be selected. Point IV is relevant for this. Then there is always a chance, if the remaining best time is faster than the PB time, in particular a few runs are selected. Can be adjusted to optimize the chance estimation. + +Hint: The displaying chance on the start should be realistic. You can try with these settings to optimize the chance estimation. Keep in mind the chance will automatically grow up if you play better. Generate and open the text file pbchance_debug.txt (recommended a fixed font like currier) for understanding the calculation of PBChance. It is also recommended to read the overview picture below. + +## PB Pace Settings (Tab 2) +![Settings2](/PBChance/images/PBChance%20Settings%201.4.2%20P2c.png) + +1. Display Pace to PB + "Pace to PB" is defined as the average segment time, for all successfully simulated runs. So it displays a good, typical segment/split time, if it is on PB pace. It's not a static information, so if a pb isn't possible, it can't display, and if it's only barely possible, the times will be going harder to beat. +2. Split time instead of segment time + If you want to display the total time, check "Split time instead of Segment Time". +3. Worst segments instead of average in a successful pace + If a successful run is found, it remembers the worst time per segment. It can display the worst segment, but it was successful in a simulated run. Use it, if you want to know the slowest time you have to beat to continue. Use the average segment time, if you want to know an average segment time for a run to PB. +4. Extra goal: # milliseconds faster then PB + An extra goal can be specified for the PB pace. Use it, if you want to PB a better time, e.g. your PB is currently 1:30:20 and you want 1:30:00, then you can set the difference time to 20000 milliseconds. The regular PB Chance remains untouched for this setting, but you can see the chance in the data-list under "PB Regular/Extra Goal". +5. Display Resolution: # Digits of milliseconds + The number of digits for a pace can be specified between 0-3 (1 second up to 1-millisecond resolution). +6. Refresh list + Check in the table for "total" - this is the sample size. This information can be used to know the information in the table is complete. If not, the sample size to low, click on "Refresh List". Every time, you change a setting, the list will be automatically quick-updated, for a fast response, but not the whole sample size. After the calculation is complete - it takes about one second after a change in the settings - the results will no longer be changed when clicking on "refresh list" twice or more. +7. Data table + You can make a data-table of a complete run based on a PB pace. It displays the average PB pace (Avg Pace), worst PB pace (Worst Pace), and the best pace (Best). It displays the total Time in third row, following by all segment details. You can compare between the columns. If you want to beat a certain pb-time, you can adjust the setting "goal time", to shift it (time difference in the debugging settings will also work and can be shift in both directions). The first two rows are specials and have nothing to do with the column names. The first row is described as "Faster/Extra Goal/Total". Faster means the number of successful runs, Extra Goal means the same, but considering the setting in (4.), Total is the sample size. The second row is described as "PB regular/Extra Goal". It displays the regular PB chance, and the PB chance including the extra goal, described in (4.). + +## Display Settings (Tab 3) +![Settings3](/PBChance/images/PBChance%20Settings%201.4.2%20P3.png) + +1. Display Options + 1. Update automatically every # seconds when the chance drops +During a run, PBChance compares the current segment time with the best segment time. If it's slower, and the chance is above zero, PBChance calculates the new chance in the background as if you were splitting. If that chance becomes lower than the displayed one, the chance will be updated automatically. 0 means as fast as possible. +Valid values: 0-999 Suggestion: 1 + 2. Do not increase chance on "Skip Split" +Otherwise the chance will be recalculated similar to the command "Split". + 3. Display additional Split info +The first number is the difference of average split time and the best split time. The second number is the chance, to fail on the actual split. + 4. Display survival chance +This will display in addition two percent numbers. The first number is the chance to survive on actual segment, the second number is the chance to survive to the end. It considers the settings "Use most recent...attempts" and "Consider at least...attempts". + 5. Display standard deviation +Formula: Root of the average sum of the square difference of actual segment time to average segment time. + 6. Display every # seconds a random information for # seconds. +It will display a randomly chosen information at periodic intervals. For example, you can set to display every 60s the information for 10s. Then, it will start to display at 0:00:30 until 0:00:40, next will be 0:01:30 - 0:01:40 etc. Alternatively, you can set it to every 0s, then it will display a information once per segment (in the middle). For example, display every 0 seconds ... for 10 seconds, and the best segment time is 2:00, then it will display between 0:55 and 1:05 in this segment. In any case it will stop to display, if the chance is decreasing, and between splits with a gap of 10 seconds. It displays one of the following informations: + 1. Remaining Combinations + 2. Sample Size + 3. Survival in this Segment + 4. Survival to the End + 5. Standard Deviation + 6. Average Difference to Best + 7. Until here has Survived + 8. Combinations per Second + 9. Worth to continue + 10. Health Status + 11. Pace to PB + 12. Avg Difference to Best (All/Suc) + 13. Worst Pace to PB + 14. Avg/Worst Pace to PB + 15. Considered Runs (here/end) + +2. Debugging settings (should be 0 during regular runs) + 1. Time difference # seconds +This will simply add to the pb-time. +Valid values: -86400-86400 (24h) + 2. Skip the newest attempts # +To see how high the chance was before. +Valid values: 0-99999 + 3. Only calc to segment # +The calculation will stop at segment #, if it's not set to 0. + 4. Generate Debug File +This will generate a debug file "pbchance_debug.txt", and will be saved in your LiveSplit folder. You can open it with any text editor. See Features 4. for more information. + +## Check New Version + +When you are online, you can check for the newest version. If a newer version is available, you will be notified and PBChance automatically downloads PBChance.dll into your LiveSplit directory. To install the latest version, close LiveSplit and move PBChance.dll from the LiveSplit directory into the Components subdirectory. Your current PBChance.dll will be overwritten. + +## Pictures + +PBChance-Settings4 +[The component in action](https://ibb.co/byjJzq) + +PBChance-Overview2[Overview](https://ibb.co/bBt2mF2) + +## Troubleshooting + +*It displays W3 no times found in S# [Segment name] for a moment* + +PBChance can't find historical times, gives a warning and uses best split time instead. This can in certain circumstances happen, if the setting "Only consider segments, which are faster than the best segment x # percent" is set too low. + +*What's the difference between 0.00% and 0%?* + +If it displays 0%, then there are zero success runs found. If it displays 0.00%, then there are a few successful runs found, but the chance is rounded to 0.00%. However, it will display # in #, if you split it. These are the odds, and the chance is <0.01%. For example, 5 in 125000 means, 5 runs are faster than pb, 125000 runs are tested (it's equal to a 0.004% chance). + +*I'm starting to speedrun, and it displays 100%. Why that?* -[The component in action.](http://i.imgur.com/YIjln5P.png) +This chance isn't really calculated. It's assumed that the run will be finished, even if the run is restarted. As a result, the best personal time will be set, therefore a PB. Only then does PB Chance work with a real probability calculation. -[The configuration screen.](http://i.imgur.com/CgUuB46.png) +*It tells me there is a 0% chance, although it would theoretically be possible, so it can't be correct* -## Troubleshooting: +As long as a number of segments are pending, mathematically, this is still possible, but it is simply too unlikely that a randomly chosen run will be successful. Keep in mind that the number of possible combinations is incredibly large. In another example, it is theoretically possible to roll a 6 10 times in a row, but you will never manage to do it in your whole life because it is simply too unrealistic. -**It always displays "0%" or "-"** +*I've found a hidden setting. Does it work?* -You may need to configure the plugin to use a different number of attempts. For instance, it may not be reading any attempts in which you've completed a run. Additionally, you may have reset your split data at some point, which will remove the data necessary for PBChance to calculate its probability. If you want to debug the issue, try opening your splits file in a text editor (it's XML formatted). You may be able to spot missing splits, and it will inform you how to configure the PBChance component. +Yes.