Fix linear forwards backwards
This commit is contained in:
@@ -15,6 +15,7 @@ import 'package:rimworld_modman/mod_list.dart';
|
|||||||
class ModListTroubleshooter {
|
class ModListTroubleshooter {
|
||||||
final ModList originalModList;
|
final ModList originalModList;
|
||||||
ModList currentModList;
|
ModList currentModList;
|
||||||
|
// These indices should ALWAYS represent the CURRENT selection of mods
|
||||||
int _startIndex = 0;
|
int _startIndex = 0;
|
||||||
int _endIndex = 0;
|
int _endIndex = 0;
|
||||||
|
|
||||||
@@ -48,20 +49,25 @@ class ModListTroubleshooter {
|
|||||||
return currentModList;
|
return currentModList;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If the current selection is not equal to our proposed step size
|
||||||
|
// We do not MOVE but instead just return the correct amount of mods from the start
|
||||||
ModList linearForward({int stepSize = 20}) {
|
ModList linearForward({int stepSize = 20}) {
|
||||||
final totalMods = originalModList.activeMods.length;
|
// If we are not "in step"
|
||||||
|
if (_endIndex - _startIndex == stepSize) {
|
||||||
if (_startIndex >= totalMods || _startIndex == _endIndex) {
|
// Move the indices forward by the step size, step forward
|
||||||
int newStart = totalMods - stepSize;
|
_startIndex += stepSize;
|
||||||
if (newStart < 0) {
|
_endIndex += stepSize;
|
||||||
newStart = 0;
|
} else {
|
||||||
|
// Correct the end index to be in step
|
||||||
|
_endIndex = _startIndex + stepSize;
|
||||||
}
|
}
|
||||||
_startIndex = newStart;
|
if (_endIndex > originalModList.activeMods.length) {
|
||||||
|
// If we are at the end of the list, move the start index such that we return
|
||||||
|
// At most the step size amount of mods
|
||||||
|
_endIndex = originalModList.activeMods.length;
|
||||||
|
_startIndex = (_endIndex - stepSize).clamp(0, _endIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
_startIndex = _startIndex.clamp(0, totalMods);
|
|
||||||
_endIndex = (_startIndex + stepSize).clamp(0, totalMods);
|
|
||||||
|
|
||||||
final subset = originalModList.activeMods.keys.toList().sublist(
|
final subset = originalModList.activeMods.keys.toList().sublist(
|
||||||
_startIndex,
|
_startIndex,
|
||||||
_endIndex,
|
_endIndex,
|
||||||
@@ -69,25 +75,21 @@ class ModListTroubleshooter {
|
|||||||
|
|
||||||
currentModList.disableAll();
|
currentModList.disableAll();
|
||||||
currentModList.enableMods(subset);
|
currentModList.enableMods(subset);
|
||||||
_startIndex = _endIndex;
|
|
||||||
|
|
||||||
return currentModList;
|
return currentModList;
|
||||||
}
|
}
|
||||||
|
|
||||||
ModList linearBackward({int stepSize = 20}) {
|
ModList linearBackward({int stepSize = 20}) {
|
||||||
final totalMods = originalModList.activeMods.length;
|
if (_endIndex - _startIndex == stepSize) {
|
||||||
|
_startIndex -= stepSize;
|
||||||
if (_endIndex <= 0 || _startIndex == _endIndex) {
|
_endIndex -= stepSize;
|
||||||
int newEnd = stepSize;
|
} else {
|
||||||
if (newEnd > totalMods) {
|
_startIndex = _endIndex - stepSize;
|
||||||
newEnd = totalMods;
|
|
||||||
}
|
}
|
||||||
_endIndex = newEnd;
|
if (_startIndex < 0) {
|
||||||
|
_startIndex = 0;
|
||||||
|
_endIndex = stepSize.clamp(0, originalModList.activeMods.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
_endIndex = _endIndex.clamp(0, totalMods);
|
|
||||||
_startIndex = (_endIndex - stepSize).clamp(0, _endIndex);
|
|
||||||
|
|
||||||
final subset = originalModList.activeMods.keys.toList().sublist(
|
final subset = originalModList.activeMods.keys.toList().sublist(
|
||||||
_startIndex,
|
_startIndex,
|
||||||
_endIndex,
|
_endIndex,
|
||||||
@@ -95,8 +97,6 @@ class ModListTroubleshooter {
|
|||||||
|
|
||||||
currentModList.disableAll();
|
currentModList.disableAll();
|
||||||
currentModList.enableMods(subset);
|
currentModList.enableMods(subset);
|
||||||
_endIndex = _startIndex;
|
|
||||||
|
|
||||||
return currentModList;
|
return currentModList;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -75,7 +75,7 @@ void main() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test(
|
test(
|
||||||
'Bisect search should end up with half the mods every forward iteration until 1',
|
'Should end up with half the mods every forward iteration until 1',
|
||||||
() {
|
() {
|
||||||
final troubleshooter = ModListTroubleshooter(modList);
|
final troubleshooter = ModListTroubleshooter(modList);
|
||||||
|
|
||||||
@@ -103,7 +103,7 @@ void main() {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
test(
|
test(
|
||||||
'Bisect search should end up with half the mods every backward iteration until 1',
|
'Should end up with half the mods every backward iteration until 1',
|
||||||
() {
|
() {
|
||||||
final troubleshooter = ModListTroubleshooter(modList);
|
final troubleshooter = ModListTroubleshooter(modList);
|
||||||
|
|
||||||
@@ -131,7 +131,7 @@ void main() {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
test(
|
test(
|
||||||
'Bisect search should end up with half the mods every iteration until 1',
|
'Should end up with half the mods every iteration until 1',
|
||||||
() {
|
() {
|
||||||
final troubleshooter = ModListTroubleshooter(modList);
|
final troubleshooter = ModListTroubleshooter(modList);
|
||||||
|
|
||||||
@@ -158,7 +158,7 @@ void main() {
|
|||||||
expect(result.activeMods.keys.last, equals('test.mod9'));
|
expect(result.activeMods.keys.last, equals('test.mod9'));
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
test('Bisect should handle abuse gracefully', () {
|
test('Should handle abuse gracefully', () {
|
||||||
final troubleshooter = ModListTroubleshooter(modList);
|
final troubleshooter = ModListTroubleshooter(modList);
|
||||||
|
|
||||||
var result = troubleshooter.binaryBackward();
|
var result = troubleshooter.binaryBackward();
|
||||||
@@ -225,7 +225,7 @@ void main() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test(
|
test(
|
||||||
'Linear search should end up with 10 mods every forward iteration',
|
'Should end up with 10 mods every forward iteration',
|
||||||
() {
|
() {
|
||||||
final troubleshooter = ModListTroubleshooter(modList);
|
final troubleshooter = ModListTroubleshooter(modList);
|
||||||
|
|
||||||
@@ -246,7 +246,7 @@ void main() {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
test(
|
test(
|
||||||
'Linear search should end up with 10 mods every backward iteration',
|
'Should end up with 10 mods every backward iteration',
|
||||||
() {
|
() {
|
||||||
final troubleshooter = ModListTroubleshooter(modList);
|
final troubleshooter = ModListTroubleshooter(modList);
|
||||||
|
|
||||||
@@ -266,7 +266,7 @@ void main() {
|
|||||||
expect(result.activeMods.keys.last, equals('test.mod9'));
|
expect(result.activeMods.keys.last, equals('test.mod9'));
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
test('Linear search should end up with 10 mods every iteration', () {
|
test('Should end up with 10 mods every iteration', () {
|
||||||
final troubleshooter = ModListTroubleshooter(modList);
|
final troubleshooter = ModListTroubleshooter(modList);
|
||||||
|
|
||||||
var result = troubleshooter.linearBackward(stepSize: 10);
|
var result = troubleshooter.linearBackward(stepSize: 10);
|
||||||
@@ -281,10 +281,10 @@ void main() {
|
|||||||
|
|
||||||
result = troubleshooter.linearBackward(stepSize: 10);
|
result = troubleshooter.linearBackward(stepSize: 10);
|
||||||
expect(result.activeMods.length, equals(10));
|
expect(result.activeMods.length, equals(10));
|
||||||
expect(result.activeMods.keys.first, equals('test.mod20'));
|
expect(result.activeMods.keys.first, equals('test.mod10'));
|
||||||
expect(result.activeMods.keys.last, equals('test.mod29'));
|
expect(result.activeMods.keys.last, equals('test.mod19'));
|
||||||
});
|
});
|
||||||
test('Linear search should handle abuse gracefully', () {
|
test('Should handle abuse gracefully', () {
|
||||||
final troubleshooter = ModListTroubleshooter(modList);
|
final troubleshooter = ModListTroubleshooter(modList);
|
||||||
|
|
||||||
var result = troubleshooter.linearBackward(stepSize: 10);
|
var result = troubleshooter.linearBackward(stepSize: 10);
|
||||||
@@ -302,7 +302,25 @@ void main() {
|
|||||||
result = troubleshooter.linearForward(stepSize: 10);
|
result = troubleshooter.linearForward(stepSize: 10);
|
||||||
expect(result.activeMods.length, equals(10));
|
expect(result.activeMods.length, equals(10));
|
||||||
});
|
});
|
||||||
test('Linear search cannot return more items than there are', () {
|
test('Should handle different step sizes', () {
|
||||||
|
final troubleshooter = ModListTroubleshooter(modList);
|
||||||
|
|
||||||
|
var result = troubleshooter.linearBackward(stepSize: 10);
|
||||||
|
expect(result.activeMods.length, equals(10));
|
||||||
|
|
||||||
|
result = troubleshooter.linearForward(stepSize: 10);
|
||||||
|
expect(result.activeMods.length, equals(10));
|
||||||
|
|
||||||
|
result = troubleshooter.linearBackward(stepSize: 10);
|
||||||
|
expect(result.activeMods.length, equals(10));
|
||||||
|
|
||||||
|
result = troubleshooter.linearForward(stepSize: 10);
|
||||||
|
expect(result.activeMods.length, equals(10));
|
||||||
|
|
||||||
|
result = troubleshooter.linearForward(stepSize: 10);
|
||||||
|
expect(result.activeMods.length, equals(10));
|
||||||
|
});
|
||||||
|
test('Cannot return more items than there are', () {
|
||||||
final troubleshooter = ModListTroubleshooter(modList);
|
final troubleshooter = ModListTroubleshooter(modList);
|
||||||
|
|
||||||
var result = troubleshooter.linearBackward(stepSize: 10000);
|
var result = troubleshooter.linearBackward(stepSize: 10000);
|
||||||
@@ -312,6 +330,63 @@ void main() {
|
|||||||
expect(result.activeMods.length, equals(30));
|
expect(result.activeMods.length, equals(30));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
group('Navigation tests', () {
|
||||||
|
late ModList modList = ModList();
|
||||||
|
setUp(() {
|
||||||
|
modList = ModList();
|
||||||
|
|
||||||
|
// Add some base mods
|
||||||
|
for (int i = 0; i < 20; i++) {
|
||||||
|
final modId = 'test.mod$i';
|
||||||
|
final mod = makeDummy().copyWith(name: 'Test Mod $i', id: modId);
|
||||||
|
modList.mods[modId] = mod;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add some mods with dependencies
|
||||||
|
for (int i = 20; i < 30; i++) {
|
||||||
|
final modId = 'test.mod$i';
|
||||||
|
final mod = makeDummy().copyWith(
|
||||||
|
name: 'Test Mod $i',
|
||||||
|
id: modId,
|
||||||
|
dependencies: ['test.mod${i - 20}'], // Depend on earlier mods
|
||||||
|
);
|
||||||
|
modList.mods[modId] = mod;
|
||||||
|
}
|
||||||
|
modList.enableAll();
|
||||||
|
});
|
||||||
|
|
||||||
|
test(
|
||||||
|
'Mixed navigation should work',
|
||||||
|
() {
|
||||||
|
final troubleshooter = ModListTroubleshooter(modList);
|
||||||
|
|
||||||
|
var result = troubleshooter.linearForward(stepSize: 10);
|
||||||
|
expect(result.activeMods.length, equals(10));
|
||||||
|
expect(result.activeMods.keys.first, equals('test.mod0'));
|
||||||
|
expect(result.activeMods.keys.last, equals('test.mod9'));
|
||||||
|
|
||||||
|
result = troubleshooter.binaryForward();
|
||||||
|
expect(result.activeMods.length, equals(5));
|
||||||
|
expect(result.activeMods.keys.first, equals('test.mod5'));
|
||||||
|
expect(result.activeMods.keys.last, equals('test.mod9'));
|
||||||
|
|
||||||
|
result = troubleshooter.linearBackward(stepSize: 10);
|
||||||
|
expect(result.activeMods.length, equals(10));
|
||||||
|
expect(result.activeMods.keys.first, equals('test.mod0'));
|
||||||
|
expect(result.activeMods.keys.last, equals('test.mod9'));
|
||||||
|
|
||||||
|
result = troubleshooter.binaryForward();
|
||||||
|
expect(result.activeMods.length, equals(5));
|
||||||
|
expect(result.activeMods.keys.first, equals('test.mod5'));
|
||||||
|
expect(result.activeMods.keys.last, equals('test.mod9'));
|
||||||
|
|
||||||
|
result = troubleshooter.linearForward(stepSize: 10);
|
||||||
|
expect(result.activeMods.length, equals(10));
|
||||||
|
expect(result.activeMods.keys.first, equals('test.mod5'));
|
||||||
|
expect(result.activeMods.keys.last, equals('test.mod14'));
|
||||||
|
},
|
||||||
|
);
|
||||||
|
});
|
||||||
group('Loading dependencies', () {
|
group('Loading dependencies', () {
|
||||||
late ModList modList = ModList();
|
late ModList modList = ModList();
|
||||||
setUp(() {
|
setUp(() {
|
||||||
@@ -336,7 +411,7 @@ void main() {
|
|||||||
modList.enableAll();
|
modList.enableAll();
|
||||||
});
|
});
|
||||||
// Not that it has any reason to since they're completely detached...
|
// Not that it has any reason to since they're completely detached...
|
||||||
test('Loading dependencies should not fuck up troubleshooter', () {
|
test('Should not fuck up troubleshooter', () {
|
||||||
final troubleshooter = ModListTroubleshooter(modList);
|
final troubleshooter = ModListTroubleshooter(modList);
|
||||||
final expectedFirst = [
|
final expectedFirst = [
|
||||||
'test.mod1',
|
'test.mod1',
|
||||||
|
Reference in New Issue
Block a user