Skip to content

Commit

Permalink
Merge main
Browse files Browse the repository at this point in the history
  • Loading branch information
Tamalera committed Oct 23, 2022
2 parents 37a011d + a6410c2 commit 29cea2f
Show file tree
Hide file tree
Showing 13 changed files with 3,544 additions and 26 deletions.
82 changes: 67 additions & 15 deletions CreateSearchIndex/Program.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System.Diagnostics;
using System.Globalization;
using System.Text.Json;
using System.Text.RegularExpressions;
using CreateSearchIndex;
using CsvHelper;
Expand All @@ -19,8 +20,10 @@ public class Program
const LuceneVersion AppLuceneVersion = LuceneVersion.LUCENE_48;
const string FIELD_INGREDIENTS = "INGREDIENTS";
const string FIELD_RECIPE_NAME = "RECIPE";
const string FIELD_INGREDIENTS_RAW = "INGREDIENTS_RAW";
const string FIELD_STEPS = "STEPS";

public static void Main(string[] args)
public static int Main(string[] args)
{
string? basePath = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
string indexPath = Path.Combine(basePath, "index");
Expand All @@ -30,7 +33,23 @@ public static void Main(string[] args)
StandardAnalyzer analyzer = new StandardAnalyzer(AppLuceneVersion);

// CreateIndex(dir, analyzer);
SearchInIndex(dir, analyzer);

string? searchTerms = string.Join(" ", args);
if (string.IsNullOrWhiteSpace(searchTerms))
{
// No search terms -> No output
return -1;
}

if (TryGetRecipes(dir, analyzer, searchTerms, out List<Recipe> recipes))
{
string jsonString = JsonSerializer.Serialize(recipes);
Console.Out.WriteLine(jsonString);
return 0;
}

// No results -> No output
return -1;
}

public static void DeleteIndex(string indexPath)
Expand All @@ -43,7 +62,7 @@ public static void DeleteIndex(string indexPath)

public static void CreateIndex(Directory dir, StandardAnalyzer analyzer)
{
Console.WriteLine("Creating index");
Trace.WriteLine("Creating index");
Stopwatch watch = Stopwatch.StartNew();

var indexConfig = new IndexWriterConfig(AppLuceneVersion, analyzer);
Expand Down Expand Up @@ -78,28 +97,27 @@ public static void CreateIndex(Directory dir, StandardAnalyzer analyzer)

Document doc = new Document
{
// This field is searchable by the user.
new TextField(FIELD_INGREDIENTS, ingredientsAsString, Field.Store.NO),

// These values can be returned from the found document. (and returned to the client)
new StoredField(FIELD_RECIPE_NAME, record.Name),
new TextField(FIELD_INGREDIENTS, ingredientsAsString, Field.Store.NO)
new StoredField(FIELD_INGREDIENTS_RAW, record.IngredientsRaw),
new StoredField(FIELD_STEPS, record.Steps)
};
writer.AddDocument(doc);
recipeCount++;
}

writer.Flush(triggerMerge: false, applyAllDeletes: false);
watch.Stop();
Console.WriteLine($"Done ({watch.ElapsedMilliseconds}). Index created with {writer.NumDocs} documents.");
Trace.WriteLine($"Done ({watch.ElapsedMilliseconds}). Index created with {writer.NumDocs} documents.");
}

public static void SearchInIndex(Directory dir, StandardAnalyzer analyzer)
public static bool TryGetRecipes(Directory dir, StandardAnalyzer analyzer, string searchTerms, out List<Recipe> recipes)
{
Console.Write("Enter search terms: ");
string? searchTerms = Console.ReadLine();
recipes = new List<Recipe>();

if (searchTerms is null)
{
return;
}

DirectoryReader directoryReader = DirectoryReader.Open(dir);
IndexSearcher indexSearcher = new IndexSearcher(directoryReader);

Expand All @@ -108,11 +126,45 @@ public static void SearchInIndex(Directory dir, StandardAnalyzer analyzer)
Query query = parser.Parse(searchTerms);
ScoreDoc[] hits = indexSearcher.Search(query, null, 10).ScoreDocs;

Console.Write("Hits:");
Trace.WriteLine("Hits:");
foreach (ScoreDoc hit in hits)
{
Document? foundDoc = indexSearcher.Doc(hit.Doc);
Console.WriteLine(foundDoc.Get(FIELD_RECIPE_NAME));
recipes.Add(ConvertDocumentToRecipe(foundDoc));
}

Recipe ConvertDocumentToRecipe(Document doc)
{
Regex matchSteps = new Regex(@"'(.*?)(?<!\\)'", RegexOptions.Compiled);
Regex matchIngredientsRaw = new Regex("\"(.*?)(?<!\\\\)\"", RegexOptions.Compiled);

string stepsField = doc.Get(FIELD_STEPS);
List<string> steps = new List<string>();
foreach (Match match in matchSteps.Matches(stepsField))
{
steps.Add(match.Groups[1].Value);
}

List<string> ingredientsRaw = new List<string>();
string ingredientsRawField = doc.Get(FIELD_INGREDIENTS_RAW);
foreach (Match match in matchIngredientsRaw.Matches(ingredientsRawField))
{
string value = match.Groups[1].Value;

// Replace multiple whitespace characters with single whitespace.
value = Regex.Replace(value, @"\s+", " ");

ingredientsRaw.Add(value);
}

return new Recipe
{
Name = doc.Get(FIELD_RECIPE_NAME),
IngredientsWithQuantity = ingredientsRaw,
Steps = steps
};
}

return recipes.Count > 0;
}
}
10 changes: 10 additions & 0 deletions CreateSearchIndex/Recipe.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
namespace CreateSearchIndex;

