patterns.js generates various pattern analysis results. Currently matches Billa products with Spar products and spits out some files to be imported as carts.
This commit is contained in:
parent
cb38e6c5c1
commit
d09bdc47e6
|
@ -14,3 +14,4 @@ tmp-dir/
|
|||
site/data/latest-canonical*.json*
|
||||
site/output
|
||||
copy
|
||||
patterns
|
||||
|
|
|
@ -0,0 +1,62 @@
|
|||
const fs = require("fs");
|
||||
const analysis = require("./analysis");
|
||||
const knn = require("./site/js/knn");
|
||||
|
||||
if (!fs.existsSync("patterns")) fs.mkdirSync("patterns");
|
||||
|
||||
if (!fs.existsSync("patterns/sorted-billa-spar.json")) {
|
||||
const items = analysis.readJSON("data/latest-canonical.json.br");
|
||||
const billaSparItem = items
|
||||
.filter((item) => item.store == "billa" || item.store == "spar")
|
||||
.filter((item) => {
|
||||
return !(
|
||||
item.name.includes("Clever") ||
|
||||
item.name.includes("S-BUDGET") ||
|
||||
item.name.includes("Ja! Natürlich") ||
|
||||
item.name.includes("SPAR") ||
|
||||
item.name.includes("BILLA")
|
||||
);
|
||||
});
|
||||
knn.vectorizeItems(billaSparItem);
|
||||
const billaItems = billaSparItem.filter((item) => item.store == "billa");
|
||||
const sparItems = billaSparItem.filter((item) => item.store == "spar");
|
||||
|
||||
console.log(billaItems.length + " " + sparItems.length);
|
||||
const sortedItems = [];
|
||||
|
||||
sparItems.forEach((item) => (item.sorted = false));
|
||||
const total = billaItems.length;
|
||||
while (billaItems.length > 0) {
|
||||
const refItem = billaItems.shift();
|
||||
const similar = knn.findMostSimilarItem(refItem, sparItems);
|
||||
if (similar.item != null) {
|
||||
sortedItems.push(refItem);
|
||||
sortedItems.push(similar.item);
|
||||
} else {
|
||||
console.log("No similar item found for " + refItem.name);
|
||||
}
|
||||
if (sortedItems.length % 100 == 0) console.log(sortedItems.length / 2 + "/" + total);
|
||||
}
|
||||
analysis.writeJSON("patterns/sorted-billa-spar.json", sortedItems);
|
||||
}
|
||||
|
||||
const sortedItems = analysis.readJSON("patterns/sorted-billa-spar.json");
|
||||
const filteredItems = [];
|
||||
let result = "";
|
||||
for (let i = 0; i < sortedItems.length; i += 2) {
|
||||
const a = sortedItems[i];
|
||||
const b = sortedItems[i + 1];
|
||||
const similarity = knn.dotProduct(a.vector, b.vector);
|
||||
result += "billa " + a.name + "\n";
|
||||
result += "spar " + b.name + " " + similarity.toFixed(5) + "\n\n";
|
||||
|
||||
if (b.priceHistory.some((price) => price.price == a.price) && a.quantity == b.quantity) {
|
||||
filteredItems.push(a);
|
||||
filteredItems.push(b);
|
||||
}
|
||||
}
|
||||
console.log("Sorted: " + sortedItems.length);
|
||||
analysis.writeJSON("patterns/sorted-billa-spar-cart.json", { name: "Billa Spar Sortiert", items: sortedItems });
|
||||
console.log("Filtered: " + filteredItems.length);
|
||||
analysis.writeJSON("patterns/sorted-billa-spar-filtered-cart.json", { name: "Billa Spar Sortiert Gefiltert", items: filteredItems });
|
||||
fs.writeFileSync("patterns/sorted-billa-spar.txt", result, "utf-8");
|
|
@ -133,7 +133,7 @@ function loadCart() {
|
|||
});
|
||||
cartList.elements.numItemsLabel.innerHTML = "<strong>Artikel:</strong>";
|
||||
cartList.elements.enableChart.checked = true;
|
||||
cartList.elements.chart.elements.sumStores.checked = true;
|
||||
cartList.elements.chart.elements.sumStores.checked = models.items.length < 2000;
|
||||
|
||||
if (cart.items.length == 0) {
|
||||
elements.noItems.classList.remove("hidden");
|
||||
|
|
|
@ -46,14 +46,19 @@ function findMostSimilarItem(refItem, items) {
|
|||
let maxSimilarity = -1;
|
||||
let similarItem = null;
|
||||
let similarItemIdx = -1;
|
||||
items.forEach((item, idx) => {
|
||||
for (let idx = 0; idx < items.length; idx++) {
|
||||
const item = items[idx];
|
||||
if (item.sorted) continue;
|
||||
let similarity = dotProduct(refItem.vector, item.vector);
|
||||
if (similarity > maxSimilarity) {
|
||||
if (similarity > maxSimilarity || similarity > 0.9999999) {
|
||||
maxSimilarity = similarity;
|
||||
similarItem = item;
|
||||
similarItemIdx = idx;
|
||||
}
|
||||
});
|
||||
if (similarity > 0.9999999) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return {
|
||||
similarity: maxSimilarity,
|
||||
item: similarItem,
|
||||
|
@ -96,16 +101,19 @@ function findMostSimilarItems(refItem, items, k = 5, accept = (ref, item) => tru
|
|||
}
|
||||
exports.findMostSimilarItems = findMostSimilarItems;
|
||||
|
||||
function similaritySortItems(items) {
|
||||
function similaritySortItems(items, progress) {
|
||||
if (items.length == 0) return items;
|
||||
sortedItems = [items.shift()];
|
||||
let refItem = sortedItems[0];
|
||||
while (items.length > 0) {
|
||||
items.forEach((item) => (item.sorted = false));
|
||||
while (items.length != sortedItems.length) {
|
||||
const similarItem = findMostSimilarItem(refItem, items);
|
||||
sortedItems.push(similarItem.item);
|
||||
items.splice(similarItem.index, 1);
|
||||
similarItem.item.sorted = true;
|
||||
refItem = similarItem.item;
|
||||
if (progress) progress(sortedItems, items);
|
||||
}
|
||||
items.forEach((item) => delete item.sorted);
|
||||
return sortedItems;
|
||||
}
|
||||
exports.similaritySortItems = similaritySortItems;
|
||||
|
|
|
@ -36,7 +36,16 @@ class Carts extends Model {
|
|||
}
|
||||
|
||||
save() {
|
||||
localStorage.setItem("carts", JSON.stringify(this._carts, null, 2));
|
||||
const carts = [];
|
||||
for (const cart of this._carts) {
|
||||
carts.push({
|
||||
name: cart.name,
|
||||
items: cart.items.map((item) => {
|
||||
return { store: item.store, id: item.id };
|
||||
}),
|
||||
});
|
||||
}
|
||||
localStorage.setItem("carts", JSON.stringify(carts, null, 2));
|
||||
this.notify();
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue