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 }"); } }
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; }
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); } }
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); }
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); }
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; } } }
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; } } }
public void AddSet(ChartSetInfo setInfo) { string relPath = Path.Combine(setInfo.FilePath, setInfo.FileName); AddSetInfoToDatabase(relPath, setInfo); }
private void EnqueuePopulateEntry(ChartSetInfo setInfo) { m_populateQueue !.Enqueue(setInfo); }
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; } } } }