Commit 5f12b065 by aquilescanta Committed by Oliver Woodman

Support removal of ranges from ShuffleOrders

This allows more efficient range removals and is consistent with addition,
which supports adding multiple elements in a single operation.

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=222396310
parent 265462bc
...@@ -570,9 +570,7 @@ public class ConcatenatingMediaSource extends CompositeMediaSource<MediaSourceHo ...@@ -570,9 +570,7 @@ public class ConcatenatingMediaSource extends CompositeMediaSource<MediaSourceHo
if (fromIndex == 0 && toIndex == shuffleOrder.getLength()) { if (fromIndex == 0 && toIndex == shuffleOrder.getLength()) {
shuffleOrder = shuffleOrder.cloneAndClear(); shuffleOrder = shuffleOrder.cloneAndClear();
} else { } else {
for (int index = toIndex - 1; index >= fromIndex; index--) { shuffleOrder = shuffleOrder.cloneAndRemove(fromIndex, toIndex);
shuffleOrder = shuffleOrder.cloneAndRemove(index);
}
} }
for (int index = toIndex - 1; index >= fromIndex; index--) { for (int index = toIndex - 1; index >= fromIndex; index--) {
removeMediaSourceInternal(index); removeMediaSourceInternal(index);
...@@ -581,7 +579,7 @@ public class ConcatenatingMediaSource extends CompositeMediaSource<MediaSourceHo ...@@ -581,7 +579,7 @@ public class ConcatenatingMediaSource extends CompositeMediaSource<MediaSourceHo
break; break;
case MSG_MOVE: case MSG_MOVE:
MessageData<Integer> moveMessage = (MessageData<Integer>) Util.castNonNull(message); MessageData<Integer> moveMessage = (MessageData<Integer>) Util.castNonNull(message);
shuffleOrder = shuffleOrder.cloneAndRemove(moveMessage.index); shuffleOrder = shuffleOrder.cloneAndRemove(moveMessage.index, moveMessage.index + 1);
shuffleOrder = shuffleOrder.cloneAndInsert(moveMessage.customData, 1); shuffleOrder = shuffleOrder.cloneAndInsert(moveMessage.customData, 1);
moveMediaSourceInternal(moveMessage.index, moveMessage.customData); moveMediaSourceInternal(moveMessage.index, moveMessage.customData);
scheduleListenerNotification(moveMessage.actionOnCompletion); scheduleListenerNotification(moveMessage.actionOnCompletion);
......
...@@ -135,15 +135,16 @@ public interface ShuffleOrder { ...@@ -135,15 +135,16 @@ public interface ShuffleOrder {
} }
@Override @Override
public ShuffleOrder cloneAndRemove(int removalIndex) { public ShuffleOrder cloneAndRemove(int indexFrom, int indexToExclusive) {
int[] newShuffled = new int[shuffled.length - 1]; int numberOfElementsToRemove = indexToExclusive - indexFrom;
boolean foundRemovedElement = false; int[] newShuffled = new int[shuffled.length - numberOfElementsToRemove];
int foundElementsCount = 0;
for (int i = 0; i < shuffled.length; i++) { for (int i = 0; i < shuffled.length; i++) {
if (shuffled[i] == removalIndex) { if (shuffled[i] >= indexFrom && shuffled[i] < indexToExclusive) {
foundRemovedElement = true; foundElementsCount++;
} else { } else {
newShuffled[foundRemovedElement ? i - 1 : i] = shuffled[i] > removalIndex newShuffled[i - foundElementsCount] =
? shuffled[i] - 1 : shuffled[i]; shuffled[i] >= indexFrom ? shuffled[i] - numberOfElementsToRemove : shuffled[i];
} }
} }
return new DefaultShuffleOrder(newShuffled, new Random(random.nextLong())); return new DefaultShuffleOrder(newShuffled, new Random(random.nextLong()));
...@@ -213,8 +214,8 @@ public interface ShuffleOrder { ...@@ -213,8 +214,8 @@ public interface ShuffleOrder {
} }
@Override @Override
public ShuffleOrder cloneAndRemove(int removalIndex) { public ShuffleOrder cloneAndRemove(int indexFrom, int indexToExclusive) {
return new UnshuffledShuffleOrder(length - 1); return new UnshuffledShuffleOrder(length - indexToExclusive + indexFrom);
} }
@Override @Override
...@@ -268,12 +269,14 @@ public interface ShuffleOrder { ...@@ -268,12 +269,14 @@ public interface ShuffleOrder {
ShuffleOrder cloneAndInsert(int insertionIndex, int insertionCount); ShuffleOrder cloneAndInsert(int insertionIndex, int insertionCount);
/** /**
* Returns a copy of the shuffle order with one element removed. * Returns a copy of the shuffle order with a range of elements removed.
* *
* @param removalIndex The index of the element in the unshuffled order which is to be removed. * @param indexFrom The starting index in the unshuffled order of the range to remove.
* @return A copy of this {@link ShuffleOrder} without the removed element. * @param indexToExclusive The smallest index (must be greater or equal to {@code indexFrom}) that
* will not be removed.
* @return A copy of this {@link ShuffleOrder} without the elements in the removed range.
*/ */
ShuffleOrder cloneAndRemove(int removalIndex); ShuffleOrder cloneAndRemove(int indexFrom, int indexToExclusive);
/** Returns a copy of the shuffle order with all elements removed. */ /** Returns a copy of the shuffle order with all elements removed. */
ShuffleOrder cloneAndClear(); ShuffleOrder cloneAndClear();
......
...@@ -45,10 +45,32 @@ public final class ShuffleOrderTest { ...@@ -45,10 +45,32 @@ public final class ShuffleOrderTest {
testCloneAndInsert(new DefaultShuffleOrder(initialLength, RANDOM_SEED), insertionPoint, 5); testCloneAndInsert(new DefaultShuffleOrder(initialLength, RANDOM_SEED), insertionPoint, 5);
} }
} }
testCloneAndRemove(new DefaultShuffleOrder(5, RANDOM_SEED), 0); testCloneAndRemove(new DefaultShuffleOrder(5, RANDOM_SEED), 0, 1);
testCloneAndRemove(new DefaultShuffleOrder(5, RANDOM_SEED), 2); testCloneAndRemove(new DefaultShuffleOrder(5, RANDOM_SEED), 2, 3);
testCloneAndRemove(new DefaultShuffleOrder(5, RANDOM_SEED), 4); testCloneAndRemove(new DefaultShuffleOrder(5, RANDOM_SEED), 4, 5);
testCloneAndRemove(new DefaultShuffleOrder(1, RANDOM_SEED), 0); testCloneAndRemove(new DefaultShuffleOrder(1, RANDOM_SEED), 0, 1);
testCloneAndRemove(new DefaultShuffleOrder(1000, RANDOM_SEED), 0, 1000);
testCloneAndRemove(new DefaultShuffleOrder(1000, RANDOM_SEED), 0, 999);
testCloneAndRemove(new DefaultShuffleOrder(1000, RANDOM_SEED), 0, 500);
testCloneAndRemove(new DefaultShuffleOrder(1000, RANDOM_SEED), 100, 600);
testCloneAndRemove(new DefaultShuffleOrder(1000, RANDOM_SEED), 500, 1000);
}
@Test
public void testDefaultShuffleOrderSideloaded() {
int[] shuffledIndices = new int[] {2, 1, 0, 4, 3};
ShuffleOrder shuffleOrder = new DefaultShuffleOrder(shuffledIndices, RANDOM_SEED);
assertThat(shuffleOrder.getFirstIndex()).isEqualTo(2);
assertThat(shuffleOrder.getLastIndex()).isEqualTo(3);
for (int i = 0; i < 4; i++) {
assertThat(shuffleOrder.getNextIndex(shuffledIndices[i])).isEqualTo(shuffledIndices[i + 1]);
}
assertThat(shuffleOrder.getNextIndex(3)).isEqualTo(C.INDEX_UNSET);
for (int i = 4; i > 0; i--) {
assertThat(shuffleOrder.getPreviousIndex(shuffledIndices[i]))
.isEqualTo(shuffledIndices[i - 1]);
}
assertThat(shuffleOrder.getPreviousIndex(2)).isEqualTo(C.INDEX_UNSET);
} }
@Test @Test
...@@ -63,10 +85,15 @@ public final class ShuffleOrderTest { ...@@ -63,10 +85,15 @@ public final class ShuffleOrderTest {
testCloneAndInsert(new UnshuffledShuffleOrder(initialLength), insertionPoint, 5); testCloneAndInsert(new UnshuffledShuffleOrder(initialLength), insertionPoint, 5);
} }
} }
testCloneAndRemove(new UnshuffledShuffleOrder(5), 0); testCloneAndRemove(new UnshuffledShuffleOrder(5), 0, 1);
testCloneAndRemove(new UnshuffledShuffleOrder(5), 2); testCloneAndRemove(new UnshuffledShuffleOrder(5), 2, 3);
testCloneAndRemove(new UnshuffledShuffleOrder(5), 4); testCloneAndRemove(new UnshuffledShuffleOrder(5), 4, 5);
testCloneAndRemove(new UnshuffledShuffleOrder(1), 0); testCloneAndRemove(new UnshuffledShuffleOrder(1), 0, 1);
testCloneAndRemove(new UnshuffledShuffleOrder(1000), 0, 1000);
testCloneAndRemove(new UnshuffledShuffleOrder(1000), 0, 999);
testCloneAndRemove(new UnshuffledShuffleOrder(1000), 0, 500);
testCloneAndRemove(new UnshuffledShuffleOrder(1000), 100, 600);
testCloneAndRemove(new UnshuffledShuffleOrder(1000), 500, 1000);
} }
@Test @Test
...@@ -79,23 +106,6 @@ public final class ShuffleOrderTest { ...@@ -79,23 +106,6 @@ public final class ShuffleOrderTest {
} }
} }
@Test
public void testSideloadedShuffleOrder() {
int[] shuffledIndices = new int[] {2, 1, 0, 4, 3};
ShuffleOrder shuffleOrder = new DefaultShuffleOrder(shuffledIndices, RANDOM_SEED);
assertThat(shuffleOrder.getFirstIndex()).isEqualTo(2);
assertThat(shuffleOrder.getLastIndex()).isEqualTo(3);
for (int i = 0; i < 4; i++) {
assertThat(shuffleOrder.getNextIndex(shuffledIndices[i])).isEqualTo(shuffledIndices[i + 1]);
}
assertThat(shuffleOrder.getNextIndex(3)).isEqualTo(C.INDEX_UNSET);
for (int i = 4; i > 0; i--) {
assertThat(shuffleOrder.getPreviousIndex(shuffledIndices[i]))
.isEqualTo(shuffledIndices[i - 1]);
}
assertThat(shuffleOrder.getPreviousIndex(2)).isEqualTo(C.INDEX_UNSET);
}
private static void assertShuffleOrderCorrectness(ShuffleOrder shuffleOrder, int length) { private static void assertShuffleOrderCorrectness(ShuffleOrder shuffleOrder, int length) {
assertThat(shuffleOrder.getLength()).isEqualTo(length); assertThat(shuffleOrder.getLength()).isEqualTo(length);
if (length == 0) { if (length == 0) {
...@@ -137,22 +147,24 @@ public final class ShuffleOrderTest { ...@@ -137,22 +147,24 @@ public final class ShuffleOrderTest {
} }
} }
private static void testCloneAndRemove(ShuffleOrder shuffleOrder, int position) { private static void testCloneAndRemove(
ShuffleOrder newOrder = shuffleOrder.cloneAndRemove(position); ShuffleOrder shuffleOrder, int indexFrom, int indexToExclusive) {
assertShuffleOrderCorrectness(newOrder, shuffleOrder.getLength() - 1); int numberOfElementsToRemove = indexToExclusive - indexFrom;
ShuffleOrder newOrder = shuffleOrder.cloneAndRemove(indexFrom, indexToExclusive);
assertShuffleOrderCorrectness(newOrder, shuffleOrder.getLength() - numberOfElementsToRemove);
// Assert all elements still have the relative same order // Assert all elements still have the relative same order
for (int i = 0; i < shuffleOrder.getLength(); i++) { for (int i = 0; i < shuffleOrder.getLength(); i++) {
if (i == position) { if (i >= indexFrom && i < indexToExclusive) {
continue; continue;
} }
int expectedNextIndex = shuffleOrder.getNextIndex(i); int expectedNextIndex = shuffleOrder.getNextIndex(i);
if (expectedNextIndex == position) { while (expectedNextIndex >= indexFrom && expectedNextIndex < indexToExclusive) {
expectedNextIndex = shuffleOrder.getNextIndex(expectedNextIndex); expectedNextIndex = shuffleOrder.getNextIndex(expectedNextIndex);
} }
if (expectedNextIndex != C.INDEX_UNSET && expectedNextIndex >= position) { if (expectedNextIndex != C.INDEX_UNSET && expectedNextIndex >= indexFrom) {
expectedNextIndex--; expectedNextIndex -= numberOfElementsToRemove;
} }
int newNextIndex = newOrder.getNextIndex(i < position ? i : i - 1); int newNextIndex = newOrder.getNextIndex(i < indexFrom ? i : i - numberOfElementsToRemove);
assertThat(newNextIndex).isEqualTo(expectedNextIndex); assertThat(newNextIndex).isEqualTo(expectedNextIndex);
} }
} }
......
...@@ -61,8 +61,8 @@ public final class FakeShuffleOrder implements ShuffleOrder { ...@@ -61,8 +61,8 @@ public final class FakeShuffleOrder implements ShuffleOrder {
} }
@Override @Override
public ShuffleOrder cloneAndRemove(int removalIndex) { public ShuffleOrder cloneAndRemove(int indexFrom, int indexToExclusive) {
return new FakeShuffleOrder(length - 1); return new FakeShuffleOrder(length - indexToExclusive + indexFrom);
} }
@Override @Override
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment