#include "library/dao/autodjcratesdao.h"
#if (QT_VERSION >= QT_VERSION_CHECK(5, 10, 0))
#include <QRandomGenerator>
#endif
#include <QtDebug>
#include <QtSql>
#include "library/crate/crateschema.h"
#include "library/dao/settingsdao.h"
#include "library/dao/trackdao.h"
#include "library/dao/trackschema.h"
#include "library/queryutil.h"
#include "library/trackcollection.h"
#include "mixer/playerinfo.h"
#include "mixer/playermanager.h"
#include "track/track.h"
#define AUTODJCRATESTABLE_TRACKID "track_id"
#define AUTODJCRATESTABLE_CRATEREFS "craterefs"
#define AUTODJCRATESTABLE_TIMESPLAYED "timesplayed"
#define AUTODJCRATESTABLE_AUTODJREFS "autodjrefs"
#define AUTODJCRATESTABLE_LASTPLAYED "lastplayed"
#define AUTODJCRATES_TABLE "temp_autodj_crates"
// A table of all tracks that are assigned to the AutoDJ via a crate
// Columns:
// INTEGER AUTODJCRATESTABLE_TRACKID -> Tracks that are member of crate assigned to AutoDj
// INTEGER AUTODJCRATESTABLE_CRATEREFS -> counts the occurrences of track in auto dj crates
// INTEGER AUTODJCRATESTABLE_TIMESPLAYED -> library played counter
// INTEGER AUTODJCRATESTABLE_AUTODJREFS -> counts the occurrences of the track in the AutoDj queue
// DATETIME AUTODJCRATESTABLE_LASTPLAYED -> from the history feature
#define AUTODJACTIVETRACKS_TABLE "temp_autodj_activetracks"
// The same table like above, but of all tracks that not already queued into Auto DJ
// ordered by TimesPlayed.
namespace {
// Percentage of most and least played tracks to ignore [0,50)
const int kLeastPreferredPercent = 15;
// These consts are only used for DEBUG_ASSERTs
#ifdef MIXXX_DEBUG_ASSERTIONS_ENABLED
const int kLeastPreferredPercentMin = 0;
const int kLeastPreferredPercentMax = 50;
#endif
int bounded_rand(int highest) {
#if (QT_VERSION >= QT_VERSION_CHECK(5, 10, 0))
return QRandomGenerator::global()->bounded(highest);
#else
return qrand() % highest;
#endif
}
} // anonymous namespace
AutoDJCratesDAO::AutoDJCratesDAO(
int iAutoDjPlaylistId,
TrackCollection* pTrackCollection,
UserSettingsPointer pConfig)
: m_iAutoDjPlaylistId(iAutoDjPlaylistId),
m_pTrackCollection(pTrackCollection),
m_database(pTrackCollection->database()),
m_pConfig(pConfig),
// The database has not been created yet.
m_bAutoDjCratesDbCreated(false),
// By default, active tracks are not tracks that haven't been played in
// a while.
m_bUseIgnoreTime(false) {
}
AutoDJCratesDAO::~AutoDJCratesDAO() {
}
// Create the temporary auto-DJ-crates table.
// Done the first time it's used, since the user might not even make
// use of this feature.
void AutoDJCratesDAO::createAndConnectAutoDjCratesDatabase() {
// If the use of tracks that haven't been played in a while has changed,
// then the active-tracks view must be recreated.
bool bUseIgnoreTime = m_pConfig->getValue(
ConfigKey("[Auto DJ]", "UseIgnoreTime"), false);
if (m_bAutoDjCratesDbCreated) {
if (m_bUseIgnoreTime != bUseIgnoreTime) {
// Do all this in a single transaction.
ScopedTransaction oTransaction(m_database);
// Get rid of the old active-tracks view.
QSqlQuery oQuery(m_database);
oQuery.exec ("DROP VIEW IF EXISTS " AUTODJACTIVETRACKS_TABLE);
if (!oQuery.exec()) {
LOG_FAILED_QUERY(oQuery);
return;
}
// Create the new active-tracks view.
if (!createActiveTracksView(bUseIgnoreTime)) {
return;
}
// Remember the new setting.
m_bUseIgnoreTime = bUseIgnoreTime;
// Commit these changes.
oTransaction.commit();
}
} else {
m_bUseIgnoreTime = bUseIgnoreTime;
}
// If this database has already been created, skip this.
if (m_bAutoDjCratesDbCreated) {
return;
}
// Do all of this in a single transaction.
ScopedTransaction