Author: duncan
Date: Tue Jan 23 20:54:47 2007
New Revision: 9049

Modified:
   branches/rel-1/freevo/freevo_config.py
   branches/rel-1/freevo/src/helpers/recordserver.py

Log:
[ 1641236 ] Conflict resolution for duplicated recordings
Patch from Justin Wetherell applied


Modified: branches/rel-1/freevo/freevo_config.py
==============================================================================
--- branches/rel-1/freevo/freevo_config.py      (original)
+++ branches/rel-1/freevo/freevo_config.py      Tue Jan 23 20:54:47 2007
@@ -1482,6 +1482,9 @@
 # This will enable the commercial detection. It is quite process intensive.
 REMOVE_COMMERCIALS = None
 
+# This will try to resolve scheduling conflicts and re-schedule when needed
+CONFLICT_RESOLUTION = None
+
 #
 # Watching TV
 #

Modified: branches/rel-1/freevo/src/helpers/recordserver.py
==============================================================================
--- branches/rel-1/freevo/src/helpers/recordserver.py   (original)
+++ branches/rel-1/freevo/src/helpers/recordserver.py   Tue Jan 23 20:54:47 2007
@@ -27,7 +27,7 @@
 # -----------------------------------------------------------------------
 
 
-import sys, string, random, time, os, re, pwd, stat, threading, pickle, md5, 
datetime
+import sys, string, random, time, os, re, pwd, stat, threading, pickle, md5, 
datetime, copy
 import config
 from util import vfs
 
@@ -360,11 +360,10 @@
 
        return text
 
-    #
-    # Return the key to be used for a given prog in the
-    # previouslyRecordedShows hashtable.
-    #
+
     def getPreviousRecordingKey(self, prog):
+        '''Return the key to be used for a given prog in the
+        previouslyRecordedShows hashtable.'''
         shrunkTitle = self.shrink(prog.title)
         shrunkSub   = self.shrink(prog.sub_title)
         shrunkDesc  = self.shrink(prog.desc);
@@ -372,19 +371,17 @@
                 '%s-%s-'   % (shrunkTitle, shrunkSub),              \
                 '%s--%s'   % (shrunkTitle, shrunkDesc))
 
-    #
-    # Get a previous recording, or None if none.
-    #
+
     def getPreviousRecording(self, prog):
+        '''Get a previous recording, or None if none.'''
         try:
             return 
self.previouslyRecordedShows[self.getPreviousRecordingKey(prog)]
         except KeyError:
             return None
 
-    #
-    # Remove a duplicate recording
-    #
+
     def removeDuplicate(self, prog=None):
+        '''Remove a duplicate recording'''
         self.loadPreviouslyRecordedShows()
         previous = self.getPreviousRecording(prog)
         if previous:
@@ -392,11 +389,10 @@
            del 
self.previouslyRecordedShows[self.getPreviousRecordingKey(previous)]
            self.savePreviouslyRecordedShows()
 
-    #
-    # Identify if the given programme is a duplicate. If not,
-    # record it as previously recorded.
-    #
+
     def duplicate(self, prog=None):
+        '''Identify if the given programme is a duplicate. If not,
+        record it as previously recorded.'''
         self.loadPreviouslyRecordedShows()
         previous = self.getPreviousRecording(prog)
         if previous:
@@ -411,6 +407,199 @@
         self.savePreviouslyRecordedShows()
         return FALSE
 
