cook-mcp-windy
Version:
HowToCook MCP Server - Intelligent Chinese recipe management and meal planning for AI assistants
180 lines • 6.14 kB
JavaScript
import { Recipe } from '../types/index.js';
import { readFileSync } from 'fs';
import { fileURLToPath } from 'url';
import { dirname, join } from 'path';
// Get current directory for ES modules
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
// Load sample recipes from JSON file
const sampleRecipesJson = JSON.parse(readFileSync(join(__dirname, 'sampleRecipes.json'), 'utf-8'));
// Type assertion to ensure the JSON data matches our Recipe type
export const sampleRecipes = sampleRecipesJson;
/**
* Recipe data manager class
*/
export class RecipeDataManager {
recipes = [];
constructor(initialRecipes = sampleRecipes) {
this.recipes = [...initialRecipes];
}
/**
* Get all recipes
*/
getAllRecipes() {
return [...this.recipes];
}
/**
* Get recipe by ID
*/
getRecipeById(id) {
return this.recipes.find(recipe => recipe.id === id);
}
/**
* Get recipes by category
*/
getRecipesByCategory(category) {
return this.recipes.filter(recipe => recipe.category === category);
}
/**
* Search recipes by name or ingredients
*/
searchRecipes(query) {
const lowerQuery = query.toLowerCase();
return this.recipes.filter(recipe => recipe.name.toLowerCase().includes(lowerQuery) ||
recipe.description?.toLowerCase().includes(lowerQuery) ||
recipe.ingredients.some(ingredient => ingredient.name.toLowerCase().includes(lowerQuery)) ||
recipe.tags?.some(tag => tag.toLowerCase().includes(lowerQuery)));
}
/**
* Add a new recipe
*/
addRecipe(recipe) {
// Check if recipe with same ID already exists
const existingIndex = this.recipes.findIndex(r => r.id === recipe.id);
if (existingIndex !== -1) {
throw new Error(`Recipe with ID ${recipe.id} already exists`);
}
this.recipes.push(recipe);
}
/**
* Update an existing recipe
*/
updateRecipe(id, updatedRecipe) {
const index = this.recipes.findIndex(recipe => recipe.id === id);
if (index === -1) {
return null;
}
this.recipes[index] = {
...this.recipes[index],
...updatedRecipe,
id, // Ensure ID doesn't change
lastModified: new Date().toISOString()
};
return this.recipes[index];
}
/**
* Delete a recipe
*/
deleteRecipe(id) {
const index = this.recipes.findIndex(recipe => recipe.id === id);
if (index === -1) {
return false;
}
this.recipes.splice(index, 1);
return true;
}
/**
* Get recipes by multiple criteria
*/
getRecipesByCriteria(criteria) {
return this.recipes.filter(recipe => {
// Filter by categories
if (criteria.categories && criteria.categories.length > 0) {
if (!criteria.categories.includes(recipe.category)) {
return false;
}
}
// Filter by difficulty
if (criteria.difficulty && recipe.difficulty !== criteria.difficulty) {
return false;
}
// Filter by prep time
if (criteria.maxPrepTime) {
const prepMinutes = this.parseTimeInMinutes(recipe.prepTime);
if (prepMinutes > criteria.maxPrepTime) {
return false;
}
}
// Filter by cook time
if (criteria.maxCookTime) {
const cookMinutes = this.parseTimeInMinutes(recipe.cookTime);
if (cookMinutes > criteria.maxCookTime) {
return false;
}
}
// Filter by tags
if (criteria.tags && criteria.tags.length > 0) {
if (!recipe.tags || !criteria.tags.some(tag => recipe.tags.includes(tag))) {
return false;
}
}
return true;
});
}
/**
* Get recipe statistics
*/
getStatistics() {
const categoryCounts = {};
const difficultyCounts = {};
let totalPrepTime = 0;
let totalCookTime = 0;
this.recipes.forEach(recipe => {
// Count categories
categoryCounts[recipe.category] = (categoryCounts[recipe.category] || 0) + 1;
// Count difficulties
difficultyCounts[recipe.difficulty] = (difficultyCounts[recipe.difficulty] || 0) + 1;
// Sum times
totalPrepTime += this.parseTimeInMinutes(recipe.prepTime);
totalCookTime += this.parseTimeInMinutes(recipe.cookTime);
});
return {
totalRecipes: this.recipes.length,
categoryCounts,
difficultyCounts,
averagePrepTime: Math.round(totalPrepTime / this.recipes.length),
averageCookTime: Math.round(totalCookTime / this.recipes.length)
};
}
/**
* Parse time string to minutes
*/
parseTimeInMinutes(timeStr) {
const hourMatch = timeStr.match(/(\d+)小时/);
const minuteMatch = timeStr.match(/(\d+)分钟/);
let totalMinutes = 0;
if (hourMatch && hourMatch[1]) {
totalMinutes += parseInt(hourMatch[1]) * 60;
}
if (minuteMatch && minuteMatch[1]) {
totalMinutes += parseInt(minuteMatch[1]);
}
return totalMinutes;
}
/**
* Get random recipes
*/
getRandomRecipes(count) {
const shuffled = [...this.recipes].sort(() => 0.5 - Math.random());
return shuffled.slice(0, Math.min(count, this.recipes.length));
}
/**
* Get recipes suitable for a number of people
*/
getRecipesForServings(targetServings, tolerance = 2) {
return this.recipes.filter(recipe => Math.abs(recipe.servings - targetServings) <= tolerance);
}
}
// Create a default instance
export const recipeDataManager = new RecipeDataManager();
//# sourceMappingURL=recipeData.js.map