Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • xslanin/pv254-city-recommender
1 result
Show changes
Commits on Source (4)
Showing
with 230 additions and 73 deletions
......@@ -22,7 +22,13 @@ The dataset, found in the `data/` folder, is scraped from user pages of [nomadli
- Random (for reference and as a baseline)
- randomly sample `n` cities from `cities` dataset
- TripSimilarity using `trips` dataset
- TBD: Jirka
0. Groups cities based on user
1. Removes duplicities
2. Finds groups that satisfies user input (has same cities in group or biggest subsection if no group with full satisfaction)
3. From groups finds most cities with most occurrences (excluding user input)
4. Shuffle in groups positions (to avoid discrimination based on position)
5. Recommend first x (based on preferences)
- Minkowski distance on `cities` with imputed data, using SimilarityCoefficient on `trips` dataset
0. Impute the data - replace `-1` as missing values by most frequent value in that row
......
......@@ -2,6 +2,8 @@ from flask import Flask, render_template, url_for, request, redirect
from flask_sqlalchemy import SQLAlchemy
from datetime import datetime
import csv
from backend.views.RecommendationAlgorithmScore import scoreBlueprint
from .models.UserCityModel import UserCityModel
from .models.DestinationModel import DestinationModel
from .models import db
......@@ -36,6 +38,8 @@ def create_app(env_name):
app.register_blueprint(userCityBlueprint)
app.register_blueprint(recommendBlueprint)
app.register_blueprint(recommendationsBlueprint)
app.register_blueprint(scoreBlueprint)
with app.test_request_context():
db.init_app(app)
db.create_all()
......
from . import db
class ScoreModel(db.Model):
__tablename__ = "score"
algorithm_name = db.Column(db.String(200), primary_key=True, nullable=False, unique=True)
score = db.Column(db.Integer, nullable=False)
def __init__(self, data, algorithm_name, score):
self.algorithm_name = algorithm_name
self.score = score
......@@ -45,4 +45,27 @@ body {
/*when navigating through the items using the arrow keys:*/
background-color: DodgerBlue !important;
color: #ffffff;
}
\ No newline at end of file
}
div.info {
height:700px!important;
width: 45%!important;
position: relative;
margin-top: 30px;
float:right;
direction: ltr;
overflow:hidden;
}
.scroll {
unicode-bidi:bidi-override;
direction: rtl;
overflow-y: scroll;
overflow-x:hidden;
}
.info_inside{
position: absolute;
top: -65px;
left: -830px;
width: 1300px;
height: 1450px;
}
\ No newline at end of file
......@@ -272,21 +272,47 @@ var ingredients = ['ho-chi-minh-city', 'seoul', 'alicante', 'amsterdam', 'london
'ferrara', 'giza', 'bakersfield', 'lake-havasu-city', 'senggigi',
'lansing', 'vladivostok', 'indore', 'lucknow'];
let elements;
var addMore = document.getElementById("add");
if (addMore.addEventListener) {
addMore.addEventListener("click", myFunction);
let addMoreAuto = document.getElementsByName("city_name");
addMoreAuto.forEach(el => {
assignListeners(el);
});
function assignListeners(element) {
autocomplete(element, ingredients);
element.addEventListener("input", autoAdder);
element.addEventListener("input", autoRemover);
}
function myFunction(){
document.getElementById("first").insertAdjacentHTML('beforeend', "<input class='autocomplete' class='form-control' type='text' name='city_name'placeholder='Enter a city'/>");
elements = document.getElementsByClassName("autocomplete");
for (var i = 0; i < elements.length; i++){
autocomplete(elements[i], ingredients);
function autoAdder() {
let inputs = document.getElementsByName('city_name');
let allFull = true;
inputs.forEach(input => {
if (input.value == null || input.value === ""){
allFull = false
}
});
if (allFull){
document.getElementById("first").insertAdjacentHTML('beforeend', "<input class='autocomplete' class='form-control' type='text' name='city_name' placeholder='Enter a city'/>");
let els = document.getElementsByName("city_name");
let lastAdded = els[els.length - 1];
assignListeners(lastAdded);
}
}
elements = document.getElementsByClassName("autocomplete");
for (var i = 0; i < elements.length; i++){
autocomplete(elements[i], ingredients);
function autoRemover() {
let inputs = document.getElementsByName('city_name');
let first = true;
inputs.forEach(input => {
if (input.value == null || input.value === ""){
if (first){
first = false;
}else{
input.parentNode.removeChild(input);
}
}
});
}
\ No newline at end of file
function createOption(){
let newForm = document.createElement("OPTION");
}
function sendLike(elem, alg) {
let request = new XMLHttpRequest();
disableButtons(elem, "#b3ffe0")
// Open a new connection, using the GET request on the URL endpoint
request.open('GET', window.location.origin + '/like?alg=' + alg, true);
// Send request
request.send();
}
function sendDislike(elem, alg) {
let request = new XMLHttpRequest();
disableButtons(elem, "#bfbfbf")
// Open a new connection, using the GET request on the URL endpoint
request.open('GET', window.location.origin + '/dislike?alg=' + alg, true);
// Send request
request.send();
}
function disableButtons(elem, color){
elem.disabled = true;
elem.style.backgroundColor = color;
elem.parentNode.parentNode.style.backgroundColor = color;
}
function showInfo(city){
let iframe = document.getElementsByClassName("info_inside")[0];
iframe.parentNode.removeChild(iframe);
document.getElementsByClassName("info")[0].insertAdjacentHTML('beforeend', "<iframe class='info_inside' src='https://www.google.com/search?igu=1&ei=&q="+ city + "' frameborder='0' style='border:0' scrolling='no'></iframe>");
}
\ No newline at end of file
{% extends "bootstrap/base.html" %}
{% block title %}This is an example page{% endblock %}
{% block title %}Awesome Recommender{% endblock %}
{% block navbar %}
<div class="navbar navbar-fixed-top">
......
{% extends "bootstrap/base.html" %}
{% block title %}This is an example page{% endblock %}
{% block title %}Awesome Recommender{% endblock %}
{% block styles %}
{{super()}}
......@@ -9,46 +9,58 @@
{% block scripts %}
{{super()}}
<script src="{{url_for('static', filename='js/autocomplete.js')}}"></script>
<script src="{{ url_for('static', filename='js/autocomplete.js') }}"></script>
<script src="{{ url_for('static', filename='js/general.js') }}"></script>
{% endblock %}
{% block content %}
<h1 class="display-4">Travel destinations recommendations</h1>
{% if not results %}
<p>Enter a city / more cities that you've been to and liked</p>
<p>Enter cities that you've been to and liked</p>
<form action="/recommend/results" method="POST" autocomplete="off">
<divclass='col-xs-12 col-sm-12 col-md-10 col-lg-10'>
<div class='input-group', id='first'>
<div class='col-xs-12 col-sm-12 col-md-10 col-lg-10'>
<div class='input-group' , id='first'>
<input class="autocomplete" class='form-control' type='text' name='city_name' placeholder="Enter a city"/>
</div>
<button type="button" id="add" class="btn btn-light">Add a city</button>
<button type="submit" id="submit" value="submit" class="btn btn-light">Get recommendations</button>
<button type="submit" id="submit" value="submit" class="btn btn-light">Get recommendations</button>
</div>
</form>
{% endif %}
{% if results %}
<p>Input: {{cities}}</p>
{% for key, value in results.items() %}
<div class="col-xs-6">
<h2 class="sub-header">{{key}}</h2>
<div class="table-responsive"></div>
<table class="table table-striped" >
<thead>
<th>City</th>
<th>Because you liked</th>
</thead>
{% for val in value %}
<tr>
<td><a href="https://www.google.com/search?q={{ val[0] }}">{{val[0]}}</a></td>
<td>{{val[2]}}</td>
</tr>
{% endfor %}
</table>
</div>
</div>
{% endfor %}
<p>Input: {{cities}}</p>
<div class="info">
<iframe class="info_inside"
src="https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d3309.3312622412445!2d-83.37737678492407!3d33.958324180631536!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x88f66cdecc8d0783%3A0x4f152e9d93fa5d6!2s170+College+Ave%2C+Athens%2C+GA+30601%2C+USA!5e0!3m2!1sen!2sie!4v1464026910465"
frameborder="0" style="border:0">
</iframe>
</div>
{% for key, value in results.items() %}
<div class="col-xs-6">
<h2 class="sub-header">{{key}}</h2>
<div class="table-responsive"></div>
<table class="table table-striped">
<thead>
<th>City</th>
<th>Because you liked</th>
</thead>
{% for val in value %}
<tr>
<td><a href="https://www.google.com/search?q={{ val[0] }}" target="_blank" onmouseover="showInfo('{{val[0]}}')">{{val[0]}}</a></td>
<td>{{val[2]}}</td>
<td>
<button type="button" onclick="sendLike(this, '{{key}}')">+1</button>
<button type="button" onclick="sendDislike(this, '{{key}}')">-1</button>
</td>
</tr>
{% endfor %}
</table>
</div>
</div>
{% endfor %}
{% endif %}
{% endblock %}
\ No newline at end of file
from flask import app, Blueprint, request
from . import db
from backend.models.ScoreModel import ScoreModel
scoreBlueprint = Blueprint('score', __name__, url_prefix='')
@scoreBlueprint.route('/like', methods=['GET'])
def like():
alg = request.args.get("alg")
score = ScoreModel.query.get(alg)
score.score = score.score + 1
db.session.merge(score)
db.session.commit()
db.session.flush()
return "OK"
@scoreBlueprint.route('/dislike', methods=['GET'])
def dislike():
alg = request.args.get("alg")
score = ScoreModel.query.get(alg)
score.score = score.score - 1
db.session.merge(score)
db.session.commit()
db.session.flush()
return "OK"
from http import HTTPStatus
from backend.models import db
from flask import json, render_template, request, redirect, Blueprint, Response
from ..models.UserCityModel import UserCityModel
from ..models.DestinationModel import DestinationModel
import sys
from flask import render_template, request, Blueprint
import os
sys.path.append(os.path.dirname(os.path.abspath(__file__))+ "/../../src/")
from algorithms.CosineSimilarityWithSimilarityCoefficient import CosineSimilarityWithSimilarityCoefficient
from algorithms.CosineSimilarity import CosineSimilarity
from algorithms.CollaborativeFiltering import CollaborativeFiltering
from algorithms.RandomSimilarity import RandomSimilarity
from algorithms.TripSimilarity import TripSimilarity
from algorithms.OtherSimilarity import OtherSimilarity
from algorithms.OtherSimilarityWithSimilarityCoefficient import OtherSimilarityWithSimilarityCoefficient
import sys
from flask import render_template, request, Blueprint
from src.algorithms.CosineSimilarityWithSimilarityCoefficient import CosineSimilarityWithSimilarityCoefficient
from ..models.DestinationModel import DestinationModel
sys.path.append(os.path.dirname(os.path.abspath(__file__)) + "/../../src/")
from src.algorithms.CosineSimilarity import CosineSimilarity
from src.algorithms.CollaborativeFiltering import CollaborativeFiltering
from src.algorithms.RandomSimilarity import RandomSimilarity
from src.algorithms.TripSimilarity import TripSimilarity
from src.algorithms.OtherSimilarityWithSimilarityCoefficient import OtherSimilarityWithSimilarityCoefficient
recommendationsBlueprint = Blueprint(
'recommendations', __name__, url_prefix='')
@recommendationsBlueprint.route('/recommend/results', methods=['POST'])
def recommendationsResults():
cities = request.form.getlist("city_name")
result = DestinationModel.query.all()
available_cities = [str(r).split(" ")[1].split(">")[0] for r in result]
......@@ -46,7 +45,9 @@ def recommendationsResults():
if len(cities) != 0:
recommendations = {
masking_dict["Manhattan iteratively imputed data with SimilarityCoefficient"]: other_sim_manhattan.similarity_on_iteratively_imputed_data(cities),
masking_dict[
"Manhattan iteratively imputed data with SimilarityCoefficient"]: other_sim_manhattan.similarity_on_iteratively_imputed_data(
cities),
masking_dict["SVD"]: collab.similarity_with_SVD(cities),
masking_dict["Random"]: random.random_similarity(cities),
masking_dict["Cosine Raw data with SimilarityCoefficient"]: cosine_sim.similarity_on_raw_data(cities),
......
......@@ -5,7 +5,7 @@ from ..models.UserCityModel import UserCityModel
recommendBlueprint = Blueprint('recommend', __name__, url_prefix='')
@recommendBlueprint.route('/recommend', methods=['GET'])
def recommendInput():
return render_template("recommend.html")
\ No newline at end of file
return render_template("recommend.html")
from algorithms.recommender import *
from algorithms.helpers import *
from src.algorithms.recommender import *
from src.algorithms.helpers import *
from scipy.sparse.linalg import svds
#from recommender import *
#from helpers import *
......
from algorithms.recommender import *
from algorithms.helpers import *
from src.algorithms.recommender import *
from src.algorithms.helpers import *
class CosineSimilarity():
......
from algorithms.recommender import *
from algorithms.helpers import *
from src.algorithms.recommender import *
from src.algorithms.helpers import *
from src.algorithms.helpers import load_data
class CosineSimilarityWithSimilarityCoefficient():
......
from algorithms.recommender import *
from algorithms.helpers import *
from src.algorithms.recommender import *
from src.algorithms.helpers import *
class OtherSimilarity():
......
from algorithms.recommender import *
from algorithms.helpers import *
from src.algorithms.recommender import *
from src.algorithms.helpers import *
class OtherSimilarityWithSimilarityCoefficient():
......
from algorithms.recommender import *
from algorithms.helpers import *
from src.algorithms.recommender import *
from src.algorithms.helpers import *
class RandomSimilarity():
......
......@@ -4,7 +4,7 @@ import random
from typing import List, Dict
from sympy.utilities.iterables import multiset_permutations
import pandas as pd
from algorithms.helpers import *
from src.algorithms.helpers import *
#from helpers import *
"""
DEBUG if true, there will be small debug logs (on system.in)
......