Developpez-un-algorithme-de-recherche-en-JavaScript

Benchmark created on


Description

teste de version A et B

Preparation HTML

<!DOCTYPE html>
<html>

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  
    <title>Les Petits Plats</title>
    <link rel="stylesheet" type="text/css" href="./css/style.css">
    <link rel="stylesheet" type="text/css" href="./css/filter.css">
    <link rel="preconnect" href="https://fonts.googleapis.com">
    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
    <link href="https://fonts.googleapis.com/css2?family=Anton&display=swap" rel="stylesheet">
    <link href="https://fonts.googleapis.com/css2?family=Manrope:wght@200;300;400;500&display=swap" rel="stylesheet">
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css" integrity="sha512-..." crossorigin="anonymous" />



</head>

<body>
    <header>
        <h1 style="display: none;">Les Petits Plats</h1>

        <img src="asset/img/Logo.png" alt="logo">
        <h2>CHERCHEZ PARMI PLUS DE 1500 RECETTES DU QUOTIDIEN, SIMPLES ET DÉLICIEUSES</h2>
        <div id="search-bar">
            <input type="text" id="main-search-input" placeholder="Rechercher...">
        </div>
    </header>

    <main>
      <div class="row">
        <div class="container">
          <div class="searchInput">
            <input type="text" placeholder="Ingrédients">
            <div class="resultBox">
              <!-- here list are inserted from javascript -->
            </div>
            <div class="icon"><i class="fas fa-angle-up"></i></div>
          </div>
          <div class="selectedIngredients"></div>
        </div>
      
        <div class="container">
          <div class="ustensilsearchInput">
            <input type="text" placeholder="Appareils ">
            <div class="ustensilsresultBox">
              <!-- here list are inserted from javascript -->
            </div>
            <div class="icon"><i class="fas fa-angle-up"></i></div>
          </div>
          <div class="selectedUstensils"></div>
        </div>
        <div class="container">
          <div class="appliancesearchInput">
            <input type="text" placeholder="Ustensiles">
       
            <div class="appliancesresultBox">
           
            </div>
            <div class="icon"><i class="fas fa-angle-up"></i></div>
          </div>
          <div class="selectedAppliances"></div>
        </div>
      
       
      </div>
    
          
          
          
        
        
        <div id="selected-keywords-container">
            <ul id="keyword-tags-list"></ul>
        </div>
        <div id="results">
            <!-- Résultats de recherche ici -->
        </div>
    </main>

    <script src="./script/script.js" type="module"></script>

</body>

</html>

Test runner

Ready to run.

Testing in
TestOps/sec
version A
import RecipeFetcher from './moduel/RecipeFetcher.js';
import IngredientManager from './moduel/IngredientManager.js';
import ApplianceManager from './moduel/ApplianceManager.js';
import UstensilManager from './moduel/UstensilManager.js';
import Autocomplete from './moduel/Autocomplete.js';

export class RecipeApp {
  constructor() {
    this.recipes = [];
    this.resultsContainer = document.getElementById('results');
    this.searchInput = document.getElementById('main-search-input');

    this.ingredientManager = new IngredientManager();
    this.applianceManager = new ApplianceManager();
    this.ustensilManager = new UstensilManager();

    this.loadRecipesAndKeywords();
    this.addEventListeners();
  }

  async loadRecipesAndKeywords() {
    try {
      const apiUrl = './script/data/recette.json';
      const recipeFetcher = new RecipeFetcher(apiUrl);
      this.recipes = await recipeFetcher.fetchRecipes();

      this.displayRecipes(this.recipes);

      // Instanciate Autocomplete for ingredients, appliances, and ustensils here
      const ingredientAutocomplete = new Autocomplete(
        document.querySelector(".searchInput"),
        document.querySelector(".resultBox"),
        this.ingredientManager,
        this.recipes,
        'ingredients'
      );

      const applianceAutocomplete = new Autocomplete(
        document.querySelector(".appliancesearchInput"),
        document.querySelector(".appliancesresultBox"),
        this.applianceManager,
        this.recipes,
        'appliances'
      );

      const ustensilAutocomplete = new Autocomplete(
        document.querySelector(".ustensilsearchInput"),
        document.querySelector(".ustensilsresultBox"),
        this.ustensilManager,
        this.recipes,
        'ustensils'
      );
    } catch (error) {
      console.error('Une erreur s\'est produite lors du chargement des recettes :', error);
    }
  }

