예제 #1
0
        private void SerializeSetInfo(StreamWriter writer, ChartSetInfo setInfo)
        {
            foreach (var chartInfo in setInfo.Charts)
            {
                if (chartInfo.GameMode == null)
                {
                    Logger.Log($"Cannot serialize a chart without a gamemode. Skipping for {Path.Combine(chartInfo.Set.FilePath, chartInfo.FileName)}");
                    continue;
                }

                writer.WriteLine($"[chart-info]");
                writer.WriteLine($"chart-file={ chartInfo.FileName }");
                writer.WriteLine($"game-mode={ chartInfo.GameMode!.Name }");
                writer.WriteLine($"song-title={ chartInfo.SongTitle }");
                writer.WriteLine($"song-artist={ chartInfo.SongArtist }");
                writer.WriteLine($"song-file={ chartInfo.SongFileName }");
                writer.WriteLine($"song-volume={ chartInfo.SongVolume }");
                writer.WriteLine($"chart-offset={ chartInfo.ChartOffset.Seconds }");
                writer.WriteLine($"charter={ chartInfo.Charter }");
                writer.WriteLine($"chart-duration={ chartInfo.ChartDuration.Seconds }");

                WriteOptS("file-type", chartInfo.ChartFileType);
                WriteOptS("jacket-file", chartInfo.JacketFileName);
                WriteOptS("jacket-artist", chartInfo.JacketArtist);
                WriteOptS("background-file", chartInfo.BackgroundFileName);
                WriteOptS("background-artist", chartInfo.BackgroundArtist);
                writer.WriteLine($"difficulty-level={ chartInfo.DifficultyLevel }");
                WriteOptI("difficulty-index", chartInfo.DifficultyIndex);
                WriteOptS("difficulty-name", chartInfo.DifficultyName);
                WriteOptS("difficulty-name-short", chartInfo.DifficultyNameShort);

                if (chartInfo.DifficultyColor != null)
                {
                    var c = chartInfo.DifficultyColor.Value;
                    int ival(float f) => MathL.RoundToInt(f * 255);

                    writer.WriteLine($"difficulty-color={ival(c.X):X2}{ival(c.Y):X2}{ival(c.Z):X2}");
                }
            }

            void WriteOptI(string key, int?value)
            {
                if (value == null)
                {
                    return;
                }
                writer.WriteLine($"{ key }={ value.Value }");
            }

            void WriteOptS(string key, string?value)
            {
                if (string.IsNullOrWhiteSpace(value))
                {
                    return;
                }
                writer.WriteLine($"{ key }={ value }");
            }
        }
예제 #2
0
        public void SaveToFile(ChartSetInfo setInfo)
        {
            string filePath = Path.Combine(ParentDirectory, setInfo.FilePath, setInfo.FileName);

            Directory.CreateDirectory(Path.Combine(ParentDirectory, setInfo.FilePath));

            using (var writer = new StreamWriter(File.Open(filePath, FileMode.Create)))
                SerializeSetInfo(writer, setInfo);

            var fsi = new FileInfo(filePath);

            fsi.Refresh(); // TODO(local): is this needed?

            setInfo.LastWriteTime = fsi.LastWriteTimeUtc.Ticks;
        }
예제 #3
0
        public void RemoveSet(ChartSetInfo setInfo)
        {
            string relPath = Path.Combine(setInfo.FilePath, setInfo.FileName);

            m_chartSets.Remove(setInfo.ID, out var _);
            m_chartSetsByFilePath.Remove(relPath, out var _);

            m_setFiles.Remove(relPath);

            Exec("DELETE FROM Sets WHERE filePath=?", setInfo.FilePath);

            foreach (var chart in setInfo.Charts)
            {
                RemoveChart(chart);
            }
        }
예제 #4
0
        public ChartSetInfo LoadFromFile(string directory, string fileName)
        {
            string filePath = Path.Combine(ParentDirectory, directory, fileName);
            var    fsi      = new FileInfo(filePath);

            fsi.Refresh(); // TODO(local): is this needed?

            long lastWriteTime = fsi.LastWriteTimeUtc.Ticks;
            var  setInfo       = new ChartSetInfo()
            {
                LastWriteTime = lastWriteTime,
                FilePath      = directory,
                FileName      = fileName,
            };

            using (var reader = new StreamReader(File.OpenRead(filePath)))
                DeserializeChartSetInfo(reader, setInfo);

            return(setInfo);
        }
