fix messed up bisection search

This commit is contained in:
geoffrey45
2022-05-07 14:45:16 +03:00
parent d6a01cd35e
commit fb67f568ad
8 changed files with 137 additions and 59 deletions
+44 -23
View File
@@ -1,20 +1,20 @@
"""
This library contains all the functions related to albums.
"""
from copy import deepcopy
import random
import urllib
from pprint import pprint
from typing import List
from app import api
from app import functions
from app import instances
from app import models
from app import settings
from app.lib import taglib
from app.lib import trackslib
from progress.bar import Bar
from app import helpers
def get_all_albums() -> List[models.Album]:
"""
@@ -23,6 +23,7 @@ def get_all_albums() -> List[models.Album]:
print("Getting all albums...")
albums: List[models.Album] = []
db_albums = instances.album_instance.get_all_albums()
_bar = Bar("Creating albums", max=len(db_albums))
@@ -44,7 +45,7 @@ def create_everything() -> List[models.Track]:
albums: list[models.Album] = get_all_albums()
api.ALBUMS = albums
api.ALBUMS.sort(key=lambda x: x.title)
api.ALBUMS.sort(key=lambda x: x.hash)
tracks = trackslib.create_all_tracks()
@@ -57,6 +58,7 @@ def find_album(albumtitle: str, artist: str) -> int or None:
"""
Finds an album by album title and artist.
"""
left = 0
right = len(api.ALBUMS) - 1
iter = 0
@@ -64,12 +66,15 @@ def find_album(albumtitle: str, artist: str) -> int or None:
while left <= right:
iter += 1
mid = (left + right) // 2
hash = helpers.create_album_hash(albumtitle, artist)
if api.ALBUMS[mid].title == albumtitle and api.ALBUMS[
mid].artist == artist:
return mid
try:
if api.ALBUMS[mid].hash == hash:
return mid
except:
print(api.ALBUMS[mid])
if api.ALBUMS[mid].title < albumtitle:
if api.ALBUMS[mid].hash < hash:
left = mid + 1
else:
right = mid - 1
@@ -125,18 +130,33 @@ def get_album_image(album: list) -> str:
return use_defaults()
class GetAlbumTracks:
"""
Finds all the tracks that match a specific album, given the album title
and album artist.
"""
def __init__(self, album: str, artist: str) -> None:
self.hash = helpers.create_album_hash(album, artist)
self.tracks = api.DB_TRACKS
self.tracks.sort(key=lambda x: x["albumhash"])
def find_tracks(self):
tracks = []
index = trackslib.find_track(self.tracks, self.hash)
while index is not None:
track = self.tracks[index]
tracks.append(track)
self.tracks.remove(track)
index = trackslib.find_track(self.tracks, self.hash)
api.DB_TRACKS.extend(tracks)
return tracks
def get_album_tracks(album: str, artist: str) -> List:
tracks = []
for track in api.DB_TRACKS:
try:
if track["album"] == album and track["albumartist"] == artist:
tracks.append(track)
except TypeError:
pprint(track, indent=4)
print(album, artist)
return tracks
return GetAlbumTracks(album, artist).find_tracks()
def create_album(track) -> models.Album:
@@ -144,20 +164,21 @@ def create_album(track) -> models.Album:
Generates and returns an album object from a track object.
"""
album = {
"album": track["album"],
"title": track["album"],
"artist": track["albumartist"],
}
album_tracks = get_album_tracks(album["album"], album["artist"])
album_tracks = get_album_tracks(album["title"], album["artist"])
album["date"] = album_tracks[0]["date"]
album["artistimage"] = urllib.parse.quote_plus(
album_tracks[0]["albumartist"] + ".webp")
album_tracks[0]["albumartist"] + ".webp"
)
album["image"] = get_album_image(album_tracks)
return models.Album(album)
return album
def search_albums_by_name(query: str) -> List[models.Album]:
+21 -10
View File
@@ -3,7 +3,7 @@ from os import path
from app import api
from app import settings
from app.helpers import run_fast_scandir
from app.helpers import create_album_hash, run_fast_scandir
from app.instances import album_instance
from app.instances import tracks_instance
from app.lib import folderslib
@@ -11,7 +11,7 @@ from app.lib.albumslib import create_album
from app.lib.albumslib import find_album
from app.lib.taglib import get_tags
from app.logger import Log
from app.models import Track
from app.models import Album, Track
from progress.bar import Bar
@@ -44,6 +44,7 @@ class Populate:
self.tag_files()
self.create_pre_albums()
self.create_albums()
api.ALBUMS.sort(key=lambda x: x.hash)
self.create_tracks()
self.create_folders()
@@ -73,6 +74,9 @@ class Populate:
self.folders.add(folder)
if tags is not None:
tags["albumhash"] = create_album_hash(
tags["album"], tags["albumartist"]
)
self.tagged_tracks.append(tags)
api.DB_TRACKS.append(tags)
@@ -108,16 +112,17 @@ class Populate:
if index is None:
try:
track = [
track for track in self.tagged_tracks
track
for track in self.tagged_tracks
if track["album"] == album["title"]
and track["albumartist"] == album["artist"]
][0]
album = create_album(track)
api.ALBUMS.append(album)
api.ALBUMS.append(Album(album))
self.albums.append(album)
album_instance.insert_album(asdict(album))
album_instance.insert_album(album)
except IndexError:
print("😠\n")
@@ -128,8 +133,9 @@ class Populate:
bar.next()
bar.finish()
Log(f"{exist_count} of {len(self.pre_albums)} albums were already in the database"
)
Log(
f"{exist_count} of {len(self.pre_albums)} albums were already in the database"
)
def create_tracks(self):
"""
@@ -137,13 +143,16 @@ class Populate:
"""
bar = Bar("Creating tracks", max=len(self.tagged_tracks))
failed_count = 0
for track in self.tagged_tracks:
try:
album_index = find_album(track["album"], track["albumartist"])
album = api.ALBUMS[album_index]
track["image"] = album.image
upsert_id = tracks_instance.insert_song(track)
track["_id"] = {"$oid": str(upsert_id)}
api.TRACKS.append(Track(track))
except:
# Bug: some albums are not found although they exist in `api.ALBUMS`. It has something to do with the bisection method used or sorting. Not sure yet.
@@ -151,19 +160,21 @@ class Populate:
bar.next()
bar.finish()
Log(f"Added {len(self.tagged_tracks) - failed_count} of {len(self.tagged_tracks)} new tracks and {len(self.albums)} new albums"
)
Log(
f"Added {len(self.tagged_tracks) - failed_count} of {len(self.tagged_tracks)} new tracks and {len(self.albums)} new albums"
)
def create_folders(self):
"""
Creates the folder objects for all the tracks.
"""
bar = Bar("Creating folders", max=len(self.folders))
old_f_count = len(api.FOLDERS)
for folder in self.folders:
api.VALID_FOLDERS.add(folder)
fff = folderslib.create_folder(folder)
api.FOLDERS.append(fff)
bar.next()
bar.finish()
+25
View File
@@ -26,6 +26,7 @@ def create_all_tracks() -> List[models.Track]:
except FileNotFoundError:
instances.tracks_instance.remove_song_by_id(track["_id"]["$oid"])
api.DB_TRACKS.remove(track)
try:
tracks.append(models.Track(track))
except KeyError:
@@ -54,3 +55,27 @@ def get_track_by_id(trackid: str) -> models.Track:
for track in api.TRACKS:
if track.trackid == trackid:
return track
def find_track(tracks: list, hash: str) -> int or None:
"""
Finds an album by album title and artist.
"""
left = 0
right = len(tracks) - 1
iter = 0
while left <= right:
iter += 1
mid = (left + right) // 2
if tracks[mid]["albumhash"] == hash:
return mid
if tracks[mid]["albumhash"] < hash:
left = mid + 1
else:
right = mid - 1
return None
+19 -8
View File
@@ -8,11 +8,13 @@ from app import api
from app import instances
from app import models
from app.lib import folderslib
from app.lib.albumslib import create_album
from app.lib.albumslib import create_album, find_album
from app.lib.taglib import get_tags
from watchdog.events import PatternMatchingEventHandler
from watchdog.observers import Observer
from app.helpers import create_album_hash
class OnMyWatch:
"""
@@ -48,14 +50,24 @@ def add_track(filepath: str) -> None:
tags = get_tags(filepath)
if tags is not None:
instances.tracks_instance.insert_song(tags)
tags = instances.tracks_instance.get_song_by_path(tags["filepath"])
tags["albumhash"] = create_album_hash(tags["album"], tags["albumartist"])
api.DB_TRACKS.append(tags)
album = create_album(tags)
api.ALBUMS.append(album)
albumindex = find_album(tags["album"], tags["albumartist"])
if albumindex is not None:
album = api.ALBUMS[albumindex]
else:
album_data = create_album(tags)
instances.album_instance.insert_album(album_data)
album = models.Album(album_data)
api.ALBUMS.append(album)
tags["image"] = album.image
upsert_id = instances.tracks_instance.insert_song(tags)
tags["_id"] = {"$oid": str(upsert_id)}
api.TRACKS.append(models.Track(tags))
folder = tags["folder"]
@@ -74,8 +86,7 @@ def remove_track(filepath: str) -> None:
fpath = filepath.replace(fname, "")
try:
trackid = instances.tracks_instance.get_song_by_path(
filepath)["_id"]["$oid"]
trackid = instances.tracks_instance.get_song_by_path(filepath)["_id"]["$oid"]
except TypeError:
print(f"💙 Watchdog Error: Error removing track {filepath} TypeError")
return