aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbrunzelchen <brunzelchen@b956fd51-792f-4845-bead-9b4dfca2ff2c>2011-04-25 10:53:52 +0000
committerbrunzelchen <brunzelchen@b956fd51-792f-4845-bead-9b4dfca2ff2c>2011-04-25 10:53:52 +0000
commit3de159b0d467f57967642431f96b7d675b004b8e (patch)
treea690bb422069071e4d8c0a5c8ddf92642ba24925
parented610027abbb1ffebc8067a623f785ed48680ecc (diff)
downloadusdx-3de159b0d467f57967642431f96b7d675b004b8e.tar.gz
usdx-3de159b0d467f57967642431f96b7d675b004b8e.tar.xz
usdx-3de159b0d467f57967642431f96b7d675b004b8e.zip
added song quality check
git-svn-id: svn://svn.code.sf.net/p/ultrastardx/svn/branches/1.0.1 Challenge MOD@2829 b956fd51-792f-4845-bead-9b4dfca2ff2c
-rw-r--r--Game/Code/Classes/UDataBase.pas30
-rw-r--r--Game/Code/Classes/UFiles.pas124
-rw-r--r--Game/Code/Classes/UIni.pas2
-rw-r--r--Game/Code/Classes/ULog.pas43
-rw-r--r--Game/Code/Classes/USongs.pas12
-rw-r--r--Game/Code/Screens/UScreenEditSub.pas3
-rw-r--r--Game/Code/Screens/UScreenSong.pas37
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;