aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--game/languages/English.ini5
-rw-r--r--game/languages/German.ini5
-rw-r--r--game/themes/Deluxe.ini75
-rw-r--r--src/base/UDataBase.pas127
-rw-r--r--src/base/USong.pas1
-rw-r--r--src/base/UThemes.pas2
-rw-r--r--src/screens/UScreenStatDetail.pas2
-rw-r--r--src/screens/UScreenTop5.pas78
8 files changed, 234 insertions, 61 deletions
diff --git a/game/languages/English.ini b/game/languages/English.ini
index 9053328e..243415fb 100644
--- a/game/languages/English.ini
+++ b/game/languages/English.ini
@@ -233,6 +233,7 @@ SING_SCORE_ULTRASTAR=Ultrastar
SING_TOP_5_CHARTS=top 5 Players
SING_TOP_5_CHARTS_WHEREAMI=top 5
SING_TOP_5_CHARTS_CONTINUE=to song selection
+SING_TOP_5_CHARTS_SWITCH_DIFFICULTY=switch difficulty
POPUP_PERFECT=perfect!
POPUP_AWESOME=awesome!
@@ -361,6 +362,8 @@ STAT_OVERVIEW_INTRO=%0:s Statistics. \n Last Reset at %2:.2d.%1:.2d.%3:d
STAT_OVERVIEW_SONG=%0:d Songs(%3:d with Video), whereof %1:d already were played and %2:d were not played yet.\n The most popular Song is %5:s from %4:s.
STAT_OVERVIEW_PLAYER=Since the last Reset there were/was %0:d different Player(s).\n The best Player is %1:s with an average Score of %2:d Points.\n %3:s did the highest Score with %4:d Points.
+STAT_FORMAT_DATE=%1:.2d.%0:.2d.%2:d
+
STAT_DETAIL=Statistics
STAT_DETAIL_WHEREAMI=Detail Statistics
@@ -371,7 +374,7 @@ STAT_PAGE=Seite %0:d of %1:d Pages\n (%2:d of %3:d Entrys)
STAT_DESC_SCORES=HighScores
STAT_DESC_SCORES_REVERSED=LowScores
-STAT_FORMAT_SCORES=%0:s - %1:d [%2:s] \n (%3:s - %4:s)
+STAT_FORMAT_SCORES=%0:s - %1:d [%2:s] %5:s \n (%3:s - %4:s)
STAT_DESC_SINGERS=Best Singers
STAT_DESC_SINGERS_REVERSED=Worst Singers
diff --git a/game/languages/German.ini b/game/languages/German.ini
index 7b29c494..4aae568f 100644
--- a/game/languages/German.ini
+++ b/game/languages/German.ini
@@ -233,6 +233,7 @@ SING_SCORE_ULTRASTAR=UltraStar
SING_TOP_5_CHARTS=Top-5-Spieler
SING_TOP_5_CHARTS_WHEREAMI=Top 5
SING_TOP_5_CHARTS_CONTINUE=Zur Songauswahl
+SING_TOP_5_CHARTS_SWITCH_DIFFICULTY=Schwierigkeitsstufen
POPUP_PERFECT=Perfekt!
POPUP_AWESOME=Cool!
@@ -361,6 +362,8 @@ STAT_OVERVIEW_INTRO=%0:s Statistiken. \n Letzter Reset am %1:.2d.%2:.2d.%3:d
STAT_OVERVIEW_SONG=%0:d Songs(%3:d mit Video), davon wurden %1:d schon einmal gesungen und %2:d noch nicht. \n Der am häufigsten gesungene Song ist %5:s von %4:s.
STAT_OVERVIEW_PLAYER=Seit dem letzten Reset haben %0:d verschiedene Spieler gesungen. \n Der beste Spieler ist %1:s mit %2:d Punkten. \n Die höchste Punktzahl, %4:d, wurde von %3:s erreicht.
+STAT_FORMAT_DATE=%0:.2d.%1:.2d.%2:d
+
STAT_DETAIL=Statistiken
STAT_DETAIL_WHEREAMI=Detaillierte Statistiken
@@ -371,7 +374,7 @@ STAT_PAGE=Seite %0:d von %1:d \n (%2:d von %3:d Einträgen)
STAT_DESC_SCORES=Highscores
STAT_DESC_SCORES_REVERSED=Lowscores
-STAT_FORMAT_SCORES=%0:s - %1:d [%2:s] \n (%3:s - %4:s)
+STAT_FORMAT_SCORES=%0:s - %1:d [%2:s] %5:s \n (%3:s - %4:s)
STAT_DESC_SINGERS=Beste Sänger
STAT_DESC_SINGERS_REVERSED=Schlechteste Sänger
diff --git a/game/themes/Deluxe.ini b/game/themes/Deluxe.ini
index f4bee1ab..cf3ad368 100644
--- a/game/themes/Deluxe.ini
+++ b/game/themes/Deluxe.ini
@@ -725,7 +725,6 @@ Align = 2
Text = PARTY_SONG_WHEREAMI
#variable statics end
-
# Jokers, 5 for each team, only shown in party Mode
[SongStaticTeam1Joker1]
Tex = Joker
@@ -4442,6 +4441,24 @@ Size = 21
Align = 0
Text = SING_TOP_5_CHARTS_CONTINUE
+[Top5Static5]
+X = 530
+Y = 552
+W = 24
+H = 23
+Tex = ButtonNavi
+Color = White
+Type = Transparent
+
+[Top5Text5]
+X = 560
+Y = 552
+Color = Black
+Font = 0
+Size = 21
+Align = 0
+Text = SING_TOP_5_CHARTS_SWITCH_DIFFICULTY
+
[Top5TextName1]
X = 150
Y = 190
@@ -4488,7 +4505,7 @@ Align = 0
Text = 5. Player5
[Top5TextScore1]
-X = 680
+X = 560
Y = 190
Color = White
Font = 0
@@ -4497,7 +4514,7 @@ Align = 2
Text = 00000
[Top5TextScore2]
-X = 680
+X = 560
Y = 240
Color = White
Font = 0
@@ -4506,7 +4523,7 @@ Align = 2
Text = 00000
[Top5TextScore3]
-X = 680
+X = 560
Y = 290
Color = White
Font = 0
@@ -4515,7 +4532,7 @@ Align = 2
Text = 00000
[Top5TextScore4]
-X = 680
+X = 560
Y = 340
Color = White
Font = 0
@@ -4524,7 +4541,53 @@ Align = 2
Text = 00000
[Top5TextScore5]
-X = 680
+X = 560
+Y = 390
+Color = White
+Font = 0
+Size = 42
+Align = 2
+Text = 00000
+
+
+[Top5TextDate1]
+X = 760
+Y = 190
+Color = White
+Font = 0
+Size = 42
+Align = 2
+Text = 00000
+
+[Top5TextDate2]
+X = 760
+Y = 240
+Color = White
+Font = 0
+Size = 42
+Align = 2
+Text = 00000
+
+[Top5TextDate3]
+X = 760
+Y = 290
+Color = White
+Font = 0
+Size = 42
+Align = 2
+Text = 00000
+
+[Top5TextDate4]
+X = 760
+Y = 340
+Color = White
+Font = 0
+Size = 42
+Align = 2
+Text = 00000
+
+[Top5TextDate5]
+X = 760
Y = 390
Color = White
Font = 0
diff --git a/src/base/UDataBase.pas b/src/base/UDataBase.pas
index bdcbd30f..85b4b8e8 100644
--- a/src/base/UDataBase.pas
+++ b/src/base/UDataBase.pas
@@ -64,6 +64,7 @@ type
Difficulty: byte;
SongArtist: UTF8String;
SongTitle: UTF8String;
+ Date: UTF8String;
end;
TStatResultBestSingers = class(TStatResult)
@@ -85,7 +86,7 @@ type
TimesSungTot: word;
end;
-
+
TDataBaseSystem = class
private
ScoreDB: TSQLiteDatabase;
@@ -107,6 +108,7 @@ type
procedure FreeStats(StatList: TList);
function GetTotalEntrys(Typ: TStatType): cardinal;
function GetStatReset: TDateTime;
+ function FormatDate(time_stamp: integer): UTF8String;
end;
var
@@ -116,6 +118,7 @@ implementation
uses
DateUtils,
+ ULanguage,
StrUtils,
SysUtils,
ULog;
@@ -145,7 +148,7 @@ begin
Log.LogStatus('Initializing database: "' + Filename.ToNative + '"', 'TDataBaseSystem.Init');
try
-
+
// open database
ScoreDB := TSQLiteDatabase.Create(Filename.ToUTF8);
fFilename := Filename;
@@ -192,7 +195,8 @@ begin
'[SongID] INTEGER NOT NULL, ' +
'[Difficulty] INTEGER NOT NULL, ' +
'[Player] TEXT NOT NULL, ' +
- '[Score] INTEGER NOT NULL' +
+ '[Score] INTEGER NOT NULL, ' +
+ '[Date] INTEGER NULL' +
');');
ScoreDB.ExecSQL('CREATE TABLE IF NOT EXISTS [' + cUS_Songs + '] (' +
@@ -200,7 +204,7 @@ begin
'[Artist] TEXT NOT NULL, ' +
'[Title] TEXT NOT NULL, ' +
'[TimesPlayed] INTEGER NOT NULL, ' +
- '[Rating] INTEGER NULL' +
+ '[Rating] INTEGER NULL' +
');');
// convert data from 1.01 to 1.1
@@ -221,7 +225,15 @@ begin
if not ScoreDB.ContainsColumn(cUS_Songs, 'Rating') then
begin
Log.LogInfo('Outdated song database found - adding column rating to "' + cUS_Songs + '"', 'TDataBaseSystem.Init');
- ScoreDB.ExecSQL('ALTER TABLE ' + cUS_Songs + ' ADD COLUMN Rating INTEGER NULL');
+ ScoreDB.ExecSQL('ALTER TABLE ' + cUS_Songs + ' ADD COLUMN [Rating] INTEGER NULL');
+ end;
+
+
+ //add column date to cUS-Scores
+ if not ScoreDB.ContainsColumn(cUS_Scores, 'Date') then
+ begin
+ Log.LogInfo('adding column date to "' + cUS_Scores + '"', 'TDataBaseSystem.Init');
+ ScoreDB.ExecSQL('ALTER TABLE ' + cUS_Scores + ' ADD COLUMN [Date] INTEGER NULL');
end;
except
@@ -245,33 +257,55 @@ begin
end;
(**
+ * Format a UNIX-Timestamp into DATE (If 0 then '')
+ *)
+function TDataBaseSystem.FormatDate(time_stamp: integer): UTF8String;
+var
+ Year, Month, Day: word;
+begin
+ Result:='';
+ try
+ if time_stamp<>0 then
+ begin
+ DecodeDate(UnixToDateTime(time_stamp), Year, Month, Day);
+ Result := Format(Language.Translate('STAT_FORMAT_DATE'), [Day, Month, Year]);
+ end;
+ except
+ on E: EConvertError do
+ Log.LogError('Error Parsing FormatString "STAT_FORMAT_DATE": ' + E.Message);
+ end;
+end;
+
+
+(**
* Read Scores into SongArray
*)
procedure TDataBaseSystem.ReadScore(Song: TSong);
var
TableData: TSQLiteUniTable;
Difficulty: integer;
+ I: integer;
+ PlayerListed: boolean;
begin
if not Assigned(ScoreDB) then
Exit;
TableData := nil;
-
try
// Search Song in DB
TableData := ScoreDB.GetUniTable(
- 'SELECT [Difficulty], [Player], [Score] FROM [' + cUS_Scores + '] ' +
+ 'SELECT [Difficulty], [Player], [Score], [Date] FROM [' + cUS_Scores + '] ' +
'WHERE [SongID] = (' +
'SELECT [ID] FROM [' + cUS_Songs + '] ' +
'WHERE [Artist] = ? AND [Title] = ? ' +
'LIMIT 1) ' +
- 'ORDER BY [Score] DESC LIMIT 15',
+ 'ORDER BY [Score] DESC;', //no LIMIT! see filter below!
[Song.Artist, Song.Title]);
// Empty Old Scores
- SetLength(Song.Score[0], 0);
- SetLength(Song.Score[1], 0);
- SetLength(Song.Score[2], 0);
+ SetLength(Song.Score[0], 0); //easy
+ SetLength(Song.Score[1], 0); //medium
+ SetLength(Song.Score[2], 0); //hard
// Go through all Entrys
while (not TableData.EOF) do
@@ -281,12 +315,31 @@ begin
if ((Difficulty >= 0) and (Difficulty <= 2)) and
(Length(Song.Score[Difficulty]) < 5) then
begin
- SetLength(Song.Score[Difficulty], Length(Song.Score[Difficulty]) + 1);
+ //filter player
+ PlayerListed:=false;
+ if (Length(Song.Score[Difficulty])>0) then
+ begin
+ for I := 0 to Length(Song.Score[Difficulty]) - 1 do
+ begin
+ if (Song.Score[Difficulty, I].Name = TableData.FieldByName['Player']) then
+ begin
+ PlayerListed:=true;
+ break;
+ end;
+ end;
+ end;
- Song.Score[Difficulty, High(Song.Score[Difficulty])].Name :=
+ if not PlayerListed then
+ begin
+ SetLength(Song.Score[Difficulty], Length(Song.Score[Difficulty]) + 1);
+
+ Song.Score[Difficulty, High(Song.Score[Difficulty])].Name :=
TableData.FieldByName['Player'];
- Song.Score[Difficulty, High(Song.Score[Difficulty])].Score :=
+ Song.Score[Difficulty, High(Song.Score[Difficulty])].Score :=
TableData.FieldAsInteger(TableData.FieldIndex['Score']);
+ Song.Score[Difficulty, High(Song.Score[Difficulty])].Date :=
+ FormatDate(TableData.FieldAsInteger(TableData.FieldIndex['Date']));
+ end;
end;
TableData.Next;
@@ -314,9 +367,9 @@ begin
if not Assigned(ScoreDB) then
Exit;
- // Prevent 0 Scores from being added
- if (Score <= 0) then
- Exit;
+ // Prevent 0 Scores from being added EDIT: ==> UScreenTop5.pas!
+ //if (Score <= 0) then
+ // Exit;
TableData := nil;
@@ -339,37 +392,10 @@ begin
end;
// Create new entry
ScoreDB.ExecSQL(
- 'INSERT INTO [' + cUS_Scores + '] ' +
- '([SongID] ,[Difficulty], [Player], [Score]) VALUES ' +
- '(?, ?, ?, ?);',
- [ID, Level, Name, Score]);
-
- // Delete last position when there are more than 5 entrys.
- // Fixes crash when there are > 5 ScoreEntrys
- // Note: GetUniTable is not applicable here, as the results are used while
- // table entries are deleted.
- TableData := ScoreDB.GetTable(
- 'SELECT [Player], [Score] FROM [' + cUS_Scores + '] ' +
- 'WHERE [SongID] = ' + InttoStr(ID) + ' AND ' +
- '[Difficulty] = ' + InttoStr(Level) + ' ' +
- 'ORDER BY [Score] DESC LIMIT -1 OFFSET 5');
-
- while (not TableData.EOF) do
- begin
- // Note: Score is an int-value, so in contrast to Player, we do not bind
- // this value. Otherwise we had to convert the string to an int to avoid
- // an automatic cast of this field to the TEXT type (although it might even
- // work that way).
- ScoreDB.ExecSQL(
- 'DELETE FROM [' + cUS_Scores + '] ' +
- 'WHERE [SongID] = ' + InttoStr(ID) + ' AND ' +
- '[Difficulty] = ' + InttoStr(Level) +' AND ' +
- '[Player] = ? AND ' +
- '[Score] = ' + TableData.FieldByName['Score'],
- [TableData.FieldByName['Player']]);
-
- TableData.Next;
- end;
+ 'INSERT INTO [' + cUS_Scores + '] ' +
+ '([SongID] ,[Difficulty], [Player], [Score], [Date]) VALUES ' +
+ '(?, ?, ?, ?, ?);',
+ [ID, Level, Name, Score, DateTimeToUnix(Now())]);
except on E: Exception do
Log.LogError(E.Message, 'TDataBaseSystem.AddScore');
@@ -386,7 +412,7 @@ procedure TDataBaseSystem.WriteScore(Song: TSong);
begin
if not Assigned(ScoreDB) then
Exit;
-
+
try
// Increase TimesPlayed
ScoreDB.ExecSQL(
@@ -421,7 +447,7 @@ begin
// Create query
case Typ of
stBestScores: begin
- Query := 'SELECT [Player], [Difficulty], [Score], [Artist], [Title] FROM [' + cUS_Scores + '] ' +
+ Query := 'SELECT [Player], [Difficulty], [Score], [Artist], [Title], [Date] FROM [' + cUS_Scores + '] ' +
'INNER JOIN [' + cUS_Songs + '] ON ([SongID] = [ID]) ORDER BY [Score]';
end;
stBestSingers: begin
@@ -471,6 +497,7 @@ begin
Score := TableData.FieldAsInteger(2);
SongArtist := TableData.Fields[3];
SongTitle := TableData.Fields[4];
+ Date := FormatDate(TableData.FieldAsInteger(5));
end;
end;
stBestSingers: begin
diff --git a/src/base/USong.pas b/src/base/USong.pas
index f8698d43..c465f198 100644
--- a/src/base/USong.pas
+++ b/src/base/USong.pas
@@ -74,6 +74,7 @@ type
TScore = record
Name: UTF8String;
Score: integer;
+ Date: UTF8String;
end;
{ used to hold header tags that are not supported by this version of
diff --git a/src/base/UThemes.pas b/src/base/UThemes.pas
index c1a26927..4322815e 100644
--- a/src/base/UThemes.pas
+++ b/src/base/UThemes.pas
@@ -409,6 +409,7 @@ type
TextNumber: AThemeText;
TextName: AThemeText;
TextScore: AThemeText;
+ TextDate: AThemeText;
end;
TThemeOptions = class(TThemeBasic)
@@ -1176,6 +1177,7 @@ begin
ThemeLoadTexts(Top5.TextNumber, 'Top5TextNumber');
ThemeLoadTexts(Top5.TextName, 'Top5TextName');
ThemeLoadTexts(Top5.TextScore, 'Top5TextScore');
+ ThemeLoadTexts(Top5.TextDate, 'Top5TextDate');
// Options
ThemeLoadBasic(Options, 'Options');
diff --git a/src/screens/UScreenStatDetail.pas b/src/screens/UScreenStatDetail.pas
index 249626b0..1638cd85 100644
--- a/src/screens/UScreenStatDetail.pas
+++ b/src/screens/UScreenStatDetail.pas
@@ -234,7 +234,7 @@ begin
if (Score > 0) then
begin
Text[I].Text := Format(FormatStr,
- [Singer, Score, Theme.ILevel[Difficulty], SongArtist, SongTitle]);
+ [Singer, Score, Theme.ILevel[Difficulty], SongArtist, SongTitle, Date]);
end;
end;
end;
diff --git a/src/screens/UScreenTop5.pas b/src/screens/UScreenTop5.pas
index f9c86643..b0795f54 100644
--- a/src/screens/UScreenTop5.pas
+++ b/src/screens/UScreenTop5.pas
@@ -47,11 +47,13 @@ type
public
TextLevel: integer;
TextArtistTitle: integer;
+ DifficultyShow: integer;
StaticNumber: array[1..5] of integer;
TextNumber: array[1..5] of integer;
TextName: array[1..5] of integer;
TextScore: array[1..5] of integer;
+ TextDate: array[1..5] of integer;
Fadeout: boolean;
@@ -59,6 +61,7 @@ type
function ParseInput(PressedKey: cardinal; CharCode: UCS4Char; PressedDown: boolean): boolean; override;
function ParseMouse(MouseButton: integer; BtnDown: boolean; X, Y: integer): boolean; override;
procedure OnShow; override;
+ procedure DrawScores(difficulty: integer);
function Draw: boolean; override;
end;
@@ -98,6 +101,34 @@ begin
Fadeout := true;
end;
end;
+ SDLK_RIGHT:
+ begin
+ inc(DifficultyShow);
+ if (DifficultyShow>2) then
+ DifficultyShow:=0;
+ DrawScores(DifficultyShow);
+ end;
+ SDLK_LEFT:
+ begin
+ dec(DifficultyShow);
+ if (DifficultyShow<0) then
+ DifficultyShow:=2;
+ DrawScores(DifficultyShow);
+ end;
+ SDLK_UP:
+ begin
+ inc(DifficultyShow);
+ if (DifficultyShow>2) then
+ DifficultyShow:=0;
+ DrawScores(DifficultyShow);
+ end;
+ SDLK_DOWN:
+ begin
+ dec(DifficultyShow);
+ if (DifficultyShow<0) then
+ DifficultyShow:=2;
+ DrawScores(DifficultyShow);
+ end;
SDLK_SYSREQ:
begin
Display.SaveScreenShot;
@@ -133,6 +164,7 @@ begin
TextNumber[I+1] := AddText (Theme.Top5.TextNumber[I]);
TextName[I+1] := AddText (Theme.Top5.TextName[I]);
TextScore[I+1] := AddText (Theme.Top5.TextScore[I]);
+ TextDate[I+1] := AddText (Theme.Top5.TextDate[I]);
end;
end;
@@ -141,10 +173,13 @@ procedure TScreenTop5.OnShow;
var
I: integer;
PMax: integer;
+ sung: boolean; //score added? otherwise in wasn't sung!
begin
inherited;
+ sung := false;
Fadeout := false;
+ DifficultyShow := Ini.Difficulty;
//ReadScore(CurrentSong);
@@ -152,9 +187,16 @@ begin
if PMax = 4 then
PMax := 5;
for I := 0 to PMax do
- DataBase.AddScore(CurrentSong, Ini.Difficulty, Ini.Name[I], Round(Player[I].ScoreTotalInt));
+ begin
+ if (Round(Player[I].ScoreTotalInt) > 0) then
+ begin
+ DataBase.AddScore(CurrentSong, Ini.Difficulty, Ini.Name[I], Round(Player[I].ScoreTotalInt));
+ sung:=true;
+ end;
+ end;
- DataBase.WriteScore(CurrentSong);
+ if sung then
+ DataBase.WriteScore(CurrentSong);
DataBase.ReadScore(CurrentSong);
Text[TextArtistTitle].Text := CurrentSong.Artist + ' - ' + CurrentSong.Title;
@@ -165,9 +207,11 @@ begin
Text[TextNumber[I]].Visible := true;
Text[TextName[I]].Visible := true;
Text[TextScore[I]].Visible := true;
+ Text[TextDate[I]].Visible := true;
Text[TextName[I]].Text := CurrentSong.Score[Ini.Difficulty, I-1].Name;
Text[TextScore[I]].Text := IntToStr(CurrentSong.Score[Ini.Difficulty, I-1].Score);
+ Text[TextDate[I]].Text := CurrentSong.Score[Ini.Difficulty, I-1].Date;
end;
for I := Length(CurrentSong.Score[Ini.Difficulty]) + 1 to 5 do
@@ -176,11 +220,41 @@ begin
Text[TextNumber[I]].Visible := false;
Text[TextName[I]].Visible := false;
Text[TextScore[I]].Visible := false;
+ Text[TextDate[I]].Visible := false;
end;
Text[TextLevel].Text := IDifficulty[Ini.Difficulty];
end;
+procedure TScreenTop5.DrawScores(difficulty: integer);
+var
+ I: integer;
+begin
+ for I := 1 to Length(CurrentSong.Score[difficulty]) do
+ begin
+ Static[StaticNumber[I]].Visible := true;
+ Text[TextNumber[I]].Visible := true;
+ Text[TextName[I]].Visible := true;
+ Text[TextScore[I]].Visible := true;
+ Text[TextDate[I]].Visible := true;
+
+ Text[TextName[I]].Text := CurrentSong.Score[difficulty, I-1].Name;
+ Text[TextScore[I]].Text := IntToStr(CurrentSong.Score[difficulty, I-1].Score);
+ Text[TextDate[I]].Text := CurrentSong.Score[difficulty, I-1].Date;
+ end;
+
+ for I := Length(CurrentSong.Score[difficulty]) + 1 to 5 do
+ begin
+ Static[StaticNumber[I]].Visible := false;
+ Text[TextNumber[I]].Visible := false;
+ Text[TextName[I]].Visible := false;
+ Text[TextScore[I]].Visible := false;
+ Text[TextDate[I]].Visible := false;
+ end;
+
+ Text[TextLevel].Text := IDifficulty[difficulty];
+end;
+
function TScreenTop5.Draw: boolean;
//var
{