예제 #5
0
        private ChartSetInfo ConvertKSHAndSave(string primaryKshFile, out ChartInfo selected)
        {
            var primaryKshChart = KshChart.CreateFromFile(primaryKshFile);
            var primaryChart    = primaryKshChart.ToVoltex();

            string setDir  = Directory.GetParent(primaryKshFile).FullName;
            string setName = Path.GetFileName(setDir);

            List <(string, Chart)> chartFiles =
                new List <(string, Chart)> {
                (primaryKshFile, primaryChart)
            };

            foreach (string kshChartFile in Directory.EnumerateFiles(setDir, "*.ksh"))
            {
                // we're filtering out invalid charts, as :theori will only support one song per set.
                // skipping files with non-matching meta and logging the issue for now.
                if (Path.GetFileName(kshChartFile) == Path.GetFileName(primaryKshFile))
                {
                    continue;
                }

                KshChartMetadata kshMeta;
                using (var reader = new StreamReader(File.OpenRead(kshChartFile)))
                    kshMeta = KshChartMetadata.Create(reader);

                // don't worry about checking the nofx one, as we'll only keep the primary file anyway.

                /*
                 * if ((kshMeta.MusicFile, kshMeta.Title, kshMeta.Artist) !=
                 *  (primaryKshMeta.MusicFile, primaryKshMeta.Title, primaryKshMeta.Artist))
                 * {
                 *  Logger.Log($"Skipping '{ Path.GetFileName(kshChartFile) }' chart file in the set '{ setDir }'.\n:theori and NeuroSonic only support a single song for each set, and the chosen set does not comply.\nOnly charts of the same song will be added to this converted set.");
                 *  continue;
                 * }
                 */

                var kshChart = KshChart.CreateFromFile(kshChartFile);
                var chart    = kshChart.ToVoltex();

                chartFiles.Add((kshChartFile, chart));
            }

            var chartSetInfo = new ChartSetInfo()
            {
                ID       = 0,    // no database ID, it's not in the database yet
                OnlineID = null, // no online stuff, it's not uploaded

                FilePath = setName,
            };

            string nscChartDirectory = Path.Combine(m_chartsDir, setName);

            if (!Directory.Exists(nscChartDirectory))
            {
                Directory.CreateDirectory(nscChartDirectory);
            }

            foreach (var(kshChartFile, chart) in chartFiles)
            {
                string audioFile = Path.Combine(setDir, chart.Info.SongFileName);
                if (File.Exists(audioFile))
                {
                    string audioFileDest = Path.Combine(m_chartsDir, setName, Path.GetFileName(audioFile));
                    if (File.Exists(audioFileDest))
                    {
                        File.Delete(audioFileDest);
                    }
                    File.Copy(audioFile, audioFileDest);
                }

                chart.Info.Set      = chartSetInfo;
                chart.Info.FileName = $"{ Path.GetFileNameWithoutExtension(kshChartFile) }.theori";

                chartSetInfo.Charts.Add(chart.Info);
            }

            selected = primaryChart.Info;

            var setSerializer = new ChartSetSerializer();
            var serializer    = BinaryTheoriChartSerializer.GetSerializerFor(NeuroSonicGameMode.Instance);

            using (var setInfoStream = File.Open(Path.Combine(nscChartDirectory, ".theori-set"), FileMode.Create))
                setSerializer.SerializeSetInfo(chartSetInfo, setInfoStream);

            foreach (var(_, chart) in chartFiles)
            {
                var chartInfo = chart.Info;
                using (var chartInfoStream = File.Open(Path.Combine(nscChartDirectory, chartInfo.FileName), FileMode.Create))
                    serializer.SerializeChart(chart, chartInfoStream);
            }

            return(chartSetInfo);
        }
