private static void UpdateManifest2014(string songDirectory, Platform platform)
        {
            // UPDATE MANIFEST (RS2014)
            if (platform.version == GameVersion.RS2014)
            {
                var xmlFiles  = Directory.EnumerateFiles(songDirectory, "*.xml", SearchOption.AllDirectories);
                var jsonFiles = Directory.EnumerateFiles(songDirectory, "*.json", SearchOption.AllDirectories);
                foreach (var xml in xmlFiles)
                {
                    var xmlName = Path.GetFileNameWithoutExtension(xml);
                    if (xmlName.ToUpperInvariant().Contains("SHOWLIGHT"))
                    {
                        continue;
                    }
                    if (xmlName.ToUpperInvariant().Contains("VOCAL"))
                    {
                        continue;//TODO: Re-generate vocals manifest.
                    }
                    string json = jsonFiles.Where(name => Path.GetFileNameWithoutExtension(name) == xmlName).FirstOrDefault();
                    if (!String.IsNullOrEmpty(json))
                    {
                        var xmlContent = Song2014.LoadFromFile(xml);
                        var manifest   = new Manifest2014 <Attributes2014>();
                        var attr       = Manifest2014 <Attributes2014> .LoadFromFile(json).Entries.First().Value.First().Value;

                        var manifestFunctions = new ManifestFunctions(platform.version);

                        attr.PhraseIterations = new List <Manifest.PhraseIteration>();
                        manifestFunctions.GeneratePhraseIterationsData(attr, xmlContent, platform.version);

                        attr.Phrases = new List <Manifest.Phrase>();
                        manifestFunctions.GeneratePhraseData(attr, xmlContent);

                        attr.Sections = new List <Manifest.Section>();
                        manifestFunctions.GenerateSectionData(attr, xmlContent);

                        attr.MaxPhraseDifficulty = manifestFunctions.GetMaxDifficulty(xmlContent);

                        var attributeDictionary = new Dictionary <string, Attributes2014> {
                            { "Attributes", attr }
                        };
                        manifest.Entries.Add(attr.PersistentID, attributeDictionary);
                        manifest.SaveToFile(json);
                    }
                }
            }
        }
        private static void UpdateManifest2014(string songDirectory, Platform platform)
        {
            // UPDATE MANIFEST (RS2014)
            if (platform.version == GameVersion.RS2014)
            {
                var xmlFiles = Directory.EnumerateFiles(songDirectory, "*.xml", SearchOption.AllDirectories);
                var jsonFiles = Directory.EnumerateFiles(songDirectory, "*.json", SearchOption.AllDirectories);
                foreach (var xml in xmlFiles)
                {
                    var xmlName = Path.GetFileNameWithoutExtension(xml);
                    if (xmlName.ToUpperInvariant().Contains("SHOWLIGHT"))
                        continue;
                    if (xmlName.ToUpperInvariant().Contains("VOCAL"))
                        continue;//TODO: Re-generate vocals manifest.

                    string json = jsonFiles.FirstOrDefault(name => Path.GetFileNameWithoutExtension(name) == xmlName);
                    if (!String.IsNullOrEmpty(json))
                    {
                        var xmlContent = Song2014.LoadFromFile(xml);
                        var manifest = new Manifest2014<Attributes2014>();
                        var attr = Manifest2014<Attributes2014>.LoadFromFile(json).Entries.First().Value.First().Value;

                        var manifestFunctions = new ManifestFunctions(platform.version);

                        attr.PhraseIterations = new List<Manifest.PhraseIteration>();
                        manifestFunctions.GeneratePhraseIterationsData(attr, xmlContent, platform.version);

                        attr.Phrases = new List<Manifest.Phrase>();
                        manifestFunctions.GeneratePhraseData(attr, xmlContent);

                        attr.Sections = new List<Manifest.Section>();
                        manifestFunctions.GenerateSectionData(attr, xmlContent);

                        attr.MaxPhraseDifficulty = manifestFunctions.GetMaxDifficulty(xmlContent);

                        var attributeDictionary = new Dictionary<string, Attributes2014> { { "Attributes", attr } };
                        manifest.Entries.Add(attr.PersistentID, attributeDictionary);
                        manifest.SaveToFile(json);
                    }
                }
            }
        }
