From 270a541a7c98e975d6c848fce9ee232b6620432b Mon Sep 17 00:00:00 2001 From: GGAutomaton <32899400+GGAutomaton@users.noreply.github.com> Date: Wed, 13 Apr 2022 22:46:24 +0800 Subject: [PATCH] Implement algorithm to merge playlists --- .../database/playlist/PlaylistLocalItem.java | 58 ++++++++++++++++--- .../playlist/PlaylistMetadataEntry.java | 5 ++ .../playlist/model/PlaylistRemoteEntity.java | 1 + 3 files changed, 57 insertions(+), 7 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/database/playlist/PlaylistLocalItem.java b/app/src/main/java/org/schabi/newpipe/database/playlist/PlaylistLocalItem.java index bc17c51c4..ae81ce3f5 100644 --- a/app/src/main/java/org/schabi/newpipe/database/playlist/PlaylistLocalItem.java +++ b/app/src/main/java/org/schabi/newpipe/database/playlist/PlaylistLocalItem.java @@ -11,18 +11,62 @@ import java.util.List; public interface PlaylistLocalItem extends LocalItem { String getOrderingName(); + long getDisplayIndex(); + static List merge( final List localPlaylists, final List remotePlaylists) { - // todo: merge algorithm - final List items = new ArrayList<>( + + // Merge localPlaylists and remotePlaylists by displayIndex. + // If two items have the same displayIndex, sort them in CASE_INSENSITIVE_ORDER. + // This algorithm is similar to the merge operation in merge sort. + + final List result = new ArrayList<>( localPlaylists.size() + remotePlaylists.size()); - items.addAll(localPlaylists); - items.addAll(remotePlaylists); + final List itemsWithSameIndex = new ArrayList<>(); + int i = 0; + int j = 0; + while (i < localPlaylists.size()) { + while (j < remotePlaylists.size()) { + if (remotePlaylists.get(j).getDisplayIndex() + <= localPlaylists.get(i).getDisplayIndex()) { + addItem(result, remotePlaylists.get(j), itemsWithSameIndex); + j++; + } else { + break; + } + } + addItem(result, localPlaylists.get(i), itemsWithSameIndex); + i++; + } + addItemsWithSameIndex(result, itemsWithSameIndex); - Collections.sort(items, Comparator.comparing(PlaylistLocalItem::getOrderingName, - Comparator.nullsLast(String.CASE_INSENSITIVE_ORDER))); + // If displayIndex does not match actual index, update displayIndex. + // This may happen when a new list is created with default displayIndex = 0. + // todo: update displayIndex - return items; + return result; + } + + static void addItem(final List result, final PlaylistLocalItem item, + final List itemsWithSameIndex) { + if (!itemsWithSameIndex.isEmpty() + && itemsWithSameIndex.get(0).getDisplayIndex() != item.getDisplayIndex()) { + // The new item has a different displayIndex, + // add previous items with same index to the result. + addItemsWithSameIndex(result, itemsWithSameIndex); + itemsWithSameIndex.clear(); + } + itemsWithSameIndex.add(item); + } + + static void addItemsWithSameIndex(final List result, + final List itemsWithSameIndex) { + if (itemsWithSameIndex.size() > 1) { + Collections.sort(itemsWithSameIndex, + Comparator.comparing(PlaylistLocalItem::getOrderingName, + Comparator.nullsLast(String.CASE_INSENSITIVE_ORDER))); + } + result.addAll(itemsWithSameIndex); } } diff --git a/app/src/main/java/org/schabi/newpipe/database/playlist/PlaylistMetadataEntry.java b/app/src/main/java/org/schabi/newpipe/database/playlist/PlaylistMetadataEntry.java index 29bad45dc..f54ffff13 100644 --- a/app/src/main/java/org/schabi/newpipe/database/playlist/PlaylistMetadataEntry.java +++ b/app/src/main/java/org/schabi/newpipe/database/playlist/PlaylistMetadataEntry.java @@ -39,4 +39,9 @@ public class PlaylistMetadataEntry implements PlaylistLocalItem { public String getOrderingName() { return name; } + + @Override + public long getDisplayIndex() { + return displayIndex; + } } diff --git a/app/src/main/java/org/schabi/newpipe/database/playlist/model/PlaylistRemoteEntity.java b/app/src/main/java/org/schabi/newpipe/database/playlist/model/PlaylistRemoteEntity.java index 1fddfa732..454526769 100644 --- a/app/src/main/java/org/schabi/newpipe/database/playlist/model/PlaylistRemoteEntity.java +++ b/app/src/main/java/org/schabi/newpipe/database/playlist/model/PlaylistRemoteEntity.java @@ -153,6 +153,7 @@ public class PlaylistRemoteEntity implements PlaylistLocalItem { this.uploader = uploader; } + @Override public long getDisplayIndex() { return displayIndex; }