コード例 #1
0
ファイル: Beatmap.cs プロジェクト: CelegaS/ctb_calc
        //Get a string array from an entire section
        public string[] GetSection(string sectionname)
        {
            //Make a list of tags that will be returned
            List <string> tags = new List <string>();

            //Get where the section begins
            int sectionline = this.section.GetSectionLine(sectionname);

            //Loop through each line of the section
            //Start at sectionline + 1 to skip the section header itself
            for (int i = sectionline + 1; i < filelines.Length; i++)
            {
                //Exit the loop if we hit another section
                if (section.IsSection(filelines[i]))
                {
                    break;
                }

                //Otherwise add the line to the list
                tags.Add(filelines[i]);
            }

            string[] finaltags = tags.ToArray();
            finaltags = Dewlib.RemoveEmptyEntries(finaltags);

            //Return the list
            return(finaltags);
        }
コード例 #2
0
        private double Accuracy()
        {
            if (TotalHits() == 0)
            {
                return(0);
            }

            return(Dewlib.Clamp((double)TotalSuccessfulHits() / TotalHits(), 0.0, 1.0));
        }
コード例 #3
0
        //TODO: Throw error if somethings messed up with the timing section
        //Calculates the slider velocity at a specified time using the default
        //velocity and the relevant timing section
        //Timing points inside sliders don't affect the slider itself
        protected double GetSliderVelocity()
        {
            int ms = Int32.Parse(HitObjectParser.GetProperty(id, "time"));
            //Get the default slider velocity of the beatmap
            double slidervelocity = Double.Parse(map.GetTag("Difficulty", "SliderMultiplier"), CultureInfo.InvariantCulture);

            //Get all the timing sections of the beatmap
            string[] timings = this.map.GetSection("TimingPoints");
            //Will hold the relevant timing point
            string timingpoint = null;

            //Find the section that applies to the given time
            for (int i = 0; i < timings.Length; i++)
            {
                //Split the string by commas to get all the relevant times
                string[] attributes = timings[i].Split(',');
                //Trim each string just in case
                attributes = Dewlib.TrimStringArray(attributes);
                //If the timing point is a higher time, then we want the previous timing section
                if (Int32.Parse(attributes[0]) > ms)
                {
                    //avoid accessing a negative timing point
                    if (i == 0)
                    {
                        timingpoint = timings[0];
                    }
                    else
                    {
                        timingpoint = timings[i - 1];
                    }
                    break;
                }
            }

            //If the timing point needed is the very last one
            if (timingpoint == null)
            {
                timingpoint = timings[timings.Length - 1];
            }

            string[] properties = timingpoint.Split(',');
            //If the offset is positive, then there is no slider multiplication
            if (Double.Parse(properties[1], CultureInfo.InvariantCulture) > 0)
            {
                return(slidervelocity);
            }
            //Otherwise the slider multiplier is 100 / abs(offset)
            else
            {
                double offset = Double.Parse(properties[1], CultureInfo.InvariantCulture);
                return(slidervelocity * (100 / Math.Abs(offset)));
            }
        }
コード例 #4
0
ファイル: DiffCalc.cs プロジェクト: CelegaS/ctb_calc
        //Gets the difficulty of the entire map
        public double GetDifficulty()
        {
            HitPoint[] notes = this.GetNoteDifficulty();

            List <double> notedifficulties = new List <double>();

            foreach (HitPoint notepoint in notes)
            {
                notedifficulties.Add(notepoint.HitDifficulty);
            }
            return(Dewlib.SumScaledList(notedifficulties.ToArray(), 0.95));
        }
コード例 #5
0
ファイル: DiffCalc.cs プロジェクト: CelegaS/ctb_calc
        //Calculates the average of the top ten % of speeds between hitpoints in the given beatmap
        //(speeds = change in position / change in time)
        public double CalculateDistances()
        {
            List <double> speeds = new List <double>();

            for (int i = 1; i < positions.Length; i++)
            {
                //Cast to make division operation a double
                speeds.Add(Math.Abs(positions[i] - positions[i - 1]) / (double)(times[i] - times[i - 1]));
            }

            return(Dewlib.SumScaledList(speeds.ToArray(), 0.95));
        }
