Esempio n. 1
0
    def get_next_neighbour(self, p_node_name_now : str, p_mpdj_data : MPDJData,
                         p_play_data : PlayData,
                         p_mpd_connection : MPDConnection) -> str:
        """Returns the next neighbour, according to a random choice
            weighted by songs in collected divided by 1 plays
            of songs in this node."""
        random.seed()
        neighbour_node_names = p_mpdj_data.get_neighbours_for_node_name(p_node_name_now)
        # If node does not have any neighbours, we will select a random one from the set
        # of all neighbours.
        if len(neighbour_node_names) < 1:
            print('No neighbours for {} considering all nodes as next'.format(p_node_name_now))
            neighbour_node_names = p_mpdj_data.get_song_selection_names()
        if len(neighbour_node_names) > 1 and p_play_data.previous_node in neighbour_node_names:
            neighbour_node_names.remove(p_play_data.previous_node)

        nodes_with_song_count_not_zero = self.get_possible_next_neighbours(p_node_name_now,
                                                                           p_mpdj_data,
                                                                           p_play_data,
                                                                           p_mpd_connection)
        node_weights = calculate_node_weight_with_song_play_count(
            p_play_data,
            list(nodes_with_song_count_not_zero.values()))
        choice = random.choices(population=[*nodes_with_song_count_not_zero],
                                weights=node_weights,k=1)
        return choice[0]
Esempio n. 2
0
 def new_mpdj(self):
     """Creates a new mpdj data to work on (empties all the data
         currently loaded)"""
     self.mpdj_data = MPDJData()
     self.mpdj_data.add_function_to_call_on_change(inform_about_changes_in_mpdj)
     self.path_of_current_file = ''
     self.changes_happened_since_last_save = False
     self.inform_update_listener()
Esempio n. 3
0
 def get_next_neighbour(self, p_node_name_now : str, p_mpdj_data : MPDJData,
                      p_play_data : PlayData,
                      p_mpd_connection : MPDConnection) -> str:
     """Return the next node by selecting the one with minimal
         average play count. When more than on has minimal play
         count, the next one will be on of those with minimum play
         count, selected randomly."""
     random.seed()
     neighbour_node_names = p_mpdj_data.get_neighbours_for_node_name(p_node_name_now)
     print (neighbour_node_names)
     candidates_with_minimal_average_play_count = list()
     min_average = math.inf
     if p_play_data.previous_node and p_play_data.previous_node in neighbour_node_names:
         neighbour_node_names.remove(p_play_data.previous_node)
     for node_name in neighbour_node_names:
         node = p_mpdj_data.song_selections[node_name]
         songs_of_node = node.get_songs(p_mpd_connection)
         song_count = len(songs_of_node)
         if song_count == 0:
             continue
         playcount = reduce(lambda x,y: x+y,
                            (map(lambda song:
                             p_play_data.get_play_count_of_song_value(song['file'], 'file'),
                             songs_of_node)))
         play_count_average = float(playcount) / float (song_count)
         print ("Node: {}: {}".format(node_name,play_count_average))
         if play_count_average < min_average:
             candidates_with_minimal_average_play_count = list()
             min_average = play_count_average
         if play_count_average <= min_average:
             candidates_with_minimal_average_play_count.append(node_name)
     print (candidates_with_minimal_average_play_count)
     choice = random.choice(candidates_with_minimal_average_play_count)
     print (choice)
     return choice
Esempio n. 4
0
 def get_possible_next_neighbours(self, p_node_name_now : str, p_mpdj_data : MPDJData,
                                  p_play_data : PlayData, p_mpd_connection : MPDConnection):
     """Returns those neighbors who could be selected as next neighbors. Dependent of
         p_node_name_now, p_mpdj_data, p_play_data and p_mpd_connection."""
     neighbours_in_graph = p_mpdj_data.get_neighbours_for_node_name(p_node_name_now)
     if len(neighbours_in_graph) < 1:
         print('No neighbours for {} considering all nodes as next'.format(p_node_name_now))
         neighbours_in_graph = p_mpdj_data.get_song_selection_names()
     if len(neighbours_in_graph) > 1 and p_play_data.previous_node in neighbours_in_graph:
         neighbours_in_graph.remove(p_play_data.previous_node)
     neighbours_with_song_count_not_zero = dict()
     for node in neighbours_in_graph:
         songs_in_node = p_mpdj_data.get_song_selection_by_name(node).get_songs(p_mpd_connection)
         if len(songs_in_node) == 0:
             sys.stderr.write('Node {} has now songs, ignoring it.'.format(node))
             sys.stderr.flush()
             continue
         neighbours_with_song_count_not_zero[node] = songs_in_node
     return neighbours_with_song_count_not_zero
Esempio n. 5
0
 def __init__(self, pHost, pPort):
     '''
     Constructor
     '''
     self.mpdj_data = MPDJData()
     self.mpd_connection = MPDConnection(pHost, pPort)
     self.keep_running = True
     self.play_data = PlayData()
     self.node_selector = NodeSelectionMinimalAveragePlaycountWeightedProbabilities(
     )
     self.song_selector = SongSelectorMinimalPlayCount()
