private double WeightPV(double UnweightedPV, TimeSpan ChartLength, ChotaikoChartInfo ChartInfo) { double WeightedPV = UnweightedPV; // Average over length WeightedPV = 1000 * UnweightedPV / ChartLength.TotalMilliseconds; // Apply strain weight WeightedPV = Math.Pow(WeightedPV, StrainWeight); // Apply length bonus double LengthBonus = -(Math.Pow(LengthWeight, -ChartLength.TotalMilliseconds)) + 1; WeightedPV *= LengthBonus; // Apply accuracy bonus WeightedPV *= AccBonus(ChartInfo.AccValue); // Apply speed bonus WeightedPV *= SpeedBonus(ChartInfo.SpeedValue); // Multiply by PV constant WeightedPV *= PVConstant; // Return return(WeightedPV); }
public void Update(TimeSpan CurrentOffset, ChotaikoChartInfo ChartInfo) { // If too late, set as hit and accuracy to 0 if (!HitOffset.HasValue && CurrentOffset > this.Offset + ChartInfo.HitRange) { this.HitOffset = CurrentOffset; this.Accuracy = 0; } }
public void Draw(TimeSpan CurrentOffset, ChotaikoChartInfo ChartInfo) { /*// Error * double Error = -(CurrentOffset - this.Offset).TotalMilliseconds; * * // Error percentage * double ErrorPercent = 30 * Error / ChartInfo.ScreenInterval.TotalMilliseconds; * * if (ErrorPercent < 30 && ErrorPercent > 0) * { * for (int i = 0; i < ErrorPercent; i++) Console.Write("|"); * Console.WriteLine(); * }*/ Console.WriteLine("Beat with angle " + this.Theta + " ID " + this.NoteID); }
public bool OnPress(TimeSpan CurrentOffset, ChotaikoChartInfo ChartInfo) { // Already hit if (this.HitOffset.HasValue) { return(false); } // Too late if (CurrentOffset > this.Offset + ChartInfo.HitRange) { this.HitOffset = this.Offset + ChartInfo.HitRange; return(false); } // Too early else if (CurrentOffset < this.Offset - ChartInfo.HitRange) { // Hit now this.HitOffset = CurrentOffset; // Miss this.Accuracy = 0; } // Within range else { // Hit now this.HitOffset = CurrentOffset; // Hit error double Error = Math.Abs((CurrentOffset - this.Offset).TotalMilliseconds); // Error percentage double ErrorPercent = Error / ChartInfo.HitRange.TotalMilliseconds; // Accuracy = Hit error * 100 this.Accuracy = 100 - Convert.ToInt32(100 * ErrorPercent); } Console.WriteLine(this.Accuracy); return(true); }
/// <summary> /// Calculates performance value (PV) based on the accuracies of each note /// </summary> /// <returns>Performance value</returns> public double CalculatePerformanceValue(ChotaikoChartInfo ChartInfo) { // Unweighted performance value double UnweightedPV = 0; // Strain value of last object double Strain = 0; // Length of chart is difference between first and last objects TimeSpan ChartLength = PlayObjects[PlayObjects.Count - 1].GetOffset() - PlayObjects[0].GetOffset(); for (int i = 0; i < PlayObjects.Count - 1; i++) { IChotaikoPlayObject FirstObject = PlayObjects[i]; IChotaikoPlayObject SecondObject = PlayObjects[i + 1]; // Add accuracy to strain Strain += ((double)(FirstObject.GetAccuracy()) / 100); // Time difference between objects TimeSpan TimeDifference = SecondObject.GetOffset() - FirstObject.GetOffset(); // Inverse of strain to decay double InverseStrain = InversePVDecay(Strain); // Strain at clicking of second object double AfterStrain = PVDecay(InverseStrain + TimeDifference.TotalMilliseconds); // Strain is now start of next object Strain = AfterStrain; // Accumulated PV over this interval = Integral of strain double AccumulatedPV = IntegratePVDecay(InverseStrain, InverseStrain + TimeDifference.TotalMilliseconds); // Add accumulated PV to total unweighted PV UnweightedPV += AccumulatedPV; } double WeightedPV = WeightPV(UnweightedPV, ChartLength, ChartInfo); return(WeightedPV); }