コード例 #6
0
ファイル: CatmullCurve.cs プロジェクト: CelegaS/ctb_calc
        public Point[] GetTickLocations(double interval, int count, int length)
        {
            List <Point> ticks = new List <Point>();

            //Make the number of steps 1000 for each curve
            double steps = 1000 / controlpoints.Count - 2 - 1;
            //how much to increment t by with every loop
            double increment = 1 / steps;
            //how much along the curve we have traveled so far
            double travelled = 0;
            //where to get the next point on a given curve
            //assign increment to get the next intended point
            double t = increment;
            //track which curve (defined by two points) is being looked at
            //start at 1 to not break tangent points
            int   curvestartpoint = 1;
            Point prev            = controlpoints[0];

            //Subtract two for the extra points to get the number of curves
            while (curvestartpoint < controlpoints.Count - 2)
            {
                Point  next     = GetPointBetween(curvestartpoint, curvestartpoint + 1, t);
                double distance = Dewlib.GetDistance(prev.x, prev.y, next.x, next.y);
                travelled += distance;
                prev       = next;
                if (travelled >= interval)
                {
                    ticks.Add(next);
                    travelled = 0;
                    if (ticks.Count == count)
                    {
                        break;
                    }
                }
                t += increment;
                if (t > 1)
                {
                    curvestartpoint++;
                    t -= 1;
                }
            }

            if (travelled > 0)
            {
                throw new Exception("Error, too many ticks to get in catmull curve");
            }

            return(ticks.ToArray());
        }
コード例 #7
0
ファイル: CircleCurve.cs プロジェクト: CelegaS/ctb_calc
        //Helper method that calculates the angles of the first and last points
        //of the curve
        private void calculateAngles(Point p1, Point p2, Point p3, double length)
        {
            this.startangle = Dewlib.RestrictRange(Math.Atan2(p1.y - center.y, p1.x - center.x), 0, 2 * Math.PI);
            double midangle = Dewlib.RestrictRange(Math.Atan2(p2.y - center.y, p2.x - center.x), 0, 2 * Math.PI);
            //NOT the last point of this curve
            //Only used to calculate the direction of the curve
            double lastangle = Dewlib.RestrictRange(Math.Atan2(p3.y - center.y, p3.x - center.x), 0, 2 * Math.PI);

            if (startangle >= midangle && midangle >= lastangle)
            {
                clockwise = false;
            }
            else if (startangle >= lastangle && lastangle >= midangle)
            {
                clockwise = true;
            }
            else if (midangle >= startangle && startangle >= lastangle)
            {
                clockwise = true;
            }
            else if (midangle >= lastangle && lastangle >= startangle)
            {
                clockwise = false;
            }
            else if (lastangle >= startangle && startangle >= midangle)
            {
                clockwise = false;
            }
            else if (lastangle >= midangle && midangle >= startangle)
            {
                clockwise = true;
            }

            //Use the arclength to calculate the final angle since the last control point
            //of the slider is NOT the last point of the curve
            //This is an angle differential since the formula assumes a start from an angle of 0
            double anglediff = length / radius;

            if (clockwise)
            {
                this.endangle = Dewlib.RestrictRange(startangle + anglediff, 0, 2 * Math.PI);
            }
            else
            {
                this.endangle = Dewlib.RestrictRange(startangle - anglediff, 0, 2 * Math.PI);
            }
        }
コード例 #8
0
ファイル: BezierCurve.cs プロジェクト: CelegaS/ctb_calc
        //Calculates a point on the curve
        public Point Bezier(double t)
        {
            Point result = new Point(0, 0);

            //Degree of the bezier curve
            int degree = points.Length - 1;

            int[] pascalrow = Dewlib.GetPascalRow(degree);

            for (int i = 0; i < points.Length; i++)
            {
                result.x += pascalrow[i] * Math.Pow((1 - t), degree - i) * Math.Pow(t, i) * points[i].x;
                result.y += pascalrow[i] * Math.Pow((1 - t), degree - i) * Math.Pow(t, i) * points[i].y;
            }

            return(result);
        }