  addEventListeners() {
    this.searchInput.addEventListener('input', () => {
      const searchTerm = this.searchInput.value.trim();
      this.searchRecipes(searchTerm);
    });

    // Add event listeners for ingredient, appliance, and ustensil selections
    this.ingredientManager.onChange(() => {
      const searchTerm = this.searchInput.value.trim();
      this.searchRecipes(searchTerm);
    });

    this.applianceManager.onChange(() => {
      const searchTerm = this.searchInput.value.trim();
      this.searchRecipes(searchTerm);
    });

    this.ustensilManager.onChange(() => {
      const searchTerm = this.searchInput.value.trim();
      this.searchRecipes(searchTerm);
    });
    
  }



  filterRecipesByKeywords(searchTerm) {
    const keywordsFromSearch = searchTerm.toLowerCase().split(' ');
    const selectedIngredients = this.ingredientManager.getSelectedIngredients().map(keyword => keyword.toLowerCase());
    const selectedAppliances = this.applianceManager.getSelectedAppliances().map(keyword => keyword.toLowerCase());
    const selectedUstensils = this.ustensilManager.getSelectedUstensils().map(keyword => keyword.toLowerCase());
  
    const allKeywords = [...keywordsFromSearch, ...selectedIngredients, ...selectedAppliances, ...selectedUstensils];
  
    const filteredRecipes = [];
  
    for (const recipe of this.recipes) {
      const searchFields = [
        recipe.name.toLowerCase(),
        recipe.description.toLowerCase(),
      ];
  
      for (const ingredient of recipe.ingredients) {
        searchFields.push(ingredient.ingredient.toLowerCase());
      }
  
      searchFields.push(recipe.appliance.toLowerCase());
  
      for (const ustensil of recipe.ustensils) {
        searchFields.push(ustensil.toLowerCase());
      }
  
      const matchesAllKeywords = allKeywords.every(keyword => {
        return searchFields.some(field => field.includes(keyword));
      });
  
      if (matchesAllKeywords) {
        filteredRecipes.push(recipe);
      }
    }
  
    return filteredRecipes;
  }
  
  

  searchRecipes(searchTerm) {
    const filteredRecipes = this.filterRecipesByKeywords(searchTerm);
    this.displayRecipes(filteredRecipes);
  }

  fuzzySearch(str, searchTerm) {
    return str.includes(searchTerm);
  }

  displayRecipes(recipes) {
    this.resultsContainer.innerHTML = '';

    if (recipes.length === 0) {
      this.resultsContainer.innerHTML = 'Aucune recette trouvée.';
      return;
    }

    recipes.forEach(recipe => {
      const recipeElement = this.createRecipeElement(recipe);
      this.resultsContainer.appendChild(recipeElement);
    });
  }

  createRecipeElement(recipe) {
    const template = `
      <div class="recipe">
        <img src="asset/img/${recipe.image}" alt="${recipe.name}">
        <p class="time">${recipe.time} min </p>
        <div class="block">
          <h3>${recipe.name}</h3><br>
          <p>RECETTE</p>
          <p>${recipe.description}</p>
          <h4>Ingrédients:</h4>
          <div class="ingredients-list">
            <ul class="ingredients-column">
              ${recipe.ingredients
                .slice(0, Math.ceil(recipe.ingredients.length / 2))
                .map(ingredient => `
                  <li>
                    <p class="bol">${ingredient.ingredient}</p>
                    ${ingredient.quantity ? `<p>${ingredient.quantity} ${ingredient.unit || ''}</p>` : ''}
                  </li>
                `)
                .join('')}
            </ul>
            <ul class="ingredients-column">
              ${recipe.ingredients
                .slice(Math.ceil(recipe.ingredients.length / 2))
                .map(ingredient => `
                  <li>
                    <p class="bol">${ingredient.ingredient}</p>
                    ${ingredient.quantity ? `<p>${ingredient.quantity} ${ingredient.unit || ''}</p>` : ''}
                  </li>
                `)
                .join('')}
            </ul>
          </div>
        </div>
      </div>
    `;

    const recipeElement = document.createElement('div');
    recipeElement.innerHTML = template.trim();

    return recipeElement.firstChild;
  }
}

