Skip to content

Commit

Permalink
ai,meal planner,profile upgrade
Browse files Browse the repository at this point in the history
  • Loading branch information
Dogapinarr committed May 22, 2024
1 parent 20ce0ed commit 960a798
Show file tree
Hide file tree
Showing 6 changed files with 360 additions and 102 deletions.
170 changes: 155 additions & 15 deletions recommendSystem/recommend.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,27 @@
import pandas as pd
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.metrics.pairwise import linear_kernel
from azure.storage.blob import BlobServiceClient, BlobClient, ContainerClient
import requests
import json
from recipeRecDTO import RecipeRecommendationObject


app = Flask(__name__)

sas_token = "sp=racwdyti&st=2024-05-14T12:06:34Z&se=2024-06-04T20:06:34Z&sv=2022-11-02&sr=b&sig=%2FYZk57JEkcpWlOKhm9rl5y2roVMQbwl%2Fa%2FgyPS5uL5A%3D"
blob_url = "https://blobrecipeimages.blob.core.windows.net/data-set-kaggle/recipes_with_no_tags_and_cuisine.csv?" + sas_token
#Blob Service Client oluştur
blob_service_client = BlobServiceClient(account_url="https://blobrecipeimages.blob.core.windows.net", credential=sas_token)

# Container Client oluştur
container_client = blob_service_client.get_container_client("data-set-kaggle")

#blob_url="https://blobrecipeimages.blob.core.windows.net/data-set-kaggle/recipes_with_no_tags_and_cuisine.csv?"


# Load recipe data
recipe_data = pd.read_csv('https://blobrecipeimages.blob.core.windows.net/data-set-kaggle/recipes_with_no_tags_and_cuisine.csv')
recipe_data = pd.read_csv(blob_url)
recipe_data = recipe_data.dropna(subset=['ingredients', 'cuisine_path'])
recipe_data['total_time'] = recipe_data['total_time'].astype(str)
recipe_data['combined_features'] = recipe_data['total_time'] + ' ' + recipe_data['ingredients'] + ' ' + recipe_data['cuisine_path']
Expand All @@ -15,25 +31,149 @@
tfidf_vectorizer = TfidfVectorizer(stop_words='english')
tfidf_matrix = tfidf_vectorizer.fit_transform(recipe_data['combined_features'])
cosine_sim = linear_kernel(tfidf_matrix, tfidf_matrix)
def get_recommendations(title=None, ingredients=None):
matching_recipes = recipe_data

if title:
matching_recipes = matching_recipes[matching_recipes['recipe_name'].str.contains(title, case=False)]

if ingredients:
ingredient_query = '|'.join(ingredients)
matching_recipes = matching_recipes[matching_recipes['ingredients'].str.contains(ingredient_query, case=False)]

def get_recommendations(query):
matching_recipes = recipe_data[recipe_data['recipe_name'].str.contains(query, case=False)]
if matching_recipes.empty:
return []
selected_recipe = matching_recipes.iloc[0]['recipe_name']
idx = recipe_data[recipe_data['recipe_name'] == selected_recipe].index[0]
sim_scores = list(enumerate(cosine_sim[idx]))

combined_features_with_ingredients = matching_recipes['total_time'] + ' ' + matching_recipes['ingredients'] + ' ' + matching_recipes['cuisine_path']
tfidf_matrix_with_ingredients = tfidf_vectorizer.fit_transform(combined_features_with_ingredients)
cosine_sim_with_ingredients = linear_kernel(tfidf_matrix_with_ingredients, tfidf_matrix_with_ingredients)

# Calculate similarity scores for matched recipes
sim_scores = []
for i in range(len(matching_recipes)):
sim_scores.append((i, cosine_sim_with_ingredients[i,-1])) # similarity score for the last recipe

