mirror of
https://github.com/DeviceFarmer/stf.git
synced 2026-04-18 08:03:30 +02:00
Refactored all device list components to its own module.
This commit is contained in:
71
res/app/device-list/util/patch-array/index.js
Normal file
71
res/app/device-list/util/patch-array/index.js
Normal file
@@ -0,0 +1,71 @@
|
||||
function existenceMap(array) {
|
||||
var map = Object.create(null)
|
||||
for (var i = 0, l = array.length; i < l; ++i) {
|
||||
map[array[i]] = 1
|
||||
}
|
||||
return map
|
||||
}
|
||||
|
||||
// Returns a list of operations to transform array a into array b. May not
|
||||
// return the optimal set of operations.
|
||||
module.exports = function patchArray(a, b) {
|
||||
var ops = []
|
||||
|
||||
var workA = [].concat(a)
|
||||
, inA = Object.create(null)
|
||||
, itemA
|
||||
, cursorA
|
||||
|
||||
var inB = existenceMap(b)
|
||||
, posB = Object.create(null)
|
||||
, itemB
|
||||
, cursorB
|
||||
|
||||
// First, check what was removed from a.
|
||||
for (cursorA = 0; cursorA < workA.length;) {
|
||||
itemA = workA[cursorA]
|
||||
|
||||
// If b does not contain the item, surely it must have been removed.
|
||||
if (!inB[itemA]) {
|
||||
workA.splice(cursorA, 1)
|
||||
ops.push(['remove', cursorA])
|
||||
}
|
||||
// Otherwise, the item is still alive.
|
||||
else {
|
||||
inA[itemA] = true
|
||||
cursorA += 1
|
||||
}
|
||||
}
|
||||
|
||||
// Then, check what was inserted into b.
|
||||
for (cursorB = 0; cursorB < b.length; ++cursorB) {
|
||||
itemB = b[cursorB]
|
||||
|
||||
// If a does not contain the item, it must have been added.
|
||||
if (!inA[itemB]) {
|
||||
workA.splice(cursorB, 0, itemB)
|
||||
ops.push(['insert', cursorB, itemB])
|
||||
}
|
||||
|
||||
posB[itemB] = cursorB
|
||||
}
|
||||
|
||||
// At this point, workA contains the same items as b, but swaps may
|
||||
// be needed.
|
||||
for (cursorA = 0; cursorA < workA.length;) {
|
||||
itemA = workA[cursorA]
|
||||
var posInB = posB[itemA]
|
||||
|
||||
if (posInB === cursorA) {
|
||||
cursorA += 1
|
||||
}
|
||||
else {
|
||||
var temp = workA[posInB]
|
||||
workA[posInB] = itemA
|
||||
workA[cursorA] = temp
|
||||
ops.push(['swap', cursorA, posInB])
|
||||
}
|
||||
}
|
||||
|
||||
return ops
|
||||
}
|
||||
123
res/app/device-list/util/patch-array/patch-array-test.js
Normal file
123
res/app/device-list/util/patch-array/patch-array-test.js
Normal file
@@ -0,0 +1,123 @@
|
||||
var assert = require('assert')
|
||||
|
||||
var patchArray = require('./patch-array')
|
||||
|
||||
var tests = [
|
||||
{
|
||||
a: ['a', 'b', 'c', 'd', 'e']
|
||||
, b: ['a', 'e', 'c', 'd', 'b']
|
||||
, ops: [
|
||||
['swap', 4, 1]
|
||||
]
|
||||
}
|
||||
, {
|
||||
a: ['a', 'b', 'c', 'd', 'e']
|
||||
, b: ['e', 'd', 'c', 'b', 'a']
|
||||
, ops: [
|
||||
['swap', 4, 0]
|
||||
, ['swap', 3, 1]
|
||||
]
|
||||
}
|
||||
, {
|
||||
a: ['a', 'b', 'c', 'd', 'e', 'f']
|
||||
, b: ['f', 'e', 'd', 'c', 'b', 'a']
|
||||
, ops: [
|
||||
['swap', 5, 0]
|
||||
, ['swap', 4, 1]
|
||||
, ['swap', 3, 2]
|
||||
]
|
||||
}
|
||||
, {
|
||||
a: ['a', 'b', 'c', 'd', 'e', 'f']
|
||||
, b: ['f', 'e']
|
||||
, ops: [
|
||||
['remove', 0]
|
||||
, ['remove', 0]
|
||||
, ['remove', 0]
|
||||
, ['remove', 0]
|
||||
, ['swap', 1, 0]
|
||||
]
|
||||
}
|
||||
, {
|
||||
a: ['a', 'b', 'c', 'd', 'e', 'f']
|
||||
, b: ['f', 'a']
|
||||
, ops: [
|
||||
['remove', 1]
|
||||
, ['remove', 1]
|
||||
, ['remove', 1]
|
||||
, ['remove', 1]
|
||||
, ['swap', 1, 0]
|
||||
]
|
||||
}
|
||||
, {
|
||||
a: []
|
||||
, b: ['a', 'b', 'c', 'd', 'e', 'f']
|
||||
, ops: [
|
||||
['insert', 0, 'a']
|
||||
, ['insert', 1, 'b']
|
||||
, ['insert', 2, 'c']
|
||||
, ['insert', 3, 'd']
|
||||
, ['insert', 4, 'e']
|
||||
, ['insert', 5, 'f']
|
||||
]
|
||||
}
|
||||
, {
|
||||
a: ['a', 'd']
|
||||
, b: ['a', 'b', 'c', 'd', 'e', 'f']
|
||||
, ops: [
|
||||
['insert', 1, 'b']
|
||||
, ['insert', 2, 'c']
|
||||
, ['insert', 4, 'e']
|
||||
, ['insert', 5, 'f']
|
||||
]
|
||||
}
|
||||
, {
|
||||
a: ['b', 'd', 'a']
|
||||
, b: ['a', 'b', 'c', 'd', 'e', 'f']
|
||||
, ops: [
|
||||
['swap', 2, 0]
|
||||
, ['swap', 2, 1]
|
||||
, ['insert', 2, 'c']
|
||||
, ['insert', 4, 'e']
|
||||
, ['insert', 5, 'f']
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
function verify(a, b, ops) {
|
||||
var c = [].concat(a)
|
||||
ops.forEach(function(op) {
|
||||
switch (op[0]) {
|
||||
case 'swap':
|
||||
var temp = c[op[1]]
|
||||
c[op[1]] = c[op[2]]
|
||||
c[op[2]] = temp
|
||||
break
|
||||
case 'move':
|
||||
c.splice(op[2] + 1, 0, c[op[1]])
|
||||
c.splice(op[1], 1)
|
||||
break
|
||||
case 'insert':
|
||||
c.splice(op[1], 0, op[2])
|
||||
break
|
||||
case 'remove':
|
||||
c.splice(op[1], 1)
|
||||
break
|
||||
default:
|
||||
throw new Error('Unknown op ' + op[0])
|
||||
}
|
||||
})
|
||||
assert.deepEqual(c, b)
|
||||
}
|
||||
|
||||
tests.forEach(function(test) {
|
||||
console.log('Running test:')
|
||||
console.log(' <- ', test.a)
|
||||
console.log(' -> ', test.b)
|
||||
console.log('Verifying test expectations')
|
||||
verify(test.a, test.b, test.ops)
|
||||
console.log('Verifying patchArray')
|
||||
var patch = patchArray(test.a, test.b)
|
||||
console.log(' patch', patch)
|
||||
verify(test.a, test.b, patch)
|
||||
})
|
||||
Reference in New Issue
Block a user