Created
March 3, 2021 20:37
-
-
Save joepuzzo/6cfe73bbe714fdd7013d15b3be3d5842 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const s1 = [ | |
{ id: 1, key: 'a', value: 20 }, // --- a | |
{ id: 2, key: 'b', value: 50 }, | |
{ id: 3, key: 'c', value: 30 }, // ------ c | |
{ id: 4, key: 'd', value: 40 }, // ------------------ d | |
]; | |
const s2 = [ | |
{ id: 5, key: 'a', value: 10 }, // --- a | |
{ id: 6, key: 'c', value: 70 }, // ----- c | |
{ id: 7, key: 'e', value: 15 }, // ---------- e | |
{ id: 8, key: 'd', value: 55 }, // ------------------ d | |
]; | |
const s3 = [ | |
{ id: 9, key: 'e', value: 25 }, // ---------- e | |
{ id: 10, key: 'f', value: 15 }, | |
{ id: 11, key: 'd', value: 35 }, // ----------------- d | |
]; | |
const setCompare = (a, b) => a.key === b.key; | |
// Example output ----------------------- | |
const exampleConflicts = [ | |
{ | |
resolutions: [ | |
{ id: 1, key: 'a', value: 20 }, // X | |
{ id: 5, key: 'a', value: 10 }, | |
] | |
}, | |
{ | |
resolutions: [ | |
{ id: 3, key: 'c', value: 30 }, | |
{ id: 6, key: 'c', value: 70 }, // X | |
] | |
}, | |
{ | |
resolutions: [ | |
{ id: 4, key: 'd', value: 40 }, // X | |
{ id: 8, key: 'd', value: 55 }, | |
{ id: 11, key: 'd', value: 35 }, // X | |
] | |
}, | |
{ | |
resolutions: [ | |
{ id: 7, key: 'e', value: 15 }, | |
{ id: 9, key: 'e', value: 25 }, | |
] | |
}, | |
] | |
// -------------------------------------- | |
const findConflicts = ( sets, compareFunction ) => { | |
const conflicts = []; | |
// Combine sets into one single set | |
const set = sets.flat().map( e => ({ value: e, stored: false })); | |
// Go through each element in the set and find duplicates | |
for( let i = 0; i < set.length; i++ ){ | |
// Foucus on the current element | |
const matcher = set[i]; | |
const resolutions = []; | |
// We have already found logically equivalent things so don't do it again | |
if( !matcher.stored ){ | |
// Search the rest of the array for matches | |
for( let j = i + 1; j < set.length; j++ ){ | |
// Get the guy we want to compare | |
const current = set[j]; | |
// Check to see if he matches | |
if( compareFunction(current.value, matcher.value) ){ | |
// If this is the first conflict found for this matcher then push that on as well | |
if( !matcher.stored ){ | |
matcher.stored = true; | |
resolutions.push(matcher.value); | |
} | |
// We have already found logically equivalent things so update this flag | |
current.stored = true; | |
// Push this onto the resolutions for this conflict | |
resolutions.push(current.value); | |
} | |
} | |
// Only add conflict if we found one | |
if( resolutions.length > 0 ){ | |
conflicts.push({ resolutions }); | |
} | |
} | |
} | |
return conflicts; | |
}; | |
console.log(JSON.stringify(findConflicts([s1, s2, s3], setCompare), null, 2)); | |
const changeset1 = { | |
priceAdjustments: [ | |
{ market: { code: "US" }, partNumber: "1063260-00-C", value: 100 }, | |
{ market: { code: "US" }, partNumber: "1063260-00-D", value: 200 }, | |
{ market: { code: "US" }, partNumber: "1063260-00-E", value: 300 }, | |
], | |
marginRules: [ | |
{ | |
marginPercent: .5, | |
conditions: [{ scope: 2, type: "Market", comparator: "CONTAINS_ANY", value: "CO,CN,CA" }] | |
}, | |
{ | |
marginPercent: .6, operator: "OR", | |
conditions: [{ scope: 2, type: "Market", comparator: "EQUAL", value: "CO" }, { scope: 2, type: "Market", comparator: "EQUAL", value: "CN" }] | |
}, | |
{ | |
marginPercent: .6, operator: "AND", | |
conditions: [{ scope: 2, type: "Market", comparator: "EQUAL", value: "CN" }, { scope: 3, type: "Model", comparator: "EQUAL", value: "MS" }] | |
}, | |
{ | |
marginPercent: .7, operator: "AND", | |
conditions: [{ scope: 2, type: "Market", comparator: "EQUAL", value: "CN" }, { scope: 8, type: "PartNumber", comparator: "EQUAL", value: "123" }] | |
}, | |
{ | |
marginPercent: .3, operator: "AND", | |
conditions: [{ scope: 3, type: "Model", comparator: "EQUAL", value: "MX" }] | |
} | |
] | |
} | |
const changeset2 = { | |
priceAdjustments: [ | |
{ market: { code: "US" }, partNumber: "1063260-00-C", value: 200 }, | |
{ market: { code: "US" }, partNumber: "1063260-00-D", value: 200 }, | |
{ market: { code: "US" }, partNumber: "1063260-00-F", value: 400 }, // <<< Model X part | |
], | |
marginRules: [ | |
{ | |
marginPercent: .7, operator: "AND", | |
conditions: [{ scope: 2, type: "Market", comparator: "CONTAINS_ANY", value: "CO,CN" }] | |
}, | |
{ | |
marginPercent: .1, operator: "AND", | |
conditions: [{ scope: 8, type: "PartNumber", comparator: "EQUAL", value: "1063260-00-E" }] | |
} | |
] | |
} | |
// EXAMPLE Resolution object | |
const resolution = { | |
changesets: ['1', '2', '3'], | |
actions: [ | |
{ type: 'DELETE', context: 'PRICE_ADJUSTMENT', id: '3124'}, | |
{ type: 'DELETE', context: 'MARGIN_RULE', id: '7465'}, | |
] | |
} | |
// Above we have | |
// 1. Two price adjustments that directly conflict with one another | |
// 2. A Model X Margin rule that technically speaking conflicts with a price adjustment | |
// 3. A Margin rule that technically speaking conflicts with a price adjustment | |
// 4. Two margin rules in changeset1 that conflict with a margin rule in changeset2 | |
/* ------------------ Price Adjustment Compare ----------------- */ | |
/** | |
* Goal determine if priceAdjustments are equal | |
* | |
* @param {*} a | |
* @param {*} b | |
*/ | |
const comparePriceAdjustments = (a, b) => { | |
const marketsMatch = a.market.code === b.market.code; | |
const numbersMatch = a.partNumber === b.partNumber; | |
return marketsMatch && numbersMatch; | |
}; | |
/* -------------------- Margin Rule Compare -------------------- */ | |
const compareMarketMarginCondition = ( a, b ) => { | |
const comparatorMatch = a.comparator === b.comparator; | |
// 'CN,CA,FR' ---> [ 'CN', 'CA', 'FR' ] | |
const v1 = a.value.split(','); | |
const v2 = b.value.split(','); | |
} | |
/* -------------------- Helpers -------------------- */ | |
const findHighestScope = ( arr ) => { | |
// Check for empty array | |
let largest = arr.length > 0 ? arr[0].scope : 0; | |
for( let i = 1; i < arr.length; i++ ){ | |
if( arr[i].scope > largest ){ | |
largest = arr[i].scope; | |
} | |
} | |
return largest; | |
} | |
console.log('Largest [7]', findHighestScope([])); | |
console.log('Largest [7]', findHighestScope([{ scope: 7}])); | |
console.log('Largest [1, 7]', findHighestScope([{scope: 1},{ scope: 7}])); | |
console.log('Largest [1, 7, 5]', findHighestScope([{scope: 1},{ scope: 7}, { scope: 5}])); | |
// 8 7 6 5 4 3 2 1 | |
// 64 32 16 8 4 2 1 | |
// [ 1, 4 ] == 0 0 0 0 1 0 0 1 | |
// [ 2, 3 ] 0 0 0 0 0 1 1 0 | |
// [ 2, 3 ] 0 0 0 0 0 1 1 0 | |
const determineSpecificity = () => { | |
// 8 7 6 5 4 3 2 1 | |
const specificity = [0, 0, 0, 0, 0, 0, 0, 0] | |
} | |
/** | |
* Goal determine if margin are equal | |
* | |
* Facts: | |
* 1. Margin rules can only conflict if they have the same specificity | |
* | |
* @param {*} a | |
* @param {*} b | |
*/ | |
const compareMarginRules = (a, b) => { | |
// | |
}; | |
const conflicts = { | |
priceAdjustments: findConflicts([changeset1.priceAdjustments, changeset2.priceAdjustments], comparePriceAdjustments), | |
marginRules: findConflicts([changeset1.marginRules, changeset2.marginRules], compareMarginRules) | |
} | |
console.log('conflicts:', JSON.stringify(conflicts, null, 2)); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment