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

One platform to build and deploy the best data apps

Experiment and prototype by building visualizations in live JavaScript notebooks. Collaborate with your team and decide which concepts to build out.
Use Observable Framework to build data apps locally. Use data loaders to build in any language or library, including Python, SQL, and R.
Seamlessly deploy to Observable. Test before you ship, use automatic deploy-on-commit, and ensure your projects are always up-to-date.
Learn more