Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(126)

Side by Side Diff: appengine/config_service/ui/bower_components/polymer/lib/utils/array-splice.html

Issue 2923973003: Added base template for config ui. (Closed)
Patch Set: Created 3 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 <!--
2 @license
3 Copyright (c) 2017 The Polymer Project Authors. All rights reserved.
4 This code may only be used under the BSD style license found at http://polymer.g ithub.io/LICENSE.txt
5 The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
6 The complete set of contributors may be found at http://polymer.github.io/CONTRI BUTORS.txt
7 Code distributed by Google as part of the polymer project is also
8 subject to an additional IP rights grant found at http://polymer.github.io/PATEN TS.txt
9 -->
10 <link rel="import" href="boot.html">
11 <script>
12 (function() {
13
14 'use strict';
15
16 function newSplice(index, removed, addedCount) {
17 return {
18 index: index,
19 removed: removed,
20 addedCount: addedCount
21 };
22 }
23
24 const EDIT_LEAVE = 0;
25 const EDIT_UPDATE = 1;
26 const EDIT_ADD = 2;
27 const EDIT_DELETE = 3;
28
29 const ArraySplice = {
30
31 // Note: This function is *based* on the computation of the Levenshtein
32 // "edit" distance. The one change is that "updates" are treated as two
33 // edits - not one. With Array splices, an update is really a delete
34 // followed by an add. By retaining this, we optimize for "keeping" the
35 // maximum array items in the original array. For example:
36 //
37 // 'xxxx123' -> '123yyyy'
38 //
39 // With 1-edit updates, the shortest path would be just to update all seven
40 // characters. With 2-edit updates, we delete 4, leave 3, and add 4. This
41 // leaves the substring '123' intact.
42 calcEditDistances(current, currentStart, currentEnd,
43 old, oldStart, oldEnd) {
44 // "Deletion" columns
45 let rowCount = oldEnd - oldStart + 1;
46 let columnCount = currentEnd - currentStart + 1;
47 let distances = new Array(rowCount);
48
49 // "Addition" rows. Initialize null column.
50 for (let i = 0; i < rowCount; i++) {
51 distances[i] = new Array(columnCount);
52 distances[i][0] = i;
53 }
54
55 // Initialize null row
56 for (let j = 0; j < columnCount; j++)
57 distances[0][j] = j;
58
59 for (let i = 1; i < rowCount; i++) {
60 for (let j = 1; j < columnCount; j++) {
61 if (this.equals(current[currentStart + j - 1], old[oldStart + i - 1]))
62 distances[i][j] = distances[i - 1][j - 1];
63 else {
64 let north = distances[i - 1][j] + 1;
65 let west = distances[i][j - 1] + 1;
66 distances[i][j] = north < west ? north : west;
67 }
68 }
69 }
70
71 return distances;
72 },
73
74 // This starts at the final weight, and walks "backward" by finding
75 // the minimum previous weight recursively until the origin of the weight
76 // matrix.
77 spliceOperationsFromEditDistances(distances) {
78 let i = distances.length - 1;
79 let j = distances[0].length - 1;
80 let current = distances[i][j];
81 let edits = [];
82 while (i > 0 || j > 0) {
83 if (i == 0) {
84 edits.push(EDIT_ADD);
85 j--;
86 continue;
87 }
88 if (j == 0) {
89 edits.push(EDIT_DELETE);
90 i--;
91 continue;
92 }
93 let northWest = distances[i - 1][j - 1];
94 let west = distances[i - 1][j];
95 let north = distances[i][j - 1];
96
97 let min;
98 if (west < north)
99 min = west < northWest ? west : northWest;
100 else
101 min = north < northWest ? north : northWest;
102
103 if (min == northWest) {
104 if (northWest == current) {
105 edits.push(EDIT_LEAVE);
106 } else {
107 edits.push(EDIT_UPDATE);
108 current = northWest;
109 }
110 i--;
111 j--;
112 } else if (min == west) {
113 edits.push(EDIT_DELETE);
114 i--;
115 current = west;
116 } else {
117 edits.push(EDIT_ADD);
118 j--;
119 current = north;
120 }
121 }
122
123 edits.reverse();
124 return edits;
125 },
126
127 /**
128 * Splice Projection functions:
129 *
130 * A splice map is a representation of how a previous array of items
131 * was transformed into a new array of items. Conceptually it is a list of
132 * tuples of
133 *
134 * <index, removed, addedCount>
135 *
136 * which are kept in ascending index order of. The tuple represents that at
137 * the |index|, |removed| sequence of items were removed, and counting forwa rd
138 * from |index|, |addedCount| items were added.
139 */
140
141 /**
142 * Lacking individual splice mutation information, the minimal set of
143 * splices can be synthesized given the previous state and final state of an
144 * array. The basic approach is to calculate the edit distance matrix and
145 * choose the shortest path through it.
146 *
147 * Complexity: O(l * p)
148 * l: The length of the current array
149 * p: The length of the old array
150 *
151 * @param {Array} current The current "changed" array for which to
152 * calculate splices.
153 * @param {number} currentStart Starting index in the `current` array for
154 * which splices are calculated.
155 * @param {number} currentEnd Ending index in the `current` array for
156 * which splices are calculated.
157 * @param {Array} old The original "unchanged" array to compare `current`
158 * against to determine splices.
159 * @param {number} oldStart Starting index in the `old` array for
160 * which splices are calculated.
161 * @param {number} oldEnd Ending index in the `old` array for
162 * which splices are calculated.
163 * @return {Array} Returns an array of splice record objects. Each of these
164 * contains: `index` the location where the splice occurred; `removed`
165 * the array of removed items from this location; `addedCount` the number
166 * of items added at this location.
167 */
168 calcSplices(current, currentStart, currentEnd,
169 old, oldStart, oldEnd) {
170 let prefixCount = 0;
171 let suffixCount = 0;
172 let splice;
173
174 let minLength = Math.min(currentEnd - currentStart, oldEnd - oldStart);
175 if (currentStart == 0 && oldStart == 0)
176 prefixCount = this.sharedPrefix(current, old, minLength);
177
178 if (currentEnd == current.length && oldEnd == old.length)
179 suffixCount = this.sharedSuffix(current, old, minLength - prefixCount);
180
181 currentStart += prefixCount;
182 oldStart += prefixCount;
183 currentEnd -= suffixCount;
184 oldEnd -= suffixCount;
185
186 if (currentEnd - currentStart == 0 && oldEnd - oldStart == 0)
187 return [];
188
189 if (currentStart == currentEnd) {
190 splice = newSplice(currentStart, [], 0);
191 while (oldStart < oldEnd)
192 splice.removed.push(old[oldStart++]);
193
194 return [ splice ];
195 } else if (oldStart == oldEnd)
196 return [ newSplice(currentStart, [], currentEnd - currentStart) ];
197
198 let ops = this.spliceOperationsFromEditDistances(
199 this.calcEditDistances(current, currentStart, currentEnd,
200 old, oldStart, oldEnd));
201
202 splice = undefined;
203 let splices = [];
204 let index = currentStart;
205 let oldIndex = oldStart;
206 for (let i = 0; i < ops.length; i++) {
207 switch(ops[i]) {
208 case EDIT_LEAVE:
209 if (splice) {
210 splices.push(splice);
211 splice = undefined;
212 }
213
214 index++;
215 oldIndex++;
216 break;
217 case EDIT_UPDATE:
218 if (!splice)
219 splice = newSplice(index, [], 0);
220
221 splice.addedCount++;
222 index++;
223
224 splice.removed.push(old[oldIndex]);
225 oldIndex++;
226 break;
227 case EDIT_ADD:
228 if (!splice)
229 splice = newSplice(index, [], 0);
230
231 splice.addedCount++;
232 index++;
233 break;
234 case EDIT_DELETE:
235 if (!splice)
236 splice = newSplice(index, [], 0);
237
238 splice.removed.push(old[oldIndex]);
239 oldIndex++;
240 break;
241 }
242 }
243
244 if (splice) {
245 splices.push(splice);
246 }
247 return splices;
248 },
249
250 sharedPrefix(current, old, searchLength) {
251 for (let i = 0; i < searchLength; i++)
252 if (!this.equals(current[i], old[i]))
253 return i;
254 return searchLength;
255 },
256
257 sharedSuffix(current, old, searchLength) {
258 let index1 = current.length;
259 let index2 = old.length;
260 let count = 0;
261 while (count < searchLength && this.equals(current[--index1], old[--index2 ]))
262 count++;
263
264 return count;
265 },
266
267 calculateSplices(current, previous) {
268 return this.calcSplices(current, 0, current.length, previous, 0,
269 previous.length);
270 },
271
272 equals(currentValue, previousValue) {
273 return currentValue === previousValue;
274 }
275
276 };
277
278 /**
279 * @namespace
280 * @memberof Polymer
281 * @summary Module that provides utilities for diffing arrays.
282 */
283 Polymer.ArraySplice = {
284 /**
285 * Returns an array of splice records indicating the minimum edits required
286 * to transform the `previous` array into the `current` array.
287 *
288 * Splice records are ordered by index and contain the following fields:
289 * - `index`: index where edit started
290 * - `removed`: array of removed items from this index
291 * - `addedCount`: number of items added at this index
292 *
293 * This function is based on the Levenshtein "minimum edit distance"
294 * algorithm. Note that updates are treated as removal followed by addition.
295 *
296 * The worst-case time complexity of this algorithm is `O(l * p)`
297 * l: The length of the current array
298 * p: The length of the previous array
299 *
300 * However, the worst-case complexity is reduced by an `O(n)` optimization
301 * to detect any shared prefix & suffix between the two arrays and only
302 * perform the more expensive minimum edit distance calculation over the
303 * non-shared portions of the arrays.
304 *
305 * @memberof Polymer.ArraySplice
306 * @param {Array} current The "changed" array for which splices will be
307 * calculated.
308 * @param {Array} previous The "unchanged" original array to compare
309 * `current` against to determine the splices.
310 * @return {Array} Returns an array of splice record objects. Each of these
311 * contains: `index` the location where the splice occurred; `removed`
312 * the array of removed items from this location; `addedCount` the number
313 * of items added at this location.
314 */
315 calculateSplices(current, previous) {
316 return ArraySplice.calculateSplices(current, previous);
317 }
318 }
319
320 })();
321 </script>
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698