Started to restore clusters based recommendation engine

This commit is contained in:
emeric
2020-02-15 15:52:39 +01:00
parent 7f05a1d4e6
commit d1bdaf6203
26 changed files with 326 additions and 177 deletions
+15
View File
@@ -104,6 +104,21 @@ Artist::getAllOrphans(Session& session)
return std::vector<pointer>(res.begin(), res.end());
}
std::vector<IdType>
Artist::getAllIdsWithClusters(Session& session, std::optional<std::size_t> limit)
{
session.checkSharedLocked();
Wt::Dbo::collection<IdType> res = session.getDboSession().query<IdType>
("SELECT DISTINCT a.id FROM artist a"
" INNER JOIN track t ON t.id = t_a_l.track_id INNER JOIN track_artist_link t_a_l ON t_a_l.artist_id = a.id"
" INNER JOIN track_cluster t_c ON t_c.track_id = t.id")
.limit(limit ? static_cast<int>(*limit) : -1);
return std::vector<IdType>(res.begin(), res.end());
}
static
Wt::Dbo::Query<Artist::pointer>
getQuery(Session& session,
+15
View File
@@ -252,6 +252,21 @@ Release::getByFilter(Session& session,
return res;
}
std::vector<IdType>
Release::getAllIdsWithClusters(Session& session, std::optional<std::size_t> limit)
{
session.checkSharedLocked();
Wt::Dbo::collection<IdType> res = session.getDboSession().query<IdType>
("SELECT DISTINCT r.id FROM release r"
" INNER JOIN track t ON t.release_id = r.id"
" INNER JOIN track_cluster t_c ON t_c.track_id = t.id")
.limit(limit ? static_cast<int>(*limit) : -1);
return std::vector<IdType>(res.begin(), res.end());
}
std::optional<std::size_t>
Release::getTotalTrackNumber(void) const
{
+1 -1
View File
@@ -118,7 +118,7 @@ Session::doDatabaseMigrationIfNeeded()
{
_session.execute("DROP TABLE similarity_settings");
_session.execute("DROP TABLE similarity_settings_feature");
_session.execute("ALTER TABLE scan_settings ADD similarity_engine_type INTEGER NOT NULL DEFAULT(" + std::to_string(static_cast<int>(ScanSettings::SimilarityEngineType::Clusters)) + ")");
_session.execute("ALTER TABLE scan_settings ADD similarity_engine_type INTEGER NOT NULL DEFAULT(" + std::to_string(static_cast<int>(ScanSettings::RecommendationEngineType::Clusters)) + ")");
}
else if (version == 8)
{
+14 -1
View File
@@ -163,6 +163,19 @@ Track::getAllIdsWithFeatures(Session& session, std::optional<std::size_t> limit)
return std::vector<IdType>(res.begin(), res.end());
}
std::vector<IdType>
Track::getAllIdsWithClusters(Session& session, std::optional<std::size_t> limit)
{
session.checkSharedLocked();
Wt::Dbo::collection<IdType> res = session.getDboSession().query<IdType>
("SELECT DISTINCT t.id FROM track t"
" INNER JOIN track_cluster t_c ON t_c.track_id = t.id")
.limit(limit ? static_cast<int>(*limit) : -1);
return std::vector<IdType>(res.begin(), res.end());
}
std::vector<Cluster::pointer>
Track::getClusters(void) const
{
@@ -263,7 +276,7 @@ Track::getByFilter(Session& session,
std::vector<Track::pointer>
Track::getSimilarTracks(Session& session,
const std::set<IdType>& tracks,
const std::unordered_set<IdType>& tracks,
std::optional<std::size_t> offset,
std::optional<std::size_t> size)
{
@@ -68,6 +68,7 @@ class Artist : public Wt::Dbo::Dbo<Artist>
static std::vector<IdType> getAllIds(Session& session);
static std::vector<pointer> getAllOrphans(Session& session); // No track related
static std::vector<pointer> getLastAdded(Session& session, Wt::WDateTime after, std::optional<std::size_t> size = {});
static std::vector<IdType> getAllIdsWithClusters(Session& session, std::optional<std::size_t> limit = {});
// Accessors
const std::string& getName(void) const { return _name; }
@@ -66,6 +66,7 @@ class Release : public Wt::Dbo::Dbo<Release>
std::optional<std::size_t> offset,
std::optional<std::size_t> size,
bool& moreExpected);
static std::vector<IdType> getAllIdsWithClusters(Session& session, std::optional<std::size_t> limit = {});
std::vector<Wt::Dbo::ptr<Track>> getTracks(const std::set<IdType>& clusters = std::set<IdType>()) const;
std::size_t getTracksCount() const;
@@ -43,7 +43,7 @@ class ScanSettings : public Wt::Dbo::Dbo<ScanSettings>
};
// Do not modify values (just add)
enum class SimilarityEngineType
enum class RecommendationEngineType
{
Clusters = 0,
Features,
@@ -60,7 +60,7 @@ class ScanSettings : public Wt::Dbo::Dbo<ScanSettings>
UpdatePeriod getUpdatePeriod() const { return _updatePeriod; }
std::vector<Wt::Dbo::ptr<ClusterType>> getClusterTypes() const;
std::set<std::filesystem::path> getAudioFileExtensions() const;
SimilarityEngineType getSimilarityEngineType() const { return _similarityEngineType; }
RecommendationEngineType getRecommendationEngineType() const { return _recommendationEngineType; }
// Setters
void addAudioFileExtension(const std::filesystem::path& ext);
@@ -68,7 +68,7 @@ class ScanSettings : public Wt::Dbo::Dbo<ScanSettings>
void setUpdateStartTime(Wt::WTime t) { _startTime = t; }
void setUpdatePeriod(UpdatePeriod p) { _updatePeriod = p; }
void setClusterTypes(Session& session, const std::set<std::string>& clusterTypeNames);
void setSimilarityEngineType(SimilarityEngineType type) { _similarityEngineType = type; }
void setRecommendationEngineType(RecommendationEngineType type) { _recommendationEngineType = type; }
void incScanVersion();
template<class Action>
@@ -79,7 +79,7 @@ class ScanSettings : public Wt::Dbo::Dbo<ScanSettings>
Wt::Dbo::field(a, _startTime, "start_time");
Wt::Dbo::field(a, _updatePeriod, "update_period");
Wt::Dbo::field(a, _audioFileExtensions, "audio_file_extensions");
Wt::Dbo::field(a, _similarityEngineType,"similarity_engine_type");
Wt::Dbo::field(a, _recommendationEngineType,"similarity_engine_type");
Wt::Dbo::hasMany(a, _clusterTypes, Wt::Dbo::ManyToOne, "scan_settings");
}
@@ -89,7 +89,7 @@ class ScanSettings : public Wt::Dbo::Dbo<ScanSettings>
std::string _mediaDirectory;
Wt::WTime _startTime = Wt::WTime {0,0,0};
UpdatePeriod _updatePeriod {UpdatePeriod::Never};
SimilarityEngineType _similarityEngineType {SimilarityEngineType::Clusters};
RecommendationEngineType _recommendationEngineType {RecommendationEngineType::Clusters};
std::string _audioFileExtensions {".alac .mp3 .ogg .oga .aac .m4a .m4b .flac .wav .wma .aif .aiff .ape .mpc .shn .opus"};
Wt::Dbo::collection<Wt::Dbo::ptr<ClusterType>> _clusterTypes;
};
+4 -2
View File
@@ -22,8 +22,9 @@
#include <chrono>
#include <filesystem>
#include <optional>
#include <vector>
#include <string>
#include <unordered_set>
#include <vector>
#include <Wt/Dbo/Dbo.h>
#include <Wt/WDateTime.h>
@@ -58,7 +59,7 @@ class Track : public Wt::Dbo::Dbo<Track>
static pointer getById(Session& session, IdType id);
static pointer getByMBID(Session& session, const UUID& MBID);
static std::vector<pointer> getSimilarTracks(Session& session,
const std::set<IdType>& trackIds,
const std::unordered_set<IdType>& trackIds,
std::optional<std::size_t> offset = {},
std::optional<std::size_t> size = {});
static std::vector<pointer> getByClusters(Session& session,
@@ -78,6 +79,7 @@ class Track : public Wt::Dbo::Dbo<Track>
static std::vector<pointer> getLastAdded(Session& session, const Wt::WDateTime& after, std::optional<std::size_t> size = 1);
static std::vector<pointer> getAllWithMBIDAndMissingFeatures(Session& session);
static std::vector<IdType> getAllIdsWithFeatures(Session& session, std::optional<std::size_t> limit = {});
static std::vector<IdType> getAllIdsWithClusters(Session& session, std::optional<std::size_t> limit = {});
// Create utility
static pointer create(Session& session, const std::filesystem::path& p);
+1
View File
@@ -1,5 +1,6 @@
add_library(lmsrecommendation SHARED
impl/clusters/ClustersClassifier.cpp
impl/Engine.cpp
impl/ClassifierCreator.cpp
)
@@ -17,22 +17,17 @@
* along with LMS. If not, see <http://www.gnu.org/licenses/>.
*/
#include "recommendation/ClustersClassifierCreator.hpp"
#include "recommendation/FeaturesClassifierCreator.hpp"
#include "recommendation/Classifier.hpp"
#include "recommendation/IClassifier.hpp"
namespace Recommendation
{
std::unique_ptr<Classifier> createClustersClassifier()
std::unique_ptr<IClassifier> createFeaturesClassifier()
{
return {};
}
std::unique_ptr<Classifier> createFeaturesClassifier()
{
return {};
}
}
+58 -47
View File
@@ -19,30 +19,49 @@
#include "Engine.hpp"
//#include "features/SimilarityFeaturesScannerAddon.hpp"
//#include "cluster/SimilarityClusterSearcher.hpp"
#include "recommendation/ClustersClassifierCreator.hpp"
#include "recommendation/FeaturesClassifierCreator.hpp"
#include "database/ScanSettings.hpp"
#include "database/Session.hpp"
#include "database/TrackList.hpp"
namespace Recommendation {
std::unique_ptr<IEngine>
createEngine()
createEngine(Database::Session& session)
{
return std::make_unique<Engine>();
return std::make_unique<Engine>(session);
}
Engine::Engine(Database::Session& session)
{
reloadSettings(session);
}
void
Engine::clearClassifiers()
Engine::reloadSettings(Database::Session& session)
{
_classifiers.clear();
}
using namespace Database;
void
Engine::addClassifier(std::unique_ptr<Classifier> classifier, unsigned priority)
{
_classifiers.emplace(priority, std::move(classifier));
const ScanSettings::RecommendationEngineType engineType {[&]()
{
auto transaction {session.createSharedTransaction()};
return ScanSettings::get(session)->getRecommendationEngineType();
}()};
clearClassifiers();
switch (engineType)
{
case ScanSettings::RecommendationEngineType::Features:
// _classifiers.emplace(0, createFeaturesClassifier()); // higher priority
// [[fallthrough]];
case ScanSettings::RecommendationEngineType::Clusters:
_classifiers.emplace(1, createClustersClassifier(session)); // lower priority
break;
}
}
std::vector<Database::IdType>
@@ -79,60 +98,52 @@ Engine::getSimilarTracksFromTrackList(Database::Session& /*session*/, Database::
}
std::vector<Database::IdType>
Engine::getSimilarTracks(Database::Session& /*dbSession*/, const std::unordered_set<Database::IdType>& /*trackIds*/, std::size_t /*maxCount*/)
Engine::getSimilarTracks(Database::Session& dbSession, const std::unordered_set<Database::IdType>& trackIds, std::size_t maxCount)
{
#if 0
auto engineType {getEngineType(dbSession)};
auto somSearcher {_somAddon.getSearcher()};
if (engineType == Database::ScanSettings::SimilarityEngineType::Features
&& somSearcher
&& std::any_of(std::cbegin(trackIds), std::cend(trackIds), [&](Database::IdType trackId) { return somSearcher->isTrackClassified(trackId); } ))
for (const auto& [priority, classifier] : _classifiers)
{
return somSearcher->getSimilarTracks(trackIds, maxCount);
if (std::any_of(std::cbegin(trackIds), std::cend(trackIds), [&](Database::IdType trackId) { return classifier->isTrackClassified(trackId); } ))
return classifier->getSimilarTracks(dbSession, trackIds, maxCount);
}
else
return ClusterEngine::getSimilarTracks(dbSession, trackIds, maxCount);
#endif
return {};
}
std::vector<Database::IdType>
Engine::getSimilarReleases(Database::Session& /*dbSession*/, Database::IdType /*releaseId*/, std::size_t /*maxCount*/)
Engine::getSimilarReleases(Database::Session& dbSession, Database::IdType releaseId, std::size_t maxCount)
{
#if 0
auto engineType {getEngineType(dbSession)};
auto somSearcher {_somAddon.getSearcher()};
if (engineType == Database::ScanSettings::SimilarityEngineType::Features
&& somSearcher
&& somSearcher->isReleaseClassified(releaseId))
for (const auto& [priority, classifier] : _classifiers)
{
return somSearcher->getSimilarReleases(releaseId, maxCount);
if (classifier->isReleaseClassified(releaseId))
return classifier->getSimilarReleases(dbSession, releaseId, maxCount);
}
else
return ClusterEngine::getSimilarReleases(dbSession, releaseId, maxCount);
#endif
return {};
}
std::vector<Database::IdType>
Engine::getSimilarArtists(Database::Session& /*dbSession*/, Database::IdType /*artistId*/, std::size_t /*maxCount*/)
Engine::getSimilarArtists(Database::Session& dbSession, Database::IdType artistId, std::size_t maxCount)
{
#if 0
auto engineType {getEngineType(dbSession)};
auto somSearcher {_somAddon.getSearcher()};
if (engineType == Database::ScanSettings::SimilarityEngineType::Features
&& somSearcher
&& somSearcher->isArtistClassified(artistId))
for (const auto& [priority, classifier] : _classifiers)
{
return somSearcher->getSimilarArtists(artistId, maxCount);
if (classifier->isArtistClassified(artistId))
return classifier->getSimilarArtists(dbSession, artistId, maxCount);
}
else
return ClusterEngine::getSimilarArtists(dbSession, artistId, maxCount);
#endif
return {};
}
void
Engine::clearClassifiers()
{
_classifiers.clear();
}
void
Engine::addClassifier(std::unique_ptr<IClassifier> classifier, unsigned priority)
{
_classifiers.emplace(priority, std::move(classifier));
}
} // ns Similarity
+9 -4
View File
@@ -22,7 +22,7 @@
#include <map>
#include "recommendation/IEngine.hpp"
#include "recommendation/Classifier.hpp"
#include "recommendation/IClassifier.hpp"
namespace Database
{
@@ -34,17 +34,22 @@ namespace Recommendation
class Engine : public IEngine
{
public:
Engine(Database::Session& session);
private:
void reloadSettings(Database::Session& session) override;
// Closest results first
std::vector<Database::IdType> getSimilarTracksFromTrackList(Database::Session& session, Database::IdType tracklistId, std::size_t maxCount) override;
std::vector<Database::IdType> getSimilarTracks(Database::Session& session, const std::unordered_set<Database::IdType>& tracksId, std::size_t maxCount) override;
std::vector<Database::IdType> getSimilarReleases(Database::Session& session, Database::IdType releaseId, std::size_t maxCount) override;
std::vector<Database::IdType> getSimilarArtists(Database::Session& session, Database::IdType artistId, std::size_t maxCount) override;
private:
void clearClassifiers();
void addClassifier(std::unique_ptr<Classifier> classifier, unsigned priority);
void addClassifier(std::unique_ptr<IClassifier> classifier, unsigned priority);
std::map<unsigned, std::unique_ptr<Classifier>> _classifiers;
std::map<unsigned, std::unique_ptr<IClassifier>> _classifiers;
};
} // ns Recommendation
@@ -1,40 +0,0 @@
/*
* Copyright (C) 2018 Emeric Poupon
*
* This file is part of LMS.
*
* LMS 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 3 of the License, or
* (at your option) any later version.
*
* LMS 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 LMS. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <set>
#include "database/Types.hpp"
namespace Database {
class Session;
}
namespace Similarity {
namespace ClusterSearcher
{
std::vector<Database::IdType> getSimilarTracksFromTrackList(Database::Session& session, Database::IdType tracklistId, std::size_t maxCount);
std::vector<Database::IdType> getSimilarTracks(Database::Session& session, const std::set<Database::IdType>& tracksId, std::size_t maxCount);
std::vector<Database::IdType> getSimilarReleases(Database::Session& session, Database::IdType releaseId, std::size_t maxCount);
std::vector<Database::IdType> getSimilarArtists(Database::Session& session, Database::IdType artistId, std::size_t maxCount);
};
} // namespace Similarity
@@ -17,7 +17,7 @@
* along with LMS. If not, see <http://www.gnu.org/licenses/>.
*/
#include "SimilarityClusterSearcher.hpp"
#include "ClustersClassifier.hpp"
#include "database/Artist.hpp"
#include "database/Cluster.hpp"
@@ -26,11 +26,60 @@
#include "database/Track.hpp"
#include "database/TrackList.hpp"
namespace Similarity {
namespace ClusterSearcher {
namespace Recommendation {
std::unique_ptr<IClassifier> createClustersClassifier(Database::Session& session)
{
return std::make_unique<ClusterClassifier>(session);
}
ClusterClassifier::ClusterClassifier(Database::Session& session)
{
classify(session);
}
void
ClusterClassifier::classify(Database::Session& session)
{
auto transaction {session.createSharedTransaction()};
{
std::vector<Database::IdType> trackIds {Database::Track::getAllIdsWithClusters(session)};
_classifiedTracks = std::unordered_set<Database::IdType>(std::cbegin(trackIds), std::cend(trackIds));
}
{
std::vector<Database::IdType> releaseIds {Database::Release::getAllIdsWithClusters(session)};
_classifiedReleases = std::unordered_set<Database::IdType>(std::cbegin(releaseIds), std::cend(releaseIds));
}
{
std::vector<Database::IdType> artistIds {Database::Artist::getAllIdsWithClusters(session)};
_classifiedArtists = std::unordered_set<Database::IdType>(std::cbegin(artistIds), std::cend(artistIds));
}
}
bool
ClusterClassifier::isTrackClassified(Database::IdType trackId) const
{
return _classifiedTracks.find(trackId) != std::cend(_classifiedTracks);
}
bool
ClusterClassifier::isReleaseClassified(Database::IdType releaseId) const
{
return _classifiedReleases.find(releaseId) != std::cend(_classifiedReleases);
}
bool
ClusterClassifier::isArtistClassified(Database::IdType artistId) const
{
return _classifiedArtists.find(artistId) != std::cend(_classifiedArtists);
}
std::vector<Database::IdType>
getSimilarTracks(Database::Session& dbSession, const std::set<Database::IdType>& trackIds, std::size_t maxCount)
ClusterClassifier::getSimilarTracks(Database::Session& dbSession, const std::unordered_set<Database::IdType>& trackIds, std::size_t maxCount) const
{
auto transaction {dbSession.createSharedTransaction()};
@@ -43,7 +92,7 @@ getSimilarTracks(Database::Session& dbSession, const std::set<Database::IdType>&
}
std::vector<Database::IdType>
getSimilarTracksFromTrackList(Database::Session& session, Database::IdType tracklistId, std::size_t maxCount)
ClusterClassifier::getSimilarTracksFromTrackList(Database::Session& session, Database::IdType tracklistId, std::size_t maxCount) const
{
std::vector<Database::IdType> res;
@@ -62,7 +111,7 @@ getSimilarTracksFromTrackList(Database::Session& session, Database::IdType track
}
std::vector<Database::IdType>
getSimilarReleases(Database::Session& dbSession, Database::IdType releaseId, std::size_t maxCount)
ClusterClassifier::getSimilarReleases(Database::Session& dbSession, Database::IdType releaseId, std::size_t maxCount) const
{
std::vector<Database::IdType> res;
@@ -80,7 +129,7 @@ getSimilarReleases(Database::Session& dbSession, Database::IdType releaseId, std
}
std::vector<Database::IdType>
getSimilarArtists(Database::Session& dbSession, Database::IdType artistId, std::size_t maxCount)
ClusterClassifier::getSimilarArtists(Database::Session& dbSession, Database::IdType artistId, std::size_t maxCount) const
{
std::vector<Database::IdType> res;
@@ -97,5 +146,4 @@ getSimilarArtists(Database::Session& dbSession, Database::IdType artistId, std::
return res;
}
} // namespace ClusterSearcher
} // namespace Similarity
} // namespace Recommendation
@@ -0,0 +1,56 @@
/*
* Copyright (C) 2018 Emeric Poupon
*
* This file is part of LMS.
*
* LMS 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 3 of the License, or
* (at your option) any later version.
*
* LMS 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 LMS. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include "recommendation/IClassifier.hpp"
namespace Recommendation
{
class ClusterClassifier : public IClassifier
{
public:
ClusterClassifier(Database::Session& session);
ClusterClassifier(const ClusterClassifier&) = delete;
ClusterClassifier(ClusterClassifier&&) = delete;
ClusterClassifier& operator=(const ClusterClassifier&) = delete;
ClusterClassifier& operator=(ClusterClassifier&&) = delete;
private:
bool isTrackClassified(Database::IdType trackId) const override;
bool isReleaseClassified(Database::IdType releaseId) const override;
bool isArtistClassified(Database::IdType artistId) const override;
std::vector<Database::IdType> getSimilarTracksFromTrackList(Database::Session& session, Database::IdType tracklistId, std::size_t maxCount) const override;
std::vector<Database::IdType> getSimilarTracks(Database::Session& session, const std::unordered_set<Database::IdType>& tracksId, std::size_t maxCount) const override;
std::vector<Database::IdType> getSimilarReleases(Database::Session& session, Database::IdType releaseId, std::size_t maxCount) const override;
std::vector<Database::IdType> getSimilarArtists(Database::Session& session, Database::IdType artistId, std::size_t maxCount) const override;
void classify(Database::Session& session);
std::unordered_set<Database::IdType> _classifiedArtists;
std::unordered_set<Database::IdType> _classifiedReleases;
std::unordered_set<Database::IdType> _classifiedTracks;
};
} // namespace Recommendation
@@ -21,15 +21,10 @@
#include <memory>
namespace Database
{
class Session;
}
namespace Recommendation
{
class Classifier;
class IClassifier;
std::unique_ptr<Classifier> createClustersClassifier();
std::unique_ptr<IClassifier> createClustersClassifier(Database::Session& session);
}
@@ -21,15 +21,10 @@
#include <memory>
namespace Database
{
class Session;
}
namespace Recommendation
{
class Classifier;
class IClassifier;
std::unique_ptr<Classifier> createFeaturesClassifier();
std::unique_ptr<IClassifier> createFeaturesClassifier();
}
@@ -32,21 +32,19 @@ namespace Database
namespace Recommendation
{
class Classifier
class IClassifier
{
public:
virtual ~Classifier() = default;
virtual void classify() = 0;
virtual ~IClassifier() = default;
virtual bool isTrackClassified(Database::IdType trackId) const = 0;
virtual bool isReleaseClassified(Database::IdType releaseId) const = 0;
virtual bool isArtistClassified(Database::IdType artistId) const = 0;
virtual std::vector<Database::IdType> getSimilarTracksFromTrackList(Database::Session& session, Database::IdType tracklistId, std::size_t maxCount) = 0;
virtual std::vector<Database::IdType> getSimilarTracksFromTrackList(Database::Session& session, Database::IdType tracklistId, std::size_t maxCount) const = 0;
virtual std::vector<Database::IdType> getSimilarTracks(Database::Session& session, const std::unordered_set<Database::IdType>& tracksId, std::size_t maxCount) const = 0;
virtual std::vector<Database::IdType> getSimilarReleases(Database::IdType releaseId, std::size_t maxCount) const = 0;
virtual std::vector<Database::IdType> getSimilarArtists(Database::IdType artistId, std::size_t maxCount) const = 0;
virtual std::vector<Database::IdType> getSimilarReleases(Database::Session& session, Database::IdType releaseId, std::size_t maxCount) const = 0;
virtual std::vector<Database::IdType> getSimilarArtists(Database::Session& session, Database::IdType artistId, std::size_t maxCount) const = 0;
};
} // ns Recommendation
@@ -23,7 +23,6 @@
#include <unordered_set>
#include "database/Types.hpp"
#include "Classifier.hpp"
namespace Database
{
@@ -32,12 +31,13 @@ namespace Database
namespace Recommendation
{
class Classifier;
class IEngine
{
public:
virtual ~IEngine() = default;
virtual void reloadSettings(Database::Session& session) = 0;
// Closest results first
virtual std::vector<Database::IdType> getSimilarTracksFromTrackList(Database::Session& session, Database::IdType tracklistId, std::size_t maxCount) = 0;
virtual std::vector<Database::IdType> getSimilarTracks(Database::Session& session, const std::unordered_set<Database::IdType>& tracksId, std::size_t maxCount) = 0;
@@ -45,7 +45,7 @@ namespace Recommendation
virtual std::vector<Database::IdType> getSimilarArtists(Database::Session& session, Database::IdType artistId, std::size_t maxCount) = 0;
};
std::unique_ptr<IEngine> createEngine();
std::unique_ptr<IEngine> createEngine(Database::Session& session);
} // ns Recommendation