summaryrefslogtreecommitdiff
path: root/pieces/retro-search.js
diff options
context:
space:
mode:
authorGeo Halkiadakis <gchalkiadakis@sklavenitis.co.gr>2024-04-12 18:31:00 +0300
committerGeo Halkiadakis <gchalkiadakis@sklavenitis.co.gr>2024-04-12 18:31:00 +0300
commitb122279ece06a9381e805c6087f130b41616fe3d (patch)
tree2ec0a8fc3c570417d972b18a7a7b878758ce3a6f /pieces/retro-search.js
parent762d85c95690f510bec4dd8c37c05454ae1be4fc (diff)
downloadoseine-b122279ece06a9381e805c6087f130b41616fe3d.tar.gz
oseine-b122279ece06a9381e805c6087f130b41616fe3d.tar.bz2
oseine-b122279ece06a9381e805c6087f130b41616fe3d.zip
added utils folder; added several suplamentary modules
Diffstat (limited to 'pieces/retro-search.js')
-rw-r--r--pieces/retro-search.js304
1 files changed, 304 insertions, 0 deletions
diff --git a/pieces/retro-search.js b/pieces/retro-search.js
new file mode 100644
index 0000000..ba4d937
--- /dev/null
+++ b/pieces/retro-search.js
@@ -0,0 +1,304 @@
+const kb = require('../utils/kb-util.js');
+const match = require('../utils/match-util.js');
+
+const products = require('../data/products.json');
+
+/** VARIABLES
+ * may passed as module arguments
+ * -----------------------------------------------------------------------------
+ *//////////////////////////////////////////////////////////////////////////////
+
+
+var _allowFuzzy = true; // enable|disable fuzzy search
+var n = 2; // Ngram base
+var _fuzzyLimit = .5; // minimum bigram score for being considered a match
+var max_list = 24;
+var tolerance = 42;
+var STORE = { id: 904 };
+
+var _kwlinks; // keyword links (word-connections; imported via ajax-get)
+var _products = []; // all products (imported via ajax-get)
+
+// setup options
+var _maxResults = options.max_list; // limit suggestions
+var _blendProds = 4; // minimum final-produncts to blend with next-word suggestions
+var _Ngram_base = 2; // number of N in Ngram spliting algorithm
+var _isReady = false; // whether the searchbox is ready to be used
+
+// product keywords
+var keywordsURL = options.keywords_json;
+
+var cursor_on = { none: true }; // what product is highlighted; if not on product then { none: true }
+
+
+
+
+
+
+/** SUPPLEMENTARY FUNCTIONS
+ * -----------------------------------------------------------------------------
+ *//////////////////////////////////////////////////////////////////////////////
+
+
+
+// callback function for sorting resulrs per r (=rating) property
+function compare_rate(a,b) {
+ return (a.r < b.r);
+}
+
+
+
+/** SEARCH ENGINE
+ * -------------------------------------------------------------------------
+ *//////////////////////////////////////////////////////////////////////////
+
+
+
+
+function matchWordInList(q, list = false) {
+
+ if (list !== false && list.length == 0) return []; // no results
+
+ var result = [];
+ var firstPass = false;
+
+ if (list === false) {
+ firstPass = true; // on first pass
+ list = products; // list is all products
+ }
+
+ for(let i = 0 ; i < list.length ; i++) {
+
+ // check exact + rate
+
+ // else check partial + rate
+
+ // else check similarity + rate
+
+ let found = false;
+ let similarity = 0;
+ products[i].kb.split(' ').forEach( w => {
+ let sim = match.resemblance(q, w, 2);
+ if (sim > 0.5) {
+ found = true;
+ similarity = (sim > similarity) ? sim : similarity;
+ }
+ });
+ if (found) {
+ products[i].similarity = similarity;
+ products[i].rating = (firstPass)
+ ? similarity * 2.0
+ : products[i].rating + similarity * 2.0
+ result.push(products[i]);
+ }
+ }
+
+ return result
+}
+
+
+
+// suggestions engine //////////////////////////////////////////////////
+// ---
+function suggestions_engine(query) {
+ var results = [];
+ var pot = []; pot.length = 0;
+
+ // clean and sanitize and mark links onto q(uery) string
+ var q = kb.keyboardize( kb.sanitizeGR( kb.clean(query.trim()) ) ).trim();
+
+ // TODO:
+ // construct direct-linked words
+ // = do unequivocally replaces
+ // steps:
+ // 1. replace accented vowels with non accented ones
+ // 2. replace `/some pattern/gi , 'SOME-REPLACE-PATTERN'`
+
+ var qAr = q.split(' '); // split to words
+ /// if (space_ended) qAr.push(' '); // if space-end existed, push a space to query array
+ ///
+ /// if (qAr.slice(-1) == "") {
+ /// qAr.pop();
+ /// }
+
+
+ pot = _products; // potential results // NOTE: CRITICAL: BY REFERENCE
+
+ var wi = 0; // word index (from list)
+ var wc = qAr.length;
+
+ qAr.forEach( w => {
+
+ let sf = []; // (matches) so far
+ let mi; // position of match
+ wi++;
+
+ pot.forEach( it => {
+ let matched = false;
+ let tester = ' '+ it.kb + ' ';
+
+ // reset previous history and ratings
+ if (wi == 1) {
+ it.r = 0;
+ it.history = [];
+ }
+
+
+ // rate word-match > start-match > simple-match
+ // ... up to 8 points
+
+ if (tester.indexOf(' '+ w +' ') != -1) {
+ it.r += 9;
+ it.history.push({ w: w, rate: 9 });
+ matched = true;
+ }
+ else if (tester.indexOf(' '+ w) != -1) {
+ it.r += 5;
+ it.history.push({ w: w, rate: 5 });
+ matched = true;
+ }
+ else if (tester.indexOf(w) != -1) {
+ it.r += 2;
+ it.history.push({ w: w, rate: 2 });
+ matched = true;
+ }
+
+ // rate `near-to-start` matching .. up to 7p
+ // rate `earlyness` of word in query .. up to 7p
+
+ if ((mi = tester.indexOf(' '+w)) != -1) {
+ let fc1 = 100 - ((mi < 99) ? mi : 99); // near-to-start factor
+ let fc2 = wc - wi + 1; // query earlyness factor
+ let r1 = Math.floor(7*fc1/100);
+ let r2 = Math.floor(7*fc2/wc);
+
+ it.r += (r1 + r2);
+ it.history.push({ w: w, left: [fc1, r1], early: [fc2, r2] });
+ }
+ if (matched) sf.push(it);
+ });
+
+ if ((sf.length > (_maxResults + Math.floor(_maxResults/2)))
+ || (wi == 1) ) {
+ // ..if pot has a fair amount (= max + 50%) of results
+ // ..or these are results of '1st-query-word'
+ // set sf as new source
+ pot.lenght = 0; pot = [];
+ pot = JSON.parse(JSON.stringify(sf)); // copy by value
+
+ } else {
+ // else.. keep the source list and increase of 'so-far rating'
+ // console.log('found small list', sf, pot)
+ pot.forEach( it => {
+ sf.forEach( si => {
+ if (it.id == si.id) {
+ it.r += 10;
+ it.history.push({ w: w, plus: '+10'});
+ }
+ });
+ });
+ }
+ });
+
+ // sort results, get max-list of best rated
+ results = (pot.length > _maxResults)
+ ? pot.sort(compare_rate).slice(0, _maxResults)
+ : pot.sort(compare_rate)
+
+ if (options.debug) console.log(results);
+
+ return results;
+}
+
+
+// sub-module (start)
+////////////////////////////////////////////////////////////////////////////
+
+function update_common_search_results(q, results) {
+ let queries = getSessionObj('sr');
+ let newSRlist = [];
+ let isnewQ = true;
+ if (queries === null) {
+ setSessionObj('sr', [{
+ q: q,
+ result: result,
+ t: + new Date()
+ }]);
+ return true;
+
+ } else {
+
+ queries.forEach(it => {
+ if (it.q == q) {
+ newSRlist.push({
+ q:q,
+ result: result,
+ t: + new Date()
+ });
+ isnewQ = false;
+ } else { newSRlist.push(it); }
+ });
+
+ if (isnewQ) {
+ newSRlist.push({
+ q:q,
+ result: result,
+ t: + new Date()
+ });
+ }
+
+ return true;
+ }
+}
+
+
+
+////////////////////////////////////////////////////////////////////////////
+// sub-module (end)
+
+
+function common_search(query) {
+ // clear ; sanitize ; split
+ var qAr = keyboardize( sanitize_GR( clean_text(query) ) ).toLowerCase().split(' ');
+
+ // if last item is empty, remove it
+ if ((qAr.slice(-1) == ' ') || (qAr.slice(-1) == '')) qAr.pop()
+
+ var results = _products;
+
+ // for each key fitler results
+ qAr.forEach( key => {
+ results = key_sublist(key, results)
+ });
+
+ // echo products (and prepare list to POST)
+ var list_ = [];
+ results.forEach( item => {
+ if (options.debug) console.log(item.id, ':', item.w);
+ list_.push(item.id)
+ })
+
+ // *** TODO: keep results in local storage (or on session storage)
+
+ // update_common_search_results(query, list_);
+
+ let l = list_.join(',');
+ var url = encodeURI(`${options.visualize_search_results_url}?search=${query}&eys_code=${l}`);
+
+ console.log('common search: search query > location = search')
+ window.location.href = encodeURI(`${options.visualize_search_results_url}?search=${query}`);
+
+}
+
+/** return from list only items that include 'key'
+ */
+function key_sublist(key, list) {
+ var result = [];
+ list.forEach( item => {
+ if (item.kb.includes(key)) {
+ result.push(item);
+ }
+ });
+
+ return result;
+}