예제 #1
0
        public override bool Parse(MSDFile.Value value)
        {
            // Only consider this line if it matches this property name.
            if (!DoesValueMatchProperty(value))
            {
                return(false);
            }

            List <T> parsedList = new List <T>();

            for (var paramIndex = 1; paramIndex < value.Params.Count; paramIndex++)
            {
                if (!string.IsNullOrEmpty(value.Params[paramIndex]))
                {
                    T tValue;
                    try
                    {
                        tValue = (T)Convert.ChangeType(value.Params[paramIndex], typeof(T));
                    }
                    catch (Exception)
                    {
                        Logger?.Warn($"{PropertyName}: Failed to Convert '{value.Params[paramIndex]}' to type '{typeof(T)}'.");
                        return(true);
                    }
                    parsedList.Add(tValue);
                }
            }

            Extras.AddSourceExtra(PropertyName, parsedList, true);
            return(true);
        }
예제 #2
0
        public override bool Parse(MSDFile.Value value)
        {
            // Only consider this line if it matches this property name.
            if (!ParseFirstParameter(value, out var rawStr))
            {
                return(false);
            }

            // Record the raw string to preserve formatting when writing.
            if (!string.IsNullOrEmpty(RawStringPropertyName))
            {
                Extras?.AddSourceExtra(RawStringPropertyName, rawStr);
            }

            if (!string.IsNullOrEmpty(rawStr))
            {
                var pairs = value.Params[1].Trim().Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
                foreach (var pair in pairs)
                {
                    var kvp = pair.Split('=');
                    if (kvp.Length != 2)
                    {
                        Logger?.Warn($"{PropertyName}: Malformed pair '{pair}'. This value will be ignored.");
                        continue;
                    }

                    if (!double.TryParse(kvp[0], out var time))
                    {
                        Logger?.Warn($"{PropertyName}: Malformed value '{kvp[0]}'. Expected double. This value will be ignored.");
                        continue;
                    }

                    var valueStr = kvp[1];
                    if (valueStr.IndexOf(';') >= 0)
                    {
                        valueStr = valueStr.Substring(0, valueStr.IndexOf(';'));
                    }

                    T tValue;
                    try
                    {
                        tValue = (T)Convert.ChangeType(valueStr, typeof(T));
                    }
                    catch (Exception)
                    {
                        Logger?.Warn($"{PropertyName}: Failed to Convert '{valueStr}' to type '{typeof(T)}'.");
                        continue;
                    }

                    Values[time] = tValue;
                }
            }

            Extras?.AddSourceExtra(PropertyName, Values);

            return(true);
        }
예제 #3
0
        /// <summary>
        /// Helper to check if the MSDFile.Value matches our PropertyName and parse
        /// the first Param as a string.
        /// </summary>
        /// <param name="value">MSDFile.Value to check.</param>
        /// <param name="parsedValue">Out param to hold the parsed string value.</param>
        /// <returns>
        /// True if this MSDFile.Value matches our PropertyName and false otherwise.
        /// </returns>
        protected bool ParseFirstParameter(MSDFile.Value value, out string parsedValue)
        {
            parsedValue = "";

            // Only consider this line if it matches this property name.
            if (!DoesValueMatchProperty(value))
            {
                return(false);
            }

            if (value.Params.Count > 1 && !string.IsNullOrEmpty(value.Params[1]))
            {
                parsedValue = value.Params[1];
            }

            return(true);
        }
예제 #4
0
        public override bool Parse(MSDFile.Value value)
        {
            // Only consider this line if it matches this property name.
            if (!ParseFirstParameter(value, out var notesStr))
            {
                return(false);
            }

            // Record whether this chart was written under NOTES or NOTES2.
            Chart.Extras.AddSourceExtra(SMCommon.TagFumenNotesType, PropertyName, true);

            // Parse the notes.
            if (!ParseNotes(Chart, notesStr))
            {
                Chart.Type = null;
            }

            return(true);
        }
예제 #5
0
        public override bool Parse(MSDFile.Value value)
        {
            // Only consider this line if it matches this property name.
            if (!ParseFirstParameter(value, out var chartValueStr))
            {
                return(false);
            }

            // Record the string value in the extras.
            Chart.Extras.AddSourceExtra(PropertyName, chartValueStr, true);

            // Only consider this line if the property is valid.
            var prop = Chart.GetType().GetProperty(ChartPropertyName, BindingFlags.Public | BindingFlags.Instance);

            if (null == prop || !prop.CanWrite)
            {
                Logger?.Error($"{PropertyName}: Could not find public instance writable property for Chart property '{ChartPropertyName}'.");
                return(true);
            }

            // Set the property on the Chart.
            object o;

            try
            {
                o = Convert.ChangeType(chartValueStr, prop.PropertyType);
            }
            catch (Exception)
            {
                Logger?.Warn($"{PropertyName}: Failed to Convert '{chartValueStr}' to type '{prop.PropertyType}' for Chart property '{ChartPropertyName}'.");
                return(true);
            }
            prop.SetValue(Chart, o, null);

            // Overwrite the extras value with the correct type.
            Chart.Extras.AddSourceExtra(PropertyName, o, true);

            return(true);
        }
