diff --git a/PseudoChannel.py b/PseudoChannel.py index 816ad24..ff768e5 100644 --- a/PseudoChannel.py +++ b/PseudoChannel.py @@ -12,6 +12,8 @@ from plexapi.server import PlexServer import sys import datetime +import calendar +import itertools from xml.dom import minidom import xml.etree.ElementTree as ET @@ -21,6 +23,12 @@ class PseudoChannel(): MEDIA = [] + TIME_GAP = 15 + + OVERLAP_GAP = 15 + + OVERLAP_MAX = 30 + def __init__(self): self.db = PseudoChannelDatabase("pseudo-channel.db") @@ -232,6 +240,135 @@ class PseudoChannel(): * Returns time * ''' + ''' + * + * Returns time difference in minutes + * + ''' + def time_diff(self, time1,time2): + ''' + * + * Getting the offest by comparing both times from the unix epoch time and getting the difference. + * + ''' + timeA = datetime.datetime.strptime(time1, "%I:%M %p") + timeB = datetime.datetime.strptime(time2, "%I:%M %p") + + timeAEpoch = calendar.timegm(timeA.timetuple()) + timeBEpoch = calendar.timegm(timeB.timetuple()) + + tdelta = abs(timeAEpoch) - abs(timeBEpoch) + + return int(tdelta/60) + + + ''' + * + * Passing in the endtime from the prev episode and desired start time of this episode, calculate the best start time + + * Returns time - for new start time + * + ''' + def calculate_start_time(self, prevEndTime, intendedStartTime, timeGap, overlapMax): + + self.TIME_GAP = timeGap + + self.OVERLAP_MAX = overlapMax + + time1 = datetime.datetime.strptime(prevEndTime, '%I:%M %p').strftime('%-I:%M %p') + + timeB = intendedStartTime.strftime('%-I:%M %p') + + timeDiff = self.time_diff(time1, timeB) + + print("timeDiff "+ str(timeDiff)) + print("startTimeUNIX: "+ str(intendedStartTime)) + + newTimeObj = intendedStartTime.strftime('%-I:%M %p') + + newStartTime = intendedStartTime.strftime('%-I:%M %p') + + ''' + * + * If time difference is negative, then we know there is overlap + * + ''' + if timeDiff < 0: + + print("There is overlap ") + + ''' + * + * If there is an overlap, then the overlapGap var in config will determine the next increment. If it is set to "15", then the show will will bump up to the next 15 minute interval past the hour. + * + ''' + timeset=[datetime.time(h,m).strftime("%H:%M") for h,m in itertools.product(xrange(0,24),xrange(0,60,int(self.OVERLAP_GAP)))] + + print(timeset) + + timeSetToUse = None + + for time in timeset: + + #print(time) + theTimeSetInterval = datetime.datetime.strptime(time, '%H:%M') + + # print(theTimeSetInterval) + + # print(prevEndTime) + + if theTimeSetInterval >= prevEndTime: + + print("Setting new time by interval... " + time) + print("made it!") + + newStartTime = theTimeSetInterval + + break + + #newStartTime = newTimeObj + datetime.timedelta(minutes=abs(timeDiff + overlapGap)) + + elif (timeDiff >= 0) and (self.TIME_GAP != -1): + + ''' + * + * If there this value is configured, then the timeGap var in config will determine the next increment. If it is set to "15", then the show will will bump up to the next 15 minute interval past the hour. + * + ''' + timeset=[datetime.time(h,m).strftime("%H:%M") for h,m in itertools.product(xrange(0,24),xrange(0,60,int(self.TIME_GAP)))] + + # print(timeset) + + timeSetToUse = None + + for time in timeset: + + #print(time) + theTimeSetInterval = datetime.datetime.strptime(time, '%H:%M') + + tempTimeTwoStr = datetime.datetime.strptime(time1, '%I:%M %p').strftime('%H:%M') + + formatted_time_two = datetime.datetime.strptime(tempTimeTwoStr, '%H:%M') + + # print(theTimeSetInterval) + + # print(prevEndTime) + + if theTimeSetInterval >= formatted_time_two: + + print("Setting new time by interval... " + time) + print("made it!") + + newStartTime = theTimeSetInterval + + break + + else: + + print("Not sure what to do here") + + return newStartTime.strftime('%-I:%M %p') + def get_end_time_from_duration(self, startTime, duration): time = datetime.datetime.strptime(startTime, '%I:%M %p') @@ -248,14 +385,16 @@ class PseudoChannel(): schedule = self.db.get_schedule() + schedule_advance_watcher = 0 + for entry in schedule: + schedule_advance_watcher += 1 + section = entry[9] if section == "TV Shows": - print "getting", entry[3] - next_episode = self.db.get_next_episode(entry[3]) if next_episode != None: @@ -267,20 +406,22 @@ class PseudoChannel(): self.get_end_time_from_duration(entry[5], next_episode[4]), # natural_end_time next_episode[4], # duration entry[7], # day_of_week - False, # is_strict_time + entry[10], # is_strict_time + entry[11], # time_shift + entry[12], # overlap_max entry[3], # show_series_title next_episode[5], # episode_number next_episode[6] # season_number ) + self.MEDIA.append(episode) + else: print("Cannot find TV Show Episode, {} in the local db".format(entry[3])) #print(episode) - self.MEDIA.append(episode) - elif section == "Movies": the_movie = self.db.get_movie(entry[3]) @@ -294,7 +435,9 @@ class PseudoChannel(): self.get_end_time_from_duration(entry[5], the_movie[4]), # natural_end_time the_movie[4], # duration entry[7], # day_of_week - False, # is_strict_time + entry[10], # is_strict_time + entry[11], # time_shift + entry[12] # overlap_max ) #print(movie.natural_end_time) @@ -318,7 +461,9 @@ class PseudoChannel(): self.get_end_time_from_duration(entry[5], the_music[4]), # natural_end_time the_music[4], # duration entry[7], # day_of_week - False, # is_strict_time + entry[10], # is_strict_time + entry[11], # time_shift + entry[12] # overlap_max ) #print(music.natural_end_time) @@ -342,7 +487,9 @@ class PseudoChannel(): self.get_end_time_from_duration(entry[5], the_video[4]), # natural_end_time the_video[4], # duration entry[7], # day_of_week - False, # is_strict_time + entry[10], # is_strict_time + entry[11], # time_shift + entry[12] # overlap_max ) #print(music.natural_end_time) @@ -357,22 +504,71 @@ class PseudoChannel(): pass + """If we reached the end of the schedule we are ready to kick off the daily_schedule + + """ + if schedule_advance_watcher >= len(schedule): + + previous_episode = None + + self.db.remove_all_daily_scheduled_items() + + for entry in self.MEDIA: + + #print entry.natural_end_time + + if previous_episode != None: + + previous_episode = entry + + natural_start_time = datetime.datetime.strptime(entry.natural_start_time, '%I:%M %p') + + natural_end_time = entry.natural_end_time + + if entry.is_strict_time.lower() == "true": + + print "Using strict-time: {}".format(entry.title) + + entry.end_time = self.get_end_time_from_duration(entry.start_time, entry.duration) + + self.db.add_media_to_daily_schedule(entry) + + else: + + print "NOT strict-time. {}".format(entry.title) + + new_starttime = self.calculate_start_time( + entry.natural_start_time, + entry.end_time, + previous_episode.time_shift, + previous_episode.overlap_max + ) + + print new_starttime + + entry.start_time = datetime.datetime.strptime(new_starttime, '%I:%M %p').strftime('%-I:%M %p') + + entry.end_time = self.get_end_time_from_duration(entry.start_time, entry.duration) + + self.db.add_media_to_daily_schedule(entry) + + else: + + self.db.add_media_to_daily_schedule(entry) + + previous_episode = entry + if __name__ == '__main__': pseudo_channel = PseudoChannel() - pseudo_channel.update_db() + #pseudo_channel.db.create_tables() - pseudo_channel.update_schedule() + #pseudo_channel.update_db() + + #pseudo_channel.update_schedule() pseudo_channel.generate_daily_schedule() - """for item in pseudo_channel.MEDIA: - if item.day_of_week == "saturdays": - - print(item.title)""" - #pass - - #pseudo_channel.update_db() diff --git a/src/Commercial.py b/src/Commercial.py index b681f27..10b9a92 100644 --- a/src/Commercial.py +++ b/src/Commercial.py @@ -22,7 +22,9 @@ class Commercial(Media): natural_end_time, duration, day_of_week, - is_strict_time + is_strict_time, + time_shift, + overlap_max ): super(Commercial, self).__init__( @@ -32,5 +34,7 @@ class Commercial(Media): natural_end_time, duration, day_of_week, - is_strict_time + is_strict_time, + time_shift, + overlap_max ) diff --git a/src/Episode.py b/src/Episode.py index 2bffa60..3c579d5 100644 --- a/src/Episode.py +++ b/src/Episode.py @@ -26,6 +26,8 @@ class Episode(Media): duration, day_of_week, is_strict_time, + time_shift, + overlap_max, show_series_title, episode_number, season_number @@ -38,7 +40,9 @@ class Episode(Media): natural_end_time, duration, day_of_week, - is_strict_time + is_strict_time, + time_shift, + overlap_max ) self.show_series_title = show_series_title diff --git a/src/Media.py b/src/Media.py index 2cffa53..66e72d7 100644 --- a/src/Media.py +++ b/src/Media.py @@ -27,7 +27,9 @@ class Media(object): natural_end_time, duration, day_of_week, - is_strict_time + is_strict_time, + time_shift, + overlap_max ): self.section_type = section_type @@ -37,6 +39,8 @@ class Media(object): self.duration = duration self.day_of_week = day_of_week self.is_strict_time = is_strict_time + self.time_shift = time_shift + self.overlap_max = overlap_max self.start_time = natural_start_time self.end_time = natural_end_time diff --git a/src/Movie.py b/src/Movie.py index ce2c649..a8258b0 100644 --- a/src/Movie.py +++ b/src/Movie.py @@ -22,7 +22,9 @@ class Movie(Media): natural_end_time, duration, day_of_week, - is_strict_time + is_strict_time, + time_shift, + overlap_max ): super(Movie, self).__init__( @@ -32,5 +34,7 @@ class Movie(Media): natural_end_time, duration, day_of_week, - is_strict_time + is_strict_time, + time_shift, + overlap_max ) diff --git a/src/Music.py b/src/Music.py index a968858..0ac53bb 100644 --- a/src/Music.py +++ b/src/Music.py @@ -22,7 +22,9 @@ class Music(Media): natural_end_time, duration, day_of_week, - is_strict_time + is_strict_time, + time_shift, + overlap_max ): super(Music, self).__init__( @@ -32,5 +34,7 @@ class Music(Media): natural_end_time, duration, day_of_week, - is_strict_time + is_strict_time, + time_shift, + overlap_max ) diff --git a/src/PseudoChannelDatabase.py b/src/PseudoChannelDatabase.py index 8709158..7e54303 100644 --- a/src/PseudoChannelDatabase.py +++ b/src/PseudoChannelDatabase.py @@ -54,7 +54,8 @@ class PseudoChannelDatabase(): self.cursor.execute('CREATE TABLE IF NOT EXISTS ' 'daily_schedule(id INTEGER PRIMARY KEY AUTOINCREMENT, unix INTEGER, ' 'mediaID INTEGER, title TEXT, episodeNumber INTEGER, seasonNumber INTEGER, ' - 'showTitle TEXT, duration INTEGER, startTime INTEGER, endTime INTEGER, dayOfWeek TEXT)') + 'showTitle TEXT, duration INTEGER, startTime INTEGER, endTime INTEGER, ' + 'dayOfWeek TEXT, sectionType TEXT)') self.cursor.execute('CREATE TABLE IF NOT EXISTS ' 'app_settings(id INTEGER PRIMARY KEY AUTOINCREMENT, version TEXT)') @@ -103,6 +104,14 @@ class PseudoChannelDatabase(): self.conn.commit() + def remove_all_daily_scheduled_items(self): + + sql = "DELETE FROM daily_schedule WHERE id > -1" + + self.cursor.execute(sql) + + self.conn.commit() + """Database functions. Setters, etc. @@ -189,26 +198,69 @@ class PseudoChannelDatabase(): self.conn.rollback() raise e - def add_daily_schedule_to_db(self, mediaID, title, duration, startTime, endTime, dayOfWeek): + def add_daily_schedule_to_db( + self, + mediaID, + title, + episodeNumber, + seasonNumber, + showTitle, + duration, + startTime, + endTime, + dayOfWeek, + sectionType + ): + unix = int(time.time()) - startTimeUnix = str(datetime.datetime.strptime(startTime, '%I:%M %p')) + try: - self.cursor.execute("INSERT OR REPLACE INTO schedule " - "(unix, mediaID, title, duration, startTime, endTime, dayOfWeek, startTimeUnix) " - "VALUES (?, ?, ?, ?, ?, ?, ?, ?)", - (unix, mediaID, title, duration, startTime, endTime, dayOfWeek, startTimeUnix)) + self.cursor.execute("INSERT OR REPLACE INTO daily_schedule " + "(unix, mediaID, title, episodeNumber, seasonNumber, " + "showTitle, duration, startTime, endTime, dayOfWeek, sectionType) " + "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", + ( + unix, + mediaID, + title, + episodeNumber, + seasonNumber, + showTitle, + duration, + startTime, + endTime, + dayOfWeek, + sectionType + )) + self.conn.commit() - self.cursor.close() - self.conn.close() + # Catch the exception except Exception as e: - # Roll back any change if something goes wrong - self.conn.rollback() - self.cursor.close() - self.conn.close() - raise e + # Roll back any change if something goes wrong + + self.conn.rollback() + + raise e + + def add_media_to_daily_schedule(self, media): + + print "Adding media to db", media.title, media.start_time + + self.add_daily_schedule_to_db( + 0, + media.title, + media.episode_number if media.__class__.__name__ == "Episode" else 0, + media.season_number if media.__class__.__name__ == "Episode" else 0, + media.show_series_title if media.__class__.__name__ == "Episode" else '', + media.duration, + media.start_time, + media.end_time, + media.day_of_week, + media.section_type + ) """Database functions. diff --git a/src/Video.py b/src/Video.py index d938528..d9f6a5d 100644 --- a/src/Video.py +++ b/src/Video.py @@ -22,7 +22,9 @@ class Video(Media): natural_end_time, duration, day_of_week, - is_strict_time + is_strict_time, + time_shift, + overlap_max ): super(Video, self).__init__( @@ -32,5 +34,7 @@ class Video(Media): natural_end_time, duration, day_of_week, - is_strict_time + is_strict_time, + time_shift, + overlap_max )