// Le reste du code reste inchangé
  const app = new RecipeApp();

ready
version B
import RecipeFetcher from './moduel/RecipeFetcher.js';
import IngredientManager from './moduel/IngredientManager.js';
import ApplianceManager from './moduel/ApplianceManager.js';
import UstensilManager from './moduel/UstensilManager.js';
import Autocomplete from './moduel/Autocomplete.js';

export class RecipeApp {
  constructor() {
    this.recipes = [];
    this.resultsContainer = document.getElementById('results');
    this.searchInput = document.getElementById('main-search-input');

    this.ingredientManager = new IngredientManager();
    this.applianceManager = new ApplianceManager();
    this.ustensilManager = new UstensilManager();

    this.loadRecipesAndKeywords();
    this.addEventListeners();
  }

  async loadRecipesAndKeywords() {
    try {
      const apiUrl = './script/data/recette.json';
      const recipeFetcher = new RecipeFetcher(apiUrl);
      this.recipes = await recipeFetcher.fetchRecipes();

      this.displayRecipes(this.recipes);

      // Instanciate Autocomplete for ingredients, appliances, and ustensils here
      const ingredientAutocomplete = new Autocomplete(
        document.querySelector(".searchInput"),
        document.querySelector(".resultBox"),
        this.ingredientManager,
        this.recipes,
        'ingredients'
      );

      const applianceAutocomplete = new Autocomplete(
        document.querySelector(".appliancesearchInput"),
        document.querySelector(".appliancesresultBox"),
        this.applianceManager,
        this.recipes,
        'appliances'
      );

      const ustensilAutocomplete = new Autocomplete(
        document.querySelector(".ustensilsearchInput"),
        document.querySelector(".ustensilsresultBox"),
        this.ustensilManager,
        this.recipes,
        'ustensils'
      );
    } catch (error) {
      console.error('Une erreur s\'est produite lors du chargement des recettes :', error);
    }
  }

  addEventListeners() {
    this.searchInput.addEventListener('input', () => {
      const searchTerm = this.searchInput.value.trim();
      this.searchRecipes(searchTerm);
    });

    // Add event listeners for ingredient, appliance, and ustensil selections
    this.ingredientManager.onChange(() => {
      const searchTerm = this.searchInput.value.trim();
      this.searchRecipes(searchTerm);
    });

    this.applianceManager.onChange(() => {
      const searchTerm = this.searchInput.value.trim();
      this.searchRecipes(searchTerm);
    });

    this.ustensilManager.onChange(() => {
      const searchTerm = this.searchInput.value.trim();
      this.searchRecipes(searchTerm);
    });
    
  }



  filterRecipesByKeywords(searchTerm) {
    const keywordsFromSearch = searchTerm.toLowerCase().split(' ');
    const selectedIngredients = this.ingredientManager.getSelectedIngredients().map(keyword => keyword.toLowerCase());
    const selectedAppliances = this.applianceManager.getSelectedAppliances().map(keyword => keyword.toLowerCase());
    const selectedUstensils = this.ustensilManager.getSelectedUstensils().map(keyword => keyword.toLowerCase());
  
    const allKeywords = [...keywordsFromSearch, ...selectedIngredients, ...selectedAppliances, ...selectedUstensils];
  
    return this.recipes.filter(recipe => {
      const searchFields = [
        recipe.name.toLowerCase(),
        recipe.description.toLowerCase(),
        ...recipe.ingredients.map(ingredient => ingredient.ingredient.toLowerCase()),
        recipe.appliance.toLowerCase(),
        ...recipe.ustensils.map(ustensil => ustensil.toLowerCase())
      ];
  
      return allKeywords.every(keyword => {
        return searchFields.some(field => field.includes(keyword));
      });
    });
  }
  

  searchRecipes(searchTerm) {
    const filteredRecipes = this.filterRecipesByKeywords(searchTerm);
    this.displayRecipes(filteredRecipes);
  }

  fuzzySearch(str, searchTerm) {
    return str.includes(searchTerm);
  }