public class Recipe
{
public string Name { get; set; }

public List<string> Steps { get; set; }

public List<string> IngredientsWithQuantity { get; set; }
}
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,3 +45,7 @@ npm run lint
```

:meat_on_bone: :computer: :green_heart: :poultry_leg: :rainbow:

### Documentation

The google presentation is [here](https://docs.google.com/presentation/d/15kZCKr3lPAo_j7qtFoXbP1KHa1h_AUIR23ijlMK8sqs/edit?usp=sharing)
67 changes: 63 additions & 4 deletions backend/controller/imageRecognition.controller.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,72 @@
var request = require('request');
const fs = require("fs")

const token = "275027b62452734123aa166829ecffa1ada17ecb"

/**
* @function CreateRecipie
* @function extractIngredients
* @param req
* @param res
*/
const extraIngredients = async (req, res) => {
return res.send("Do your magic");

/**
* Frontend Developer Notes: Pass the image and enctype as form data
* Example: 'fridge_image': {
'value': fs.createReadStream('/image.jpeg'),
'options': {
'filename': 'image.jpeg',
'contentType': null
}
},
'enctype': 'multipart/form-data'
*/

const extractIngredients = async (req, res) => {
try {
var options = {
'method': 'POST',
'url': 'https://api.logmeal.es/v2/image/segmentation/complete',
'headers': {
'Authorization': `Bearer ${token}`
},
formData: {
'image': {
'value': fs.createReadStream(req.file.path),
'options': {
'filename': 'image.jpeg',
'contentType': null
}
}
}
};

request(options, function (error, response) {
if (response.statusCode != 200) {
return res.status(response.statusCode).send({error: response.body});
}

var options = {
'method': 'POST',
'url': 'https://api.logmeal.es/v2/recipe/ingredients',
'headers': {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
"imageId": JSON.parse(response.body).imageId
})
};

request(options, (error, response) => {
parsedData = JSON.parse(response.body).foodName
return res.status(200).send({foodItems: parsedData});
});
});
} catch(err) {
return res.status(500).send({error: "Server glitch" + err});
}
};

module.exports = {
extraIngredients
extractIngredients
};
19 changes: 16 additions & 3 deletions backend/controller/recipieCreator.controller.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,26 @@
const { promisify } = require('util');
var exec = promisify(require('child_process').exec)

/**
* @function CreateRecipie
* @param req
* @param res
*/
const CreateRecipie = async (req, res) => {
return res.send("Do your magic");
};

/**
* Frontend Developer Notes: Pass foodItems in the body.
* Example: body: { foodItem: ["lettuce", "beef", "tomatoes", "beans"]}
*/
const CreateRecipie = async (req, res) => {
try {
const ingredients = req.body.foodItems ? req.body.foodItems.join(" ") : "tomatoes pasta meat"
exec("/Users/maryem/Documents/Archive/CreateSearchIndex " + `${ingredients}`, function(error, stdout, stderr) {
return res.status(200).send(JSON.parse(stdout))
});
} catch (err) {
return res.status(500).send({error: "server glitch"})
}
}
module.exports = {
CreateRecipie,
};
5 changes: 4 additions & 1 deletion backend/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ const express = require("express");
const app = express();
const cors = require("cors");
const url = require("url");
const { application } = require("express");
const index = require("./routes/index.routes")
const bodyParser = require('body-parser');

app.use(cors());

Expand All @@ -16,6 +16,9 @@ app.use(function (req, res, next) {
next();
});

app.use(bodyParser.json())
app.use(bodyParser.urlencoded({ extended: true }));

app.use("/", index)

module.exports = app
19 changes: 19 additions & 0 deletions backend/middleware/upload.middleware.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
const multer = require("multer");

const storage = multer.diskStorage({
destination: (req, file, cb) => {
cb(null, 'uploads');
},
filename: (req, file, cb) => {
cb(null, file.originalname)
}
});

const upload = multer({
storage: storage,
limits: {
fileSize: 1024 * 1024 * 5 // max 1mb for image size
}
});

module.exports = upload;

0 comments on commit 29cea2f

Please sign in to comment.