private double CalculateDCDensity(int index, CatcherInfo catcher, int[] DCtimes, double basevelocity, double difficulty) { int DCindex = Array.BinarySearch(DCtimes, times[index]); if (DCindex > 0) { int DCcount = 0; double DCsum = 0; for (int j = DCindex; j > 0 && DCcount <= 10 && DCtimes[DCindex] - DCtimes[j] < 10000; j--) { DCcount++; DCsum += DCtimes[j] - DCtimes[j - 1]; } //Want inverse of average, so flip sum and count double DCmultiplier = Math.Pow(DCcount / DCsum * 500, 1) * catcher.GetCSMultiplier(); difficulty += basevelocity * DCmultiplier; //Previous jump was a hyper checking if (index > 2 && times[index - 1] != times[index - 2]) { double prevspeed = catcher.PercentHyper(Math.Abs(positions[index - 1] - positions[index - 2]), times[index - 1] - times[index - 2]); //If the previous jump was a hyper, scale difficulty to do DC by how fast the hyper was going if (prevspeed > 1) { difficulty += Math.Pow(prevspeed * 0.70, 2.3); } } double DChypermultiplier = Math.Pow(DCcount / DCsum * 50, 2); difficulty = CalculateHyperChanges(index, DCtimes, catcher, DChypermultiplier, difficulty); } return(difficulty); }
//Each hitobject marked as a "DC" means that it requires a directional change to catch public int[] GetDirectionalChangeTimes() { double circlesize = Double.Parse(map.GetTag("Difficulty", "CircleSize"), CultureInfo.InvariantCulture); CatcherInfo catcher = new CatcherInfo(circlesize); List <int> DCtimes = new List <int>(); Direction prevnotedir = catcher.CurDirection; for (int i = 1; i < hitpositions.Length; i++) { if (hitpositions[i] == hitpositions[i - 1]) { continue; } Direction notedirection; if (hitpositions[i] - hitpositions[i - 1] > 0) { notedirection = Direction.Right; } else { notedirection = Direction.Left; } bool isprevhyper; if (i > 1 && hittimes[i - 1] != hittimes[i - 2]) { isprevhyper = catcher.PercentHyper(Math.Abs(hitpositions[i - 1] - hitpositions[i - 2]), hittimes[i - 1] - hittimes[i - 2]) > 1; } else { isprevhyper = false; } int distance = Math.Abs(hitpositions[i] - hitpositions[i - 1]); double checkedsize = catcher.CatcherSize; if (isprevhyper) { checkedsize /= 2; } if (notedirection != catcher.CurDirection && (distance > checkedsize || notedirection == prevnotedir)) { catcher.CurDirection = notedirection; DCtimes.Add(hittimes[i]); } prevnotedir = catcher.CurDirection; } return(DCtimes.ToArray()); }
public int[] GetStopGoTimes() { double circlesize = Double.Parse(map.GetTag("Difficulty", "CircleSize"), CultureInfo.InvariantCulture); CatcherInfo catcher = new CatcherInfo(circlesize); List<int> SGtimes = new List<int>(); for(int i = 1; i < hitpositions.Length; i++) { if(hittimes[i] == hittimes[i-1] || Math.Abs(hitpositions[i] - hitpositions[i-1]) < 110) continue; double velocity = catcher.PercentHyper(Math.Abs(hitpositions[i] - hitpositions[i-1]), hittimes[i] - hittimes[i-1]); //Skip if not a hyper if(velocity <= 1) continue; //Skip if last two notes can't be caught together if(i < 2 || hitpositions[i-1] - hitpositions[i-2] > catcher.CatcherSize) continue; //Represents the last note that required no movement before the hyper jump int lastnonmoveindex = i-2; int leftmost = hitpositions[i-1] > hitpositions[i-2] ? hitpositions[i-2] : hitpositions[i-1]; int rightmost = hitpositions[i-1] > hitpositions[i-2] ? hitpositions[i-1] : hitpositions[i-2]; int templeft = leftmost; int tempright = rightmost; while(lastnonmoveindex > 0) { //Update the "bounds" of the pattern if(hitpositions[lastnonmoveindex-1] < leftmost) templeft = hitpositions[lastnonmoveindex-1]; else if(hitpositions[lastnonmoveindex-1] > rightmost) tempright = hitpositions[lastnonmoveindex-1]; //Actual "check" of the loop if(tempright - templeft > (catcher.CatcherSize)) break; leftmost = templeft; rightmost = tempright; lastnonmoveindex--; } int nonmovetime = hittimes[i] - hittimes[lastnonmoveindex]; if((rightmost - leftmost) / (double)nonmovetime < 0.5) SGtimes.Add(hittimes[i]); } return SGtimes.ToArray(); }
//Scale velocity based on whether the previous note was a hyper dash or not, compared to this jump private double CalculateHyperChanges(int index, int[] DCtimes, CatcherInfo catcher, double DCmultiplier, double difficulty) { if (index > 1) { double prevvel = catcher.PercentHyper(Math.Abs(positions[index - 1] - positions[index - 2]), (times[index - 1] - times[index - 2])); double thisvel = catcher.PercentHyper(Math.Abs(positions[index] - positions[index - 1]), (times[index] - times[index - 1])); if (prevvel > 1 && thisvel <= 1 && Math.Abs(positions[index] - positions[index - 1]) > catcher.CatcherSize / 2) { //Already know that this note requires a DC difficulty += (DCmultiplier * 1 * Math.Pow(thisvel, 2)); //next note requires a DC //Does not "double dip difficulty", as this note becomes harder to catch if the next note requires a DC //(since you have to time the DC correctly) if (index + 1 < positions.Length && Array.BinarySearch(DCtimes, times[index + 1]) > 0) { difficulty += (DCmultiplier * 1 * Math.Pow(thisvel, 2)); } } } return(difficulty); }
//Gets a list of every hitpoint and its associated difficulty public HitPoint[] GetNoteDifficulty() { double circlesize = Double.Parse(map.GetTag("Difficulty", "CircleSize"), CultureInfo.InvariantCulture); CatcherInfo catcher = new CatcherInfo(circlesize); PatternParser patterndetector = new PatternParser(map, positions, times); int[] DCtimes = patterndetector.GetDirectionalChangeTimes(); int[] SGtimes = patterndetector.GetStopGoTimes(); List <HitPoint> notes = new List <HitPoint>(); for (int i = 1; i < positions.Length; i++) { //Cast to make division operation a double //double velocity = Math.Abs(positions[i] - positions[i-1]) / (double)(times[i] - times[i-1]); //Scale velocity to be a percent of a pixel-jump - a pixel jump is equal to 1 double velocity = catcher.PercentHyper(Math.Abs(positions[i] - positions[i - 1]), times[i] - times[i - 1]); if (velocity > 1) { velocity = 0.2; //velocity = 1.0 / Math.Pow((times[i] - times[i-1]), 0.3); } else { //Scale normal jumps velocity = Math.Pow(velocity, 2); } double difficulty = velocity; difficulty = this.CalculateNonmovementDifficulty(i, catcher, difficulty); difficulty = this.CalculateDCDensity(i, catcher, DCtimes, velocity, difficulty); //difficulty = this.CalculateHyperChanges(i, DCtimes, catcher, difficulty); //difficulty = this.CalculateSGDensity(i, SGtimes, velocity, difficulty); notes.Add(new HitPoint(positions[i], times[i], difficulty, i)); } return(notes.ToArray()); }
//Each hitobject marked as a "DC" means that it requires a directional change to catch public int[] GetDirectionalChangeTimes() { double circlesize = Double.Parse(map.GetTag("Difficulty", "CircleSize"), CultureInfo.InvariantCulture); CatcherInfo catcher = new CatcherInfo(circlesize); List<int> DCtimes = new List<int>(); Direction prevnotedir = catcher.CurDirection; for(int i = 1; i < hitpositions.Length; i++) { if(hitpositions[i] == hitpositions[i-1]) continue; Direction notedirection; if(hitpositions[i] - hitpositions[i-1] > 0) notedirection = Direction.Right; else notedirection = Direction.Left; bool isprevhyper; if(i > 1 && hittimes[i-1] != hittimes[i-2]) isprevhyper = catcher.PercentHyper(Math.Abs(hitpositions[i-1] - hitpositions[i-2]), hittimes[i-1] - hittimes[i-2]) > 1; else isprevhyper = false; int distance = Math.Abs(hitpositions[i]-hitpositions[i-1]); double checkedsize = catcher.CatcherSize; if(isprevhyper) checkedsize /= 2; if(notedirection != catcher.CurDirection && (distance > checkedsize || notedirection == prevnotedir)) { catcher.CurDirection = notedirection; DCtimes.Add(hittimes[i]); } prevnotedir = catcher.CurDirection; } return DCtimes.ToArray(); }
//Scale velocity based on whether the previous note was a hyper dash or not, compared to this jump private double CalculateHyperChanges(int index, int[] DCtimes, CatcherInfo catcher, double DCmultiplier, double difficulty) { if(index > 1) { double prevvel = catcher.PercentHyper(Math.Abs(positions[index-1] - positions[index-2]), (times[index-1] - times[index-2])); double thisvel = catcher.PercentHyper(Math.Abs(positions[index] - positions[index-1]), (times[index] - times[index-1])); if(prevvel > 1 && thisvel <= 1 && Math.Abs(positions[index] - positions[index-1]) > catcher.CatcherSize / 2) { //Already know that this note requires a DC difficulty += (DCmultiplier * 1 * Math.Pow(thisvel, 2)); //next note requires a DC //Does not "double dip difficulty", as this note becomes harder to catch if the next note requires a DC //(since you have to time the DC correctly) if(index + 1 < positions.Length && Array.BinarySearch(DCtimes, times[index+1]) > 0) difficulty += (DCmultiplier * 1 * Math.Pow(thisvel, 2)); } } return difficulty; }
private double CalculateDCDensity(int index, CatcherInfo catcher, int[] DCtimes, double basevelocity, double difficulty) { int DCindex = Array.BinarySearch(DCtimes, times[index]); if(DCindex > 0) { int DCcount = 0; double DCsum = 0; for(int j = DCindex; j > 0 && DCcount <= 10 && DCtimes[DCindex] - DCtimes[j] < 10000; j--) { DCcount++; DCsum += DCtimes[j] - DCtimes[j-1]; } //Want inverse of average, so flip sum and count double DCmultiplier = Math.Pow(DCcount / DCsum * 500, 1) * catcher.GetCSMultiplier(); difficulty += basevelocity * DCmultiplier; //Previous jump was a hyper checking if(index > 2 && times[index-1] != times[index-2]) { double prevspeed = catcher.PercentHyper(Math.Abs(positions[index-1] - positions[index-2]), times[index-1] - times[index-2]); //If the previous jump was a hyper, scale difficulty to do DC by how fast the hyper was going if(prevspeed > 1) difficulty += Math.Pow(prevspeed * 0.70, 2.3); } double DChypermultiplier = Math.Pow(DCcount / DCsum * 50, 2); difficulty = CalculateHyperChanges(index, DCtimes, catcher, DChypermultiplier, difficulty); } return difficulty; }
//Gets a list of every hitpoint and its associated difficulty public HitPoint[] GetNoteDifficulty() { double circlesize = Double.Parse(map.GetTag("Difficulty", "CircleSize"), CultureInfo.InvariantCulture); CatcherInfo catcher = new CatcherInfo(circlesize); PatternParser patterndetector = new PatternParser(map, positions, times); int[] DCtimes = patterndetector.GetDirectionalChangeTimes(); int[] SGtimes = patterndetector.GetStopGoTimes(); List<HitPoint> notes = new List<HitPoint>(); for(int i = 1; i < positions.Length; i++) { //Cast to make division operation a double //double velocity = Math.Abs(positions[i] - positions[i-1]) / (double)(times[i] - times[i-1]); //Scale velocity to be a percent of a pixel-jump - a pixel jump is equal to 1 double velocity = catcher.PercentHyper(Math.Abs(positions[i] - positions[i-1]), times[i] - times[i-1]); if(velocity > 1) { velocity = 0.2; //velocity = 1.0 / Math.Pow((times[i] - times[i-1]), 0.3); } else { //Scale normal jumps velocity = Math.Pow(velocity, 2); } double difficulty = velocity; difficulty = this.CalculateNonmovementDifficulty(i, catcher, difficulty); difficulty = this.CalculateDCDensity(i, catcher, DCtimes, velocity, difficulty); //difficulty = this.CalculateHyperChanges(i, DCtimes, catcher, difficulty); //difficulty = this.CalculateSGDensity(i, SGtimes, velocity, difficulty); notes.Add(new HitPoint(positions[i], times[i], difficulty, i)); } return notes.ToArray(); }
public int[] GetStopGoTimes() { double circlesize = Double.Parse(map.GetTag("Difficulty", "CircleSize"), CultureInfo.InvariantCulture); CatcherInfo catcher = new CatcherInfo(circlesize); List <int> SGtimes = new List <int>(); for (int i = 1; i < hitpositions.Length; i++) { if (hittimes[i] == hittimes[i - 1] || Math.Abs(hitpositions[i] - hitpositions[i - 1]) < 110) { continue; } double velocity = catcher.PercentHyper(Math.Abs(hitpositions[i] - hitpositions[i - 1]), hittimes[i] - hittimes[i - 1]); //Skip if not a hyper if (velocity <= 1) { continue; } //Skip if last two notes can't be caught together if (i < 2 || hitpositions[i - 1] - hitpositions[i - 2] > catcher.CatcherSize) { continue; } //Represents the last note that required no movement before the hyper jump int lastnonmoveindex = i - 2; int leftmost = hitpositions[i - 1] > hitpositions[i - 2] ? hitpositions[i - 2] : hitpositions[i - 1]; int rightmost = hitpositions[i - 1] > hitpositions[i - 2] ? hitpositions[i - 1] : hitpositions[i - 2]; int templeft = leftmost; int tempright = rightmost; while (lastnonmoveindex > 0) { //Update the "bounds" of the pattern if (hitpositions[lastnonmoveindex - 1] < leftmost) { templeft = hitpositions[lastnonmoveindex - 1]; } else if (hitpositions[lastnonmoveindex - 1] > rightmost) { tempright = hitpositions[lastnonmoveindex - 1]; } //Actual "check" of the loop if (tempright - templeft > (catcher.CatcherSize)) { break; } leftmost = templeft; rightmost = tempright; lastnonmoveindex--; } int nonmovetime = hittimes[i] - hittimes[lastnonmoveindex]; if ((rightmost - leftmost) / (double)nonmovetime < 0.5) { SGtimes.Add(hittimes[i]); } } return(SGtimes.ToArray()); }