1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
|
package com.smartdevicelink.managers.screen.menu;
import java.util.ArrayList;
import java.util.List;
class DynamicMenuUpdateAlgorithm {
// Cell state that tells the menu manager what it should do with a given MenuCell
enum MenuCellState {
DELETE, // Marks the cell to be deleted
ADD, // Marks the cell to be added
KEEP // Marks the cell to be kept
}
static DynamicMenuUpdateRunScore compatibilityRunScoreWithOldMenuCells(List<MenuCell> oldMenuCells, List<MenuCell> updatedMenuCells) {
return new DynamicMenuUpdateRunScore(buildAllDeleteStatusesForMenu(oldMenuCells), buildAllAddStatusesForMenu(updatedMenuCells), updatedMenuCells.size());
}
static DynamicMenuUpdateRunScore dynamicRunScoreOldMenuCells(List<MenuCell> oldMenuCells, List<MenuCell> updatedMenuCells) {
if (!oldMenuCells.isEmpty() && updatedMenuCells.isEmpty()) {
// Deleting all cells
return new DynamicMenuUpdateRunScore(buildAllDeleteStatusesForMenu(oldMenuCells), new ArrayList<MenuCellState>(), 0);
} else if (oldMenuCells.isEmpty() && !updatedMenuCells.isEmpty()) {
// No cells to delete
return new DynamicMenuUpdateRunScore(new ArrayList<MenuCellState>(), buildAllAddStatusesForMenu(updatedMenuCells), updatedMenuCells.size());
} else if (oldMenuCells.isEmpty() && updatedMenuCells.isEmpty()) {
// Empty menu to empty menu
return new DynamicMenuUpdateRunScore(new ArrayList<MenuCellState>(), new ArrayList<MenuCellState>(), 0);
}
return startCompareAtRun(0, oldMenuCells, updatedMenuCells);
}
private static DynamicMenuUpdateRunScore startCompareAtRun(int startRun, List<MenuCell> oldMenuCells, List<MenuCell> updatedMenuCells) {
DynamicMenuUpdateRunScore bestScore = new DynamicMenuUpdateRunScore(new ArrayList<MenuCellState>(), new ArrayList<MenuCellState>(), 0);
for (int run = startRun; run < oldMenuCells.size(); run++) {
// Set the menu status as a 1-1 list, start off will oldMenus = all Deletes, newMenu = all Adds
List<MenuCellState> oldMenuStatus = buildAllDeleteStatusesForMenu(oldMenuCells);
List<MenuCellState> newMenuStatus = buildAllAddStatusesForMenu(updatedMenuCells);
int startIndex = 0;
for (int oldCellIndex = run; oldCellIndex < oldMenuCells.size(); oldCellIndex++) {
// For each old item, create inner loop to compare old cells to new cells to find a match
// if a match if found we mark the index at match for both the old and the new status to
// keep since we do not want to send RPCs for those cases
for (int newCellIndex = startIndex; newCellIndex < updatedMenuCells.size(); newCellIndex++) {
if (oldMenuCells.get(oldCellIndex).equalsWithUniqueTitle(updatedMenuCells.get(newCellIndex))) {
oldMenuStatus.set(oldCellIndex, MenuCellState.KEEP);
newMenuStatus.set(newCellIndex, MenuCellState.KEEP);
startIndex = newCellIndex + 1;
break;
}
}
}
// Add RPC are the biggest operation so we need to find the run with the least amount of Adds.
// We will reset the run we use each time a runScore is less than the current score.
int numberOfAdds = 0;
for (int status = 0; status < newMenuStatus.size(); status++) {
if (newMenuStatus.get(status).equals(MenuCellState.ADD)) {
numberOfAdds++;
}
}
// As soon as we a run that requires 0 Adds we will use it since we cant do better then 0
if (numberOfAdds == 0) {
bestScore = new DynamicMenuUpdateRunScore(oldMenuStatus, newMenuStatus, numberOfAdds);
return bestScore;
}
// if we haven't create the bestScore object or if the current score beats the old score then we will create a new bestScore
if (bestScore.isEmpty() || numberOfAdds < bestScore.getScore()) {
bestScore = new DynamicMenuUpdateRunScore(oldMenuStatus, newMenuStatus, numberOfAdds);
}
}
return bestScore;
}
/**
* Builds a 1-1 list of Deletes for every element in the array
* @param oldMenu The old menu list
*/
static List<MenuCellState> buildAllDeleteStatusesForMenu (List<MenuCell> oldMenu){
List<MenuCellState> oldMenuStatus = new ArrayList<>(oldMenu.size());
for (int index = 0; index < oldMenu.size(); index++) {
oldMenuStatus.add(MenuCellState.DELETE);
}
return oldMenuStatus;
}
/**
* Builds a 1-1 list of Adds for every element in the list
* @param newMenu The new menu list
*/
static List<MenuCellState> buildAllAddStatusesForMenu (List<MenuCell> newMenu){
List<MenuCellState> newMenuStatus = new ArrayList<>(newMenu.size());
for (int index = 0; index < newMenu.size(); index++) {
newMenuStatus.add(MenuCellState.ADD);
}
return newMenuStatus;
}
}
|