예제 #6
0
        public override bool Parse(MSDFile.Value value)
        {
            // Only consider this line if it matches this property name.
            if (!ParseFirstParameter(value, out var valueStr))
            {
                return(false);
            }

            T tValue;

            try
            {
                tValue = (T)Convert.ChangeType(valueStr, typeof(T));
            }
            catch (Exception)
            {
                Logger?.Warn($"{PropertyName}: Failed to Convert '{valueStr}' to type '{typeof(T)}'.");
                return(true);
            }

            Extras.AddSourceExtra(PropertyName, tValue, true);
            return(true);
        }
예제 #7
0
        public override bool Parse(MSDFile.Value value)
        {
            // Only consider this line if it matches this property name.
            if (!ParseFirstParameter(value, out var type))
            {
                return(false);
            }

            Chart.Type = type;

            // Parse chart type and set number of players and inputs.
            if (!SMCommon.TryGetChartType(Chart.Type, out var smChartType))
            {
                Chart.Type = null;
                Logger?.Error($"{PropertyName}: Failed to parse {SMCommon.TagStepsType} value '{smChartType}'. This chart will be ignored.");
                return(true);
            }
            Chart.NumPlayers = SMCommon.Properties[(int)smChartType].NumPlayers;
            Chart.NumInputs  = SMCommon.Properties[(int)smChartType].NumInputs;

            Chart.Extras.AddSourceExtra(SMCommon.TagStepsType, Chart.Type, true);

            return(true);
        }
예제 #8
0
        public override bool Parse(MSDFile.Value value)
        {
            // Only consider this line if it matches this property name.
            if (!DoesValueMatchProperty(value))
            {
                return(false);
            }

            if (value.Params.Count < 7)
            {
                Logger?.Warn($"{PropertyName}: Expected at least 7 parameters. Found {value.Params.Count}. Ignoring all note data.");
                return(true);
            }

            var chart = new Chart
            {
                Type           = value.Params[1]?.Trim(SMCommon.SMAllWhiteSpace) ?? "",
                Description    = value.Params[2]?.Trim(SMCommon.SMAllWhiteSpace) ?? "",
                DifficultyType = value.Params[3]?.Trim(SMCommon.SMAllWhiteSpace) ?? ""
            };

            chart.Layers.Add(new Layer());

            // Record whether this chart was written under NOTES or NOTES2.
            chart.Extras.AddSourceExtra(SMCommon.TagFumenNotesType, PropertyName, true);

            // Parse the chart information before measure data.
            var chartDifficultyRatingStr = value.Params[4]?.Trim(SMCommon.SMAllWhiteSpace) ?? "";
            var chartRadarValuesStr      = value.Params[5]?.Trim(SMCommon.SMAllWhiteSpace) ?? "";

            // Parse the difficulty rating as a number.
            if (int.TryParse(chartDifficultyRatingStr, out var difficultyRatingInt))
            {
                chart.DifficultyRating = (double)difficultyRatingInt;
            }

            // Parse the radar values into a list.
            var radarValues    = new List <double>();
            var radarValuesStr = chartRadarValuesStr.Split(',');

            foreach (var radarValueStr in radarValuesStr)
            {
                if (double.TryParse(radarValueStr, out var d))
                {
                    radarValues.Add(d);
                }
            }
            chart.Extras.AddSourceExtra(SMCommon.TagRadarValues, radarValues, true);

            // Parse chart type and set number of players and inputs.
            if (!SMCommon.TryGetChartType(chart.Type, out var smChartType))
            {
                Logger?.Error($"{PropertyName}: Failed to parse {SMCommon.TagStepsType} value '{chart.Type}'. This chart will be ignored.");
                return(true);
            }
            chart.NumPlayers = SMCommon.Properties[(int)smChartType].NumPlayers;
            chart.NumInputs  = SMCommon.Properties[(int)smChartType].NumInputs;

            // Add a 4/4 time signature
            chart.Layers[0].Events.Add(new TimeSignature(new Fraction(SMCommon.NumBeatsPerMeasure, SMCommon.NumBeatsPerMeasure))
            {
                Position = new MetricPosition()
            });

            // Parse the notes.
            if (!ParseNotes(chart, value.Params[6] ?? ""))
            {
                return(true);
            }

            Song.Charts.Add(chart);

            return(true);
        }
예제 #9
0
 /// <summary>
 /// Helper to check if the MSDFile.Value matches our PropertyName.
 /// The 0th entry in the MSDFile.Value's Params is the property name.
 /// </summary>
 /// <param name="value">MSDFile.Value to check.</param>
 /// <returns>
 /// True if this MSDFile.Value matches our PropertyName and false otherwise.
 /// </returns>
 protected bool DoesValueMatchProperty(MSDFile.Value value)
 {
     return(value.Params.Count > 0 &&
            !string.IsNullOrEmpty(value.Params[0]) &&
            value.Params[0].ToUpper() == PropertyName);
 }
예제 #10
0
 /// <summary>
 /// Abstract Parse method for a MSDFile.Value.
 /// Checks the MSDFile.Value to see if it matches our PropertyName and parses
 /// the Params if does.
 /// </summary>
 /// <param name="value">MSDFile.Value to check and parse.</param>
 /// <returns>
 /// True if this MSDFile.Value matches our PropertyName and false otherwise.
 /// </returns>
 public abstract bool Parse(MSDFile.Value value);