sim_scores = sorted(sim_scores, key=lambda x: x[1], reverse=True)
sim_recipes = sim_scores[1:11]
return recipe_data['recipe_name'].iloc[[i[0] for i in sim_recipes]].tolist()
sim_recipes = sim_scores[:5] # Take the top 5 similar recipes
recipe_indices = [i[0] for i in sim_recipes]
recommended_recipes = [matching_recipes.iloc[idx] for idx in recipe_indices]

return recommended_recipes

@app.route('/recommend', methods=['GET'])



@app.route('/hello', methods=['GET'])
def hello():
return "hellooooo"


@app.route('/get-recommendations', methods=['GET'])
def recommend():
query = request.args.get('query')
if not query:
return jsonify({"error": "No query parameter provided"}), 400
recommendations = get_recommendations(query)
return jsonify({"recommendations": recommendations})
title = request.args.get('title')
ingredients = request.args.get('ingredients')

if not title and not ingredients:
return jsonify({'error': 'Please provide at least one parameter.'}), 400

if ingredients and ":" in ingredients:
ingredients = format_data_ingredients(ingredients)

recommendations = get_recommendations(title, ingredients)

if not recommendations:
return jsonify({'message': 'No recipes found matching the criteria.'}), 404

# Convert recommendations to RecipeRecommendationObject
recommendation_objects = [create_recommendation_object(recipe) for recipe in recommendations]

return jsonify({'recommendations': [vars(obj) for obj in recommendation_objects]})

def format_data_ingredients(ingredients):
formatted_ingredients = []
for ingredient in ingredients.split(','):
parts = ingredient.strip().split(':')
formatted_ingredient = parts[0].strip() if len(parts) > 1 else parts[0].strip()
formatted_ingredients.append(formatted_ingredient)
return formatted_ingredients


def create_recommendation_object(recipe_row):
return RecipeRecommendationObject (
title=recipe_row['recipe_name'],
ingredients=recipe_row['ingredients'],
description=recipe_row['directions'],
cuisine=recipe_row['cuisine_path'],
timing=recipe_row['total_time'],
photoPathURL=recipe_row['img_src']
)

@app.route('/add-recipe-to-dataset', methods=['POST'])
def add_recipe_to_dataset():

global recipe_data # Declare recipe_data as global

data = request.json

# Extract data from request body
recipe_name = data.get('title', '')
prep_time = format_time(data.get('preparationTime', None))
cook_time = None
total_time = None
servings = None
yield_value = None
ingredients = data.get('ingredients', '')
directions = data.get('description', '')
rating = None
url = None
cuisine_path = data.get('cuisine', '')
nutrition = None
timing = None
img_src = data.get('photoPathURL', '')

# Process the data and add it to the dataset
# You can perform any necessary processing here, such as data validation and formatting
# Then add the recipe to the dataset
new_recipe = pd.DataFrame.from_dict({
'recipe_name': [recipe_name],
'prep_time': [prep_time],
'cook_time': [cook_time],
'total_time': [total_time],
'servings': [servings],
'yield': [yield_value],
'ingredients': [ingredients],
'directions': [directions],
'rating': [rating],
'url': [url],
'cuisine_path': [cuisine_path],
'nutrition': [nutrition],
'timing': [timing],
'img_src': [img_src]
})

recipe_data = pd.concat([recipe_data, new_recipe], ignore_index=True)

# Dosyayı bloba yükle
data = recipe_data.to_csv(index=False)
blob_client = container_client.get_blob_client(blob="recipes_with_no_tags_and_cuisine.csv")
blob_client.upload_blob(data, overwrite=True)

print("Veri başarıyla bloba yüklendi.")

return jsonify({"message": "Recipe added to dataset successfully"})

def format_time(minutes):
if not minutes:
return ''

hours, mins = divmod(minutes, 60)

if hours > 0 and mins > 0:
return f"{hours} hrs {mins} mins"
elif hours > 0:
return f"{hours} hrs"
else:
return f"{mins} mins"

