private void AssociateTechniques(Arrangement x, Attributes att, string technique)
 {
     att.AssociatedTechniques.Add(String.Format("{0}{1}", x.ArrangementType == Sng.ArrangementType.Bass ? "Bass" : "", technique));
 }
        public string GenerateManifest(string dlcName, IList<Arrangement> arrangements, SongInfo songInfo, Platform platform)
        {
            var manifest = Manifest;
            manifest.Entries = new Dictionary<string, Dictionary<string, Attributes>>();
            bool firstarrangset = false;

            Arrangement vocal = null;
            if (arrangements.Any<Arrangement>(a => a.ArrangementType == Sng.ArrangementType.Vocal))
                vocal = arrangements.Single<Arrangement>(a => a.ArrangementType == Sng.ArrangementType.Vocal);

            var manifestFunctions = new ManifestFunctions(platform.version);
            var songPartition = new SongPartition();

            foreach (var x in arrangements)
            {
                var isVocal = x.ArrangementType == Sng.ArrangementType.Vocal;
                var song = (isVocal) ? null : Song.LoadFromFile(x.SongXml.File);

                var attribute = new Attributes();
                attribute.AlbumArt = String.Format("urn:llid:{0}", AggregateGraph.AlbumArt.LLID);
                attribute.AlbumNameSort = attribute.AlbumName = songInfo.Album;
                attribute.ArrangementName = x.Name.ToString();
                attribute.ArtistName = songInfo.Artist;
                attribute.ArtistNameSort = songInfo.ArtistSort;
                attribute.AssociatedTechniques = new List<string>();
                //Should be 51 for bass, 49 for vocal and guitar
                attribute.BinaryVersion = x.ArrangementType == Sng.ArrangementType.Bass ? 51 : 49;
                attribute.BlockAsset = String.Format("urn:emergent-world:{0}", AggregateGraph.XBlock.Name);
                attribute.ChordTemplates = null;
                attribute.DISC_DLC_OTHER = "Disc";
                attribute.DisplayName = songInfo.SongDisplayName;
                attribute.DLCPreview = false;
                attribute.EffectChainMultiplayerName = string.Empty;
                attribute.EffectChainName = isVocal ? "" : (dlcName + "_" + x.ToneBase == null ? "Default" : x.ToneBase.Replace(' ', '_'));
                attribute.EventFirstTimeSortOrder = 9999;
                attribute.ExclusiveBuild = new List<object>();
                attribute.FirstArrangementInSong = false;
                if (isVocal && !firstarrangset)
                {
                    firstarrangset = true;
                    attribute.FirstArrangementInSong = true;
                }
                attribute.ForceUseXML = true;
                attribute.Tag = "PLACEHOLDER Tag";
                attribute.InputEvent = isVocal ? "Play_Tone_Standard_Mic" : "Play_Tone_";
                attribute.IsDemoSong = false;
                attribute.IsDLC = true;
                attribute.LastConversionDateTime = "";
                int masterId = isVocal ? 1 : x.MasterId;
                attribute.MasterID_PS3 = masterId;
                attribute.MasterID_Xbox360 = masterId;
                attribute.MaxPhraseDifficulty = 0;
                attribute.PersistentID = x.Id.ToString().Replace("-", "").ToUpper();
                attribute.PhraseIterations = new List<PhraseIteration>();
                attribute.Phrases = new List<Phrase>();
                attribute.PluckedType = x.PluckedType == Sng.PluckedType.Picked ? "Picked" : "Not Picked";
                attribute.RelativeDifficulty = isVocal ? 0 : song.Levels.Count();
                attribute.RepresentativeArrangement = false;
                attribute.Score_MaxNotes = 0;
                attribute.Score_PNV = 0;
                attribute.Sections = new List<Section>();
                attribute.Shipping = true;
                attribute.SongAsset = String.Format("urn:llid:{0}", x.SongFile.LLID);
                attribute.SongEvent = String.Format("Play_{0}", dlcName);
                attribute.SongKey = dlcName;
                attribute.SongLength = 0;
                attribute.SongName = songInfo.SongDisplayName;
                attribute.SongNameSort = songInfo.SongDisplayNameSort;
                attribute.SongXml = String.Format("urn:llid:{0}", x.SongXml.LLID);
                attribute.SongYear = songInfo.SongYear;
                attribute.TargetScore = 0;
                attribute.ToneUnlockScore = 0;
                attribute.TwoHandTapping = false;
                attribute.UnlockKey = "";
                attribute.Tuning = x.Tuning;
                attribute.VocalsAssetId = x.ArrangementType == Sng.ArrangementType.Vocal ? "" : (vocal != null) ? String.Format("{0}|GRSong_{1}", vocal.Id, vocal.Name) : "";
                attribute.ChordTemplates = new List<ChordTemplate>();
                manifestFunctions.GenerateDynamicVisualDensity(attribute, song, x);

                if (!isVocal)
                {
                    #region "Associated Techniques"

                    attribute.PowerChords = song.HasPowerChords();
                    if (song.HasPowerChords()) AssociateTechniques(x, attribute, "PowerChords");
                    attribute.BarChords = song.HasBarChords();
                    if (song.HasBarChords()) AssociateTechniques(x, attribute, "BarChords");
                    attribute.OpenChords = song.HasOpenChords();
                    if (song.HasOpenChords()) AssociateTechniques(x, attribute, "ChordIntro");
                    attribute.DoubleStops = song.HasDoubleStops();
                    if (song.HasDoubleStops()) AssociateTechniques(x, attribute, "DoubleStops");
                    attribute.Sustain = song.HasSustain();
                    if (song.HasSustain()) AssociateTechniques(x, attribute, "Sustain");
                    attribute.Bends = song.HasBends();
                    if (song.HasBends()) AssociateTechniques(x, attribute, "Bends");
                    attribute.Slides = song.HasSlides();
                    if (song.HasSlides()) AssociateTechniques(x, attribute, "Slides");
                    attribute.Tremolo = song.HasTremolo();
                    if (song.HasTremolo()) AssociateTechniques(x, attribute, "Tremolo");
                    attribute.SlapAndPop = song.HasSlapAndPop();
                    if (song.HasSlapAndPop()) AssociateTechniques(x, attribute, "Slap");
                    attribute.Harmonics = song.HasHarmonics();
                    if (song.HasHarmonics()) AssociateTechniques(x, attribute, "Harmonics");
                    attribute.PalmMutes = song.HasPalmMutes();
                    if (song.HasPalmMutes()) AssociateTechniques(x, attribute, "PalmMutes");
                    attribute.HOPOs = song.HasHOPOs();
                    if (song.HasHOPOs()) AssociateTechniques(x, attribute, "HOPOs");
                    attribute.FretHandMutes = song.HasFretHandMutes();
                    if (song.HasFretHandMutes()) AssociateTechniques(x, attribute, "FretHandMutes");
                    attribute.DropDPowerChords = song.HasDropDPowerChords();
                    if (song.HasDropDPowerChords()) AssociateTechniques(x, attribute, "DropDPowerChords");
                    attribute.Prebends = song.HasPrebends();
                    if (song.HasPrebends()) AssociateTechniques(x, attribute, "Prebends");
                    attribute.Vibrato = song.HasVibrato();
                    if (song.HasVibrato()) AssociateTechniques(x, attribute, "Vibrato");

                    //Bass exclusive
                    attribute.TwoFingerPlucking = song.HasTwoFingerPlucking();
                    if (song.HasTwoFingerPlucking()) AssociateTechniques(x, attribute, "Plucking");
                    attribute.FifthsAndOctaves = song.HasFifthsAndOctaves();
                    if (song.HasFifthsAndOctaves()) AssociateTechniques(x, attribute, "Octave");
                    attribute.Syncopation = song.HasSyncopation();
                    if (song.HasSyncopation()) AssociateTechniques(x, attribute, "Syncopation");

                    #endregion

                    attribute.AverageTempo = songInfo.AverageTempo;
                    attribute.RepresentativeArrangement = true;
                    attribute.SongPartition = songPartition.GetSongPartition(x.Name, x.ArrangementType);
                    attribute.SongLength = (float)Math.Round((decimal)song.SongLength, 3, MidpointRounding.AwayFromZero); //rounded
                    attribute.LastConversionDateTime = song.LastConversionDateTime;
                    attribute.TargetScore = 100000;
                    attribute.ToneUnlockScore = 70000;
                    attribute.SongDifficulty = (float)song.PhraseIterations.Average(it => song.Phrases[it.PhraseId].MaxDifficulty);
                    manifestFunctions.GenerateChordTemplateData(attribute, song);
                    manifestFunctions.GeneratePhraseData(attribute, song);
                    manifestFunctions.GenerateSectionData(attribute, song);
                    manifestFunctions.GeneratePhraseIterationsData(attribute, song, platform.version);
                }
                var attrDict = new Dictionary<string, Attributes> { { "Attributes", attribute } };
                manifest.Entries.Add(attribute.PersistentID, attrDict);
            }
            manifest.ModelName = "GRSong_Asset";
            manifest.IterationVersion = 2;
            return JsonConvert.SerializeObject(manifest, Formatting.Indented);
        }
        public string GenerateManifest(string dlcName, IList<Arrangement> arrangements, SongInfo songInfo, RocksmithToolkitLib.Sng.GamePlatform platform)
        {
            var manifest = Manifest;
            manifest.Entries = new Dictionary<string, Dictionary<string, Attributes>>();
            bool firstarrangset = false;

            Arrangement vocal = null;
            if (arrangements.Any<Arrangement>(a => a.ArrangementType == Sng.ArrangementType.Vocal))
                vocal = arrangements.Single<Arrangement>(a => a.ArrangementType == Sng.ArrangementType.Vocal);

            foreach (var x in arrangements)
            {
                var attribute = new Attributes();
                attribute.AlbumArt = String.Format("urn:llid:{0}", AggregateGraph.AlbumArt.LLID);
                attribute.AlbumNameSort = attribute.AlbumName = songInfo.Album;
                attribute.ArrangementName = x.Name.ToString();
                attribute.ArtistName = songInfo.Artist;
                attribute.ArtistNameSort = songInfo.ArtistSort;
                attribute.AssociatedTechniques = new List<string>();
                //Should be 51 for bass, 49 for vocal and guitar
                attribute.BinaryVersion = x.ArrangementType == Sng.ArrangementType.Bass ? 51 : 49;
                attribute.BlockAsset = String.Format("urn:emergent-world:{0}", AggregateGraph.XBlock.Name);
                attribute.ChordTemplates = null;//
                attribute.DISC_DLC_OTHER = "Disc";
                attribute.DisplayName = songInfo.SongDisplayName;
                attribute.DLCPreview = false;
                attribute.EffectChainMultiplayerName = string.Empty;
                attribute.EffectChainName = x.ArrangementType == Sng.ArrangementType.Vocal ? "" : (dlcName + "_" + x.ToneName == null ? "Default" : x.ToneName.Replace(' ', '_'));
                attribute.EventFirstTimeSortOrder = 9999;
                attribute.ExclusiveBuild = new List<object>();
                attribute.FirstArrangementInSong = false;
                if (x.ArrangementType == Sng.ArrangementType.Vocal && !firstarrangset)
                {
                    firstarrangset = true;
                    attribute.FirstArrangementInSong = true;
                }
                attribute.ForceUseXML = true;
                attribute.Genre = "PLACEHOLDER Genre";
                attribute.InputEvent = x.ArrangementType == Sng.ArrangementType.Vocal ? "Play_Tone_Standard_Mic" : "Play_Tone_";
                attribute.IsDemoSong = false;
                attribute.IsDLC = true;
                attribute.LastConversionDateTime = "";
                int masterId = x.ArrangementType == Sng.ArrangementType.Vocal ? 1 : x.MasterId;
                attribute.MasterID_PS3 = masterId;
                attribute.MasterID_Xbox360 = masterId;
                attribute.MaxPhraseDifficulty = 0;
                attribute.PersistentID = x.Id.ToString().Replace("-", "").ToUpper();
                attribute.PhraseIterations = new List<PhraseIteration>();
                attribute.Phrases = new List<Phrase>();
                attribute.PluckedType = x.PluckedType == Sng.PluckedType.Picked ? "Picked" : "Not Picked";
                attribute.RelativeDifficulty = x.RelativeDifficulty;
                attribute.RepresentativeArrangement = false;
                attribute.Score_MaxNotes = 0;
                attribute.Score_PNV = 0;
                attribute.Sections = new List<Section>();
                attribute.Shipping = true;
                attribute.SongAsset = String.Format("urn:llid:{0}", x.SongFile.LLID);
                attribute.SongEvent = String.Format("Play_{0}", dlcName);
                attribute.SongKey = dlcName;
                attribute.SongLength = 0;
                attribute.SongName = songInfo.SongDisplayName;
                attribute.SongNameSort = songInfo.SongDisplayNameSort;
                attribute.SongXml = String.Format("urn:llid:{0}", x.SongXml.LLID);
                attribute.SongYear = songInfo.SongYear;
                attribute.TargetScore = 0;
                attribute.ToneUnlockScore = 0;
                attribute.TwoHandTapping = false;
                attribute.UnlockKey = "";
                attribute.Tuning = TunningDescription(Enum.Parse(typeof(Sng.InstrumentTuning), x.Tuning));
                attribute.VocalsAssetId = x.ArrangementType == Sng.ArrangementType.Vocal ? "" : (vocal != null) ? String.Format("{0}|GRSong_{1}", vocal.Id, vocal.Name) : "";
                attribute.ChordTemplates = new List<ChordTemplate>();

                if (x.ArrangementType == Sng.ArrangementType.Vocal)
                {
                    attribute.DynamicVisualDensity = new List<float>{
                        4.5f, 4.3000001907348633f, 4.0999999046325684f, 3.9000000953674316f, 3.7000000476837158f,
                        3.5f, 3.2999999523162842f, 3.0999999046325684f, 2.9000000953674316f, 2.7000000476837158f,
                        2.5f, 2.2999999523162842f, 2.0999999046325684f,
                        2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f};
                }
                else
                {
                    var serializer = new XmlSerializer(typeof(Song));
                    Song song;
                    using (var fileStream = File.OpenRead(x.SongXml.File))
                    {
                        song = (Song)serializer.Deserialize(fileStream);
                    }

                    attribute.DynamicVisualDensity = new List<float>(20);
                    float endSpeed = Math.Min(45f, Math.Max(10f, x.ScrollSpeed))/10f;
                    if (song.Levels.Length == 1)
                    {
                        for (int i = 0; i < 20; i++)
                        {
                            attribute.DynamicVisualDensity.Add(endSpeed);
                        }
                    }
                    else
                    {
                        double beginSpeed = 4.5d;
                        double maxLevel = Math.Min(song.Levels.Length, 16d) - 1;
                        double factor = maxLevel == 0 ? 1d : Math.Pow(endSpeed / beginSpeed, 1d / maxLevel);
                        for (int i = 0; i < 20; i++)
                        {
                            if (i >= maxLevel)
                            {
                                attribute.DynamicVisualDensity.Add(endSpeed);
                            }
                            else
                            {
                                attribute.DynamicVisualDensity.Add((float)(beginSpeed * Math.Pow(factor, i)));
                            }
                        }
                    }

                    #region "Associated Techniques"

                    attribute.PowerChords = x.PowerChords;
                    if (x.PowerChords) AssociateTechniques(x, attribute, "PowerChords");
                    attribute.BarChords = x.BarChords;
                    if (x.BarChords) AssociateTechniques(x, attribute, "BarChords");
                    attribute.OpenChords = x.OpenChords;
                    if (x.OpenChords) AssociateTechniques(x, attribute, "ChordIntro");
                    attribute.DoubleStops = x.DoubleStops;
                    if (x.DoubleStops) AssociateTechniques(x, attribute, "DoubleStops");
                    attribute.Sustain = song.HasSustain();
                    if (song.HasSustain()) AssociateTechniques(x, attribute, "Sustain");
                    attribute.Bends = song.HasBends();
                    if (song.HasBends()) AssociateTechniques(x, attribute, "Bends");
                    attribute.Slides = song.HasSlides();
                    if (song.HasSlides()) AssociateTechniques(x, attribute, "Slides");
                    attribute.Tremolo = song.HasTremolo();
                    if (song.HasTremolo()) AssociateTechniques(x, attribute, "Tremolo");
                    attribute.SlapAndPop = song.HasSlapAndPop();
                    if (song.HasSlapAndPop()) AssociateTechniques(x, attribute, "Slap");
                    attribute.Harmonics = song.HasHarmonics();
                    if (song.HasHarmonics()) AssociateTechniques(x, attribute, "Harmonics");
                    attribute.PalmMutes = song.HasPalmMutes();
                    if (song.HasPalmMutes()) AssociateTechniques(x, attribute, "PalmMutes");
                    attribute.HOPOs = song.HasHOPOs();
                    if (song.HasHOPOs()) AssociateTechniques(x, attribute, "HOPOs");
                    attribute.FretHandMutes = x.FretHandMutes;
                    if (x.FretHandMutes) AssociateTechniques(x, attribute, "FretHandMutes");
                    attribute.DropDPowerChords = x.DropDPowerChords;
                    if (x.DropDPowerChords) AssociateTechniques(x, attribute, "DropDPowerChords");
                    attribute.Prebends = x.Prebends;
                    if (x.Prebends) AssociateTechniques(x, attribute, "Prebends");
                    attribute.Vibrato = x.Vibrato;
                    if (x.Vibrato) AssociateTechniques(x, attribute, "Vibrato");

                    //Bass exclusive
                    attribute.TwoFingerPlucking = x.TwoFingerPlucking;
                    if (x.TwoFingerPlucking) AssociateTechniques(x, attribute, "Plucking");
                    attribute.FifthsAndOctaves = x.FifthsAndOctaves;
                    if (x.FifthsAndOctaves) AssociateTechniques(x, attribute, "Octave");
                    attribute.Syncopation = x.Syncopation;
                    if (x.Syncopation) AssociateTechniques(x, attribute, "Syncopation");

                    #endregion

                    attribute.AverageTempo = songInfo.AverageTempo;
                    attribute.RepresentativeArrangement = true;
                    if (x.ArrangementType != Sng.ArrangementType.Vocal)
                        attribute.SongPartition = GetSongPartition(x.Name, x.ArrangementType);
                    attribute.SongLength = song.SongLength;
                    attribute.LastConversionDateTime = song.LastConversionDateTime;
                    attribute.TargetScore = 100000;
                    attribute.ToneUnlockScore = 70000;
                    attribute.SongDifficulty = (float)song.PhraseIterations.Average(it => song.Phrases[it.PhraseId].MaxDifficulty);
                    GenerateChordTemplateData(attribute, song);
                    GeneratePhraseData(attribute, song);
                    GenerateSectionData(attribute, song);
                    GeneratePhraseIterationsData(attribute, song);
                }
                var attrDict = new Dictionary<string, Attributes> { { "Attributes", attribute } };
                manifest.Entries.Add(attribute.PersistentID, attrDict);
            }
            manifest.ModelName = "GRSong_Asset";
            manifest.IterationVersion = 2;
            return JsonConvert.SerializeObject(manifest, Formatting.Indented);
        }
        private void GenerateSectionData(Attributes attribute, Song song)
        {
            if (song.Sections == null)
            {
                return;
            }
            for (int i = 0; i < song.Sections.Length; i++)
            {
                var section = song.Sections[i];
                var sect = new Section
                {
                    Name = section.Name,
                    Number = section.Number,
                    StartTime = section.StartTime,
                    EndTime = (i >= song.Sections.Length - 1) ? song.SongLength : song.Sections[i + 1].StartTime,
                    UIName = String.Format("$[6007] {0} [1]", section.Name)

                };
                var sep = sect.Name.Split(new string[1] { " " }, StringSplitOptions.RemoveEmptyEntries);
                if (sep.Length == 1)
                {
                    string uiName;
                    if (SectionUINames.TryGetValue(sep[0], out uiName))
                        sect.UIName = uiName;
                }
                else
                {
                    string uiName;
                    if (SectionUINames.TryGetValue(sep[0], out uiName))
                    {
                        try
                        {
                            if (Convert.ToInt32(sep[1]) != 0 || Convert.ToInt32(sep[1]) != 1)
                                uiName += String.Format("|{0}", sep[1]);
                        }
                        catch { }
                        sect.UIName = uiName;
                    }
                }
                var phraseIterStart = -1;
                var phraseIterEnd = 0;
                var isSolo = false;
                if (song.PhraseIterations != null)
                {
                    for (int o = 0; o < song.PhraseIterations.Length; o++)
                    {
                        var phraseIter = song.PhraseIterations[o];
                        if (phraseIterStart == -1 && phraseIter.Time >= sect.StartTime)
                            phraseIterStart = o;
                        if (phraseIter.Time >= sect.EndTime)
                            break;
                        phraseIterEnd = o;
                        if (song.Phrases[phraseIter.PhraseId].Solo > 0)
                            isSolo = true;
                    }
                }
                sect.StartPhraseIterationIndex = phraseIterStart;
                sect.EndPhraseIterationIndex = phraseIterEnd;
                sect.IsSolo = isSolo;
                attribute.Sections.Add(sect);
            }
        }
        private void GeneratePhraseIterationsData(Attributes attribute, Song song)
        {
            if (song.PhraseIterations == null)
            {
                return;
            }
            for (int i = 0; i < song.PhraseIterations.Length; i++)
            {

                var phraseIteration = song.PhraseIterations[i];
                var phrase = song.Phrases[phraseIteration.PhraseId];
                var endTime = i >= song.PhraseIterations.Length - 1 ? song.SongLength : song.PhraseIterations[i + 1].Time;
                var phraseIt = new PhraseIteration
                {
                    StartTime = phraseIteration.Time,
                    EndTime = endTime,
                    PhraseIndex = phraseIteration.PhraseId,
                    Name = phrase.Name,
                    MaxDifficulty = phrase.MaxDifficulty,
                    MaxScorePerDifficulty = new List<float>()
                };
                attribute.PhraseIterations.Add(phraseIt);
            }
            var noteCnt = 0;
            foreach (var y in attribute.PhraseIterations)
            {
                if (song.Levels[y.MaxDifficulty].Notes != null)
                {
                    noteCnt += GetNoteCount(y.StartTime, y.EndTime, song.Levels[y.MaxDifficulty].Notes);
                }
                if (song.Levels[y.MaxDifficulty].Chords != null )
                {
                    noteCnt += GetChordCount(y.StartTime, y.EndTime, song.Levels[y.MaxDifficulty].Chords);
                }
            }
            attribute.Score_MaxNotes = noteCnt;
            attribute.Score_PNV = ((float)attribute.TargetScore) / noteCnt;

            foreach (var y in attribute.PhraseIterations)
            {
                var phrase = song.Phrases[y.PhraseIndex];
                for (int o = 0; o <= phrase.MaxDifficulty; o++)
                {
                    var multiplier = ((float)(o + 1)) / (phrase.MaxDifficulty + 1);
                    var pnv = attribute.Score_PNV;
                    var noteCount = 0;
                    if (song.Levels[o].Chords != null)
                    {
                        noteCount += GetNoteCount(y.StartTime, y.EndTime, song.Levels[o].Notes);
                    }
                    if (song.Levels[o].Chords != null)
                    {
                        noteCount += GetChordCount(y.StartTime, y.EndTime, song.Levels[o].Chords);
                    }
                    var score = pnv * noteCount * multiplier;
                    y.MaxScorePerDifficulty.Add(score);
                }
            }
        }
 private static void GeneratePhraseData(Attributes attribute, Song song)
 {
     if (song.Phrases == null)
     {
         return;
     }
     var ind = 0;
     foreach (var y in song.Phrases)
     {
         int itcount = song.PhraseIterations.Count(z => z.PhraseId == ind);
         attribute.Phrases.Add(new Phrase
         {
             IterationCount = itcount,
             MaxDifficulty = y.MaxDifficulty,
             Name = y.Name
         });
         ind++;
     }
 }
 private static void GenerateChordTemplateData(Attributes attribute, Song song)
 {
     var ind = 0;
     if (song.ChordTemplates == null)
     {
         return;
     }
     foreach (var y in song.ChordTemplates)
         attribute.ChordTemplates.Add(new ChordTemplate
         {
             ChordId = ind++,
             ChordName = y.ChordName,
             Fingers = new List<int> { y.Finger0, y.Finger1, y.Finger2, y.Finger3, y.Finger4, y.Finger5 },
             Frets = new List<int> { y.Fret0, y.Fret1, y.Fret2, y.Fret3, y.Fret4, y.Fret5 }
         });
 }