/*
* UltraStar Deluxe - Karaoke Game
*
* UltraStar Deluxe is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*
* $URL$
* $Id$
*/
#include "stats_database.hpp"
namespace usdx
{
const int db_version = 1;
const std::wstring StatDatabase::usdx_scores =
L"us_scores";
const std::wstring StatDatabase::usdx_songs =
L"us_songs";
const std::wstring StatDatabase::usdx_statistics_info =
L"us_statistics_info";
log4cxx::LoggerPtr StatDatabase::log =
log4cxx::Logger::getLogger("usdx.base.StatDatabase");
StatDatabase::StatDatabase(const std::string filename) :
Database(filename)
{
LOG4CXX_DEBUG(log, "Initializing Database: " << filename);
if (! sqlite_table_exists(usdx_statistics_info)) {
// add table usdx_statistics_info, needed in the
// conversion from 1.01 to 1.1
LOG4CXX_INFO(log, L"Outdated song database found " <<
L"- missing table'" <<
usdx_statistics_info << L"'");
sqlite_exec(L"CREATE TABLE IF NOT EXISTS [" +
usdx_statistics_info +
L"] ([ResetTime] Integer);");
// insert creation timestamp
sqlite3_stmt *sqliteStatement =
sqlite_prepare(L"INSERT INTO [" +
usdx_statistics_info +
L"] ([ResetTime]) VALUES (?1);");
sqlite3_bind_int(sqliteStatement, 1, time(NULL));
sqlite3_step(sqliteStatement);
sqlite3_finalize(sqliteStatement);
}
int version = get_version();
bool finalizeConversion = false;
if (version == 0 && sqlite_table_exists(L"US_Scores")) {
// convert data from 1.01 to 1.1
// part #1 - prearrangement: rename old tables
// to be able to insert new table structures
sqlite_exec(L"ALTER TABLE US_Scores RENAME TO us_scores_101;");
sqlite_exec(L"ALTER TABLE US_Songs RENAME TO us_songs_101;");
}
if (version == 0) {
// Set version number after creation
set_version(db_version);
}
// SQLite does not handle VARCHAR(n) or INT(n) as expected.
// Texts do not have a restricted length, no matter which type
// is used, so use the native TEXT type. INT(n) is always
// INTEGER. In addition, SQLiteTable3 will fail if other types
// than the native SQLite types are used (especially
// FieldAsInteger). Also take care to write the types in
// upper-case letters although SQLite does not care about this -
// SQLiteTable3 is very sensitive in this regard.
std::wstring sqlStatement;
sqlStatement = L"CREATE TABLE IF NOT EXISTS [";
sqlStatement += usdx_scores;
sqlStatement += L"] (";
sqlStatement += L"[SongID] INTEGER NOT NULL, ";
sqlStatement += L"[Difficulty] INTEGER NOT NULL, ";
sqlStatement += L"[Player] TEXT NOT NULL, ";
sqlStatement += L"[Score] INTEGER NOT NULL, ";
sqlStatement += L"[Date] INTEGER NULL";
sqlStatement += L");";
sqlite_exec(sqlStatement);
sqlStatement = L"CREATE TABLE IF NOT EXISTS [";
sqlStatement += usdx_songs;
sqlStatement += L"] (";
sqlStatement += L"[ID] INTEGER PRIMARY KEY, ";
sqlStatement += L"[Artist] TEXT NOT NULL, ";
sqlStatement += L"[Title] TEXT NOT NULL, ";
sqlStatement += L"[TimesPlayed] INTEGER NOT NULL, ";
sqlStatement += L"[Rating] INTEGER NULL";
sqlStatement += L");";
sqlite_exec(sqlStatement);
if (finalizeConversion) {
// convert data from 1.01 to 1.1
// part #2 - accomplishment
LOG4CXX_INFO(log, L"Outdated song database found - " <<
L"begin conversion from V1.01 to V1.1");
// insert old values into new db-schemes (/tables)
sqlStatement = L"INSERT INTO [";
sqlStatement += usdx_scores;
sqlStatement += L"] SELECT [SongID], ";
sqlStatement += L"[Difficulty], [Player], ";
sqlStatement += L"[Score] FROM [us_scores_101];";
sqlite_exec(sqlStatement);
sqlStatement = L"INSERT INTO [";
sqlStatement += usdx_songs;
sqlStatement += L"] SELECT [ID], [Artist], ";
sqlStatement += L"[Title], [TimesPlayed], NULL ";
sqlStatement += L"FROM [us_songs_101];";
sqlite_exec(sqlStatement);
// now drop old tables
sqlite_exec(L"DROP TABLE us_scores_101;");
sqlite_exec(L"DROP TABLE us_songs_101;");
}
// add column rating to cUS_Songs
// just for users of nightly builds and developers!
if (! sqlite_table_contains_column(usdx_songs, L"Rating")) {
LOG4CXX_INFO(log, L"Outdated song database found - " <<
L"adding column rating to '" <<
usdx_songs << L"'");
sqlite_exec(L"ALTER TABLE [" + usdx_songs +
L"] ADD COLUMN [Rating] INTEGER NULL;");
}
//add column date to cUS-Scores
if (! sqlite_table_contains_column(usdx_scores, L"Date")) {
LOG4CXX_INFO(log, L"Outdated score database found - " <<
L"adding column date to '" <<
usdx_scores << L"'");
sqlite_exec(L"ALTER TABLE [" + usdx_scores +
L"] ADD COLUMN [Date] INTEGER NULL;");
}
}
StatDatabase::~StatDatabase(void)
{
this->Database::~Database();
}
char* StatDatabase::format_date(char* time,
size_t max,
time_t timestamp)
{
if (timestamp != 0) {
struct tm tmp;
if (localtime_r(×tamp, &tmp)) {
strftime(time, max, "%d.%m.%y"
/* TODO: Language.Translate("STAT_FORMAT_DATE")*/,
&tmp);
return time;
}
}
if (max > 0) {
time[0] = '\0';
return time;
}
return NULL;
}
};