Exemple #1
0
 public IList <IEvent> Decode(
     TimingChunk timings,
     IEnumerable <Step> steps,
     IEnumerable <Trigger> triggers,
     IPanelMapper panelMapper)
 {
     return(_timingEventDecoder.Decode(timings)
            .Concat(_stepEventDecoder.Decode(steps, panelMapper))
            .Concat(_triggerEventDecoder.Decode(triggers))
            .OrderBy(ev => ev[NumericData.MetricOffset])
            .AsList());
 }
        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);
            }
        }