コード例 #9
0
ファイル: LinearSlider.cs プロジェクト: CelegaS/ctb_calc
        //Uses the given list of control points to construct a list of curves
        //to account for red points
        public LinearSlider(string id, Beatmap amap) : base(id, amap)
        {
            //Get the initial hit point of the slider
            //Split into three lines for readibility
            Point initialcoord = new Point();

            initialcoord.x = Int32.Parse(HitObjectParser.GetProperty(id, "x"));
            initialcoord.y = Int32.Parse(HitObjectParser.GetProperty(id, "y"));

            //List<Point> curvepoints = new List<Point>();
            List <LinearCurve> accumulatedcurves = new List <LinearCurve>();

            //Normal linear slider
            if (controlpoints.Length == 1)
            {
                accumulatedcurves.Add(new LinearCurve(initialcoord, controlpoints[0]));
            }
            else
            {
                List <Point> allcontrolpoints = new List <Point>();

                //Add first point only if it's not repeated in the control points (old maps)
                if (initialcoord.IntX() != controlpoints[0].IntX() && initialcoord.IntY() != controlpoints[0].IntY())
                {
                    allcontrolpoints.Add(initialcoord);
                }
                allcontrolpoints.AddRange(controlpoints);

                Point[][] curvepoints = Dewlib.SplitPointList(allcontrolpoints.ToArray());
                foreach (Point[] curve in curvepoints)
                {
                    if (curve.Length > 2)
                    {
                        for (int i = 1; i < curve.Length; i++)
                        {
                            accumulatedcurves.Add(new LinearCurve(curve[i - 1], curve[i]));
                        }
                    }
                    else
                    {
                        accumulatedcurves.Add(new LinearCurve(curve[0], curve[1]));
                    }
                }
            }
            curves = accumulatedcurves.ToArray();
        }
コード例 #10
0
ファイル: BezierSlider.cs プロジェクト: CelegaS/ctb_calc
        protected override Point GetLastPoint()
        {
            //Necessary to avoid cases where the pixellength is something like 105.000004005432
            int length = Convert.ToInt32(Math.Floor(Double.Parse(HitObjectParser.GetProperty(id, "pixelLength"), CultureInfo.InvariantCulture)));

            //how many steps to travel through the curve
            //divide by curves.Length to scale this with the number of curves
            double steps = length * 2 / curves.Length;
            //how much to increment t by with every loop
            double increment = 1 / steps;
            //how much along the curve we have traveled so far
            double travelled = 0;
            //where to get the next point on a given curve
            //assign increment to get the next intended point
            double t    = increment;
            Point  prev = new Point();

            prev.x = Int32.Parse(HitObjectParser.GetProperty(id, "x"));
            prev.y = Int32.Parse(HitObjectParser.GetProperty(id, "y"));
            //which curve we are looking at
            int curvenumber = 0;

            while (curvenumber < curves.Length)
            {
                Point  next     = curves[curvenumber].Bezier(t);
                double distance = Dewlib.GetDistance(prev.x, prev.y, next.x, next.y);
                travelled += distance;
                prev       = next;
                if (travelled >= length)
                {
                    return(next);
                }

                t += increment;
                if (t > 1)
                {
                    curvenumber++;
                    t -= 1;
                }
            }

            //If we reached the end of the slider without accumulated sliderlength distance,
            //just assume that the last point is the last point of the bezier curve
            return(curves[curves.Length - 1].Bezier(1));
        }
