diff options
-rw-r--r-- | Game/Code/Classes/UDataBase.pas | 30 | ||||
-rw-r--r-- | Game/Code/Classes/UFiles.pas | 124 | ||||
-rw-r--r-- | Game/Code/Classes/UIni.pas | 2 | ||||
-rw-r--r-- | Game/Code/Classes/ULog.pas | 43 | ||||
-rw-r--r-- | Game/Code/Classes/USongs.pas | 12 | ||||
-rw-r--r-- | Game/Code/Screens/UScreenEditSub.pas | 3 | ||||
-rw-r--r-- | Game/Code/Screens/UScreenSong.pas | 37 |
7 files changed, 245 insertions, 6 deletions
diff --git a/Game/Code/Classes/UDataBase.pas b/Game/Code/Classes/UDataBase.pas index 586e742d..40079b1e 100644 --- a/Game/Code/Classes/UDataBase.pas +++ b/Game/Code/Classes/UDataBase.pas @@ -57,6 +57,8 @@ type function GetHandicap(P1: string; P2: string): THandicapResult; //for Handicap-Mode
function GetAspect(Artist, Title: string; def: integer): integer;
procedure SetAspect(Artist, Title: string; aspect: integer);
+
+ function GetMaxScore(Artist, Title: string; difficulty: integer): integer;
end;
var
@@ -119,6 +121,34 @@ begin end;
end;
+function TDataBaseSystem.GetMaxScore(Artist, Title: string; difficulty: integer): integer;
+var
+ ID: Integer;
+ tArtist, tTitle: string;
+
+begin
+ Result := 0;
+
+ if not Assigned(ScoreDB) then
+ Exit;
+
+ try
+ tArtist := StringReplace(Artist,'"','""',[rfReplaceAll, rfIgnoreCase]);
+ tTitle := StringReplace(Title,'"','""',[rfReplaceAll, rfIgnoreCase]);
+
+ ID := ScoreDB.GetTableValue('SELECT `ID` FROM `US_Songs` WHERE `Artist` = "' +
+ tArtist + '" AND `Title` = "' + tTitle + '"');
+
+ if ID <> 0 then
+ begin
+ Result := ScoreDB.GetTableValue('SELECT MAX(`Score`) FROM `US_Scores` WHERE `SongID` = "' +
+ IntToStr(ID) + '" AND `Difficulty` = "' + IntToStr(difficulty) + '"');
+ end;
+ except
+ Result := 0;
+ end;
+end;
+
function TDataBaseSystem.GetAspect(Artist, Title: string; def: integer): integer;
var
ID: Integer;
diff --git a/Game/Code/Classes/UFiles.pas b/Game/Code/Classes/UFiles.pas index 382f39ff..7a5e7de4 100644 --- a/Game/Code/Classes/UFiles.pas +++ b/Game/Code/Classes/UFiles.pas @@ -6,7 +6,8 @@ uses USongs, SysUtils,
StrUtils,
ULog,
- UMusic;
+ UMusic,
+ UDataBase;
const
DEFAULT_FADE_IN_TIME = 8; //TODO in INI
@@ -33,9 +34,10 @@ procedure ClearSong(var Song: TSong); //Clears Song Header values procedure ResetSingTemp;
procedure ParseNote(NrCzesci: integer; TypeP: char; StartP, DurationP, NoteP: integer; LyricS: string);
procedure NewSentence(NrCzesciP: integer; Param1, Param2: integer; LoadFullFile: boolean);
-function LoadSong(Name: string; LoadFullFile: boolean): boolean;
-function CheckSong: boolean;
-function SaveSong(Song: TSong; Czesc: array of TCzesci; Name: string; Relative: boolean): boolean;
+function LoadSong(Name: string; LoadFullFile: boolean): boolean;
+function CheckSong: boolean;
+procedure SongQuality(Check: boolean);
+function SaveSong(Song: TSong; Czesc: array of TCzesci; Name: string; Relative: boolean): boolean;
procedure FindRefrainStart(var Song: TSong);
procedure SetMedleyMode;
@@ -180,6 +182,14 @@ begin SetLength(Song.DuetNames, 2);
Song.DuetNames[0] := 'P1';
Song.DuetNames[1] := 'P2';
+
+ //Quality
+ Song.Quality.Syntax := 0;
+ Song.Quality.BPM := 0;
+ Song.Quality.NoteGaps := 0;
+ Song.Quality.NoteJumps := 0;
+ Song.Quality.Scores := 50;
+ Song.Quality.Value := 0;
end;
//--------------------
@@ -879,6 +889,112 @@ begin if (Ini.LoadFaultySongs=0) and (Ini.LoadFaultySongs_temp=0) then
Result := false;
end;
+
+ SongQuality(Result);
+end;
+
+procedure SongQuality(Check: boolean);
+var
+ p, line, note: integer;
+ numLines: integer;
+ numNotes: integer;
+ firstNote: boolean;
+
+ lastNoteTone: integer;
+ lastNoteEnd: integer;
+
+ Gaps: array[0..2] of integer; //0=total; 1=gaps with length 0; 2=gaps with length 0 + note jump
+ GoldenNotes: integer;
+ gn: real;
+
+begin
+ // syntax quality
+ if Check then
+ AktSong.Quality.Syntax := 100
+ else
+ AktSong.Quality.Syntax := 0;
+
+ // BPM quality (check only 1st)
+ if (AktSong.BPM[0].BPM/4 < 100) then
+ AktSong.Quality.BPM := 5
+ else if (AktSong.BPM[0].BPM/4 < 200) then
+ AktSong.Quality.BPM := (AktSong.BPM[0].BPM/4-100)*0.95 + 5
+ else if (AktSong.BPM[0].BPM/4 < 1000) then
+ AktSong.Quality.BPM := 100
+ else
+ AktSong.Quality.BPM := 50;
+
+ // Score quality
+ p := Database.GetMaxScore(AktSong.Artist, AktSong.Title, 0);
+ if (p=0) then
+ begin
+ p := round(Database.GetMaxScore(AktSong.Artist, AktSong.Title, 1)*1.2);
+ if (p=0) then
+ p := round(Database.GetMaxScore(AktSong.Artist, AktSong.Title, 2)*1.5);
+ end;
+
+ if (p=0) then
+ AktSong.Quality.Scores := 50
+ else
+ begin
+ if (p>10000) then
+ p := 10000;
+
+ AktSong.Quality.Scores := p/100;
+ end;
+
+ Gaps[0] := 0;
+ Gaps[1] := 0;
+ Gaps[2] := 0;
+
+ GoldenNotes := 0;
+ gn := 0;
+
+ for p := 0 to Length(Czesci) - 1 do
+ begin
+ numLines := Length(Czesci[p].Czesc);
+ firstNote := true;
+
+ for line := 0 to numLines - 1 do
+ begin
+ numNotes := Length(Czesci[p].Czesc[line].Nuta);
+
+ for note := 0 to numNotes - 1 do
+ begin
+ if (Czesci[p].Czesc[line].Nuta[note].Wartosc = 2) then
+ Inc(GoldenNotes);
+
+ if firstNote then
+ firstNote := false
+ else
+ begin
+ Gaps[0] := Gaps[0] + 1;
+ if (lastNoteEnd = Czesci[p].Czesc[line].Nuta[note].Start) then
+ begin
+ Gaps[1] := Gaps[1] + 1;
+ if (abs(lastNoteTone - Czesci[p].Czesc[line].Nuta[note].Ton) > 1) then
+ Gaps[2] := Gaps[2] + 1;
+ end;
+ end;
+
+ lastNoteTone := Czesci[p].Czesc[line].Nuta[note].Ton;
+ lastNoteEnd := Czesci[p].Czesc[line].Nuta[note].Start + Czesci[p].Czesc[line].Nuta[note].Dlugosc;
+ end;
+ end;
+ end;
+
+ if (Gaps[0]>0) then
+ begin
+ AktSong.Quality.NoteGaps := 100 * (1-Gaps[1]/Gaps[0]);
+ AktSong.Quality.NoteJumps := 100 * (1-Gaps[2]/Gaps[0]);
+ gn := 100 * GoldenNotes/(Gaps[0]+1);
+ end;
+
+ AktSong.Quality.Value := (AktSong.Quality.Syntax + AktSong.Quality.BPM*3 + AktSong.Quality.NoteGaps*2 +
+ AktSong.Quality.NoteJumps*2 + AktSong.Quality.Scores*2) / 10;
+
+ Log.LogSongQuality(AktSong.Artist, AktSong.Title, AktSong.Quality.Syntax, AktSong.Quality.BPM, AktSong.Quality.NoteGaps,
+ AktSong.Quality.NoteJumps, AktSong.Quality.Scores, AktSong.Quality.Value, gn);
end;
diff --git a/Game/Code/Classes/UIni.pas b/Game/Code/Classes/UIni.pas index 3546e196..3b33785b 100644 --- a/Game/Code/Classes/UIni.pas +++ b/Game/Code/Classes/UIni.pas @@ -358,7 +358,7 @@ begin if Tekst = IResolution[Pet] then Ini.Resolution := Pet;
// FullScreen
- Tekst := IniFile.ReadString('Graphics', 'FullScreen', 'On');
+ Tekst := IniFile.ReadString('Graphics', 'FullScreen', 'Off');
for Pet := 0 to High(IFullScreen) do
if Tekst = IFullScreen[Pet] then Ini.FullScreen := Pet;
diff --git a/Game/Code/Classes/ULog.pas b/Game/Code/Classes/ULog.pas index a3e7f156..9e6f26fb 100644 --- a/Game/Code/Classes/ULog.pas +++ b/Game/Code/Classes/ULog.pas @@ -17,6 +17,9 @@ type FileSession: TextFile;
FileSessionO: boolean; // opened
+ FileSongQuality: TextFile;
+ FileSongQualityO: boolean; // opened
+
NumErrors: integer;
NumSungSongs: integer;
@@ -43,6 +46,7 @@ type function LogVoice(SoundNr: Integer; Player, Artist, Title, Points: string): string;
procedure LogSession(names: array of string; points: array of string; Artist, Title, singmode: string);
+ procedure LogSongQuality(artist, title: string; syntax, bpm, notegaps, notejumps, score, value, goldennotes: real);
// compability
procedure LogStatus(Log1, Log2: string);
@@ -285,7 +289,7 @@ begin // if FileAnalyzeO then CloseFile(FileAnalyze);
if FileErrorO then CloseFile(FileError);
if FileSessionO then CloseFile(FileSession);
-
+ if FileSongQualityO then CloseFile(FileSongQuality);
end;
procedure TLog.BenchmarkStart(Number: integer);
@@ -627,6 +631,43 @@ begin end;
end;
+procedure TLog.LogSongQuality(artist, title: string;
+ syntax, bpm, notegaps, notejumps, score, value, goldennotes: real);
+var
+ FileName: string;
+
+begin
+ if not FileSongQualityO then
+ begin
+ NumSungSongs := 0;
+ FileName := GamePath + 'quality.csv';
+
+ AssignFile(FileSongQuality, FileName);
+ {$I-}
+ Rewrite(FileSongQuality);
+ if IOResult = 0 then FileSongQualityO := true;
+ {$I+}
+
+ //If File is opened write column names to File
+ If (FileSongQualityO) then
+ begin
+ WriteLn(FileSongQuality, 'Artist; Title; Syntax; BPM; Note Gaps; Note Jumps; Scores; Value; Anteil Goldene Noten');
+ Flush(FileSongQuality);
+ end;
+ end;
+
+ if FileSongQualityO then
+ begin
+ try
+ WriteLn(FileSongQuality, artist + ';' + title + ';' + FloatToStr(syntax) + ';' +
+ FloatToStr(bpm) + ';' + FloatToStr(notegaps) + ';' + FloatToStr(notejumps) + ';' +
+ FloatToStr(score) + ';' + FloatToStr(value) + ';' + FloatToStr(goldennotes) + ';');
+ except
+ FileSongQualityO := false;
+ end;
+ end;
+end;
+
procedure TLog.LogStatus(Log1, Log2: string);
begin
//Just for Debugging
diff --git a/Game/Code/Classes/USongs.pas b/Game/Code/Classes/USongs.pas index f3323244..20d107e1 100644 --- a/Game/Code/Classes/USongs.pas +++ b/Game/Code/Classes/USongs.pas @@ -18,6 +18,16 @@ type FadeOut_time: real; //FadeOut-Time in seconds
end;
+ TSongQuality = record // 0..100% 0% = worst, 100% = should be good
+ Syntax: real; // are there syntax errors in txt?
+ BPM: real; // should be between 200 and 450
+ NoteGaps: real; // notes should have some space between each other
+ NoteJumps: real; // don't change the note level too much if there's no space between the notes
+ Scores: real; // 50% if no highscore available, else: maximum highscore/10
+
+ Value: real; // summarized quality indicator
+ end;
+
{ used to hold header tags that are not supported by this version of
usdx (e.g. some tags from ultrastar 0.7.0) when songs are loaded in
songeditor. They will be written the end of the song header } //from usdx 1.1
@@ -43,6 +53,8 @@ type Folder: string; // for sorting by folder
FileName: string;
+ Quality: TSongQuality;
+
isDuet: boolean;
DuetNames: array of string;
Medley: TMedley;
diff --git a/Game/Code/Screens/UScreenEditSub.pas b/Game/Code/Screens/UScreenEditSub.pas index b232ff19..31196d45 100644 --- a/Game/Code/Screens/UScreenEditSub.pas +++ b/Game/Code/Screens/UScreenEditSub.pas @@ -387,6 +387,9 @@ begin if SResult then
begin
Text[TextDebug].Text := Language.Translate('INFO_FILE_SAVED');
+ if not CheckSong then
+ ScreenPopupError.ShowPopup('This song contains some syntax errors!');
+
CatSongs.Song[SongIndex] := AktSong;
end else
begin
diff --git a/Game/Code/Screens/UScreenSong.pas b/Game/Code/Screens/UScreenSong.pas index 011e4b26..9b811a62 100644 --- a/Game/Code/Screens/UScreenSong.pas +++ b/Game/Code/Screens/UScreenSong.pas @@ -40,6 +40,7 @@ type ChooseableSongs: integer;
isScrolling: boolean;
FadeOut: boolean;
+ ShowSongQuality: boolean;
public
Sel3: integer; //Selection in party mode (0=current, -1=left, 1=right)
@@ -517,6 +518,12 @@ begin Music.EnableVocalRemover;
end;
+ SDLK_I:
+ begin
+ if (Mode = smNormal) then
+ ShowSongQuality := not ShowSongQuality;
+ end;
+
SDLK_O:
begin
if (Mode = smNormal) then
@@ -1388,6 +1395,8 @@ begin EqualizerBands[I] := 3;
MP3Volume := Ini.PreviewVolume * 10;
+
+ ShowSongQuality := false;
end;
procedure TScreenSong.ChangeSorting(tabs: boolean; sorting: integer);
@@ -2681,6 +2690,34 @@ begin DrawExtensions;
+ // Song Quality
+ if ShowSongQuality and not CatSongs.Song[Interaction].Main then
+ begin
+ SetFontStyle(0);
+ SetFontItalic(false); + SetFontSize(6);
+
+ glColor4f(1, 1, 1, 1);
+
+ SetFontPos (525, 80); + glPrint(PChar(FormatFloat('STX: 000%', CatSongs.Song[Interaction].Quality.Syntax)));
+
+ SetFontPos (600, 80);
+ glPrint(PChar(FormatFloat('BPM: 000%', CatSongs.Song[Interaction].Quality.BPM)));
+
+ SetFontPos (675, 80);
+ glPrint(PChar(FormatFloat('NGP: 000%', CatSongs.Song[Interaction].Quality.NoteGaps)));
+
+ SetFontPos (525, 95);
+ glPrint(PChar(FormatFloat('NJP: 000%', CatSongs.Song[Interaction].Quality.NoteJumps)));
+
+ SetFontPos (600, 95);
+ glPrint(PChar(FormatFloat('SCO: 000%', CatSongs.Song[Interaction].Quality.Scores)));
+
+ SetFontPos (675, 95);
+ glPrint(PChar(FormatFloat('VAL: 000%', CatSongs.Song[Interaction].Quality.Value)));
+ end;
+
StartPreview;
end;
|