fix(suggestions): enable combined search, progressive BPM widening, and include db in docker build
This commit is contained in:
1 parent
8b917c78ad
commit
3d4372b154
6 files changed
+37
-13
No files matched your search
@@ -3,6 +3,5 @@ node_modules
|
||||
.git
|
||||
.gitignore
|
||||
.env
|
||||
db
|
||||
docs
|
||||
*.webm
|
||||
@@ -13,6 +13,7 @@ RUN cd server && npm ci --omit=dev
|
||||
COPY server/ ./server/
|
||||
COPY public/ ./public/
|
||||
COPY shared/ ./shared/
|
||||
COPY db/ ./db/
|
||||
|
||||
# Set ownership and switch to non-root user
|
||||
RUN chown -R node:node /app
|
||||
|
||||
+8
-8
@@ -151,14 +151,14 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="../shared/mixing-rules.js"></script>
|
||||
<script src="../shared/color-matrix.js"></script>
|
||||
<script src="../shared/camelot-angle.js"></script>
|
||||
<script src="../shared/camelot-to-musickey.js"></script>
|
||||
<script src="/shared/mixing-rules.js?v=2.0.1"></script>
|
||||
<script src="/shared/color-matrix.js?v=2.0.1"></script>
|
||||
<script src="/shared/camelot-angle.js?v=2.0.1"></script>
|
||||
<script src="/shared/camelot-to-musickey.js?v=2.0.1"></script>
|
||||
|
||||
<script src="wheel.js"></script>
|
||||
<script src="cover.js"></script>
|
||||
<script src="search.js"></script>
|
||||
<script src="app.js"></script>
|
||||
<script src="wheel.js?v=2.0.1"></script>
|
||||
<script src="cover.js?v=2.0.1"></script>
|
||||
<script src="search.js?v=2.0.1"></script>
|
||||
<script src="app.js?v=2.0.1"></script>
|
||||
</body>
|
||||
</html>
|
||||
+8
-1
@@ -134,6 +134,8 @@ async function selectTrack(track) {
|
||||
key = metaJson.data.key;
|
||||
bpm = metaJson.data.bpm;
|
||||
tags = metaJson.data.tags || tags;
|
||||
document.getElementById('stat-match').textContent = metaJson.data.is_corrected ? '100%' : (metaJson.data.source === 'postgresql' ? '100%' : 'Online');
|
||||
document.getElementById('stat-source-sub').textContent = metaJson.data.source === 'postgresql' ? (metaJson.data.is_corrected ? 'PostgreSQL (Fix)' : 'PostgreSQL') : 'PostgreSQL (Neu)';
|
||||
}
|
||||
} catch (e) {
|
||||
console.warn('[Search] Metadata fetch failed, using fallback', e);
|
||||
@@ -205,7 +207,12 @@ async function renderSuggestions(currentKey, currentBpm = 120, artist = '', titl
|
||||
const res = await fetch(url);
|
||||
const json = await res.json();
|
||||
|
||||
if (json.status !== 'success' || !json.data || json.data.length === 0) {
|
||||
if (json.status !== 'success') {
|
||||
sugContainer.innerHTML = `<div style="color:#D62828;font-size:12px;font-family:monospace;">Fehler beim Laden der Vorschläge: ${escapeHtml(json.error || 'Serverfehler')}</div>`;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!json.data || json.data.length === 0) {
|
||||
sugContainer.innerHTML = '<div style="color:var(--text-dim);font-size:12px;font-family:monospace;">Keine passenden Tracks in der Datenbank gefunden. Suche weitere Tracks, um deine Library zu erweitern.</div>';
|
||||
return;
|
||||
}
|
||||
|
||||
+7
-2
@@ -188,7 +188,10 @@ async function searchTracks(queryStr, limit = 10) {
|
||||
const res = await getPool().query(
|
||||
`SELECT id, title, artist, camelot_key, bpm, music_key, cover_url, is_corrected
|
||||
FROM tracks
|
||||
WHERE LOWER(title) LIKE $1 OR LOWER(artist) LIKE $1
|
||||
WHERE LOWER(title) LIKE $1
|
||||
OR LOWER(artist) LIKE $1
|
||||
OR LOWER(artist || ' ' || title) LIKE $1
|
||||
OR LOWER(title || ' ' || artist) LIKE $1
|
||||
ORDER BY is_corrected DESC, play_count DESC
|
||||
LIMIT $2`,
|
||||
[term, limit]
|
||||
@@ -202,7 +205,9 @@ async function searchTracks(queryStr, limit = 10) {
|
||||
const results = [];
|
||||
const q = queryStr.toLowerCase();
|
||||
for (const track of memoryTracks.values()) {
|
||||
if (track.title.toLowerCase().includes(q) || track.artist.toLowerCase().includes(q)) {
|
||||
const combined1 = `${track.artist} ${track.title}`.toLowerCase();
|
||||
const combined2 = `${track.title} ${track.artist}`.toLowerCase();
|
||||
if (track.title.toLowerCase().includes(q) || track.artist.toLowerCase().includes(q) || combined1.includes(q) || combined2.includes(q)) {
|
||||
results.push(track);
|
||||
if (results.length >= limit) break;
|
||||
}
|
||||
|
||||
@@ -26,13 +26,25 @@ router.get('/', async (req, res) => {
|
||||
// 1. Fetch tracks from PostgreSQL within ±6%
|
||||
let tracks = await db.getSuggestions(compatibleKeys, minBpm, maxBpm, 10, artist, title);
|
||||
|
||||
// 2. If fewer than 8 tracks, widen BPM range to ±12% to guarantee plenty of suggestions
|
||||
// 2. If fewer than 8 tracks, widen BPM range to ±12%
|
||||
if (tracks.length < 8) {
|
||||
minBpm = Math.round(currentBpm * 0.88);
|
||||
maxBpm = Math.round(currentBpm * 1.12);
|
||||
tracks = await db.getSuggestions(compatibleKeys, minBpm, maxBpm, 10, artist, title);
|
||||
}
|
||||
|
||||
// 3. If fewer than 5 tracks, widen BPM range to ±20% for smaller libraries
|
||||
if (tracks.length < 5) {
|
||||
minBpm = Math.round(currentBpm * 0.80);
|
||||
maxBpm = Math.round(currentBpm * 1.20);
|
||||
tracks = await db.getSuggestions(compatibleKeys, minBpm, maxBpm, 10, artist, title);
|
||||
}
|
||||
|
||||
// 4. If still empty, fetch any compatible key track (50-220 BPM)
|
||||
if (tracks.length === 0) {
|
||||
tracks = await db.getSuggestions(compatibleKeys, 50, 220, 10, artist, title);
|
||||
}
|
||||
|
||||
// 3. Map tracks with compatibility info and colors
|
||||
const enriched = tracks.map(t => {
|
||||
const ruleIdx = compatibleKeys.indexOf(t.camelot_key);
|
||||
|
||||
Reference in new issue
Block a user