diff --git a/web/directives/channel-config.js b/web/directives/channel-config.js index 63266eb..b3d7cc7 100644 --- a/web/directives/channel-config.js +++ b/web/directives/channel-config.js @@ -16,6 +16,9 @@ module.exports = function ($timeout, $location, dizquetv) { scope._frequencyMessage = ""; scope.millisecondsOffset = 0; scope.minProgramIndex = 0; + scope.episodeMemory = { + saved : false, + }; if (typeof scope.channel === 'undefined' || scope.channel == null) { scope.channel = {} scope.channel.programs = [] @@ -544,6 +547,103 @@ module.exports = function ($timeout, $location, dizquetv) { scope.channel.programs = progs; updateChannelDuration(); } + scope.savePositions = () => { + scope.episodeMemory = { + saved : false, + }; + let array = scope.channel.programs; + for (let i = 0; i < array.length; i++) { + if (array[i].type === 'episode' && array[i].season != 0) { + let key = array[i].showTitle; + if (typeof(scope.episodeMemory[key]) === 'undefined') { + scope.episodeMemory[key] = { + season: array[i].season, + episode: array[i].episode, + } + } + } + } + scope.episodeMemory.saved = true; + } + scope.recoverPositions = () => { + //this is basically the code for cyclic shuffle + let array = scope.channel.programs; + let shows = {}; + let next = {}; + let counts = {}; + // some precalculation, useful to stop the shuffle from being quadratic... + for (let i = 0; i < array.length; i++) { + let vid = array[i]; + if (vid.type === 'episode' && vid.season != 0) { + let countKey = { + title: vid.showTitle, + s: vid.season, + e: vid.episode, + } + let key = JSON.stringify(countKey); + let c = ( (typeof(counts[key]) === 'undefined') ? 0 : counts[key] ); + counts[key] = c + 1; + let showEntry = { + c: c, + it: vid + } + if ( typeof(shows[vid.showTitle]) === 'undefined') { + shows[vid.showTitle] = []; + } + shows[vid.showTitle].push(showEntry); + } + } + //this is O(|N| log|M|) where |N| is the total number of TV + // episodes and |M| is the maximum number of episodes + // in a single show. I am pretty sure this is a lower bound + // on the time complexity that's possible here. + Object.keys(shows).forEach(function(key,index) { + shows[key].sort( (a,b) => { + if (a.c == b.c) { + if (a.it.season == b.it.season) { + if (a.it.episode == b.it.episode) { + return 0; + } else { + return (a.it.episode < b.it.episode)?-1: 1; + } + } else { + return (a.it.season < b.it.season)?-1: 1; + } + } else { + return (a.c < b.c)? -1: 1; + } + }); + next[key] = 0; + if (typeof(scope.episodeMemory[key]) !== 'undefined') { + for (let i = 0; i < shows[key].length; i++) { + if ( + (shows[key][i].it.season === scope.episodeMemory[key].season) + &&(shows[key][i].it.episode === scope.episodeMemory[key].episode) + ) { + next[key] = i; + break; + } + } + } + }); + for (let i = 0; i < array.length; i++) { + if (array[i].type === 'episode' && array[i].season != 0) { + let title = array[i].showTitle; + var sequence = shows[title]; + let j = next[title]; + array[i] = sequence[j].it; + + next[title] = (j + 1) % sequence.length; + } + } + scope.channel.programs = array; + updateChannelDuration(); + + } + scope.cannotRecoverPositions = () => { + return scope.episodeMemory.saved !== true; + } + scope.addBreaks = (afterMinutes, minDurationSeconds, maxDurationSeconds) => { let after = afterMinutes * 60 * 1000 + 5000; //allow some seconds of excess let minDur = minDurationSeconds; diff --git a/web/public/templates/channel-config.html b/web/public/templates/channel-config.html index fa69d94..5dd4798 100644 --- a/web/public/templates/channel-config.html +++ b/web/public/templates/channel-config.html @@ -139,6 +139,9 @@
Sorts everything by its release date. This will only work correctly if the release dates in Plex are correct. In case any item does not have a release date specified, it will be moved to the bottom.
+Sorts everything by its release date. This will only work correctly if the release dates in Plex are correct. In case any item does not have a release date specified, it will be moved to the bottom.
+Attempts to make the total amount of time each TV show appears in the programming as balanced as possible. This works by adding multiple copies of TV shows that have too little total time and by possibly removing duplicated episodes from TV shows that have too much total time. Note that in many situations it would be impossible to achieve perfect balance because channel duration is not infinite. Movies/Clips are treated as a single TV show. Note that this will most likely result in a larger channel and that having large channels makes some UI operations slower.
@@ -160,6 +163,10 @@Divides the programming in blocks of 6, 8 or 12 hours then repeats each of the blocks the specified number of times. For example, you can make a channel that plays exactly the same channels in the morning and in the afternoon.
+The "Save" button saves the current episodes that are next to be played for each tv show. Then whenever you click the "Recover Episode Popsitions" button, episodes will be rearranged cyclically and they will start with the saved positions. So you can maintain episode sequences even after modifying the channel. If there are any new TV shows, they will start at their current positions. Movies and specials won't change positions. +
+Adds a channel redirect. During this period of time, the channel will redirect to another channel.
@@ -189,7 +196,7 @@