From 061c58bc7c3395fc4f3ceafb4b9ce75a70fe1a22 Mon Sep 17 00:00:00 2001 From: whiteshark0 Date: Sat, 24 Mar 2007 18:28:22 +0000 Subject: Initial Release There is Still a Bug Converting DB Scores to SCO Files git-svn-id: svn://svn.code.sf.net/p/ultrastardx/svn/trunk@28 b956fd51-792f-4845-bead-9b4dfca2ff2c --- ScoreConverter/ScoreConverter.dpr | 17 +++ ScoreConverter/ScoreConverter.ico | Bin 0 -> 766 bytes ScoreConverter/ScoreConverter.res | Bin 0 -> 876 bytes ScoreConverter/ToDo.txt | 2 + ScoreConverter/UScores.pas | 102 +++++++++++++++++ ScoreConverter/USongs.pas | 160 ++++++++++++++++++++++++++ ScoreConverter/Umainform.dfm | 123 ++++++++++++++++++++ ScoreConverter/Umainform.pas | 228 ++++++++++++++++++++++++++++++++++++++ 8 files changed, 632 insertions(+) create mode 100644 ScoreConverter/ScoreConverter.dpr create mode 100644 ScoreConverter/ScoreConverter.ico create mode 100644 ScoreConverter/ScoreConverter.res create mode 100644 ScoreConverter/ToDo.txt create mode 100644 ScoreConverter/UScores.pas create mode 100644 ScoreConverter/USongs.pas create mode 100644 ScoreConverter/Umainform.dfm create mode 100644 ScoreConverter/Umainform.pas (limited to 'ScoreConverter') diff --git a/ScoreConverter/ScoreConverter.dpr b/ScoreConverter/ScoreConverter.dpr new file mode 100644 index 00000000..5736b733 --- /dev/null +++ b/ScoreConverter/ScoreConverter.dpr @@ -0,0 +1,17 @@ +program ScoreConverter; + +uses + Forms, + Umainform in 'Umainform.pas' {mainform}, + UScores in 'UScores.pas', + UDataBase in '..\Game\Code\Classes\UDataBase.pas', + USongs in 'USongs.pas'; + +{$R *.res} + +begin + Application.Initialize; + Application.Title := 'Score Converter'; + Application.CreateForm(Tmainform, mainform); + Application.Run; +end. diff --git a/ScoreConverter/ScoreConverter.ico b/ScoreConverter/ScoreConverter.ico new file mode 100644 index 00000000..80319014 Binary files /dev/null and b/ScoreConverter/ScoreConverter.ico differ diff --git a/ScoreConverter/ScoreConverter.res b/ScoreConverter/ScoreConverter.res new file mode 100644 index 00000000..2d3bea87 Binary files /dev/null and b/ScoreConverter/ScoreConverter.res differ diff --git a/ScoreConverter/ToDo.txt b/ScoreConverter/ToDo.txt new file mode 100644 index 00000000..e8987f87 --- /dev/null +++ b/ScoreConverter/ToDo.txt @@ -0,0 +1,2 @@ +There is still a Bug when Writing Scores from DB back to SCo files. +Most high entrys are duplicated don't know why... \ No newline at end of file diff --git a/ScoreConverter/UScores.pas b/ScoreConverter/UScores.pas new file mode 100644 index 00000000..3e2c4e92 --- /dev/null +++ b/ScoreConverter/UScores.pas @@ -0,0 +1,102 @@ +unit UScores; + +interface + +uses USongs; + +procedure ReadScore(var Song: TSong); +procedure WriteScore(var Song: TSong); +procedure AddScore(var Song: TSong; Level: integer; Name: string; Score: integer); + +implementation + +uses IniFiles, SysUtils; + +procedure ReadScore(var Song: TSong); +var + F: TIniFile; + S: string; + P: integer; + Lev: integer; + LevS: string; +begin + F := TIniFile.Create(Song.Path + ChangeFileExt(Song.FileName, '.sco')); + + for Lev := 0 to 2 do begin + case Lev of + 0: LevS := 'Easy'; + 1: LevS := 'Normal'; + 2: LevS := 'Hard'; + end; + + P := 1; + S := F.ReadString(LevS + IntToStr(P), 'Name', ''); + while (S <> '') and (P<=5) do begin + SetLength(Song.Score[Lev], P); + Song.Score[Lev, P-1].Name := S; + Song.Score[Lev, P-1].Score := F.ReadInteger(LevS + IntToStr(P), 'Score', 0); + + Inc(P); + S := F.ReadString(LevS + IntToStr(P), 'Name', ''); + end; + end; +end; + +procedure AddScore(var Song: TSong; Level: integer; Name: string; Score: integer); +var + S: integer; + S2: integer; +begin + S := 0; + while (S <= High(Song.Score[Level])) and (Score <= Song.Score[Level, S].Score) do + Inc(S); + // S has the number for new score + + + // we create new score + SetLength(Song.Score[Level], Length(Song.Score[Level]) + 1); + + // we move down old scores + for S2 := High(Song.Score[Level])-1 downto S do + Song.Score[Level, S2+1] := Song.Score[Level, S2]; + + // we fill new score + Song.Score[Level, S].Name := Name; + Song.Score[Level, S].Score := Score; + + if Length(Song.Score[Level]) > 5 then begin + SetLength(Song.Score[Level], 5); + end; +end; + +procedure WriteScore(var Song: TSong); +var + F: TIniFile; + S: integer; + Lev: integer; + LevS: string; + FileName: string; +begin + FileName := Song.Path + ChangeFileExt(Song.FileName, '.sco'); + if (not FileExists(FileName)) or (FileExists(FileName) and DeleteFile(FileName)) then begin + // file has been deleted -> creating new file + F := TIniFile.Create(FileName); + + for Lev := 0 to 2 do begin + case Lev of + 0: LevS := 'Easy'; + 1: LevS := 'Normal'; + 2: LevS := 'Hard'; + end; + + for S := 0 to high(Song.Score[Lev]) do begin + F.WriteString(LevS + IntToStr(S+1), 'Name', Song.Score[Lev, S].Name); + F.WriteInteger(LevS + IntToStr(S+1), 'Score', Song.Score[Lev, S].Score); + + end; // for S + end; // for Lev + F.Free; + end; // if +end; + +end. diff --git a/ScoreConverter/USongs.pas b/ScoreConverter/USongs.pas new file mode 100644 index 00000000..a43ea61e --- /dev/null +++ b/ScoreConverter/USongs.pas @@ -0,0 +1,160 @@ +unit USongs; + +interface + +type + TScore = record + Name: string; + Score: integer; + Length: string; + end; + + TSong = record + Path: string; + FileName: string; + + Title: string; + Artist: string; + + Score: array[0..2] of array of TScore; + end; + + TSongs = class + LastCount: Integer; + Song: array of TSong; // array of songs + + function ReadHeader(var rSong: TSong): boolean; + procedure BrowseDir(Dir: string); // Browse a dir + subdirs for songfiles + end; + + var Songs: TSongs; + +implementation +uses Sysutils, UMainForm, Dialogs; + +function TSongs.ReadHeader(var rSong: TSong): boolean; +var + Line, Identifier, Value: String; + Temp: word; + Done: byte; + SongFile: Textfile; +begin + Result := False; + + + //Open File and set File Pointer to the beginning + AssignFile(SongFile, rSong.Path + rSong.FileName); + Reset(SongFile); + + //Read Header + Result := true; + + //Read first Line + ReadLn (SongFile, Line); + + if (Length(Line)<=0) then + begin + Result := False; + Exit; + end; + Done := 0; + //Read Lines while Line starts with # + While (Line[1] = '#') do + begin + Temp := Pos(':', Line); + + //Line has a Seperator-> Headerline + if (Temp <> 0) then + begin + //Read Identifier and Value + Identifier := Uppercase(Trim(Copy(Line, 2, Temp - 2))); //Uppercase is for Case Insensitive Checks + Value := Trim(Copy(Line, Temp + 1,Length(Line) - Temp)); + + //Check the Identifier (If Value is given) + if (Length(Value) <> 0) then + begin + + //----------- + //Required Attributes + //----------- + + //Title + if (Identifier = 'TITLE') then + begin + rSong.Title := Value; + + //Add Title Flag to Done + Done := Done or 1; + end + + //Artist + else if (Identifier = 'ARTIST') then + begin + rSong.Artist := Value; + + //Add Artist Flag to Done + Done := Done or 2; + end; + + end; + end; + + if not EOf(SongFile) then + ReadLn (SongFile, Line) + else + begin + Result := False; + break; + end; + + //End on first empty Line + if (Length(Line) = 0) then + break; + end; + + //Check if all Required Values are given + if (Done <> 3) then + begin + Result := False; + end; + + //And Close File + CloseFile(SongFile); +end; + +procedure TSongs.BrowseDir(Dir: string); +var + SR: TSearchRec; // for parsing Songs Directory + SLen: integer; +begin + if FindFirst(Dir + '*', faDirectory, SR) = 0 then begin + repeat + if (SR.Name <> '.') and (SR.Name <> '..') then + BrowseDir(Dir + Sr.Name + '\'); + until FindNext(SR) <> 0; + end; + FindClose(SR); + + if FindFirst(Dir + '*.txt', 0, SR) = 0 then begin + repeat + SLen := Length(Song); + SetLength(Song, SLen + 1); + + Song[SLen].Path := Dir; + Song[SLen].FileName := SR.Name; + + if (ReadHeader(Song[SLen]) = false) then SetLength(Song, SLen); + + //update Songs Label + if LastCount <> SLen div 30 then + begin + LastCount := SLen div 30; + MainForm.UpdateLoadedSongs(Dir, SLen); + end; + + until FindNext(SR) <> 0; + end; // if FindFirst + FindClose(SR); +end; + +end. diff --git a/ScoreConverter/Umainform.dfm b/ScoreConverter/Umainform.dfm new file mode 100644 index 00000000..a4291e7b --- /dev/null +++ b/ScoreConverter/Umainform.dfm @@ -0,0 +1,123 @@ +object mainform: Tmainform + Left = 328 + Top = 228 + HorzScrollBar.Visible = False + VertScrollBar.Visible = False + BorderIcons = [biSystemMenu, biMinimize] + BorderStyle = bsSingle + Caption = 'Ultrastar Deluxe Score Converter' + ClientHeight = 159 + ClientWidth = 449 + Color = clBtnFace + Font.Charset = DEFAULT_CHARSET + Font.Color = clWindowText + Font.Height = -11 + Font.Name = 'MS Sans Serif' + Font.Style = [] + OldCreateOrder = False + Position = poDesktopCenter + OnCreate = FormCreate + PixelsPerInch = 96 + TextHeight = 13 + object Label1: TLabel + Left = 8 + Top = 8 + Width = 60 + Height = 13 + Caption = 'SongFolder: ' + end + object lFolder: TLabel + Left = 8 + Top = 24 + Width = 29 + Height = 13 + Caption = 'Folder' + end + object Label2: TLabel + Left = 8 + Top = 48 + Width = 49 + Height = 13 + Caption = 'Database:' + end + object lDatabase: TLabel + Left = 8 + Top = 64 + Width = 46 + Height = 13 + Caption = 'Database' + end + object lDatabase2: TLabel + Left = 72 + Top = 48 + Width = 54 + Height = 13 + Caption = 'lDatabase2' + end + object lFolder2: TLabel + Left = 72 + Top = 8 + Width = 37 + Height = 13 + Caption = 'lFolder2' + end + object lStatus: TLabel + Left = 0 + Top = 96 + Width = 449 + Height = 13 + Alignment = taCenter + AutoSize = False + Caption = 'lStatus' + end + object bFLoad: TButton + Left = 176 + Top = 8 + Width = 57 + Height = 17 + Caption = 'Load' + TabOrder = 0 + OnClick = bFLoadClick + end + object bDLoad: TButton + Left = 176 + Top = 48 + Width = 57 + Height = 17 + Caption = 'Load' + TabOrder = 1 + OnClick = bDLoadClick + end + object bToDB: TButton + Left = 16 + Top = 112 + Width = 153 + Height = 17 + Caption = 'Convert *.SCO to Database' + Enabled = False + TabOrder = 2 + OnClick = bToDBClick + end + object bFromDB: TButton + Left = 288 + Top = 112 + Width = 145 + Height = 17 + Caption = 'Convert Database to *.SCO' + Enabled = False + TabOrder = 3 + OnClick = bFromDBClick + end + object pProgress: TProgressBar + Left = 8 + Top = 136 + Width = 433 + Height = 17 + TabOrder = 4 + end + object oDatabase: TOpenDialog + Filter = 'Ultrastar Deluxe Database|ultrastar.db' + Left = 136 + Top = 48 + end +end diff --git a/ScoreConverter/Umainform.pas b/ScoreConverter/Umainform.pas new file mode 100644 index 00000000..20c3e494 --- /dev/null +++ b/ScoreConverter/Umainform.pas @@ -0,0 +1,228 @@ +unit Umainform; + +interface + +uses + Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, + Dialogs, StdCtrls, ComCtrls, UDataBase, ShellAPI, ShlObj, USongs; + +type + Tmainform = class(TForm) + Label1: TLabel; + lFolder: TLabel; + bFLoad: TButton; + Label2: TLabel; + lDatabase: TLabel; + bDLoad: TButton; + lDatabase2: TLabel; + lFolder2: TLabel; + bToDB: TButton; + bFromDB: TButton; + pProgress: TProgressBar; + oDatabase: TOpenDialog; + lStatus: TLabel; + procedure FormCreate(Sender: TObject); + procedure bDLoadClick(Sender: TObject); + function BrowseDialog (const Title: string; const Flag: integer): string; + procedure bFLoadClick(Sender: TObject); + procedure UpdateLoadedSongs(Path: String; Count: integer); + procedure bToDBClick(Sender: TObject); + procedure bFromDBClick(Sender: TObject); + private + { Private-Deklarationen } + public + { Public-Deklarationen } + end; + +var + mainform: Tmainform; + DBLoaded: Boolean; + SFLoaded: Boolean; + + +implementation + +uses UScores; + +{$R *.dfm} + +function Tmainform.BrowseDialog + (const Title: string; const Flag: integer): string; +var + lpItemID : PItemIDList; + BrowseInfo : TBrowseInfo; + DisplayName : array[0..MAX_PATH] of char; + TempPath : array[0..MAX_PATH] of char; +begin + Result:=''; + FillChar(BrowseInfo, sizeof(TBrowseInfo), #0); + with BrowseInfo do begin + hwndOwner := Application.Handle; + pszDisplayName := @DisplayName; + lpszTitle := PChar(Title); + ulFlags := Flag; + end; + lpItemID := SHBrowseForFolder(BrowseInfo); + if lpItemId <> nil then begin + SHGetPathFromIDList(lpItemID, TempPath); + Result := TempPath; + GlobalFreePtr(lpItemID); + end; +end; + +procedure Tmainform.FormCreate(Sender: TObject); +begin + Database := TDataBaseSystem.Create; + Songs := TSongs.Create; + lStatus.Caption := 'Welcome to USD Score Converter'; + lFolder2.Caption := 'No Songs loaded'; + lFolder.Caption := ''; + lDataBase2.Caption := 'No Database loaded'; + lDataBase.Caption := ''; +end; + +procedure Tmainform.bDLoadClick(Sender: TObject); +begin + if oDatabase.Execute then + begin + try + Database.Init(oDataBase.FileName); + lDataBase2.Caption := 'Database loaded'; + lDataBase.Caption := oDataBase.FileName; + DBLoaded := True; + except + lDataBase2.Caption := 'No Database loaded'; + lDataBase.Caption := ''; + DBLoaded := False; + end; + end; + bToDB.Enabled := DBLoaded and SFLoaded; + bFromDB.Enabled := bToDB.Enabled; +end; + +procedure Tmainform.bFLoadClick(Sender: TObject); +var + Path: String; +begin + Path := BrowseDialog('Select UltraStar SongFolder', BIF_RETURNONLYFSDIRS); + + if Path <> '' then + begin + SetLength(Songs.Song, 0); + try + Songs.BrowseDir(Path + '\'); + lFolder2.Caption := Inttostr(Length(Songs.Song)) + ' Songs loaded'; + lFolder.Caption := Path; + SFLoaded := True; + except + lFolder2.Caption := 'No Songs loaded'; + lFolder.Caption := ''; + SFLoaded := False; + end; + end; + + bToDB.Enabled := DBLoaded and SFLoaded; + bFromDB.Enabled := bToDB.Enabled; +end; + +procedure Tmainform.UpdateLoadedSongs(Path: String; Count: integer); +begin + lFolder2.Caption := Inttostr(Count) + ' Songs loaded'; + lFolder.Caption := Path; + Application.ProcessMessages; +end; + +procedure Tmainform.bToDBClick(Sender: TObject); +var + I, J, K: Integer; + LastI: integer; +begin + pProgress.Max := high(Songs.Song); + pProgress.Position := 0; + // Go through all Songs + For I := 0 to high(Songs.Song) do + begin + try + //Read Scores from .SCO File + ReadScore (Songs.Song[I]); + + //Go from Easy to Difficult + For J := 0 to 2 do + begin + //Go through all Score Entrys with Difficulty J + For K := 0 to high(Songs.Song[I].Score[J]) do + begin + //Add to DataBase + DataBase.AddScore(Songs.Song[I], J, Songs.Song[I].Score[J][K].Name, Songs.Song[I].Score[J][K].Score); + end; + end; + + except + showmessage ('Error Converting Score From Song: ' + Songs.Song[I].Path + Songs.Song[I].FileName); + end; + + //Update ProgressBar + if (LastI <> I div 30) then + begin + LastI := I div 30; + pProgress.Position := I; + lStatus.Caption := 'Adding Songscore: ' + Songs.Song[I].Artist + ' - ' + Songs.Song[I].Title; + Application.ProcessMessages; + end; + end; + + pProgress.Position := pProgress.Max; + lStatus.Caption := 'Finished'; +end; + +procedure Tmainform.bFromDBClick(Sender: TObject); +var + I, J, K: Integer; + LastI: integer; + anyScoreinthere: boolean; +begin + pProgress.Max := high(Songs.Song); + pProgress.Position := 0; + // Go through all Songs + For I := 0 to high(Songs.Song) do + begin + try + //Not Write ScoreFile when there are no Scores for this File + anyScoreinthere := false; + //Read Scores from DB File + Database.ReadScore (Songs.Song[I]); + + //Go from Easy to Difficult + For J := 0 to 2 do + begin + //Go through all Score Entrys with Difficulty J + For K := 0 to high(Songs.Song[I].Score[J]) do + begin + //Add to ScoreFile + AddScore(Songs.Song[I], J, Songs.Song[I].Score[J][K].Name, Songs.Song[I].Score[J][K].Score); + anyScoreinthere := True; + end; + end; + + if AnyScoreinThere then + WriteScore(Songs.Song[I]); + + except + showmessage ('Error Converting Score From Song: ' + Songs.Song[I].Path + Songs.Song[I].FileName); + end; + + //Update ProgressBar + if (LastI <> I div 30) then + begin + LastI := I div 30; + pProgress.Position := I; + lStatus.Caption := 'Writing ScoreFile: ' + Songs.Song[I].Artist + ' - ' + Songs.Song[I].Title; + Application.ProcessMessages; + end; + end; + + pProgress.Position := pProgress.Max; + lStatus.Caption := 'Finished'; +end; + +end. -- cgit v1.2.3