Example #3
0
        private int ApplyPackageDD(string file, string remSUS, string rampPath, out string consoleOutputPkg)
        {
            int  singleResult  = -1;
            bool exitedByError = false;

            consoleOutputPkg = String.Empty;
            var tmpDir      = Path.GetTempPath();
            var platform    = file.GetPlatform();
            var unpackedDir = Packer.Unpack(file, tmpDir, false, true, false);

            var xmlFiles = Directory.GetFiles(unpackedDir, "*.xml", SearchOption.AllDirectories);

            foreach (var xml in xmlFiles)
            {
                if (Path.GetFileNameWithoutExtension(xml).ToLower().Contains("vocal"))
                {
                    continue;
                }

                if (Path.GetFileNameWithoutExtension(xml).ToLower().Contains("showlight"))
                {
                    continue;
                }

                singleResult = ApplyDD(xml, remSUS, rampPath, out consoleOutputPkg, true, false);

                // UPDATE MANIFEST (RS2014) for update
                if (platform.version == RocksmithToolkitLib.GameVersion.RS2014)
                {
                    var json = Directory.GetFiles(unpackedDir, String.Format("*{0}.json", Path.GetFileNameWithoutExtension(xml)), SearchOption.AllDirectories);
                    if (json.Length > 0)
                    {
                        Attributes2014 attr = Manifest2014 <Attributes2014> .LoadFromFile(json[0]).Entries.ToArray()[0].Value.ToArray()[0].Value;

                        Song2014 xmlContent = Song2014.LoadFromFile(xml);

                        var manifestFunctions = new ManifestFunctions(platform.version);

                        attr.PhraseIterations = new List <PhraseIteration>();
                        manifestFunctions.GeneratePhraseIterationsData(attr, xmlContent, platform.version);

                        attr.Phrases = new List <Phrase>();
                        manifestFunctions.GeneratePhraseData(attr, xmlContent);

                        attr.Sections = new List <Section>();
                        manifestFunctions.GenerateSectionData(attr, xmlContent);

                        attr.MaxPhraseDifficulty = manifestFunctions.GetMaxDifficulty(xmlContent);

                        var manifest            = new Manifest2014 <Attributes2014>();
                        var attributeDictionary = new Dictionary <string, Attributes2014> {
                            { "Attributes", attr }
                        };
                        manifest.Entries.Add(attr.PersistentID, attributeDictionary);
                        manifest.SaveToFile(json[0]);
                    }
                }

                if (singleResult == 1)
                {
                    exitedByError = true;
                    break;
                }
                else if (singleResult == 2)
                {
                    consoleOutputPkg = String.Format("Arrangement file '{0}' => {1}", Path.GetFileNameWithoutExtension(xml), consoleOutputPkg);
                }
            }

            if (!exitedByError)
            {
                var newName = Path.Combine(Path.GetDirectoryName(file), String.Format("{0}_{1}{2}",
                                                                                      Path.GetFileNameWithoutExtension(file).StripPlatformEndName().GetValidName(false).Replace("_DD", "").Replace("_NDD", ""), isNDD ? "NDD" :  "DD", platform.GetPathName()[2]));
                Packer.Pack(unpackedDir, newName, true, platform);
                DirectoryExtension.SafeDelete(unpackedDir);
            }
            return(singleResult);
        }
        public Attributes2014(string arrangementFileName, Arrangement arrangement, DLCPackageData info, Platform platform)
            : base(arrangementFileName, arrangement, info, platform)
        {
            #region VARIABLES

            var dlcName = info.Name.ToLower();

            var xblockUrn    = String.Format(URN_TEMPLATE_SHORT, TagValue.EmergentWorld.GetDescription(), dlcName);
            var showlightUrn = String.Format(URN_TEMPLATE, TagValue.Application.GetDescription(), TagValue.XML.GetDescription(), String.Format("{0}_showlights", dlcName));
            var songXmlUrn   = String.Format(URN_TEMPLATE, TagValue.Application.GetDescription(), TagValue.XML.GetDescription(), String.Format(AggregateGraph2014.AggregateGraph2014.NAME_ARRANGEMENT, dlcName, arrangementFileName));
            var songSngUrn   = String.Format(URN_TEMPLATE, TagValue.Application.GetDescription(), TagValue.MusicgameSong.GetDescription(), String.Format(AggregateGraph2014.AggregateGraph2014.NAME_ARRANGEMENT, dlcName, arrangementFileName));

            var manifestFunctions = new ManifestFunctions(platform.version);

            #endregion

            #region FILL ATTRIBUTES

            ArrangementSort = arrangement.ArrangementSort;
            BlockAsset      = xblockUrn;
            manifestFunctions.GenerateDynamicVisualDensity(this, song2014, arrangement, GameVersion.RS2014);//2.0 constant for vocs in RS2
            FullName           = String.Format(AggregateGraph2014.AggregateGraph2014.NAME_ARRANGEMENT, info.Name, arrangement.ArrangementName);
            MasterID_PS3       = (IsVocal) ? -1 : arrangement.MasterId;
            MasterID_XBox360   = (IsVocal) ? -1 : arrangement.MasterId;
            PreviewBankPath    = String.Format("song_{0}_preview.bnk", info.Name.ToLower());
            RelativeDifficulty = 0; //Always 0 in RS2014
            ShowlightsXML      = showlightUrn;
            SongAsset          = songSngUrn;
            SongBank           = String.Format("song_{0}.bnk", info.Name.ToLower());
            SongEvent          = String.Format("Play_{0}", info.Name);
            SongXml            = songXmlUrn;
            SongVolume         = info.Volume;
            PreviewVolume      = info.PreviewVolume ?? SongVolume;

            // Only for Vocal
            if (IsVocal)
            {
                InputEvent = "Play_Tone_Standard_Mic";
                return;
            }

            // Only for instruments
            ArrangementProperties            = song2014.ArrangementProperties;
            ArrangementProperties.BassPick   = (int)arrangement.PluckedType;
            ArrangementProperties.PathLead   = Convert.ToInt32(arrangement.RouteMask == DLCPackage.RouteMask.Lead);
            ArrangementProperties.PathRhythm = Convert.ToInt32(arrangement.RouteMask == DLCPackage.RouteMask.Rhythm);
            ArrangementProperties.PathBass   = Convert.ToInt32(arrangement.RouteMask == DLCPackage.RouteMask.Bass);
            ArrangementProperties.RouteMask  = (int)arrangement.RouteMask;
            // Automatically set as two finger style if pick is not used
            ArrangementProperties.TwoFingerPicking = ArrangementProperties.PathBass == 1 && ArrangementProperties.BassPick == 0 ? 1 : 0;

            // TODO: monitor this change
            // EOF now properly sets the bonus/represent elements
            ArrangementProperties.Represent = Convert.ToInt32(arrangement.Represent);
            ArrangementProperties.BonusArr  = Convert.ToInt32(arrangement.BonusArr);

            // Metronome
            ArrangementProperties.Metronome = (int)arrangement.Metronome;

            if (arrangement.ArrangementName == Sng.ArrangementName.Combo)
            { //Exclusive condition
                if (arrangement.RouteMask == DLCPackage.RouteMask.Lead)
                {
                    ArrangementType = (int)Sng.ArrangementName.Lead;
                }
                else if (arrangement.RouteMask == DLCPackage.RouteMask.Rhythm)
                {
                    ArrangementType = (int)Sng.ArrangementName.Rhythm;
                }
                else
                {
                    ArrangementType = (int)arrangement.ArrangementName;
                }
            }
            else
            {
                ArrangementType = (int)arrangement.ArrangementName;
            }

            LastConversionDateTime = song2014.LastConversionDateTime;
            MaxPhraseDifficulty    = manifestFunctions.GetMaxDifficulty(song2014);

            TargetScore      = 100000;
            PhraseIterations = new List <PhraseIteration>();
            manifestFunctions.GeneratePhraseIterationsData(this, song2014, platform.version);
            //Score_MaxNotes -- Generated on function above
            //Score_PNV      -- Generated on function above

            Phrases = new List <Phrase>();
            manifestFunctions.GeneratePhraseData(this, song2014);

            Sections = new List <Section>();
            manifestFunctions.GenerateSectionData(this, song2014);

            SongAverageTempo = song2014.AverageTempo;
            SongOffset       = -song2014.StartBeat; //arrangement.Sng2014.Metadata.StartTime * -1;

            //SongPartition  -- Generated in DLCPackageCreator after this constructor

            ChordTemplates = new List <ChordTemplate>();
            manifestFunctions.GenerateChordTemplateData(this, song2014);

            //Chords TODO: create me
            try
            {
                // Commented out to check if this is cause of repeating chord display in game
                manifestFunctions.GenerateChords(this, song2014);
            }
            catch (Exception ex)
            {
                Console.WriteLine("GenerateChords: " + ex.Message);
            }

            //Techniques TODO: improve me
            // not source of 100% bug
            try
            {
                manifestFunctions.GenerateTechniques(this, song2014);
            }
            catch (Exception ex)
            {
                Console.WriteLine("GenerateTechniques: " + ex.Message);
            }

            //Fix for Dead tones
            var it = info.TonesRS2014;
            Tones            = new List <Tone2014>();
            Tone_A           = GetToneName(arrangement.ToneA, it);
            Tone_B           = GetToneName(arrangement.ToneB, it);
            Tone_Base        = GetToneName(arrangement.ToneBase, it);
            Tone_C           = GetToneName(arrangement.ToneC, it);
            Tone_D           = GetToneName(arrangement.ToneD, it);
            Tone_Multiplayer = GetToneName(arrangement.ToneMultiplayer, it);

            #endregion
        }
        public Attributes2014(string arrangementFileName, Arrangement arrangement, DLCPackageData info, Platform platform)
            : base(arrangementFileName, arrangement, info, platform)
        {
            #region VARIABLES

            var dlcName = info.Name.ToLower();

            var xblockUrn    = String.Format(URN_TEMPLATE_SHORT, TagValue.EmergentWorld.GetDescription(), dlcName);
            var showlightUrn = String.Format(URN_TEMPLATE, TagValue.Application.GetDescription(), TagValue.XML.GetDescription(), String.Format("{0}_showlights", dlcName));
            var songXmlUrn   = String.Format(URN_TEMPLATE, TagValue.Application.GetDescription(), TagValue.XML.GetDescription(), String.Format(AggregateGraph2014.AggregateGraph2014.NAME_ARRANGEMENT, dlcName, arrangementFileName));
            var songSngUrn   = String.Format(URN_TEMPLATE, TagValue.Application.GetDescription(), TagValue.MusicgameSong.GetDescription(), String.Format(AggregateGraph2014.AggregateGraph2014.NAME_ARRANGEMENT, dlcName, arrangementFileName));

            var manifestFunctions = new ManifestFunctions(platform.version);

            #endregion

            #region FILL ATTRIBUTES

            ArrangementSort = arrangement.ArrangementSort;
            BlockAsset      = xblockUrn;
            manifestFunctions.GenerateDynamicVisualDensity(this, SongContent, arrangement, GameVersion.RS2014);//2.0 constant for vocs in RS2
            FullName           = String.Format(AggregateGraph2014.AggregateGraph2014.NAME_ARRANGEMENT, info.Name, arrangement.Name);
            MasterID_PS3       = (IsVocal) ? -1 : arrangement.MasterId;
            MasterID_XBox360   = (IsVocal) ? -1 : arrangement.MasterId;
            PreviewBankPath    = String.Format("song_{0}_preview.bnk", info.Name.ToLower());
            RelativeDifficulty = 0; //Always 0 in RS2014
            ShowlightsXML      = showlightUrn;
            SongAsset          = songSngUrn;
            SongBank           = String.Format("song_{0}.bnk", info.Name.ToLower());
            SongEvent          = String.Format("Play_{0}", info.Name);
            SongXml            = songXmlUrn;
            SongVolume         = info.Volume;
            PreviewVolume      = info.PreviewVolume ?? SongVolume;

            // Only for Vocal
            if (IsVocal)
            {
                InputEvent = "Play_Tone_Standard_Mic";
            }

            // Only for instruments
            if (!IsVocal)
            {
                ArrangementProperties            = SongContent.ArrangementProperties;
                ArrangementProperties.BassPick   = (int)arrangement.PluckedType;
                ArrangementProperties.PathLead   = Convert.ToInt32(arrangement.RouteMask == DLCPackage.RouteMask.Lead);
                ArrangementProperties.PathRhythm = Convert.ToInt32(arrangement.RouteMask == DLCPackage.RouteMask.Rhythm);
                ArrangementProperties.PathBass   = Convert.ToInt32(arrangement.RouteMask == DLCPackage.RouteMask.Bass);
                ArrangementProperties.RouteMask  = (int)arrangement.RouteMask;

                // BONUS ARRANGEMENT
                ArrangementProperties.BonusArr = Convert.ToInt32(arrangement.BonusArr);

                // Metronome
                ArrangementProperties.Metronome = (int)arrangement.Metronome;

                if (arrangement.Name == Sng.ArrangementName.Combo)
                { //Exclusive condition
                    if (arrangement.RouteMask == DLCPackage.RouteMask.Lead)
                    {
                        ArrangementType = (int)Sng.ArrangementName.Lead;
                    }
                    else if (arrangement.RouteMask == DLCPackage.RouteMask.Rhythm)
                    {
                        ArrangementType = (int)Sng.ArrangementName.Rhythm;
                    }
                    else
                    {
                        ArrangementType = (int)arrangement.Name;
                    }
                }
                else
                {
                    ArrangementType = (int)arrangement.Name;
                }

                //Chords        -- //TODO: MISSING GENERATE

                ChordTemplates = new List <ChordTemplate>();
                manifestFunctions.GenerateChordTemplateData(this, SongContent);

                LastConversionDateTime = SongContent.LastConversionDateTime;
                MaxPhraseDifficulty    = manifestFunctions.GetMaxDifficulty(SongContent);

                TargetScore      = 100000;
                PhraseIterations = new List <PhraseIteration>();
                manifestFunctions.GeneratePhraseIterationsData(this, SongContent, platform.version);
                //Score_MaxNotes -- Generated on function above
                //Score_PNV      -- Generated on function above

                Phrases = new List <Phrase>();
                manifestFunctions.GeneratePhraseData(this, SongContent);

                Sections = new List <Section>();
                manifestFunctions.GenerateSectionData(this, SongContent);

                SongAverageTempo = SongContent.AverageTempo;
                SongOffset       = arrangement.Sng2014.Metadata.StartTime * -1;

                //SongPartition  -- Generated in DLCPackageCreator after this constructor

                //Techniques TODO: improove me
                try
                {
                    manifestFunctions.GenerateTechniques(this, SongContent);
                }
                catch { }

                //Fix for Dead tones
                var it = info.TonesRS2014;
                Tones            = new List <Tone2014>();
                Tone_A           = GetToneName(arrangement.ToneA, it);
                Tone_B           = GetToneName(arrangement.ToneB, it);
                Tone_Base        = GetToneName(arrangement.ToneBase, it);
                Tone_C           = GetToneName(arrangement.ToneC, it);
                Tone_D           = GetToneName(arrangement.ToneD, it);
                Tone_Multiplayer = GetToneName(arrangement.ToneMultiplayer, it);
            }

            #endregion
        }
        public Attributes2014(string arrangementFileName, Arrangement arrangement, DLCPackageData info, Platform platform)
            : base(arrangementFileName, arrangement, info, platform)
        {
            #region VARIABLES

            var dlcName = info.Name.ToLower();

            var xblockUrn = String.Format(URN_TEMPLATE_SHORT, TagValue.EmergentWorld.GetDescription(), dlcName);
            var showlightUrn = String.Format(URN_TEMPLATE, TagValue.Application.GetDescription(), TagValue.XML.GetDescription(), String.Format("{0}_showlights", dlcName));
            var songXmlUrn = String.Format(URN_TEMPLATE, TagValue.Application.GetDescription(), TagValue.XML.GetDescription(), String.Format(AggregateGraph2014.AggregateGraph2014.NAME_ARRANGEMENT, dlcName, arrangementFileName));
            var songSngUrn = String.Format(URN_TEMPLATE, TagValue.Application.GetDescription(), TagValue.MusicgameSong.GetDescription(), String.Format(AggregateGraph2014.AggregateGraph2014.NAME_ARRANGEMENT, dlcName, arrangementFileName));

            var manifestFunctions = new ManifestFunctions(platform.version);

            #endregion

            #region FILL ATTRIBUTES

            ArrangementSort = arrangement.ArrangementSort;
            BlockAsset = xblockUrn;
            manifestFunctions.GenerateDynamicVisualDensity(this, SongContent, arrangement, GameVersion.RS2014);//2.0 constant for vocs in RS2
            FullName = String.Format(AggregateGraph2014.AggregateGraph2014.NAME_ARRANGEMENT, info.Name, arrangement.Name);
            MasterID_PS3 = (IsVocal) ? -1 : arrangement.MasterId;
            MasterID_XBox360 = (IsVocal) ? -1 : arrangement.MasterId;
            PreviewBankPath = String.Format("song_{0}_preview.bnk", info.Name.ToLower());
            RelativeDifficulty = 0; //Always 0 in RS2014
            ShowlightsXML = showlightUrn;
            SongAsset = songSngUrn;
            SongBank = String.Format("song_{0}.bnk", info.Name.ToLower());
            SongEvent = String.Format("Play_{0}", info.Name);
            SongXml = songXmlUrn;
            SongVolume = info.Volume;
            PreviewVolume = info.PreviewVolume ?? SongVolume;

            // Only for Vocal
            if (IsVocal)
                InputEvent = "Play_Tone_Standard_Mic";

            // Only for instruments
            if (!IsVocal)
            {
                ArrangementProperties = SongContent.ArrangementProperties;
                ArrangementProperties.BassPick = (int)arrangement.PluckedType;
                ArrangementProperties.PathLead = Convert.ToInt32(arrangement.RouteMask == DLCPackage.RouteMask.Lead);
                ArrangementProperties.PathRhythm = Convert.ToInt32(arrangement.RouteMask == DLCPackage.RouteMask.Rhythm);
                ArrangementProperties.PathBass = Convert.ToInt32(arrangement.RouteMask == DLCPackage.RouteMask.Bass);
                ArrangementProperties.RouteMask = (int)arrangement.RouteMask;

                // BONUS ARRANGEMENT
                ArrangementProperties.BonusArr = Convert.ToInt32(arrangement.BonusArr);

                // Metronome
                ArrangementProperties.Metronome = (int)arrangement.Metronome;

                if (arrangement.Name == Sng.ArrangementName.Combo)
                { //Exclusive condition
                    if (arrangement.RouteMask == DLCPackage.RouteMask.Lead)
                        ArrangementType = (int)Sng.ArrangementName.Lead;
                    else if (arrangement.RouteMask == DLCPackage.RouteMask.Rhythm)
                        ArrangementType = (int)Sng.ArrangementName.Rhythm;
                    else
                        ArrangementType = (int)arrangement.Name;
                }
                else
                    ArrangementType = (int)arrangement.Name;

                //Chords        -- //TODO: MISSING GENERATE

                ChordTemplates = new List<ChordTemplate>();
                manifestFunctions.GenerateChordTemplateData(this, SongContent);

                LastConversionDateTime = SongContent.LastConversionDateTime;
                MaxPhraseDifficulty = manifestFunctions.GetMaxDifficulty(SongContent);

                TargetScore = 100000;
                PhraseIterations = new List<PhraseIteration>();
                manifestFunctions.GeneratePhraseIterationsData(this, SongContent, platform.version);
                //Score_MaxNotes -- Generated on function above
                //Score_PNV      -- Generated on function above

                Phrases = new List<Phrase>();
                manifestFunctions.GeneratePhraseData(this, SongContent);

                Sections = new List<Section>();
                manifestFunctions.GenerateSectionData(this, SongContent);

                SongAverageTempo = SongContent.AverageTempo;
                SongOffset = arrangement.Sng2014.Metadata.StartTime * -1;

                //SongPartition  -- Generated in DLCPackageCreator after this constructor

                //Techniques TODO: improve me
                try
                {
                    manifestFunctions.GenerateTechniques(this, SongContent);
                }
                catch { }

                //Fix for Dead tones
                var it = info.TonesRS2014;
                Tones = new List<Tone2014>();
                Tone_A = GetToneName(arrangement.ToneA, it);
                Tone_B = GetToneName(arrangement.ToneB, it);
                Tone_Base = GetToneName(arrangement.ToneBase, it);
                Tone_C = GetToneName(arrangement.ToneC, it);
                Tone_D = GetToneName(arrangement.ToneD, it);
                Tone_Multiplayer = GetToneName(arrangement.ToneMultiplayer, it);
            }

            #endregion
        }
        public string GenerateManifest(string dlcKey, 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);
                // TODO: add better AlbumNameSort feature
                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 ? "" : (dlcKey + "_" + 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.Genre = "PLACEHOLDER Genre";
                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.Length;
                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}", dlcKey);
                attribute.SongKey = dlcKey;
                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, GameVersion.RS2012);

                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);
        }
        private static void UpdateManifest2014(string songDirectory, Platform platform)
        {
            if (platform.version != GameVersion.RS2014)
            {
                return;
            }

            var hsanFiles = Directory.EnumerateFiles(songDirectory, "*.hsan", SearchOption.AllDirectories).ToList();

            if (!hsanFiles.Any())
            {
                throw new DataException("Error: could not find any hsan file");
            }
            if (hsanFiles.Count > 1)
            {
                throw new DataException("Error: there is more than one hsan file");
            }

            var manifestHeader = new ManifestHeader2014 <AttributesHeader2014>(platform);
            var hsanFile       = hsanFiles.First();
            var jsonFiles      = Directory.EnumerateFiles(songDirectory, "*.json", SearchOption.AllDirectories).ToList();
            var xmlFiles       = Directory.EnumerateFiles(songDirectory, "*.xml", SearchOption.AllDirectories).ToList();

            //var songFiles = xmlFiles.Where(x => !x.ToLower().Contains("showlight") && !x.ToLower().Contains("vocal")).ToList();
            //var vocalFiles = xmlFiles.Where(x => x.ToLower().Contains("vocal")).ToList();

            foreach (var xmlFile in xmlFiles)
            {
                var xmlName = Path.GetFileNameWithoutExtension(xmlFile);
                if (xmlName.ToLower().Contains("showlight"))
                {
                    continue;
                }

                var json = jsonFiles.FirstOrDefault(name => Path.GetFileNameWithoutExtension(name) == xmlName);
                if (String.IsNullOrEmpty(json))
                {
                    continue;
                }

                var attr = Manifest2014 <Attributes2014> .LoadFromFile(json).Entries.First().Value.First().Value;

                if (!xmlName.ToLower().Contains("vocal"))
                {
                    var manifestFunctions = new ManifestFunctions(platform.version);
                    var xmlContent        = Song2014.LoadFromFile(xmlFile);

                    attr.PhraseIterations = new List <Manifest.PhraseIteration>();
                    manifestFunctions.GeneratePhraseIterationsData(attr, xmlContent, platform.version);

                    attr.Phrases = new List <Manifest.Phrase>();
                    manifestFunctions.GeneratePhraseData(attr, xmlContent);

                    attr.Sections = new List <Manifest.Section>();
                    manifestFunctions.GenerateSectionData(attr, xmlContent);

                    attr.Tuning = new TuningStrings();
                    manifestFunctions.GenerateTuningData(attr, xmlContent);

                    attr.MaxPhraseDifficulty = manifestFunctions.GetMaxDifficulty(xmlContent);
                }

                // else { // TODO: good place to update vocals }

                // write updated json file
                var attributeDictionary = new Dictionary <string, Attributes2014> {
                    { "Attributes", attr }
                };
                var manifest = new Manifest2014 <Attributes2014>();
                manifest.Entries.Add(attr.PersistentID, attributeDictionary);
                manifest.SaveToFile(json);

                // update manifestHeader (hsan) entry
                var attributeHeaderDictionary = new Dictionary <string, AttributesHeader2014> {
                    { "Attributes", new AttributesHeader2014(attr) }
                };
                if (platform.IsConsole)
                {
                    // One for each arrangements (Xbox360/PS3)
                    manifestHeader = new ManifestHeader2014 <AttributesHeader2014>(platform);
                    manifestHeader.Entries.Add(attr.PersistentID, attributeHeaderDictionary);
                }
                else
                {
                    manifestHeader.Entries.Add(attr.PersistentID, attributeHeaderDictionary);
                }
            }

            // write updated hsan file
            manifestHeader.SaveToFile(hsanFile);
        }
        private static void UpdateManifest2014(string songDirectory, Platform platform)
        {
            if (platform.version != GameVersion.RS2014)
                return;

            var hsanFiles = Directory.EnumerateFiles(songDirectory, "*.hsan", SearchOption.AllDirectories).ToList();
            if (!hsanFiles.Any())
                throw new DataException("Error: could not find any hsan file");
            if (hsanFiles.Count > 1)
                throw new DataException("Error: there is more than one hsan file");

            var manifestHeader = new ManifestHeader2014<AttributesHeader2014>(platform);
            var hsanFile = hsanFiles.First();
            var jsonFiles = Directory.EnumerateFiles(songDirectory, "*.json", SearchOption.AllDirectories).ToList();
            var xmlFiles = Directory.EnumerateFiles(songDirectory, "*.xml", SearchOption.AllDirectories).ToList();
            //var songFiles = xmlFiles.Where(x => !x.ToLower().Contains("showlight") && !x.ToLower().Contains("vocal")).ToList();
            //var vocalFiles = xmlFiles.Where(x => x.ToLower().Contains("vocal")).ToList();

            foreach (var xmlFile in xmlFiles)
            {
                var xmlName = Path.GetFileNameWithoutExtension(xmlFile);
                if (xmlName.ToLower().Contains("showlight"))
                    continue;

                var json = jsonFiles.FirstOrDefault(name => Path.GetFileNameWithoutExtension(name) == xmlName);
                if (String.IsNullOrEmpty(json))
                    continue;

                var attr = Manifest2014<Attributes2014>.LoadFromFile(json).Entries.First().Value.First().Value;

                if (!xmlName.ToLower().Contains("vocal"))
                {
                    var manifestFunctions = new ManifestFunctions(platform.version);
                    var xmlContent = Song2014.LoadFromFile(xmlFile);

                    attr.PhraseIterations = new List<Manifest.PhraseIteration>();
                    manifestFunctions.GeneratePhraseIterationsData(attr, xmlContent, platform.version);

                    attr.Phrases = new List<Manifest.Phrase>();
                    manifestFunctions.GeneratePhraseData(attr, xmlContent);

                    attr.Sections = new List<Manifest.Section>();
                    manifestFunctions.GenerateSectionData(attr, xmlContent);

                    attr.Tuning = new TuningStrings();
                    manifestFunctions.GenerateTuningData(attr, xmlContent);

                    attr.MaxPhraseDifficulty = manifestFunctions.GetMaxDifficulty(xmlContent);
                }

                // else { // TODO: good place to update vocals }

                // write updated json file
                var attributeDictionary = new Dictionary<string, Attributes2014> { { "Attributes", attr } };
                var manifest = new Manifest2014<Attributes2014>();
                manifest.Entries.Add(attr.PersistentID, attributeDictionary);
                manifest.SaveToFile(json);

                // update manifestHeader (hsan) entry
                var attributeHeaderDictionary = new Dictionary<string, AttributesHeader2014> { { "Attributes", new AttributesHeader2014(attr) } };
                if (platform.IsConsole)
                {
                    // One for each arrangements (Xbox360/PS3)
                    manifestHeader = new ManifestHeader2014<AttributesHeader2014>(platform);
                    manifestHeader.Entries.Add(attr.PersistentID, attributeHeaderDictionary);
                }
                else
                    manifestHeader.Entries.Add(attr.PersistentID, attributeHeaderDictionary);
            }

            // write updated hsan file
            manifestHeader.SaveToFile(hsanFile);
        }