コード例 #11
0
ファイル: DebugController.cs プロジェクト: CelegaS/ctb_calc
        public void WriteDebug(DiffCalc[] songs)
        {
            if (printdebug)
            {
                Console.WriteLine("Writing Debug...");

                int donecount = 0;
                Console.Write("0%\r");
                Directory.CreateDirectory("debug");

                foreach (DiffCalc calc in songs)
                {
                    HitPoint[]      notes       = calc.GetNoteDifficulty();
                    List <HitPoint> sortednotes = new List <HitPoint>(notes);

                    if (issortdifficulty)
                    {
                        sortednotes.Sort(HitPoint.CompareDifficulty);
                    }
                    else
                    {
                        sortednotes.Sort(HitPoint.CompareTime);
                    }

                    //Make sure files don't have invalid characters in the name
                    string filepath = Dewlib.MakeValidFilename(calc.GetBeatmapTitle() + ".txt");

                    filepath = "debug//" + filepath;
                    StreamWriter debugfile = new StreamWriter(filepath);

                    //Write the header
                    debugfile.WriteLine("[Difficulty]".PadRight(21) + "[Time]".PadRight(9) + "[Index]");
                    foreach (HitPoint notepoint in sortednotes)
                    {
                        string difficulty = notepoint.HitDifficulty.ToString();
                        string time       = notepoint.HitTime.ToString();
                        debugfile.WriteLine(difficulty.PadRight(21) + time.PadRight(9) + notepoint.HitID);
                    }

                    debugfile.Close();
                    donecount++;
                    Console.Write(Math.Round((double)donecount * 100 / songs.Length) + "%\r");
                }
            }
        }
コード例 #12
0
ファイル: CircleCurve.cs プロジェクト: CelegaS/ctb_calc
        //Gets a point on the approximated curve on the circle
        //Goes from 0 to 1, where 0 is the starting point and 1 is the ending point
        public Point GetPoint(double t)
        {
            //TODO: Make exception more useful
            if (t < 0 || t > 1)
            {
                throw new ArgumentOutOfRangeException();
            }

            double angle;
            double anglediff;

            if (clockwise)
            {
                if (endangle - startangle > 0)
                {
                    anglediff = endangle - startangle;
                }
                else
                {
                    anglediff = endangle + ((2 * Math.PI) - startangle);
                }

                angle = Dewlib.RestrictRange(t * anglediff + startangle, 0, 2 * Math.PI);
            }
            else
            {
                if (startangle - endangle > 0)
                {
                    anglediff = startangle - endangle;
                }
                else
                {
                    anglediff = startangle + ((2 * Math.PI) - endangle);
                }

                angle = Dewlib.RestrictRange(-t * anglediff + startangle, 0, 2 * Math.PI);
            }

            Point accessed = new Point();

            accessed.x = center.x + radius * Math.Cos(angle);
            accessed.y = center.y + radius * Math.Sin(angle);

            return(accessed);
        }
コード例 #13
0
ファイル: DebugController.cs プロジェクト: CelegaS/ctb_calc
 public DebugController()
 {
     //Checks if the file exists, then loads it if it does
     if (File.Exists("debugcommands.txt"))
     {
         using (StreamReader sr = new StreamReader("debugcommands.txt"))
         {
             string filecontents = sr.ReadToEnd();
             commandlist = filecontents.Split('\n');
             commandlist = Dewlib.TrimStringArray(commandlist);
         }
         this.FindCommands();
     }
     else
     {
         commandlist = new string[0];
     }
 }
コード例 #14
0
ファイル: Beatmap.cs プロジェクト: CelegaS/ctb_calc
        // Searches for a tag in a given section.
        // This method does not search for info in events, timingpoints, colours, or hitobjects.
        // If the tag is not found, the method returns null.
        public string GetTag(string sectionname, string tag)
        {
            sectionname = sectionname.ToUpper();

            //Get the correct line number for the given section
            int sectionline = section.GetTaggableSectionLine(sectionname);

            //If the section doesn't exist, or is not a taggable section, return null
            if (sectionline == -1)
            {
                return(null);
            }

            //Searches through each line for the requested tag
            for (int i = sectionline + 1; i < filelines.Length; i++)
            {
                //Section ends on empty line, so stop searching once you get to one
                if (filelines[i].Length == 0)
                {
                    break;
                }

                //Get a pair of strings, one side is the tag, other side is the value of the tag
                string[] pair = Dewlib.SplitFirst(filelines[i], ':');

                //Skip if the pair is invalid
                if (pair.Length != 2)
                {
                    continue;
                }

                //Trim the pair, since the tag value will have a space (e.g. Mode: 0)
                pair = Dewlib.TrimStringArray(pair);

                //Essentially if the tag is a match
                if (pair[0].ToUpper() == tag.ToUpper())
                {
                    //Return its value
                    return(pair[1]);
                }
            }
            //If nothing was found, return null
            return(null);
        }