예제 #6
0
        public void LoadData()
        {
            using (var reader = ExecReader("SELECT id,lwt,uploadID,filePath,fileName FROM Sets"))
            {
                while (reader.Read())
                {
                    var set = new ChartSetInfo();
                    set.ID            = reader.GetInt64(0);
                    set.LastWriteTime = reader.GetInt64(1);
                    set.OnlineID      = reader.GetInt64OrNull(2);
                    set.FilePath      = reader.GetString(3);
                    set.FileName      = reader.GetString(4);

                    string relPath = Path.Combine(set.FilePath, set.FileName);
                    m_setFiles.Add(relPath);

                    m_chartSets[set.ID]            = set;
                    m_chartSetsByFilePath[relPath] = set;
                }
            }

            // TODO(local): Add potential aliases to the query and extensions to the reader to make this much easier
            using (var reader = ExecReader("SELECT id,setId,lwt,fileName,songTitle,songArtist,songFileName,songVolume,chartOffset,charter,jacketFileName,jacketArtist,backgroundFileName,backgroundArtist,diffLevel,diffIndex,diffName,diffNameShort,diffColor,chartDuration,tags,gameMode FROM Charts"))
            {
                while (reader.Read())
                {
                    var set   = m_chartSets[reader.GetInt64(1)];
                    var chart = new ChartInfo();
                    chart.ID                  = reader.GetInt64(0);
                    chart.LastWriteTime       = reader.GetInt64(2);
                    chart.FileName            = reader.GetString(3);
                    chart.GameMode            = GameMode.GetInstance(reader.GetString(21));
                    chart.SongTitle           = reader.GetString(4);
                    chart.SongArtist          = reader.GetString(5);
                    chart.SongFileName        = reader.GetString(6);
                    chart.SongVolume          = reader.GetInt32(7);
                    chart.ChartOffset         = reader.GetDouble(8);
                    chart.Charter             = reader.GetString(9);
                    chart.JacketFileName      = reader.GetStringOrNull(10);
                    chart.JacketArtist        = reader.GetStringOrNull(11);
                    chart.BackgroundFileName  = reader.GetStringOrNull(12);
                    chart.BackgroundArtist    = reader.GetStringOrNull(13);
                    chart.DifficultyLevel     = reader.GetDouble(14);
                    chart.DifficultyIndex     = reader.GetInt32OrNull(15);
                    chart.DifficultyName      = reader.GetString(16);
                    chart.DifficultyNameShort = reader.GetStringOrNull(17);
                    chart.DifficultyColor     = reader.GetInt32OrNull(18) is int value?Color.HexToVector3(value) : (Vector3?)null;

                    chart.ChartDuration = reader.GetDouble(19);
                    chart.Tags          = reader.GetString(20);

                    set.Charts.Add(chart);
                    chart.Set = set;

                    m_charts[chart.ID] = chart;
                }
            }

            using (var reader = ExecReader("SELECT id,chartId,collection FROM Collections"))
            {
                while (reader.Read())
                {
                    long id = reader.GetInt64(0);

                    string name = reader.GetString(2);
                    if (!m_collections.TryGetValue(name, out var collection))
                    {
                        collection = new CollectionInfo(name);
                    }

                    collection.ChartIds.Add(reader.GetInt64(1));
                    m_collections[collection.Name] = collection;
                }
            }
        }
