Published
Edited
Apr 7, 2020
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
magick = function (currData,history) {
if (!history || history.length==0)
return;
const keys = Object.keys(history[0]);
let currentKey = null;
const currDataMap = currData.reduce((a,x) => {
a[x.sFieldID] = x;
if (x.bHasFocus==true)
currentKey = x.sFieldID;
return a;
},{});
const currentlySetData = currData.reduce( (a,x) => {
if (x.value != undefined && x.value.val != undefined)
a[x.sFieldID] = x.value.val;
return a;
},{});
//console.log(currentlySetData);
//console.log(currDataMap);
const currentlySetKeys = Object.keys(currentlySetData);
const currentlySetKeysWithoutCurrentKey = currentlySetKeys.filter(x=>x!=currentKey);
const currentlyNotSetKeys = keys.filter(x=>!currentlySetKeys.includes(x));
const bShowCaseCalcAlsoForSetFields = false;
const _incCounter = function(m,key,p) {
if (p==true || p==undefined) p=1;
if (key===null)
{
if (m.empty) m.empty = m.empty+p;
else m.empty=p;
return;
}
if (m.d.hasOwnProperty(key)) m.d[key] = m.d[key]+p;
else m.d[key]=p;
}
const _getCounter = function(m,key) {
if (key===null)
{
if (m.empty) return m.empty;
return 0;
}
if (m.d.hasOwnProperty(key)) return m.d[key];
else return 0;
}
//console.log("start for ");
//console.log(currentlySetData);
let nMatchingHistory = 0;
let nHistory = history.length;
// do the over all counting (at first excluding the current key to append
// complex testing only if the other values matches history)
// this is done in a separate loop to store/cach/flag each history with macht or not match
// to make it faster to go throug relevant history entires for each key later
history.forEach(hd=> {
if (currentKey!=null && currentlySetKeysWithoutCurrentKey.every(curKey => currentlySetData[curKey]==hd[curKey]))
{ // special case for current input:
const a = currentlySetData[currentKey];
const b = hd[currentKey];
let sim = 0;
if (a==null) sim=1;
else if (b!=null) sim = stringSimilarity.compareTwoStrings(String(currentlySetData[currentKey]),String(hd[currentKey]));
//console.log(sim);
const th = 0.1
if (sim>th) {
nMatchingHistory += sim;
hd["___MATCHED"] = sim;
} else {
nMatchingHistory += th/2;
hd["___MATCHED"] = th/2;
}
} else if (currentKey==null && currentlySetKeys.every(curKey => currentlySetData[curKey]==hd[curKey])) {
nMatchingHistory++;
hd["___MATCHED"] = true;
} else {
hd["___MATCHED"] = false;
}
});
/*history.forEach(hd=> {
if (currentlySetKeys.every(curKey => currentlySetData[curKey]==hd[curKey]))
{
nMatchingHistory++;
hd["___MATCHED"] = true;
} else {
// special case for current input:
if (currentKey!=null && currentlySetKeysWithoutCurrentKey.every(curKey => currentlySetData[curKey]==hd[curKey]))
{
const sim = stringSimilarity.compareTwoStrings(currentlySetData[currentKey],hd[currentKey]);
//console.log(sim);
const th = 0.1
if (sim>th) {
nMatchingHistory += sim;
hd["___MATCHED"] = sim;
} else {
nMatchingHistory += th/2;
hd["___MATCHED"] = th/2;
}
}
else
hd["___MATCHED"] = false;
}
});*/
let schemaUpdate = [];
if (!bShowCaseCalcAlsoForSetFields)
schemaUpdate = currentlySetKeysWithoutCurrentKey.reduce((a,key) => {
a.push({sFieldID:key,aOptions:[]});
return a;
},[]);
/* if (nMatchingHistory==0) {
console.log("no matches found");
if (currentKey!=null)
schemaUpdate.push({sFieldID:currentKey,aOptions:[]});
currentlyNotSetKeys.forEach( key => {
schemaUpdate.push({sFieldID:key,aOptions:[]});
});
} else */
{
let keysToCalc = currentlyNotSetKeys;
if (currentKey!=null)
keysToCalc = keysToCalc.concat([currentKey]);
if (bShowCaseCalcAlsoForSetFields) // this is usually not required but for demonstratino purpose its nice to see these resutls aswell
keysToCalc = keys;
keysToCalc.forEach( key => {
if (key=="___MATCHED") return;
// loop all not set fields to figure out how probable it is that they will be selected.
let oOptionChoosenForMatchingHistory = {d:{},empty:0};
let oOptionChoosenInHistoryAtAll = {d:{},empty:0};
history.forEach(hd=> {
// loop complete history
// and check how often each option has been coosen in case of matching precondition ..
if (hd["___MATCHED"]!=false)
{
_incCounter(oOptionChoosenForMatchingHistory,hd[key],hd["___MATCHED"]);
}
// and at all.
_incCounter(oOptionChoosenInHistoryAtAll,hd[key]);
});
/*console.log("key: "+key);
console.log(aOptionsChoosenInHistoryButNotMatching);*/

let aOptionsGreater0 = _getCounter(oOptionChoosenForMatchingHistory,null)>0 ? [{val:null,text:null,prop:_getCounter(oOptionChoosenForMatchingHistory,null)/nMatchingHistory}] : [];
// here in theory one should sort the oOptionChoosenForMatchingHistory to start with options of higher probability.
aOptionsGreater0 = Object.keys(oOptionChoosenForMatchingHistory.d).reduce((a,option) =>
{
if (false) {
console.log("Option: "+option);
console.log("Joined Probability for given data and option: " + oOptionChoosenForMatchingHistory.d[option]/nHistory+"\nProbability for given data: " + nMatchingHistory/nHistory+"\nProbability for that option: " + oOptionChoosenInHistoryAtAll.d[option]/nHistory);
}
a.push({val:option,prop:_getCounter(oOptionChoosenForMatchingHistory,option)/nMatchingHistory});
return a;
/*console.log(nMatchingHistory);
console.log(oOptionChoosenForMatchingHistory[option]);
console.log(oOptionChoosenInHistoryAtAll[option]);*/
},aOptionsGreater0);
aOptionsGreater0.sort((a,b) => b.prop-a.prop);
//let currData.find(
let currFieldSchema = currDataMap[key];
//console.log("key: "+key);
console.log(currFieldSchema);
aOptionsGreater0.forEach(x=>x.text=val2text(currFieldSchema,x.val).text);
console.log(aOptionsGreater0);
let aOptionsChoosenInHistoryButNotMatching = Object.keys(oOptionChoosenInHistoryAtAll.d).filter(x=>!Object.keys(oOptionChoosenForMatchingHistory.d).includes(x));
//console.log(aOptionsChoosenInHistoryButNotMatching);
let aOptionsWith0 = aOptionsChoosenInHistoryButNotMatching.reduce(
(a,x) =>{
a.push({val:x,_p:_getCounter(oOptionChoosenInHistoryAtAll,x),prop:0});
return a
},[]);
aOptionsWith0.sort((a,b) => b._p-a._p);
//console.log(aOptionsWith0);
aOptionsWith0.forEach(x=>x.text=val2text(currFieldSchema,x.val).text);
console.log(aOptionsWith0);
schemaUpdate.push({sFieldID:key,aOptions:aOptionsGreater0.concat(aOptionsWith0)});
});
}
//exampleForm.myUpdateSchema(schemaUpdate)
return schemaUpdate;
}
Insert cell
Insert cell
Insert cell
Insert cell
text2val = function(x,text) {
let val = text;
let match = null;
let bValid = true;
if (x.fValidate)
bValid = x.fValidate(text);
if (x.aTransformation)
val = x.aTransformation.fTextToVal(text);
if (x.aMinimalOptions) {
match = x.aMinimalOptions.find(xx=>xx.val==val);
if (match)
val = match.val;
}
if (val=="") val = null;
return {val:val,bMatch:match!=null,bValid:bValid};
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Type JavaScript, then Shift-Enter. Ctrl-space for more options. Arrow ↑/↓ to switch modes.

Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more