コード例 #15
0
ファイル: CatmullCurve.cs プロジェクト: CelegaS/ctb_calc
        public Point GetPointAlong(int along)
        {
            //Make the number of steps 1000 for each curve
            double steps = 1000 / controlpoints.Count - 2 - 1;
            //how much to increment t by with every loop
            double increment = 1 / steps;
            //how much along the curve we have traveled so far
            double length = 0;
            //where to get the next point on a given curve
            //assign increment to get the next intended point
            double t = increment;
            //track which curve (defined by two points) is being looked at
            //start at 1 to not break tangent points
            int   curvestartpoint = 1;
            Point prev            = controlpoints[0];

            //Subtract two for the extra points to get the number of curves
            while (curvestartpoint < controlpoints.Count - 2)
            {
                Point  next     = GetPointBetween(curvestartpoint, curvestartpoint + 1, t);
                double distance = Dewlib.GetDistance(prev.x, prev.y, next.x, next.y);
                length += distance;
                prev    = next;
                if (length >= along)
                {
                    return(next);
                }

                t += increment;
                if (t > 1)
                {
                    curvestartpoint++;
                    t -= 1;
                }
            }

            //If we reached the end of the slider without accumulated sliderlength distance,
            //just assume that the last point is the last point of the curve
            return(GetPointBetween(controlpoints.Count - 2 - 1, controlpoints.Count - 2, 1));
        }
コード例 #16
0
        //Calculates the Milliseconds per Beat at a specified time by searching
        //through the entire timing points section
        //Timing points inside sliders don't affect the slider itself
        protected double GetMpB()
        {
            int ms = Int32.Parse(HitObjectParser.GetProperty(id, "time"));

            //Get all the timing sections of the beatmap
            string[] timings = this.map.GetSection("TimingPoints");
            //Just in case there is only one timing point
            string timingpoint = timings[0];

            //Find the section that applies to the given time
            for (int i = 0; i < timings.Length; i++)
            {
                //Split the string by commas to get all the relevant times
                string[] attributes = timings[i].Split(',');
                //Trim each string just in case
                attributes = Dewlib.TrimStringArray(attributes);

                if (Int32.Parse(attributes[0]) > ms)
                {
                    break;
                }

                else if (Double.Parse(attributes[1], CultureInfo.InvariantCulture) > 0)
                {
                    timingpoint = timings[i];
                }
                else
                {
                    continue;
                }
            }

            if (timingpoint == null)
            {
                throw new Exception("Error, no relevant timing point\nms=" + ms);
            }

            string[] properties = timingpoint.Split(',');
            return(Double.Parse(properties[1], CultureInfo.InvariantCulture));
        }
コード例 #17
0
    private void CalculateCatcherSize()
    {
        CS = Dewlib.Clamp(CS, 0, 10);

        //Calculate the integer part of CS first, then modify later based on the decimal
        double size = 144 - 12 * Math.Floor(CS);

        //If CS has a decimal place
        if (CS % 1 != 0)
        {
            //Avoid precision bugs - round to one decimal place
            double CSdecimal = Math.Round(CS - Math.Floor(CS), 1);

            if (CSdecimal == 0.2)
            {
                size -= 2;
            }
            else if (0.3 <= CSdecimal && CSdecimal <= 0.4)
            {
                size -= 4;
            }
            else if (0.5 <= CSdecimal && CSdecimal <= 0.6)
            {
                size -= 6;
            }
            else if (CSdecimal == 0.7)
            {
                size -= 8;
            }
            else if (0.8 <= CSdecimal && CSdecimal <= 0.9)
            {
                size -= 10;
            }
        }

        catcherwidth = (int)size;
    }