if __name__ == '__main__':
app.run(debug=True)
app.run()
49 changes: 14 additions & 35 deletions scripts/userEditProfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,7 @@ document.addEventListener('DOMContentLoaded', function () {
];

var allergicFoodSection = document.querySelector('.allergic-food-section');
var otherFoodContainer = document.getElementById('other-food-container');

// Checkboxları oluştur
allergicFoods.forEach(function(food) {
var checkbox = document.createElement('input');
checkbox.type = 'checkbox';
Expand All @@ -22,13 +20,6 @@ document.addEventListener('DOMContentLoaded', function () {
allergicFoodSection.appendChild(document.createElement('br'));
});

// Diğer seçeneği için text kutusu oluştur
var otherInput = document.createElement('input');
otherInput.type = 'text';
otherInput.placeholder = 'Type: Allergy 1, Allergy 2';
otherInput.id = 'other-food-input';
otherFoodContainer.appendChild(otherInput);

var photoUpload = document.getElementById('photo-upload');
var photoFrame = document.getElementById('photo-frame');

Expand All @@ -47,74 +38,62 @@ document.addEventListener('DOMContentLoaded', function () {
});
});


const saveButton = document.getElementById("save-button");
saveButton.addEventListener("click", async function (event) {
event.preventDefault(); // Sayfanın yeniden yüklenmesini önle
event.preventDefault();

try {
// Kullanıcının girdiği bilgileri al
const bio = document.getElementById('bio').value;

// Seçilen alerjenleri al
const selectedFoods = [];
document.querySelectorAll('input[name="allergic-food"]:checked').forEach(function(checkbox) {
selectedFoods.push(checkbox.value);
});

// Diğer alerjeni al
let otherFoodInput = document.getElementById('other-food-input');
const otherFoodInput = document.getElementById('other-food-input');
if (otherFoodInput) {
const otherFoodValue = otherFoodInput.value.trim();
if (otherFoodValue !== '') {
selectedFoods.push(otherFoodValue);
}
}

// Boşlukları virgülle değiştir
const finalAllergiesString = selectedFoods.map(food => food.trim()).join(',');

// Kullanıcının girdiği diğer alanları al
const newPassword = document.getElementById('new-password').value;
const confirmPassword = document.getElementById('confirm-password').value;

// Kullanıcı fotoğrafını al
const photoUpload = document.getElementById('photo-upload');
const photoFile = photoUpload.files[0];

// Profil verilerini oluştur
const profileData = {
password: newPassword,
bio: bio,
allergicFoods: finalAllergiesString,
profilePhoto: photoFile
};
const formData = new FormData();
formData.append('password', newPassword);
formData.append('bio', bio);
formData.append('allergicFoods', finalAllergiesString);
if (photoFile) {
formData.append('profilePhoto', photoFile);
}

console.log(selectedFoods);
console.log('Selected Allergies:', selectedFoods);
console.log('Final Allergic Foods String:', finalAllergiesString);

// Profil verilerini kaydetme fonksiyonunu çağır
await saveProfile(profileData);
await saveProfile(formData);
} catch (error) {
console.error('Error saving profile:', error);
// Hata durumunda kullanıcıya bildirim gönderilebilir
// Örn: alert('Error saving profile: ' + error.message);
}
});


async function saveProfile(profileData) {
async function saveProfile(formData) {
const apiUrl = 'https://recipiebeckend.azurewebsites.net/user/save-user-profile';
const JWTAccessToken = sessionStorage.getItem('accessToken');

try {
const response = await fetch(apiUrl, {
method: 'PUT',
headers: {
'Authorization': JWTAccessToken,
'Content-Type': 'application/json'
'Authorization': JWTAccessToken
},
body: JSON.stringify(profileData),
body: formData
});

if (!response.ok) {
Expand Down
Loading

0 comments on commit 960a798

Please sign in to comment.