+
+    def addRecording(self, prog=None):
+        scheduledRecordings = self.getScheduledRecordings()
+        scheduledRecordings.addProgram(prog, tv_util.getKey(prog))
+        self.saveScheduledRecordings(scheduledRecordings)
+        _debug_('Added Episode')
+
+
+    def removeRecording(self, prog=None):
+        scheduledRecordings = self.getScheduledRecordings()
+        scheduledRecordings.removeProgram(prog, tv_util.getKey(prog))
+        self.saveScheduledRecordings(scheduledRecordings)
+        _debug_('Removed Episode')
+
+
+    def conflictResolution(self, prog=None):
+
+        def exactMatch(self, prog=None):
+            descResult=FALSE
+            descMatches=None
+            (descResult, descMatches)=self.findMatches(prog.desc)
+            if descResult:
+               _debug_('Exact Matches %s'%(len(descMatches)))
+               return descMatches
+            (sub_titleResult, 
sub_titleMatches)=self.findMatches(prog.sub_title)
+            descResult=FALSE
+            descMatches=None
+            if sub_titleResult:
+               _debug_('Exact Matches %s'%(len(sub_titleMatches)))
+               return sub_titleMatches
+            else:
+               titleResult=FALSE
+               titleMatches=None
+               (titleResult, titleMatches)=self.findMatches(prog.title)
+               _debug_('Exact Matches %s'%(len(titleMatches)))
+               return titleMatches
+
+        def getConflict(self, prog):
+            myScheduledRecordings = 
copy.deepcopy(self.getScheduledRecordings())
+            _debug_('Before mySched recordings; ignore all addProgram lines')
+            myScheduledRecordings.addProgram(prog, tv_util.getKey(prog))
+            progs = myScheduledRecordings.getProgramList()
+            proglist = list(progs)
+            proglist.sort(self.progsTimeCompare)
+            conflictRating=0
+            conflictedProg=None
+            for i in range(0, len(proglist)-1):
+                thisprog = progs[proglist[i]]
+                nextprog = progs[proglist[i+1]]
+                if thisprog.stop > nextprog.start:
+                   conflictRating=conflictRating+1
+                   if thisprog==prog:
+                      conflictedProg=nextprog
+                   elif nextprog==prog:
+                      conflictedProg=thisprog
+            myScheduledRecordings.removeProgram(prog)
+            _debug_('After mySched recordings; stop ignoring all addProgram 
lines')
+            return (conflictRating,conflictedProg)
+
+        def getRatedConflicts(self,prog):
+            occurances = exactMatch(self,prog)
+            ratedConflicts=[]
+            #Search through all occurances of looking for a non-conflicted 
occurance
+            for oneOccurance in occurances:
+                (rating, conflictedProg)=getConflict(self,oneOccurance)
+                if rating==0:
+                   _debug_('No Conflict')
+                   self.addRecording(oneOccurance)
+                   return(TRUE,None)
+                else:
+                   _debug_('Conflict Found')
+                   ratedConflicts.append((rating,conflictedProg,oneOccurance))
+            return(FALSE,ratedConflicts)
+
+        if config.CONFLICT_RESOLUTION:
+           _debug_('Conflict resolution enabled')
+           ratedConflicts=[]
+           (result, ratedConflicts)=getRatedConflicts(self,prog)
+           if result:
+              #No conflicts
+              return
+
+           _debug_('Going into conflict resolution via scheduled program 
re-scheduling')
+           # No viable time to schedule the program without a conflict
+           # Try and reschedule the already scheduled program
+           for 
(scheduledConflictRating,scheduledConflictProgram,conflictProgram) in 
ratedConflicts:
+               #Remove scheduled conflictinf program and add new prog
+               self.removeRecording(scheduledConflictProgram)
+               self.addRecording(conflictProgram)
+               (result, 
ratedConflicts)=getRatedConflicts(self,scheduledConflictProgram)
+               if result:
+                  #No conflicts
+                  return
+               #Return to original state
+               self.removeRecording(conflictProgram)
+               self.addRecording(scheduledConflictProgram)
+
+           _debug_('Going into conflict resolution via priority')
+           # No viable option to reschedule the original program
+           # Time to resolve the conflict via priority
+           tempRating=1000
+           tempConflicted=None
+           tempProg=None
+           #Find least conflicted
+           for (conflictedRating, conflictedProgram, tempProgram) in 
ratedConflicts:
+               _debug_('%s %s %s'%(conflictedRating, conflictedProgram.title, 
tempProgram.title))
+               if conflictedRating < tempRating:
+                  tempRating=conflictedRating
+                  tempConflicted=conflictedProgram
+                  tempProg=tempProgram
+           conflictedProgram=tempConflicted
+           prog=tempProgram
+
+           #Here is where it gets ugly
+           (isProgFav, progFav) = self.getFavoriteObject(prog)
+           (isConfFav, confFav) = self.getFavoriteObject(conflictedProgram)
+           if not isProgFav and isConfFav:
+              #Regular recording has higher priority then favorite
+              _debug_('new is regular and old is fav')
+              _debug_('resolved by removing old')
+              if config.DUPLICATE_DETECTION:
+                 #Already added to duplicates, need to remove
+                 self.removeDuplicate(conflictedProgram)
+              self.removeRecording(conflictedProgram)
+              self.addRecording(prog)
+           elif isProgFav and not isConfFav:
+              #Regular recording has higher priority then favorite
+              _debug_('old is regular and new is favorite')
+              _debug_('resolved by removing new')
+              if config.DUPLICATE_DETECTION:
+                 #Already added to duplicates, need to remove
+                 self.removeDuplicate(prog)
+              self.removeRecording(prog)
+              self.addRecording(conflictedProgram)
+           elif not isProgFav and not isConfFav:
+              _debug_('Both are regular; do not add new recording')
+           elif isProgFav and isConfFav:
+              #Both are favorites, go by priority (lower is better)
+              if progFav.priority < confFav.priority:
+                 _debug_('new prog has higher priority then old')
+                 if config.DUPLICATE_DETECTION:
+                    #Already added to duplicates, need to remove
+                    self.removeDuplicate(conflictedProgram)
+                 self.removeRecording(conflictedProgram)
+                 self.addRecording(prog)
+              elif confFav.priority < progFav.priority:
+                 _debug_('old prog has higher priority then new')
+                 if config.DUPLICATE_DETECTION:
+                    #Already added to duplicates, need to remove
+                    self.removeDuplicate(prog)
+                 self.removeRecording(prog)
+                 self.addRecording(conflictedProgram)
+              else:
+                 #Equal priority, not adding new program
+                 _debug_('Both are equal; do not add new recording')
+                 _debug_('%s %s' % (progFav.priority, confFav.priority))
+        else:
+           _debug_('Conflict resolution disabled')
+           self.addRecording(prog)
+
+
+    def checkOnlyNewDetection(self, prog=None):
+        if config.ONLY_NEW_DETECTION and 
self.doesFavoriteRecordOnlyNewEpisodes(prog):
+           _debug_('OnlyNew Episode Detection enabled 1')
+           if self.newEpisode(prog):
+              _debug_('New Episode')
+              self.conflictResolution(prog)
+           else:
+              _debug_('Old Episode')
+        else:
+           _debug_('OnlyNew Episode Detection disabled or Favorite allows all 
Episodes 1')
+           self.conflictResolution(prog)
+
+
+    def checkDuplicateDetection(self, prog=None):
+        (isFav, favorite) = self.isProgAFavorite(prog)
+        if isFav:
+           if config.DUPLICATE_DETECTION and not 
self.doesFavoriteAllowDuplicates(prog):
+              _debug_('Duplicate Detection enabled 1')
+              if not self.duplicate(prog):
+                 # This checks OnlyNew and then hands it off to conflict 
detection
+                 self.checkOnlyNewDetection(prog)
+              else:
+                 return (FALSE, 'duplicate recording')
+           else:
+              _debug_('Duplicate Detection is disabled or Favorite allows 
duplicates 2')
+              # This checks OnlyNew and then hands it off to conflict detection
+              self.checkOnlyNewDetection(prog)
+        else:
+           _debug_('Single recording')
+           self.conflictResolution(prog)
+
+
     def scheduleRecording(self, prog=None):
         global guide
 
@@ -427,51 +616,15 @@
             if prog.channel_id == chan.id:
                 _debug_('scheduleRecording: "%s"' % (prog))
                 prog.tunerid = chan.tunerid
-    
-        if config.DUPLICATE_DETECTION and not 
self.doesFavoriteAllowDuplicates(prog):
-           _debug_('Duplicate Detection enabled 1')
-           if not self.duplicate(prog):
-              if config.ONLY_NEW_DETECTION and 
self.doesFavoriteRecordOnlyNewEpisodes(prog):
-                 _debug_('OnlyNew Episode Detection enabled 1')
-                 if self.newEpisode(prog):
-                    _debug_('New Episode')
-                    scheduledRecordings = self.getScheduledRecordings()
-                    scheduledRecordings.addProgram(prog, tv_util.getKey(prog))
-                    self.saveScheduledRecordings(scheduledRecordings)
-                 else:
-                    _debug_('Old Episode')
-              else:
-                 _debug_('OnlyNew Episode Detection disabled or Favorite 
allows all Episodes 1')
-                 scheduledRecordings = self.getScheduledRecordings()
-                 scheduledRecordings.addProgram(prog, tv_util.getKey(prog))
-                 self.saveScheduledRecordings(scheduledRecordings)
-                 _debug_('Added Episode')
-           else:
-              return (FALSE, 'duplicate recording')
-        else:
-           _debug_('Duplicate Detection is disabled or Favorite allows 
duplicates 2')
-           if config.ONLY_NEW_DETECTION and 
self.doesFavoriteRecordOnlyNewEpisodes(prog):
-              _debug_('OnlyNew Detection enabled 2')
-              if self.newEpisode(prog):
-                 _debug_('New Episode')
-                 scheduledRecordings = self.getScheduledRecordings()
-                 scheduledRecordings.addProgram(prog, tv_util.getKey(prog))
-                 self.saveScheduledRecordings(scheduledRecordings)
-              else:
-                 _debug_('Old Episode')
-
-           else:
-              _debug_('OnlyNew Episode Detection disabled 2')
-              scheduledRecordings = self.getScheduledRecordings()
-              scheduledRecordings.addProgram(prog, tv_util.getKey(prog))
-              self.saveScheduledRecordings(scheduledRecordings)
-              _debug_('Added Episode')
 
+        # This check for Dups and then hands off to the OnlyNew func
+        self.checkDuplicateDetection(prog)
+    
         # check, maybe we need to start right now
         self.checkToRecord()
 
         return (TRUE, 'recording scheduled')
-    
+
 
     def removeScheduledRecording(self, prog=None):
         if not prog:
@@ -845,6 +998,15 @@
 
         return (TRUE, 'priorities adjusted')
     
+    def getFavoriteObject(self, prog, favs=None):
+        #more liberal favorite check that returns an object
+        if not favs:
+            (status, favs) = self.getFavorites()
+        for fav in favs.values():
+            if Unicode(prog.title).lower().find(Unicode(fav.title).lower()) >= 
0:
+               return (TRUE, fav)
+        # if we get this far prog is not a favorite
+        return (FALSE, 'not a favorite')
     
     def isProgAFavorite(self, prog, favs=None):
         if not favs:

-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys - and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
_______________________________________________
Freevo-cvslog mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/freevo-cvslog

Reply via email to