Various cleanup
This commit is contained in:
parent
de56d05c5d
commit
70d8bb802c
@ -84,11 +84,11 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- query output -->
|
<!-- query output -->
|
||||||
<div id="output" style="display: none;">
|
<div>
|
||||||
<!-- semantic tweaker -->
|
<!-- semantic tweaker -->
|
||||||
<div class="panel panel-default">
|
<div class="panel panel-default">
|
||||||
<div class="panel-heading">
|
<div class="panel-heading">
|
||||||
<big>Semantic tweaks to: <span id="query"></span></big>
|
<big>Semantic tweaker</big>
|
||||||
<div class="btn-group pull-right">
|
<div class="btn-group pull-right">
|
||||||
<button class="btn btn-xs btn-success" data-toggle="modal" data-target="#learnDialog">Learn</button>
|
<button class="btn btn-xs btn-success" data-toggle="modal" data-target="#learnDialog">Learn</button>
|
||||||
<button class="btn btn-xs btn-default" data-toggle="modal" data-target="#optionsDialog">Options</button>
|
<button class="btn btn-xs btn-default" data-toggle="modal" data-target="#optionsDialog">Options</button>
|
||||||
|
@ -27,26 +27,17 @@
|
|||||||
(function(hscd) {
|
(function(hscd) {
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var ctx = {
|
var _custom = '[custom]';
|
||||||
log: []
|
var _ctx = { log: [] };
|
||||||
};
|
|
||||||
|
|
||||||
function onAdjust(name, value) {
|
function onAdjust(name, value) {
|
||||||
ctx.features[name] = value;
|
_ctx.query.features[name] = value;
|
||||||
|
_ctx.grapher.enable(false);
|
||||||
|
|
||||||
var query = {
|
$.getJSON('/search', _ctx.query, function(results) {
|
||||||
features: ctx.features,
|
|
||||||
range: ctx.range,
|
|
||||||
minScore: ctx.minScore,
|
|
||||||
hintSteps: ctx.hintSteps,
|
|
||||||
maxResults: ctx.maxResults
|
|
||||||
};
|
|
||||||
|
|
||||||
ctx.grapher.enable(false);
|
|
||||||
$.getJSON('/search', query, function(results) {
|
|
||||||
saveSnapshot(results);
|
saveSnapshot(results);
|
||||||
outputSnapshot(results);
|
outputSnapshot(results);
|
||||||
ctx.grapher.enable(true);
|
_ctx.grapher.enable(true);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -54,7 +45,7 @@
|
|||||||
$('#history').on('slideStop', onSelectSnapshot);
|
$('#history').on('slideStop', onSelectSnapshot);
|
||||||
$('#history').slider({
|
$('#history').slider({
|
||||||
formatter: function(value) {
|
formatter: function(value) {
|
||||||
var delta = ctx.log.length - (value + 1);
|
var delta = _ctx.log.length - (value + 1);
|
||||||
switch (delta) {
|
switch (delta) {
|
||||||
case 0:
|
case 0:
|
||||||
return 'Most recent query';
|
return 'Most recent query';
|
||||||
@ -76,57 +67,66 @@
|
|||||||
$('#learnKeyword').prop('disabled', !$(this).val());
|
$('#learnKeyword').prop('disabled', !$(this).val());
|
||||||
});
|
});
|
||||||
|
|
||||||
$.getJSON('/get_keywords', function(keywords) {
|
$.getJSON('/get_parameters', function(parameters) {
|
||||||
ctx.keywords = keywords;
|
_ctx.parameters = parameters;
|
||||||
for (var keyword in keywords) {
|
for (var keyword in parameters.keywords) {
|
||||||
$('#keywordsToSearch').append($('<option></option>', { value: keyword, text: keyword }));
|
$('#keywordsToSearch').append($('<option></option>', { value: keyword, text: keyword }));
|
||||||
}
|
}
|
||||||
|
|
||||||
onSearch();
|
search();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function onSearch() {
|
function search(keyword) {
|
||||||
var keyword = $('#keywordsToSearch').val();
|
var features = {};
|
||||||
var query = {
|
if (typeof(keyword) == 'undefined') {
|
||||||
features: ctx.keywords[keyword],
|
for (var i = 0, count = _ctx.parameters.features.length; i < count; ++i) {
|
||||||
|
features[_ctx.parameters.features[i]] = 0.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
features = _ctx.parameters.keywords[keyword];
|
||||||
|
}
|
||||||
|
|
||||||
|
_ctx.query = {
|
||||||
|
features: features,
|
||||||
range: { min: -1.0, max: 1.0 },
|
range: { min: -1.0, max: 1.0 },
|
||||||
minScore: parseFloat($('#minScore').val()),
|
minScore: parseFloat($('#minScore').val()),
|
||||||
hintSteps: parseInt($('#hintSteps').val()),
|
hintSteps: parseInt($('#hintSteps').val()),
|
||||||
maxResults: parseInt($('#maxResults').val())
|
maxResults: parseInt($('#maxResults').val())
|
||||||
};
|
};
|
||||||
|
|
||||||
$.getJSON('/search', query, function(results) {
|
if (!_.has(_ctx, 'grapher')) {
|
||||||
ctx.features = query.features;
|
_ctx.grapher = new grapher.Grapher({
|
||||||
ctx.range = query.range;
|
|
||||||
ctx.minScore = query.minScore;
|
|
||||||
ctx.hintSteps = query.hintSteps;
|
|
||||||
ctx.maxResults = query.maxResults;
|
|
||||||
|
|
||||||
ctx.grapher = new grapher.Grapher({
|
|
||||||
canvas: new Snap('#svg'),
|
canvas: new Snap('#svg'),
|
||||||
steps: ctx.hintSteps,
|
steps: _ctx.query.hintSteps,
|
||||||
range: ctx.range,
|
range: _ctx.query.range,
|
||||||
onValueChanged: onAdjust,
|
onValueChanged: onAdjust,
|
||||||
useLocalScale: true,
|
useLocalScale: true,
|
||||||
useRelativeScale: true
|
useRelativeScale: true
|
||||||
});
|
});
|
||||||
ctx.grapher.setColumns(results.columns);
|
|
||||||
|
|
||||||
saveSnapshot(results);
|
|
||||||
outputMatches(results.items, results.count);
|
|
||||||
|
|
||||||
$('#useLocalScale').click(function() {
|
$('#useLocalScale').click(function() {
|
||||||
var useLocalScale = $('#useLocalScale').is(':checked');
|
var useLocalScale = $('#useLocalScale').is(':checked');
|
||||||
ctx.grapher.setUseLocalScale(useLocalScale);
|
_ctx.grapher.setUseLocalScale(useLocalScale);
|
||||||
});
|
});
|
||||||
$('#useRelativeScale').click(function() {
|
$('#useRelativeScale').click(function() {
|
||||||
var useRelativeScale = $('#useRelativeScale').is(':checked');
|
var useRelativeScale = $('#useRelativeScale').is(':checked');
|
||||||
ctx.grapher.setUseRelativeScale(useRelativeScale);
|
_ctx.grapher.setUseRelativeScale(useRelativeScale);
|
||||||
});
|
});
|
||||||
|
|
||||||
$('#query').text(keyword);
|
var columns = {};
|
||||||
$('#output').fadeIn();
|
for (var feature in _ctx.query.features) {
|
||||||
|
columns[feature] = { value: 0.0, hints: [] };
|
||||||
|
}
|
||||||
|
|
||||||
|
_ctx.grapher.setColumns(columns);
|
||||||
|
}
|
||||||
|
|
||||||
|
$.getJSON('/search', _ctx.query, function(results) {
|
||||||
|
_ctx.grapher.setColumns(results.columns);
|
||||||
|
saveSnapshot(results);
|
||||||
|
outputMatches(results.items, results.count);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -135,7 +135,7 @@
|
|||||||
$('#learnError').slideUp(function() {
|
$('#learnError').slideUp(function() {
|
||||||
var query = {
|
var query = {
|
||||||
keyword: $('#keywordToLearn').val(),
|
keyword: $('#keywordToLearn').val(),
|
||||||
params: ctx.features
|
params: _ctx.query.features
|
||||||
};
|
};
|
||||||
|
|
||||||
$.getJSON('/add_keyword', query, function(results) {
|
$.getJSON('/add_keyword', query, function(results) {
|
||||||
@ -153,13 +153,13 @@
|
|||||||
|
|
||||||
function onSelectSnapshot() {
|
function onSelectSnapshot() {
|
||||||
var index = $('#history').slider('getValue');
|
var index = $('#history').slider('getValue');
|
||||||
outputSnapshot(ctx.log[index]);
|
outputSnapshot(_ctx.log[index]);
|
||||||
}
|
}
|
||||||
|
|
||||||
function saveSnapshot(results) {
|
function saveSnapshot(results) {
|
||||||
ctx.log.push(results);
|
_ctx.log.push(results);
|
||||||
|
|
||||||
var count = ctx.log.length;
|
var count = _ctx.log.length;
|
||||||
var history = $('#history').slider();
|
var history = $('#history').slider();
|
||||||
history.slider('setAttribute', 'max', count - 1);
|
history.slider('setAttribute', 'max', count - 1);
|
||||||
history.slider('setValue', count - 1);
|
history.slider('setValue', count - 1);
|
||||||
@ -171,10 +171,10 @@
|
|||||||
|
|
||||||
function outputSnapshot(results) {
|
function outputSnapshot(results) {
|
||||||
for (var name in results.columns) {
|
for (var name in results.columns) {
|
||||||
ctx.features[name] = results.columns[name].value;
|
_ctx.query.features[name] = results.columns[name].value;
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.grapher.setColumns(results.columns);
|
_ctx.grapher.setColumns(results.columns);
|
||||||
outputMatches(results.items, results.count);
|
outputMatches(results.items, results.count);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -152,10 +152,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
function updateShapes() {
|
function updateShapes() {
|
||||||
var gradient = _canvas.gradient(decimateHints());
|
var fill = _data.hints.length === 0 ? _backdropColor : _canvas.gradient(decimateHints());
|
||||||
_elements.density.attr({
|
_elements.density.attr({ fill: fill });
|
||||||
fill: gradient
|
|
||||||
});
|
|
||||||
|
|
||||||
var range = computeIndicatorRange();
|
var range = computeIndicatorRange();
|
||||||
_elements.indicator.attr({
|
_elements.indicator.attr({
|
||||||
|
102
server/search.js
102
server/search.js
@ -42,47 +42,6 @@ function innerProduct(values1, values2) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
function scale(values, factor) {
|
|
||||||
var result = {};
|
|
||||||
|
|
||||||
for (var feature in values) {
|
|
||||||
result[feature] = values[feature] * factor;
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
function add(values1, values2) {
|
|
||||||
var result = {};
|
|
||||||
|
|
||||||
for (var feature in values1) {
|
|
||||||
result[feature] = values1[feature] + (values2[feature] || 0.0);
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
function combine(dict, params) {
|
|
||||||
var result = {};
|
|
||||||
|
|
||||||
for (var paramIter in params) {
|
|
||||||
var values = scale(dict[paramIter], params[paramIter]);
|
|
||||||
result = add(values, result);
|
|
||||||
}
|
|
||||||
|
|
||||||
var max = _.max(_.values(result), function(value) {
|
|
||||||
return Math.abs(value);
|
|
||||||
});
|
|
||||||
|
|
||||||
if (max > 0.0) {
|
|
||||||
for (var resultIter in result) {
|
|
||||||
result[resultIter] = result[resultIter] / max;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
function walkMatches(data, features, minScore, callback) {
|
function walkMatches(data, features, minScore, callback) {
|
||||||
for (var i = 0, count = data.records.length; i < count; ++i) {
|
for (var i = 0, count = data.records.length; i < count; ++i) {
|
||||||
var record = data.records[i];
|
var record = data.records[i];
|
||||||
@ -174,32 +133,32 @@ function loadDb(params) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function addKeyword(query, callback) {
|
function addKeyword(query, callback) {
|
||||||
var keyword = (query.keyword || '').toLowerCase();
|
// var keyword = (query.keyword || '').toLowerCase();
|
||||||
if (!/^[a-zA-Z0-9]+$/.test(keyword)) {
|
// if (!/^[a-zA-Z0-9]+$/.test(keyword)) {
|
||||||
callback({
|
// callback({
|
||||||
keyword: keyword,
|
// keyword: keyword,
|
||||||
success: false
|
// success: false
|
||||||
});
|
// });
|
||||||
}
|
// }
|
||||||
else {
|
// else {
|
||||||
getKeywords(function(keywords) {
|
// getKeywords(function(keywords) {
|
||||||
var features = combine(keywords, query.params);
|
// var features = combine(keywords, query.params);
|
||||||
var values = [
|
// var values = [
|
||||||
keyword,
|
// keyword,
|
||||||
features.food || 0.0,
|
// features.food || 0.0,
|
||||||
features.service || 0.0,
|
// features.service || 0.0,
|
||||||
features.value || 0.0,
|
// features.value || 0.0,
|
||||||
features.atmosphere || 0.0
|
// features.atmosphere || 0.0
|
||||||
];
|
// ];
|
||||||
|
|
||||||
pool.query('INSERT INTO keywords VALUES(?, ?, ?, ?, ?)', values, function(err) {
|
// pool.query('INSERT INTO keywords VALUES(?, ?, ?, ?, ?)', values, function(err) {
|
||||||
callback({
|
// callback({
|
||||||
keyword: keyword,
|
// keyword: keyword,
|
||||||
success: err === null
|
// success: err === null
|
||||||
});
|
// });
|
||||||
});
|
// });
|
||||||
});
|
// });
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
function removeKeyword(query, callback) {
|
function removeKeyword(query, callback) {
|
||||||
@ -267,6 +226,15 @@ function getData(callback) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getParameters(callback) {
|
||||||
|
getKeywords(function(keywords) {
|
||||||
|
callback({
|
||||||
|
keywords: keywords,
|
||||||
|
features: [ 'food', 'service', 'atmosphere', 'value' ]
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function execQuery(query, callback) {
|
function execQuery(query, callback) {
|
||||||
getData(function(data) {
|
getData(function(data) {
|
||||||
var searchResults = findRecords(
|
var searchResults = findRecords(
|
||||||
@ -306,6 +274,6 @@ module.exports = {
|
|||||||
'loadDb': loadDb,
|
'loadDb': loadDb,
|
||||||
'addKeyword': addKeyword,
|
'addKeyword': addKeyword,
|
||||||
'removeKeyword': removeKeyword,
|
'removeKeyword': removeKeyword,
|
||||||
'getKeywords': getKeywords,
|
'getParameters': getParameters,
|
||||||
'execQuery': execQuery
|
'execQuery': execQuery
|
||||||
};
|
};
|
||||||
|
@ -43,9 +43,9 @@ function main(staticFiles, port) {
|
|||||||
user: 'hscd'
|
user: 'hscd'
|
||||||
});
|
});
|
||||||
|
|
||||||
app.use('/get_keywords', function(req, res) {
|
app.use('/get_parameters', function(req, res) {
|
||||||
search.getKeywords(function(keywords) {
|
search.getParameters(function(parameters) {
|
||||||
res.json(keywords);
|
res.json(parameters);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -55,12 +55,6 @@ function main(staticFiles, port) {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
app.use('/remove_keyword', function(req, res) {
|
|
||||||
search.removeKeyword(req.query, function(results) {
|
|
||||||
res.json(results);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
app.use('/search', function(req, res) {
|
app.use('/search', function(req, res) {
|
||||||
search.execQuery(req.query, function(results) {
|
search.execQuery(req.query, function(results) {
|
||||||
res.json(results);
|
res.json(results);
|
||||||
|
Loading…
Reference in New Issue
Block a user