  displayRecipes(recipes) {
    this.resultsContainer.innerHTML = '';
  
    if (recipes.length === 0) {
      this.resultsContainer.innerHTML = 'Aucune recette trouvée.';
      return;
    }
  
    // Obtenez les mots-clés d'ingrédients, d'appareils et d'ustensiles correspondant aux recettes présentes
    const ingredientKeywords = this.extractIngredientKeywords(recipes);
    const applianceKeywords = this.extractApplianceKeywords(recipes);
    const ustensilKeywords = this.extractUstensilKeywords(recipes);
  
    // Affichez les mots-clés dans les listes des mots-clés
    const ingredientList = document.querySelector(".resultBox");
    ingredientList.innerHTML = '';
    ingredientKeywords.forEach(keyword => {
      const listItem = document.createElement('li');
      listItem.textContent = keyword;
      ingredientList.appendChild(listItem);
    });
  
    const applianceList = document.querySelector(".appliancesresultBox");
    applianceList.innerHTML = '';
    applianceKeywords.forEach(keyword => {
      const listItem = document.createElement('li');
      listItem.textContent = keyword;
      applianceList.appendChild(listItem);
    });
  
    const ustensilList = document.querySelector(".ustensilsresultBox");
    ustensilList.innerHTML = '';
    ustensilKeywords.forEach(keyword => {
      const listItem = document.createElement('li');
      listItem.textContent = keyword;
      ustensilList.appendChild(listItem);
    });
  
    // Affichez les recettes
    recipes.forEach(recipe => {
      const recipeElement = this.createRecipeElement(recipe);
      this.resultsContainer.appendChild(recipeElement);
    });
  }
  
  
  

  extractIngredientKeywords(recipes) {
    const ingredients = recipes.reduce((acc, recipe) => {
      const recipeIngredients = recipe.ingredients.map(ingredient => ingredient.ingredient.toLowerCase());
      const validIngredients = recipeIngredients.filter(ingredient => typeof ingredient === 'string');
      return [...acc, ...validIngredients];
    }, []);
    return ingredients;
  }
  
  extractApplianceKeywords(recipes) {
    const appliances = recipes.reduce((acc, recipe) => {
      const validAppliance = typeof recipe.appliance === 'string' ? recipe.appliance.toLowerCase() : null;
      if (validAppliance) {
        return [...acc, validAppliance];
      }
      return acc;
    }, []);
    return appliances;
  }
  
  extractUstensilKeywords(recipes) {
    const ustensils = recipes.reduce((acc, recipe) => {
      const recipeUstensils = recipe.ustensils.map(ustensil => ustensil.toLowerCase());
      const validUstensils = recipeUstensils.filter(ustensil => typeof ustensil === 'string');
      return [...acc, ...validUstensils];
    }, []);
    return ustensils;
  }
  createRecipeElement(recipe) {
    const template = `
      <div class="recipe">
        <img src="asset/img/${recipe.image}" alt="${recipe.name}">
        <p class="time">${recipe.time} min </p>
        <div class="block">
          <h3>${recipe.name}</h3><br>
          <p>RECETTE</p>
          <p>${recipe.description}</p>
          <h4>Ingrédients:</h4>
          <div class="ingredients-list">
            <ul class="ingredients-column">
              ${recipe.ingredients
                .slice(0, Math.ceil(recipe.ingredients.length / 2))
                .map(ingredient => `
                  <li>
                    <p class="bol">${ingredient.ingredient}</p>
                    ${ingredient.quantity ? `<p>${ingredient.quantity} ${ingredient.unit || ''}</p>` : ''}
                  </li>
                `)
                .join('')}
            </ul>
            <ul class="ingredients-column">
              ${recipe.ingredients
                .slice(Math.ceil(recipe.ingredients.length / 2))
                .map(ingredient => `
                  <li>
                    <p class="bol">${ingredient.ingredient}</p>
                    ${ingredient.quantity ? `<p>${ingredient.quantity} ${ingredient.unit || ''}</p>` : ''}
                  </li>
                `)
                .join('')}
            </ul>
          </div>
        </div>
      </div>
    `;

    const recipeElement = document.createElement('div');
    recipeElement.innerHTML = template.trim();

    return recipeElement.firstChild;
  }
}

// Le reste du code reste inchangé
  const app = new RecipeApp();
ready

Revisions

You can edit these tests or add more tests to this page by appending /edit to the URL.