예제 #7
0
        private void AddSetInfoToDatabase(string relPath, ChartSetInfo setInfo)
        {
            Debug.Assert(Path.Combine(setInfo.FilePath, setInfo.FileName) == relPath);

            bool isUpdate = !m_setFiles.Add(relPath);

            m_chartSetsByFilePath[relPath] = setInfo;

            if (isUpdate)
            {
            }
            else
            {
                if (setInfo.ID != 0)
                {
                    Logger.Log($"Adding a set info with non-zero primary key already set. This will be overwritten with the new key.");
                }
                int setResult = Exec("INSERT INTO Sets (lwt,uploadID,filePath,fileName) VALUES (?,?,?,?)",
                                     setInfo.LastWriteTime,
                                     setInfo.OnlineID,
                                     setInfo.FilePath,
                                     setInfo.FileName);
                if (setResult == 0)
                {
                    Logger.Log($"Failed to insert chart set { setInfo.FilePath }\\{ setInfo.FileName }");
                    return;
                }

                setInfo.ID = m_connection.LastInsertRowId;
                m_chartSets[setInfo.ID] = setInfo;

                foreach (var chart in setInfo.Charts)
                {
                    int chartResult = Exec("INSERT INTO Charts (setId,lwt,fileName,gameMode,songTitle,songArtist,songFileName,songVolume,chartOffset,charter,jacketFileName,jacketArtist,backgroundFileName,backgroundArtist,diffLevel,diffIndex,diffName,diffNameShort,diffColor,chartDuration,tags) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)",
                                           setInfo.ID,
                                           chart.LastWriteTime,
                                           chart.FileName,
                                           chart.GameMode !.Name,
                                           chart.SongTitle,
                                           chart.SongArtist,
                                           chart.SongFileName,
                                           chart.SongVolume,
                                           (double)chart.ChartOffset,
                                           chart.Charter,
                                           chart.JacketFileName,
                                           chart.JacketArtist,
                                           chart.BackgroundFileName,
                                           chart.BackgroundArtist,
                                           chart.DifficultyLevel,
                                           chart.DifficultyIndex,
                                           chart.DifficultyName,
                                           chart.DifficultyNameShort,
                                           chart.DifficultyColor == null ? (int?)null : Color.Vector3ToHex(chart.DifficultyColor.Value),
                                           (double)chart.ChartDuration,
                                           chart.Tags);

                    chart.ID = m_connection.LastInsertRowId;
                    Exec("INSERT INTO LocalChartConfig (chartId,config) VALUES (?,?)", string.Empty, chart.ID);
                }

                foreach (var chart in setInfo.Charts)
                {
                    m_charts[chart.ID] = chart;
                }
            }
        }
예제 #8
0
        public void AddSet(ChartSetInfo setInfo)
        {
            string relPath = Path.Combine(setInfo.FilePath, setInfo.FileName);

            AddSetInfoToDatabase(relPath, setInfo);
        }
예제 #9
0
 private void EnqueuePopulateEntry(ChartSetInfo setInfo)
 {
     m_populateQueue !.Enqueue(setInfo);
 }
예제 #10
0
        private void DeserializeChartSetInfo(StreamReader reader, ChartSetInfo setInfo)
        {
            ChartInfo?chartInfo = null;
            string    line;

            while ((line = reader.ReadLine()) != null)
            {
                if (line == "[chart-info]")
                {
                    chartInfo = new ChartInfo()
                    {
                        Set = setInfo
                    };
                    setInfo.Charts.Add(chartInfo);
                }
                else if (line.TrySplit('=', out string key, out string value))
                {
                    if (chartInfo == null)
                    {
                        continue;
                    }
                    switch (key)
                    {
                    case "game-mode": chartInfo.GameMode = GameMode.GetInstance(value); break;
                    //case "file-type": chartInfo.ChartFileType = value; break;

                    case "chart-file": chartInfo.FileName = value; break;

                    case "song-title": chartInfo.SongTitle = value; break;

                    case "song-artist": chartInfo.SongArtist = value; break;

                    case "song-file": chartInfo.SongFileName = value; break;

                    case "song-volume": chartInfo.SongVolume = int.Parse(value); break;

                    case "chart-offset": chartInfo.ChartOffset = double.Parse(value); break;

                    case "charter": chartInfo.Charter = value; break;

                    case "chart-duration": chartInfo.ChartDuration = double.Parse(value); break;

                    case "jacket-file": chartInfo.JacketFileName = value; break;

                    case "jacket-artist": chartInfo.JacketArtist = value; break;

                    case "background-file": chartInfo.BackgroundFileName = value; break;

                    case "background-artist": chartInfo.BackgroundArtist = value; break;

                    case "difficulty-level": chartInfo.DifficultyLevel = double.Parse(value); break;

                    case "difficulty-index": chartInfo.DifficultyIndex = int.Parse(value); break;

                    case "difficulty-name": chartInfo.DifficultyName = value; break;

                    case "difficulty-name-short": chartInfo.DifficultyNameShort = value; break;

                        float itof(int o) => int.Parse(value.Substring(o * 2, 2), NumberStyles.HexNumber) / 255.0f;

                    case "difficulty-color": chartInfo.DifficultyColor = new Vector3(itof(0), itof(1), itof(2)); break;
                    }
                }
            }
        }