Esempio n. 6
0
    def __init__(self):
        """ Virtually private constructor. """
        if GlobalProperties.__instance is not None:
            raise Exception("This class is a singleton!")
        if os.path.isfile('./path_of_file'):
            self.load_config_from_file()
        else:
            GlobalProperties.__instance = self
            # The momentary connection we are using.
            self.mpd_connection = MPDConnection('localhost', '6600')
            self.mpd_connection.connect()
            # The momentary MPDJ data.
            self.mpdj_data = MPDJData()
            self.mpdj_data.add_function_to_call_on_change(inform_about_changes_in_mpdj)
            # The update listeners which are informed about changes.
            self.update_listeners = []
            # The path of the file which we are working on
            self._path_of_current_file = ''
            # Indicates changes since the last save or load operation.
            self._changes_happened_since_last_save = False
            # Edit connections so the graph the graph simulates an undirected graph
#            self.edit_both_directions = True
            # The current opened windows.
            self.opened_windows = list()
Esempio n. 7
0
 def get_next_neighbour(self, p_node_now : str, p_mpdj_data : MPDJData,
                      p_play_data : PlayData,
                      p_mpd_connection : MPDConnection) -> str:
     """Returns the node with the minimum playcount, not weighted at all."""
     random.seed()
     neighbour_nodes = p_mpdj_data.get_neighbours_for_node_name(p_node_now)
     min_node_play_count = math.inf
     next_node_candidates = []
     for node in neighbour_nodes:
         node_play_count = p_play_data.node_play_count[node]
         if node_play_count < min_node_play_count:
             min_node_play_count = node_play_count
             next_node_candidates = []
         if node_play_count <= min_node_play_count:
             next_node_candidates.append(node)
     if p_play_data.previous_node and p_play_data in next_node_candidates:
         next_node_candidates.remove(p_play_data.previous_node.get_name())
     return random.choice(next_node_candidates)
Esempio n. 8
0
class GlobalProperties():
    """This singleton contains stuff, which needs to be accessible
    from everywhere in mpdj."""
    __instance = None
    @staticmethod
    def get_instance():
        """Static access method."""
        if GlobalProperties.__instance is None:
            GlobalProperties()
        return GlobalProperties.__instance

    @property
    def changes_happened_since_last_save(self):
        """Indicates if changes happened since last save."""
        return self._changes_happened_since_last_save

    @changes_happened_since_last_save.setter
    def changes_happened_since_last_save(self, p_new_value):
        self._changes_happened_since_last_save = p_new_value

    @changes_happened_since_last_save.deleter
    def changes_happened_since_last_save(self):
        del self._changes_happened_since_last_save

    @property
    def path_of_current_file(self):
        """The currently opened file."""
        if not hasattr(self, '_path_of_current_file'):
            self._path_of_current_file = ''
        return self._path_of_current_file
    
    @path_of_current_file.setter
    def path_of_current_file(self,p_new_path):
        self._path_of_current_file = p_new_path
        
    @path_of_current_file.deleter
    def path_of_current_file(self):
        del self._path_of_current_file

    def add_listener(self, p_listener):
        """Adds a listener so if anything changes the listener will be
        informed."""
        self.update_listeners.append(p_listener)

    def load_config_from_file(self):
        """This sould load a config from a config file.
            Not implemented, yet."""
        #TODO

    def inform_update_listener(self):
        """This method inform all added listeners about changes."""
        for update_listener in self.update_listeners:
            update_listener.update()

    def save_mpdj_data_to_file(self, p_file_name):
        """Write the momentary MPDJ-data to p_file_name."""
        with open(p_file_name, 'w') as save_file:
            save_file.write(jsonpickle.encode(self.mpdj_data))
        self.changes_happened_since_last_save = False
        self.path_of_current_file = p_file_name
        self.inform_update_listener()

    def load_mpdjdata_from_file(self, p_file_name):
        """Loads a mpdj file, overwrite the momentary MPDJ-data."""
        with open(p_file_name, 'r') as load_file:
            self.mpdj_data = jsonpickle.decode(load_file.read())
        self.mpdj_data.add_function_to_call_on_change(inform_about_changes_in_mpdj)
        self.changes_happened_since_last_save = False
        self.path_of_current_file = p_file_name
        self.inform_update_listener()

    def new_mpdj(self):
        """Creates a new mpdj data to work on (empties all the data
            currently loaded)"""
        self.mpdj_data = MPDJData()
        self.mpdj_data.add_function_to_call_on_change(inform_about_changes_in_mpdj)
        self.path_of_current_file = ''
        self.changes_happened_since_last_save = False
        self.inform_update_listener()

    def __init__(self):
        """ Virtually private constructor. """
        if GlobalProperties.__instance is not None:
            raise Exception("This class is a singleton!")
        if os.path.isfile('./path_of_file'):
            self.load_config_from_file()
        else:
            GlobalProperties.__instance = self
            # The momentary connection we are using.
            self.mpd_connection = MPDConnection('localhost', '6600')
            self.mpd_connection.connect()
            # The momentary MPDJ data.
            self.mpdj_data = MPDJData()
            self.mpdj_data.add_function_to_call_on_change(inform_about_changes_in_mpdj)
            # The update listeners which are informed about changes.
            self.update_listeners = []
            # The path of the file which we are working on
            self._path_of_current_file = ''
            # Indicates changes since the last save or load operation.
            self._changes_happened_since_last_save = False
            # Edit connections so the graph the graph simulates an undirected graph
#            self.edit_both_directions = True
            # The current opened windows.
            self.opened_windows = list()