From 624a2c3939fbd37a98a0908bf7ffc33f8c147d19 Mon Sep 17 00:00:00 2001 From: David Trattnig <david.trattnig@o94.at> Date: Thu, 29 Oct 2020 20:24:54 +0100 Subject: [PATCH] Improved model. #50 --- src/scheduling/fallback.py | 17 +++--- src/scheduling/models.py | 122 ++++++++++++++++++------------------- 2 files changed, 68 insertions(+), 71 deletions(-) diff --git a/src/scheduling/fallback.py b/src/scheduling/fallback.py index 8e007177..3ad56091 100644 --- a/src/scheduling/fallback.py +++ b/src/scheduling/fallback.py @@ -117,7 +117,7 @@ class FallbackManager: fallback_type = None if self.validate_playlist(timeslot, "playlist"): - planned_playlist = timeslot.get_playlist() + planned_playlist = timeslot.playlist fallback_type = FallbackType.NONE else: (fallback_type, planned_playlist) = self.get_fallback_playlist(timeslot) @@ -134,16 +134,16 @@ class FallbackManager: timeslot (Timeslot) Returns: - (Playlist) + (Playlist) """ playlist = None fallback_type = FallbackType.STATION if self.validate_playlist(timeslot, "schedule_fallback"): - playlist = timeslot.schedule_fallback[0] + playlist = timeslot.schedule_fallback fallback_type = FallbackType.SCHEDULE elif self.validate_playlist(timeslot, "show_fallback"): - playlist = timeslot.show_fallback[0] + playlist = timeslot.show_fallback fallback_type = FallbackType.SHOW return (fallback_type, playlist) @@ -168,18 +168,17 @@ class FallbackManager: """ playlist = getattr(timeslot, playlist_type) if playlist \ - and isinstance(playlist, list) \ - and playlist[0].entries \ - and len(playlist[0].entries) > 0: + and playlist.entries \ + and len(playlist.entries) > 0: # Default playlist if playlist_type == "playlist": return True # Fallback playlist - elif playlist[0].entries: + elif playlist.entries: is_fs_only = True - for entry in playlist[0].entries: + for entry in playlist.entries: if entry.get_content_type() not in ResourceClass.FILE.types: self.logger.error(SU.red("Fallback playlist of type '%s' contains not only file-system entries! \ Skipping fallback level..." % playlist_type)) diff --git a/src/scheduling/models.py b/src/scheduling/models.py index 7cd8373e..90ab2f58 100644 --- a/src/scheduling/models.py +++ b/src/scheduling/models.py @@ -24,9 +24,9 @@ import datetime import sqlalchemy as sa -from sqlalchemy.ext.declarative import declarative_base +from sqlalchemy import BigInteger, Boolean, Column, DateTime, Integer, String, ForeignKey, ColumnDefault from sqlalchemy import orm -from sqlalchemy import BigInteger, Boolean, Column, DateTime, Integer, String, ForeignKey +from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.orm import relationship from sqlalchemy.ext.hybrid import hybrid_property @@ -103,18 +103,9 @@ class AuraDatabaseModel(): def recreate_db(systemexit = False): """ Re-creates the database for developments purposes. - """ - manualtimeslot = Timeslot() - manualtimeslot.timeslot_id = 0 - manualtimeslot.show_name = "Manual Show" + """ Base.metadata.drop_all() Base.metadata.create_all() - - - # self.logger.debug("inserting manual scheduling possibility and fallback trackservice timeslot") - # DB.session.add(manualtimeslot) - # db.session.add(fallback_trackservice_timeslot) - # self.logger.debug("all created. commiting...") DB.session.commit() if systemexit: @@ -123,20 +114,43 @@ class AuraDatabaseModel(): # -# SCHEDULES & PLAYLISTS +# TIMESLOT # class Timeslot(DB.Model, AuraDatabaseModel): """ - One specific Timeslot for a show on a timeslot. - Holding references to playlists and fallback-playlists. + One specific timeslot for a show. """ __tablename__ = 'timeslot' # Primary keys id = Column(Integer, primary_key=True, autoincrement=True) + # Relationships + playlist = relationship("Playlist", + primaryjoin="and_(Timeslot.timeslot_start==Playlist.timeslot_start, \ + Timeslot.playlist_id==Playlist.playlist_id, Timeslot.show_name==Playlist.show_name)", + uselist=False, back_populates="timeslot") + schedule_fallback = relationship("Playlist", + primaryjoin="and_(Timeslot.timeslot_start==Playlist.timeslot_start, \ + Timeslot.schedule_fallback_id==Playlist.playlist_id, Timeslot.show_name==Playlist.show_name)", + uselist=False, back_populates="timeslot") + show_fallback = relationship("Playlist", + primaryjoin="and_(Timeslot.timeslot_start==Playlist.timeslot_start, \ + Timeslot.show_fallback_id==Playlist.playlist_id, Timeslot.show_name==Playlist.show_name)", + uselist=False, back_populates="timeslot") + station_fallback = relationship("Playlist", + primaryjoin="and_(Timeslot.timeslot_start==Playlist.timeslot_start, \ + Timeslot.station_fallback_id==Playlist.playlist_id, Timeslot.show_name==Playlist.show_name)", + uselist=False, back_populates="timeslot") + + playlist_id = Column(Integer) + schedule_fallback_id = Column(Integer) + show_fallback_id = Column(Integer) + station_fallback_id = Column(Integer) + + # Data timeslot_start = Column(DateTime, unique=True, index=True) timeslot_end = Column(DateTime, unique=True, index=True) timeslot_id = Column(Integer, unique=True) @@ -151,29 +165,10 @@ class Timeslot(DB.Model, AuraDatabaseModel): category = Column(String(256)) topic = Column(String(256)) musicfocus = Column(String(256)) - is_repetition = Column(Boolean()) - - playlist_id = Column(Integer) #, ForeignKey("playlist.playlist_id")) - schedule_fallback_id = Column(Integer) - show_fallback_id = Column(Integer) - station_fallback_id = Column(Integer) fadeouttimer = None # Used to fade-out the timeslot, even when entries are longer - playlist = relationship("Playlist", - primaryjoin="and_(Timeslot.timeslot_start==Playlist.timeslot_start, Timeslot.playlist_id==Playlist.playlist_id, Timeslot.show_name==Playlist.show_name)", - back_populates="timeslot") - schedule_fallback = relationship("Playlist", - primaryjoin="and_(Timeslot.timeslot_start==Playlist.timeslot_start, Timeslot.schedule_fallback_id==Playlist.playlist_id, Timeslot.show_name==Playlist.show_name)", - back_populates="timeslot") - show_fallback = relationship("Playlist", - primaryjoin="and_(Timeslot.timeslot_start==Playlist.timeslot_start, Timeslot.show_fallback_id==Playlist.playlist_id, Timeslot.show_name==Playlist.show_name)", - back_populates="timeslot") - station_fallback = relationship("Playlist", - primaryjoin="and_(Timeslot.timeslot_start==Playlist.timeslot_start, Timeslot.station_fallback_id==Playlist.playlist_id, Timeslot.show_name==Playlist.show_name)", - back_populates="timeslot") - @staticmethod def select_show_on_datetime(date_time): @@ -213,16 +208,6 @@ class Timeslot(DB.Model, AuraDatabaseModel): return timeslots - def get_playlist(self): - """ - Returns the assigned playlist. - """ - # TODO Refactor to avoid storing array of playlists. - if self.playlist and self.playlist[0]: - return self.playlist[0] - return None - - def has_queued_entries(self): """ Checks if entries of this timeslot have been queued at the engine. @@ -291,6 +276,9 @@ class Timeslot(DB.Model, AuraDatabaseModel): return "ID#%s [Show: %s, ShowID: %s | %s - %s ]" % (str(self.timeslot_id), self.show_name, str(self.show_id), time_start, time_end) +# +# PLAYLIST +# class Playlist(DB.Model, AuraDatabaseModel): """ @@ -298,14 +286,16 @@ class Playlist(DB.Model, AuraDatabaseModel): """ __tablename__ = 'playlist' - # pk,fk + # Primary and Foreign Key artificial_id = Column(Integer, primary_key=True) timeslot_start = Column(DateTime, ForeignKey("timeslot.timeslot_start")) - # relationships + + # Relationships timeslot = relationship("Timeslot", uselist=False, back_populates="playlist") entries = relationship("PlaylistEntry", back_populates="playlist") - # data - playlist_id = Column(Integer, autoincrement=False) # , ForeignKey("timeslot.playlist_id")) + + # Data + playlist_id = Column(Integer, autoincrement=False) show_name = Column(String(256)) entry_count = Column(Integer) @@ -434,6 +424,9 @@ class Playlist(DB.Model, AuraDatabaseModel): return "ID#%s [items: %s | %s - %s]" % (str(self.playlist_id), str(self.entry_count), str(time_start), str(time_end)) +# +# PLAYLIST ENTRY +# class PlaylistEntry(DB.Model, AuraDatabaseModel): """ @@ -441,29 +434,30 @@ class PlaylistEntry(DB.Model, AuraDatabaseModel): """ __tablename__ = 'playlist_entry' - # primary keys + # Primary and Foreign Keys artificial_id = Column(Integer, primary_key=True) - - # foreign keys artificial_playlist_id = Column(Integer, ForeignKey("playlist.artificial_id")) - entry_num = Column(Integer) # , primary_key=True) + # Relationships + playlist = relationship("Playlist", uselist=False, back_populates="entries") + meta_data = relationship("PlaylistEntryMetaData", uselist=False, back_populates="entry") + + # Data + entry_num = Column(Integer) uri = Column(String(1024)) duration = Column(BigInteger) + volume = Column(Integer, ColumnDefault(100)) source = Column(String(1024)) entry_start = Column(DateTime) + entry_start_actual = None # Assigned when the entry is actually played channel = None # Assigned when entry is actually played queue_state = None # Assigned when entry is about to be queued status = None # Assigned when state changes - switchtimer = None loadtimer = None fadeouttimer = None - # relationships - playlist = relationship("Playlist", uselist=False, back_populates="entries") - meta_data = relationship("PlaylistEntryMetaData", uselist=False, back_populates="entry") @staticmethod def select_playlistentry_for_playlist(artificial_playlist_id, entry_num): @@ -503,9 +497,6 @@ class PlaylistEntry(DB.Model, AuraDatabaseModel): def end_unix(self): return time.mktime(self.entry_end.timetuple()) - @hybrid_property - def volume(self): - return 100 # FIXME Make DB Column def get_content_type(self): return ResourceUtil.get_content_type(self.uri) @@ -572,22 +563,29 @@ class PlaylistEntry(DB.Model, AuraDatabaseModel): +# +# PLAYLIST ENTRY METADATA +# + class PlaylistEntryMetaData(DB.Model, AuraDatabaseModel): """ - Metadata for a playlist entry such as the artist and track name. + Metadata for a playlist entry such as the artist, album and track name. """ __tablename__ = "playlist_entry_metadata" + # Primary and Foreign Keys artificial_id = Column(Integer, primary_key=True) artificial_entry_id = Column(Integer, ForeignKey("playlist_entry.artificial_id")) + # Relationships + entry = relationship("PlaylistEntry", uselist=False, back_populates="meta_data") + + # Data artist = Column(String(256)) title = Column(String(256)) album = Column(String(256)) - entry = relationship("PlaylistEntry", uselist=False, back_populates="meta_data") - @staticmethod def select_metadata_for_entry(artificial_playlistentry_id): return DB.session.query(PlaylistEntryMetaData).filter(PlaylistEntryMetaData.artificial_entry_id == artificial_playlistentry_id).first() -- GitLab