コード例 #18
0
ファイル: BezierSlider.cs プロジェクト: CelegaS/ctb_calc
        //Uses the given list of control points to construct a list of bezier curves
        //to account for red points
        public BezierSlider(string id, Beatmap amap) : base(id, amap)
        {
            //Get the initial hit point of the slider
            //Split into three lines for readibility
            Point initialcoord = new Point();

            initialcoord.x = Int32.Parse(HitObjectParser.GetProperty(id, "x"));
            initialcoord.y = Int32.Parse(HitObjectParser.GetProperty(id, "y"));

            List <BezierCurve> accumulatedcurves = new List <BezierCurve>();

            List <Point> allcontrolpoints = new List <Point>();

            allcontrolpoints.Add(initialcoord);
            allcontrolpoints.AddRange(controlpoints);
            Point[][] curvepoints = Dewlib.SplitPointList(allcontrolpoints.ToArray());

            foreach (Point[] curve in curvepoints)
            {
                accumulatedcurves.Add(new BezierCurve(curve));
            }

            curves = accumulatedcurves.ToArray();
        }
コード例 #19
0
ファイル: LinearCurve.cs プロジェクト: CelegaS/ctb_calc
 //Gets the distance between the start point and end point
 //Note that this is NOT the length of the slider
 public double DistanceBetween()
 {
     return(Dewlib.GetDistance(begin.x, begin.y, end.x, end.y));
 }
コード例 #20
0
ファイル: Beatmap.cs プロジェクト: CelegaS/ctb_calc
 /// <summary>
 /// Format the file's contents into an array (each entry is one line), loads it into this.filelines, and trims each entry of whitespace.
 /// Empty lines are preserved (to determine when a section ends)
 /// </summary>
 /// <param name="filecontents">The contents of the file in a string</param>
 private void FormatFileString(string filecontents)
 {
     filelines = filecontents.Split('\n');
     filelines = Dewlib.TrimStringArray(filelines);
 }
コード例 #21
0
ファイル: BezierSlider.cs プロジェクト: CelegaS/ctb_calc
        protected override int[] GetTickLocations()
        {
            //Necessary to avoid cases where the pixellength is something like 105.000004005432
            int length = Convert.ToInt32(Math.Floor(Double.Parse(HitObjectParser.GetProperty(id, "pixelLength"), CultureInfo.InvariantCulture)));

            int sliderruns = Int32.Parse(HitObjectParser.GetProperty(id, "repeat"));
            //Only need ticks for one slider length (no repeats needed)
            //Also no need for double conversion since TickCount is always divisible by sliderruns
            int tickcount = this.GetTickCount() / sliderruns;

            double slidervelocity = this.GetSliderVelocity();
            double tickrate       = Double.Parse(map.GetTag("Difficulty", "SliderTickRate"), CultureInfo.InvariantCulture);
            int    ticklength     = (int)Math.Round(slidervelocity * (100 / tickrate));

            if (length <= ticklength)
            {
                return(new int[0]);
            }

            List <Point> ticks = new List <Point>();

            //how many steps to travel through the curve
            //divide by curves.Length to scale this with the number of curves
            double steps = length * 2 / curves.Length;
            //how much to increment t by with every loop
            double increment = 1 / steps;
            //how much along the curve we have traveled so far
            double travelled = 0;
            //where to get the next point on a given curve
            //assign increment to get the next intended point
            double t    = increment;
            Point  prev = new Point();

            prev.x = Int32.Parse(HitObjectParser.GetProperty(id, "x"));
            prev.y = Int32.Parse(HitObjectParser.GetProperty(id, "y"));
            //which curve we are looking at
            int curvenumber = 0;

            while (curvenumber < curves.Length)
            {
                Point  next     = curves[curvenumber].Bezier(t);
                double distance = Dewlib.GetDistance(prev.x, prev.y, next.x, next.y);
                travelled += distance;
                prev       = next;
                if (travelled >= ticklength)
                {
                    ticks.Add(next);
                    travelled = 0;
                    if (ticks.Count == tickcount)
                    {
                        break;
                    }
                }
                t += increment;
                if (t > 1)
                {
                    curvenumber++;
                    t -= 1;
                }
            }

            if (travelled > 0)
            {
                throw new Exception("Error, too many ticks to get in bezier curve, travelled=" + travelled);
            }

            List <int> locations = new List <int>();

            foreach (Point i in ticks)
            {
                locations.Add(i.IntX());
            }

            return(locations.ToArray());
        }