Exemple #1
0
        public IList <IEvent> Decode(IEnumerable <Step> steps, IPanelMapper panelMapper)
        {
            IEnumerable <IEvent> Do()
            {
                if (panelMapper == null)
                {
                    throw new RhythmCodexException("Panel mapper cannot be null");
                }

                var stepList = steps.AsList();

                foreach (var step in stepList)
                {
                    var panels       = step.Panels;
                    var freeze       = false;
                    var metricOffset = (BigRational)step.MetricOffset / SsqConstants.MeasureLength;

                    if (panels == 0x00)
                    {
                        freeze = true;
                        panels = step.ExtraPanels ?? 0;
                    }

                    if ((panels & 0x0F) == 0x0F)
                    {
                        yield return(new Event
                        {
                            [NumericData.MetricOffset] = metricOffset,
                            [NumericData.Player] = 0,
                            [FlagData.Shock] = true
                        });

                        panels &= 0xF0;
                    }

                    if ((panels & 0xF0) == 0xF0)
                    {
                        yield return(new Event
                        {
                            [NumericData.MetricOffset] = metricOffset,
                            [NumericData.Player] = 1,
                            [FlagData.Shock] = true
                        });

                        panels &= 0x0F;
                    }

                    foreach (var panelNumber in _stepPanelSplitter.Split(panels))
                    {
                        var mappedPanel = panelMapper.Map(panelNumber);
                        var isMapped    = mappedPanel != null;

                        yield return(new Event
                        {
                            [NumericData.MetricOffset] = metricOffset,
                            [NumericData.SourceColumn] = panelNumber,
                            [NumericData.Column] = isMapped ? mappedPanel.Panel : (BigRational?)null,
                            [NumericData.Player] = isMapped ? mappedPanel.Player : (BigRational?)null,
                            [FlagData.Freeze] = freeze ? true : (bool?)null,
                            [FlagData.Note] = freeze ? (bool?)null : true
                        });
                    }
                }
            }

            return(Do().ToList());
        }
        private IEnumerable <IChart> DecodeInternal(IEnumerable <Step1Chunk> data)
        {
            var chunks = data.AsList();

            if (!chunks.Any())
            {
                throw new RhythmCodexException("No chunks to decode.");
            }

            var timings = _timingChunkDecoder.Convert(chunks[0].Data);

            foreach (var chunk in chunks.Skip(1))
            {
                var timingEvents = _timingEventDecoder.Decode(timings);

                // Decode the raw steps.
                var steps = _stepChunkDecoder.Convert(chunk.Data);

                // Old charts store singles charts twice, as if it was a couples chart. So, check for that.
                int?panelCount = null;
                var steps1     = steps.Select(s => s.Panels & 0xF).ToArray();
                var steps2     = steps.Select(s => s.Panels >> 4).ToArray();
                var isSingle   = steps1.SequenceEqual(steps2);
                int?playerCount;
                if (isSingle)
                {
                    playerCount = 1;
                    panelCount  = 4;
                    foreach (var step in steps)
                    {
                        step.Panels &= 0xF;
                    }
                }
                else
                {
                    // Bit of a hack to make solo charts work.
                    playerCount = steps.Any(s => (s.Panels & 0xA0) != 0) ? 2 : 1;
                    panelCount  = _stepPanelSplitter.Split(steps.Aggregate(0, (i, s) => i | s.Panels)).Count() / playerCount;
                }

                // Determine what kind of chart this is based on the panels used.
                var mapper = _panelMapperSelector.Select(steps, new ChartInfo {
                    PanelCount = panelCount, PlayerCount = playerCount
                });

                // Convert the steps.
                var stepEvents = _stepEventDecoder.Decode(steps, mapper);
                var events     = timingEvents.Concat(stepEvents).ToList();
                var info       = _chartInfoDecoder.Decode(Bitter.ToInt32(chunk.Data.AsSpan(0)), mapper.PlayerCount, mapper.PanelCount);

                // Output metadata.
                var difficulty  = info.Difficulty;
                var type        = $"{SmGameTypes.Dance}-{info.Type}";
                var description = $"step1 - {events.Count(ev => ev[FlagData.Note] == true)} panels - {steps.Count(s => s.Panels != 0)} steps";

                var chart = new Chart
                {
                    Events = events,
                    [StringData.Difficulty]  = difficulty,
                    [StringData.Type]        = type,
                    [StringData.Description] = description
                };

                var firstTiming = timings.Timings.OrderBy(t => t.LinearOffset).First();
                chart[NumericData.LinearOffset] = chart.GetZeroLinearReference(
                    (BigRational)firstTiming.LinearOffset / timings.Rate,
                    (BigRational)firstTiming.MetricOffset / SsqConstants.MeasureLength);

                // Have a chart. :3
                yield return(chart);
            }
        }