From 1b4cc8f7fa5460cc026ec6f336a045a72f5de6ba Mon Sep 17 00:00:00 2001 From: codezapper Date: Tue, 24 Jan 2017 16:14:47 +0100 Subject: [PATCH 01/77] Add files via upload --- doubly_linked_list.py | 76 +++++++++++++++++++++++++++++++++++++++++++ singly_linked_list.py | 69 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 145 insertions(+) create mode 100644 doubly_linked_list.py create mode 100644 singly_linked_list.py diff --git a/doubly_linked_list.py b/doubly_linked_list.py new file mode 100644 index 0000000..ed373a5 --- /dev/null +++ b/doubly_linked_list.py @@ -0,0 +1,76 @@ +class Node(): + def __init__(self, payload): + self.payload = payload + self.prev = None + self.next = None + +class DoubleList(): + def __init__(self): + self.head = None + self.tail = None + + + def append(self, payload): + new_node = Node(payload) + new_node.prev = self.tail + + if self.tail is None: + self.head = self.tail = new_node + else: + temp_node = self.tail + self.tail.next = new_node + self.tail = self.tail.next + self.tail.prev = temp_node + + + def reverse(self): + current_node = self.head + temp_node = None + while current_node is not None: + temp_node = current_node.prev; + current_node.prev = current_node.next; + current_node.next = temp_node; + current_node = current_node.prev + + self.head = temp_node.prev + + + def remove(self, node_value): + current_node = self.head + + while current_node is not None: + if current_node.payload == node_value: + if current_node.prev is not None: + current_node.prev.next = current_node.next + current_node.next.prev = current_node.prev + else: + self.head = current_node.next + current_node.next.prev = None + + current_node = current_node.next + + + def show(self): + current_node = self.head + while current_node is not None: + print( current_node.payload) + current_node = current_node.next + + +d = DoubleList() + +d.append(1) +d.append(2) +d.append(3) +d.append(4) + +d.show() + +d.reverse() + +d.show() + +# d.remove(50) +# d.remove(5) + +# d.show() \ No newline at end of file diff --git a/singly_linked_list.py b/singly_linked_list.py new file mode 100644 index 0000000..b751173 --- /dev/null +++ b/singly_linked_list.py @@ -0,0 +1,69 @@ +class Node(): + def __init__(self, payload): + self.payload = payload + self.next = None + +class DoubleList(): + def __init__(self): + self.head = None + self.tail = None + + def append(self, payload): + new_node = Node(payload) + new_node.next = None + + if (self.tail is not None): + self.tail.next = new_node + self.tail = self.tail.next + else: + self.head = new_node + self.tail = self.head + + def reverse(self): + current_node = self.head + last_node = None + while (current_node is not None): + temp_node = current_node.next + current_node.next, last_node = last_node, current_node + current_node = temp_node + + return last_node + + def reverse_r(self, current_node): + if (current_node is None): + return None + + temp_node = current_node.next; + if (temp_node is None): + return None + + self.reverse_r(temp_node); + temp_node.next = current_node; + current_node.next = None; + current_node = temp_node; + return self.tail + + def print_payload(self): + current_node = self.head + while current_node is not None: + print( current_node.payload) + current_node = current_node.next + + +d = DoubleList() + +d.append(1) +d.append(2) +d.append(3) +d.append(4) + +d.print_payload() + +d.head = d.reverse_r(d.head) + +d.print_payload() + +# d.remove(50) +# d.remove(5) + +# d.show() \ No newline at end of file From a7251794d1aec3c499c3dbc476a57fc190ab96e3 Mon Sep 17 00:00:00 2001 From: codezapper Date: Thu, 26 Jan 2017 09:55:39 +0100 Subject: [PATCH 02/77] Updated TODO.txt --- PyLister/TODO.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/PyLister/TODO.txt b/PyLister/TODO.txt index 0ca12f1..0f2bc37 100755 --- a/PyLister/TODO.txt +++ b/PyLister/TODO.txt @@ -1,11 +1,11 @@ - Cleanup main.js - Cleanup python code +- Fix sorting when mixing filters and search words +- Remove duplicates also on client side - Fix playing when not submitted (e.g. when clicking with the mouse before pressing enter) -- Add list shuffling - Add prefixes: - - "shuffle:" adds shuffled results to the playlist - "repeat:" adds results and repeats them. This replaces the current list - - "artist:", "album:", "title:" restrict search to related fields + - "random:" adds a single track randomly chosen from current filter - Add history of recently played songs - Implement callback to play through shown items instead of having the path saved in the template From d55b548d806ddb130b85e0e127b074b00b9b284d Mon Sep 17 00:00:00 2001 From: codezapper Date: Thu, 26 Jan 2017 17:56:36 +0100 Subject: [PATCH 03/77] More cleanup --- PyLister/lister/data_utils.py | 1 - PyLister/lister/templating_utils.py | 19 +------------------ 2 files changed, 1 insertion(+), 19 deletions(-) diff --git a/PyLister/lister/data_utils.py b/PyLister/lister/data_utils.py index bf85631..8c5351a 100644 --- a/PyLister/lister/data_utils.py +++ b/PyLister/lister/data_utils.py @@ -19,7 +19,6 @@ def data_for_songs_list(request, search_string=''): search_filters = get_search_filters(search_string) search_words = [word for word in search_string.split() if ':' not in word] - cursor = connection.cursor() results_lookup = {} songs_list = [] diff --git a/PyLister/lister/templating_utils.py b/PyLister/lister/templating_utils.py index 9a5959c..4b69a60 100755 --- a/PyLister/lister/templating_utils.py +++ b/PyLister/lister/templating_utils.py @@ -1,11 +1,9 @@ -from django.db import connection from django.template import loader -import data_utils as du def render_wrapper(request): template = loader.get_template('lister/wrapper.html') - context = {'counters': get_counters()} + context = {} return template.render(context, request) @@ -14,18 +12,3 @@ def render_for_songs_list(request, album='', artist='', year=''): template = loader.get_template('lister/songs.html') context = {} return template.render(context, request) - - -def get_counters(): - counters = {} - cursor = connection.cursor() - cursor.execute('''SELECT count(*) FROM lister_song''') - counters['songs'] = cursor.fetchone()[0] - cursor.execute('''SELECT count(*) FROM lister_album''') - counters['albums'] = cursor.fetchone()[0] - cursor.execute('''SELECT count(*) FROM lister_artist''') - counters['artists'] = cursor.fetchone()[0] - cursor.execute('''SELECT count(distinct year) FROM lister_song''') - counters['years'] = cursor.fetchone()[0] - - return counters From 4ed3c4a5d8586f53591d1cba582a9ab2559fd641 Mon Sep 17 00:00:00 2001 From: codezapper Date: Fri, 27 Jan 2017 08:00:06 +0100 Subject: [PATCH 04/77] Added client-side duplicates filter --- PyLister/lister/static/lister/main.js | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/PyLister/lister/static/lister/main.js b/PyLister/lister/static/lister/main.js index c9b50f4..04e385f 100755 --- a/PyLister/lister/static/lister/main.js +++ b/PyLister/lister/static/lister/main.js @@ -21,7 +21,7 @@ var duration = -1; var playListTemplate; var prevSearchTerm; var currentSearchTerm; -var hasSubmitted = false; +var displayedSongIDs = {}; var trackListOperations = { REPLACE: 1, @@ -99,9 +99,15 @@ function setCurrentTrackList(searchTerm, searchResults, operation = trackListOpe trackList = searchResults; playTrack(0); } else if (operation === trackListOperations.PREPEND) { - trackList = searchResults.concat(trackList); + filteredSearchResults = searchResults.filter(function(song) { + return displayedSongIDs[song.song_id] != null; + }); + trackList = filteredSearchResults.concat(trackList); } else { - trackList = trackList.concat(searchResults); + filteredSearchResults = searchResults.filter(function(song) { + return displayedSongIDs[song.song_id] != null; + }); + trackList = trackList.concat(filteredSearchResults); } //TODO: This can be optimized to only render the new data and append it var html = Mustache.render(playListTemplate, {"playlist": trackList}); @@ -129,7 +135,6 @@ function bindUI() { playerElement.load(); finderBox.bind('keyup', function(event) { if (event.key != "Enter") { - hasSubmitted = false; if (inputBox.val() !== '') { showSongs(inputBox.val()); } else { @@ -143,7 +148,6 @@ function bindUI() { } else { if (searchResults.length > 0) { if (prevSearchTerm !== currentSearchTerm) { - hasSubmitted = true; inputBox.val(''); if (event.ctrlKey) { setCurrentTrackList(currentSearchTerm, searchResults, trackListOperations.REPLACE); From cb1c49c6cc2d6ddadd5d32c41540392b657cc31b Mon Sep 17 00:00:00 2001 From: codezapper Date: Fri, 27 Jan 2017 15:44:43 +0100 Subject: [PATCH 05/77] Fixed duplicates removal client-side --- PyLister/lister/static/lister/main.js | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/PyLister/lister/static/lister/main.js b/PyLister/lister/static/lister/main.js index 04e385f..04e13f1 100755 --- a/PyLister/lister/static/lister/main.js +++ b/PyLister/lister/static/lister/main.js @@ -100,12 +100,20 @@ function setCurrentTrackList(searchTerm, searchResults, operation = trackListOpe playTrack(0); } else if (operation === trackListOperations.PREPEND) { filteredSearchResults = searchResults.filter(function(song) { - return displayedSongIDs[song.song_id] != null; + if (displayedSongIDs[song.song_id] == null) { + displayedSongIDs[song.song_id] = 1; + return true; + } + return false; }); trackList = filteredSearchResults.concat(trackList); } else { filteredSearchResults = searchResults.filter(function(song) { - return displayedSongIDs[song.song_id] != null; + if (displayedSongIDs[song.song_id] == null) { + displayedSongIDs[song.song_id] = 1; + return true; + } + return false; }); trackList = trackList.concat(filteredSearchResults); } @@ -148,7 +156,6 @@ function bindUI() { } else { if (searchResults.length > 0) { if (prevSearchTerm !== currentSearchTerm) { - inputBox.val(''); if (event.ctrlKey) { setCurrentTrackList(currentSearchTerm, searchResults, trackListOperations.REPLACE); } else if (event.shiftKey) { @@ -160,6 +167,7 @@ function bindUI() { if (playerElement.paused || !playerElement.currentTime) { playTrack(currentTrack); } + inputBox.val(''); } } }); From e8a56bc33ac4f9e2d8f56c13f2ef7f860f49b1c0 Mon Sep 17 00:00:00 2001 From: codezapper Date: Fri, 27 Jan 2017 23:36:50 +0100 Subject: [PATCH 06/77] Added "random" filter --- PyLister/TODO.txt | 2 -- PyLister/lister/data_utils.py | 37 +++++++++++++++++++++++++---------- 2 files changed, 27 insertions(+), 12 deletions(-) diff --git a/PyLister/TODO.txt b/PyLister/TODO.txt index 0f2bc37..6c600b9 100755 --- a/PyLister/TODO.txt +++ b/PyLister/TODO.txt @@ -2,10 +2,8 @@ - Cleanup python code - Fix sorting when mixing filters and search words -- Remove duplicates also on client side - Fix playing when not submitted (e.g. when clicking with the mouse before pressing enter) - Add prefixes: - "repeat:" adds results and repeats them. This replaces the current list - - "random:" adds a single track randomly chosen from current filter - Add history of recently played songs - Implement callback to play through shown items instead of having the path saved in the template diff --git a/PyLister/lister/data_utils.py b/PyLister/lister/data_utils.py index 8c5351a..065931d 100644 --- a/PyLister/lister/data_utils.py +++ b/PyLister/lister/data_utils.py @@ -12,6 +12,21 @@ sorting_fields = ['artist', 'album', 'track_number'] +def get_single_random(songs_list): + return [random.choice(songs_list)] + + +def get_shuffled_list(songs_list): + random.shuffle(songs_list) + return songs_list + + +do_something = { + 'random': get_single_random, + 'shuffle': get_shuffled_list +} + + def data_for_songs_list(request, search_string=''): if (search_string == ''): return JsonResponse({}) @@ -23,15 +38,17 @@ def data_for_songs_list(request, search_string=''): songs_list = [] if (len(search_filters) > 0): - (queries, params, must_shuffle) = get_filters_queries(search_filters) + (queries, params, filter_actions) = get_filters_queries(search_filters) query_index = 0 for query in queries: results = get_rows_as_dict( query, params[query_index], results_lookup) - if (must_shuffle[query_index]): - songs_list.extend(random.shuffle(results)) - else: - songs_list.extend(results) + if (len(results) > 0): + if (filter_actions[query_index]): + songs_list.extend( + do_something[filter_actions[query_index]](results)) + else: + songs_list.extend(results) query_index += 1 if (len(search_words) > 0): @@ -74,13 +91,13 @@ def get_search_filters(search_string): def get_filters_queries(search_filters): global inner_sql single_queries = [] - must_shuffle = [] + filter_actions = [] for search_filter in search_filters: - if (search_filter[0] == 'shuffle'): + if (search_filter[0] in do_something.keys()): + filter_actions.append(search_filter[0]) search_filter.pop(0) - must_shuffle.append(True) else: - must_shuffle.append(False) + filter_actions.append(None) query_strings = [inner_sql] * len(search_filter) single_queries.append('(' + ' AND '.join(query_strings) + ') ') @@ -103,7 +120,7 @@ def get_filters_queries(search_filters): search_params.extend(['%' + filter_term + '%'] * 3) ret_search_params.append(search_params) - return (single_statements, ret_search_params, must_shuffle) + return (single_statements, ret_search_params, filter_actions) def get_word_query_sql(search_words): From 06e1f3ef795c6b811f8c4a982f703e87fe50257b Mon Sep 17 00:00:00 2001 From: codezapper Date: Fri, 27 Jan 2017 23:51:57 +0100 Subject: [PATCH 07/77] Fixed highlighting active track --- PyLister/lister/static/lister/main.js | 2 +- PyLister/lister/templates/lister/songs.html | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/PyLister/lister/static/lister/main.js b/PyLister/lister/static/lister/main.js index 04e13f1..17efbe9 100755 --- a/PyLister/lister/static/lister/main.js +++ b/PyLister/lister/static/lister/main.js @@ -150,7 +150,7 @@ function bindUI() { $('#playlist').css({display: 'block'}); if (!playerElement.paused || playerElement.currentTime) { - $('[data-index-playlist=' + currentTrack + ']').closest('ul').addClass('active-track'); + $('[data-index-playlist=' + trackList[currentTrack].song_id + ']').closest('ul').addClass('active-track'); } } } else { diff --git a/PyLister/lister/templates/lister/songs.html b/PyLister/lister/templates/lister/songs.html index c25f12b..f185e0c 100644 --- a/PyLister/lister/templates/lister/songs.html +++ b/PyLister/lister/templates/lister/songs.html @@ -13,7 +13,7 @@ {% verbatim %}{{#search_results}}