diff options
| author | Martial Simon <msimon_fr@hotmail.com> | 2025-09-15 01:08:27 +0200 |
|---|---|---|
| committer | Martial Simon <msimon_fr@hotmail.com> | 2025-09-15 01:08:27 +0200 |
| commit | c9b6b9a5ca082fe7c1b6f58d7713f785a9eb6a5c (patch) | |
| tree | 3e4f42f93c7ae89a364e4d51fff6e5cec4e55fa9 /graphs/js/foodTruck | |
add: graphs et rushs
Diffstat (limited to 'graphs/js/foodTruck')
| -rw-r--r-- | graphs/js/foodTruck/data.js | 70 | ||||
| -rw-r--r-- | graphs/js/foodTruck/dirtyFoodTruck.js | 172 | ||||
| -rw-r--r-- | graphs/js/foodTruck/foodTruck.js | 124 | ||||
| -rw-r--r-- | graphs/js/foodTruck/index.html | 40 | ||||
| -rw-r--r-- | graphs/js/foodTruck/sleep.js | 11 | ||||
| -rw-r--r-- | graphs/js/foodTruck/static/failedOnload.js | 9 | ||||
| -rw-r--r-- | graphs/js/foodTruck/static/index.js | 78 | ||||
| -rw-r--r-- | graphs/js/foodTruck/static/style.css | 200 |
8 files changed, 704 insertions, 0 deletions
diff --git a/graphs/js/foodTruck/data.js b/graphs/js/foodTruck/data.js new file mode 100644 index 0000000..dab9982 --- /dev/null +++ b/graphs/js/foodTruck/data.js @@ -0,0 +1,70 @@ +"use strict"; + +const stocks = { + mozzarella: 4, + parmesan: 5, + cheddar: 6, + "goat cheese": 7, + meat: 3, + chicken: 4, + salmon: 7, + tuna: 8, + bacon: 4, + mushrooms: 4, + tomato: 5, + "tomato sauce": 5, + "sour cream": 5, + fries: 20, + eggs: 10, + buns: 20, + lettuce: 5, + oregano: 8, +}; + +const recipes = { + pizza: { + Margarita: { + cheese: { + mozzarella: 4, + }, + sauce: "tomato sauce", + toppings: { oregano: 2 }, + }, + "4 cheese": { + cheese: { + mozzarella: 2, + parmesan: 2, + cheddar: 2, + "goat cheese": 2, + }, + toppings: { oregano: 2 }, + sauce: "tomato sauce", + }, + "Creamy 4 cheese": { + cheese: { + mozzarella: 2, + parmesan: 2, + cheddar: 2, + "goat cheese": 2, + }, + toppings: { oregano: 2 }, + sauce: "sour cream", + }, + }, + burger: { + Whoopty: { cheddar: 2, meat: 2, lettuce: 2, tomato: 2, buns: 2 }, + McChicken: { cheddar: 2, chicken: 1, lettuce: 2, buns: 2 }, + }, +}; + +if (typeof window === "undefined") { + module.exports = { + stocks, + recipes, + }; +} else { + if (!globalThis.stocks && !globalThis.recipes) { + globalThis.stocks = stocks; + globalThis.recipes = recipes; + } +} diff --git a/graphs/js/foodTruck/dirtyFoodTruck.js b/graphs/js/foodTruck/dirtyFoodTruck.js new file mode 100644 index 0000000..e0043e1 --- /dev/null +++ b/graphs/js/foodTruck/dirtyFoodTruck.js @@ -0,0 +1,172 @@ +if (typeof window === "undefined") { + if (!globalThis.stocks && !globalThis.recipes) { + const { stocks, recipes } = require("./data"); + + globalThis.stocks = stocks; + globalThis.recipes = recipes; + } +} + +function delivering(recipeName) { + setTimeout(() => { + console.log(`Delivering ${recipeName}`); + }, 2000); +} + +function end_of_order(recipeName) { + console.log("All ingredients have been prepared"); + setTimeout(() => { + console.log(`Cooking ${recipeName}`); + }, 2000); + setTimeout(() => { + delivering(recipeName); + }, 5000); +} + +function check_and_update_ingredient(recipeName, ingredient, quantity) { + if (globalThis.stocks[ingredient] < quantity) { + console.log( + `Not enough ingredients for ${recipeName} because there is no more ${ingredient}`, + ); + return false; + } + + globalThis.stocks[ingredient] -= quantity; + return true; +} + +function check_and_update_ingredients(recipeName, ingredients) { + for (const ingredient in ingredients) { + const quantity = ingredients[ingredient]; + + if (!check_and_update_ingredient(recipeName, ingredient, quantity)) { + return false; + } + } + + return true; +} + +function prepare_pizza(recipeName) { + let i = 0; + const pizza = globalThis.recipes.pizza[recipeName]; + const timeouts = []; + + timeouts.push( + setTimeout(() => { + console.log(`Preparing ${pizza.sauce}`); + if (!check_and_update_ingredient(recipeName, pizza.sauce, 1)) { + for (const t of timeouts) { + clearTimeout(t); + } + + return; + } + }, i), + ); + + timeouts.push( + setTimeout(() => { + i = 1000; + console.log(`Preparing ${Object.keys(pizza.toppings).join(", ")}`); + if (!check_and_update_ingredients(recipeName, pizza.toppings)) { + for (const t of timeouts) { + clearTimeout(t); + } + + return; + } + + setTimeout(() => { + console.log( + `Preparing ${Object.keys(pizza.cheese).join(", ")}`, + ); + if (!check_and_update_ingredients(recipeName, pizza.cheese)) { + for (const t of timeouts) { + clearTimeout(t); + } + + return; + } + }, i); + }, i + 1000), + ); + i += 3000; + timeouts.push( + setTimeout(() => { + end_of_order(recipeName); + }, i), + ); +} + +function prepare_burger(recipeName) { + const burger = globalThis.recipes.burger[recipeName]; + let i = 0; + const timeouts = []; + + for (const ingredient in burger) { + const timeout = setTimeout(() => { + console.log(`Preparing ${ingredient}`); + if ( + !check_and_update_ingredient( + recipeName, + ingredient, + burger[ingredient], + ) + ) { + for (const t of timeouts) { + clearTimeout(t); + } + + return; + } + }, i * 1000); + + timeouts.push(timeout); + i++; + } + + const lastTimeout = setTimeout(() => { + end_of_order(recipeName); + }, i * 1000); + + timeouts.push(lastTimeout); +} + +function order(recipeName) { + let i = 0; + + console.log(`Ordering ${recipeName}`); + + if ( + !(recipeName in globalThis.recipes.pizza) && + !(recipeName in globalThis.recipes.burger) + ) { + console.log(`Recipe ${recipeName} does not exist`); + return; + } + + setTimeout(() => { + i = 1000; + setTimeout(() => { + console.log(`Production has started for ${recipeName}`); + }, i); + }, i + 1000); + i += 3000; + setTimeout(() => { + if (recipeName in globalThis.recipes.pizza) { + prepare_pizza(recipeName); + } + }, i); + setTimeout(() => { + if (recipeName in globalThis.recipes.burger) { + prepare_burger(recipeName); + } + }, i); +} + +if (typeof window === "undefined") { + module.exports = { + order, + }; +} diff --git a/graphs/js/foodTruck/foodTruck.js b/graphs/js/foodTruck/foodTruck.js new file mode 100644 index 0000000..afe14d4 --- /dev/null +++ b/graphs/js/foodTruck/foodTruck.js @@ -0,0 +1,124 @@ +if (typeof window === "undefined") { + if ( + !globalThis.stocks && + !globalThis.recipes && + !globalThis.globalThis.sleep + ) { + const { stocks, recipes } = require("./data"); + const { sleep } = require("./sleep"); + + globalThis.stocks = stocks; + globalThis.recipes = recipes; + globalThis.globalThis.sleep = sleep; + } +} + +if (typeof window === "undefined") { + module.exports = { + order, + }; +} + +/* + * + * Write your code below these lines + * + */ +async function end_of_order(recipeName, wait) { + if (wait) { + await globalThis.sleep(1); + } + + console.log("All ingredients have been prepared"); + await globalThis.sleep(2); + console.log(`Cooking ${recipeName}`); + await globalThis.sleep(5); + console.log(`Delivering ${recipeName}`); + return null; +} +function check_and_update_ingredient(recipeName, ingredient, quantity) { + if (globalThis.stocks[ingredient] < quantity) { + console.log( + `Not enough ingredients for ${recipeName} because there is no more ${ingredient}`, + ); + return false; + } + + globalThis.stocks[ingredient] -= quantity; + return true; +} + +function check_and_update_ingredients(recipeName, ingredients) { + for (const ingredient in ingredients) { + const quantity = ingredients[ingredient]; + + if (!check_and_update_ingredient(recipeName, ingredient, quantity)) { + return false; + } + } + + return true; +} + +async function order(recipeName) { + console.log(`Ordering ${recipeName}`); + + if ( + !(recipeName in globalThis.recipes.pizza) && + !(recipeName in globalThis.recipes.burger) + ) { + console.log(`Recipe ${recipeName} does not exist`); + return; + } + + await globalThis.sleep(2); + console.log(`Production has started for ${recipeName}`); + await globalThis.sleep(1); + if (recipeName in globalThis.recipes.burger) { + const burger = globalThis.recipes.burger[recipeName]; + + for (const ingredient in burger) { + console.log(`Preparing ${ingredient}`); + if ( + !check_and_update_ingredient( + recipeName, + ingredient, + burger[ingredient], + ) + ) { + return; + } + + await globalThis.sleep(1); + } + + return await end_of_order(recipeName, false); + } else if (recipeName in globalThis.recipes.pizza) { + const pizza = globalThis.recipes.pizza[recipeName]; + + console.log(`Preparing ${pizza.sauce}`); + if (!check_and_update_ingredient(recipeName, pizza.sauce, 1)) { + return; + } + + await globalThis.sleep(1); + console.log(`Preparing ${Object.keys(pizza.toppings).join(", ")}`); + if (!check_and_update_ingredients(recipeName, pizza.toppings)) { + return; + } + + await globalThis.sleep(1); + console.log(`Preparing ${Object.keys(pizza.cheese).join(", ")}`); + if (!check_and_update_ingredients(recipeName, pizza.cheese)) { + return; + } + + return await end_of_order(recipeName, true); + } +} + +if (typeof window === "undefined") { + module.exports = { + order, + }; +} diff --git a/graphs/js/foodTruck/index.html b/graphs/js/foodTruck/index.html new file mode 100644 index 0000000..0bbc954 --- /dev/null +++ b/graphs/js/foodTruck/index.html @@ -0,0 +1,40 @@ +<!DOCTYPE html> +<html lang="en"> + +<head> + <meta charset="UTF-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + <title>Foodtruck</title> + <link rel="stylesheet" href="static/style.css"> + + +</head> + +<body> + <header> + <h1 id="page-title">FoodTruck</h1> + <p>Choose your order !</p> + <button id="switch-button"> + <a href="#">Switch to Dirty Foodtruck</a> + </button> + </header> + + + <div id="order"> + </div> + + <div id="display"> + </div> + + <footer> + <p>"Being a hero means fighting back even when it seems impossible."</p> + </footer> + +</body> +<script src="static/failedOnload.js"></script> +<script src="data.js" onerror="scriptFailedLoad(this.src)"></script> +<script src="sleep.js" onerror="scriptFailedLoad(this.src)"></script> +<script src="static/index.js"></script> +<script src="foodTruck.js" onerror="scriptFailedLoad(this.src)"></script> + +</html>
\ No newline at end of file diff --git a/graphs/js/foodTruck/sleep.js b/graphs/js/foodTruck/sleep.js new file mode 100644 index 0000000..e4244d9 --- /dev/null +++ b/graphs/js/foodTruck/sleep.js @@ -0,0 +1,11 @@ +function sleep(s) { + return new Promise((resolve) => setTimeout(resolve, s * 1000)); +} + +if (typeof window === "undefined") { + module.exports = { + sleep, + }; +} else { + globalThis.sleep = sleep; +} diff --git a/graphs/js/foodTruck/static/failedOnload.js b/graphs/js/foodTruck/static/failedOnload.js new file mode 100644 index 0000000..cf47073 --- /dev/null +++ b/graphs/js/foodTruck/static/failedOnload.js @@ -0,0 +1,9 @@ +function scriptFailedLoad(src) { + const container = document.getElementById("order"); + const errorDiv = document.createElement("div"); + + errorDiv.id = "errorscript"; + errorDiv.innerHTML = ` + <p><b>Script '${src.split("/").pop()}' does not exist.</b></p>`; + container.appendChild(errorDiv); +} diff --git a/graphs/js/foodTruck/static/index.js b/graphs/js/foodTruck/static/index.js new file mode 100644 index 0000000..6d84098 --- /dev/null +++ b/graphs/js/foodTruck/static/index.js @@ -0,0 +1,78 @@ +function addFood(name) { + const container = document.getElementById("order"); + const foodDiv = document.createElement("div"); + + foodDiv.classList.add("food"); + foodDiv.innerHTML = ` + <p>${name}</p> + <button onclick=" order('${name}')">Order</button>`; + container.appendChild(foodDiv); +} + +function logToDisplay(message, type = "info") { + const displayElement = document.getElementById("display"); + const logMessage = document.createElement("div"); + + logMessage.textContent = message; + logMessage.classList.add("log-message", type); + displayElement.appendChild(logMessage); + + displayElement.scrollTop = displayElement.scrollHeight; + setTimeout(() => { + logMessage.remove(); + }, 5000); +} + +console.log = logToDisplay; + +function loadMenu() { + if (document.getElementById("errorscript") === null) { + Object.keys(recipes).forEach((category) => { + Object.keys(recipes[category]).forEach((recipeName) => { + addFood(recipeName); + }); + }); + } +} + +var isDirtyFoodtruck = false; +var pageTitle = document.getElementById("page-title"); +var switchButton = document.getElementById("switch-button"); + +function loadScript(isDirty) { + var scriptContainer = document.body; + var currentScripts = [...scriptContainer.querySelectorAll("script")].filter( + (script) => { + var name_script = script.src.split("/").pop(); + + return /(dirty)?foodtruck\.js/i.test(name_script); + }, + ); + + // currentScripts should return only one value + scriptToLoad = isDirty ? "dirtyFoodTruck.js" : "foodTruck.js"; + document.body.removeChild(currentScripts[0]); + + const script = document.createElement("script"); + + script.src = scriptToLoad; + + script.onerror = () => scriptFailedLoad(scriptToLoad); + script.onload = () => loadMenu(); + document.body.appendChild(script); +} + +switchButton.addEventListener("click", () => { + isDirtyFoodtruck = !isDirtyFoodtruck; + pageTitle.textContent = isDirtyFoodtruck ? "Dirty Foodtruck" : "Foodtruck"; + switchButton.querySelector("a").textContent = isDirtyFoodtruck + ? "Switch to Foodtruck" + : "Switch to Dirty Foodtruck"; + var orderDiv = document.getElementById("order"); + + orderDiv.innerHTML = ""; + + loadScript(isDirtyFoodtruck); +}); + +loadMenu(); diff --git a/graphs/js/foodTruck/static/style.css b/graphs/js/foodTruck/static/style.css new file mode 100644 index 0000000..c094d98 --- /dev/null +++ b/graphs/js/foodTruck/static/style.css @@ -0,0 +1,200 @@ +:root { + --main-color: #21344a; + --background-color: #333; + --own-white: #FDF0E7; +} + +* { + margin: 0; + padding: 0; + box-sizing: border-box; + font-family: Arial, sans-serif; + +} + +body { + background-color: var(--background-color); + color: #333; + font-size: 16px; + line-height: 1.5; + display: flex; + flex-direction: column; + min-height: 100vh; + margin: 0; +} + +header { + background-color: var(--main-color); + color: var(--own-white); + text-align: center; + flex-shrink: 0; + padding: 20px 0; + position: relative; +} + +header h1 { + font-size: 50px; + margin-bottom: 5px; +} + +header p { + font-size: 20px; +} + +header button { + position: absolute; + right: 20px; + top: 50%; + transform: translateY(-50%); + background-color: var(--own-white); + color: var(--main-color); + padding: 10px 15px; + font-size: 1rem; + font-weight: bold; + border-radius: 10px; + border-style: solid; + border-color: #000; + border-width: 1px; + cursor: pointer; + transition: background-color 0.3s, color 0.3s; + text-decoration: none; +} + +header button:hover { + background-color: #f5f5f5; + color: var(--main-color); +} + +header button a { + text-decoration: none; + color: inherit; +} + +#order { + flex-shrink: 0; + margin: 0; + + display: flex; + flex-wrap: wrap; + gap: 20px; + padding: 30px; + margin-top: 20px; + justify-content: space-between; +} + +.food { + background-color: var(--own-white); + padding: 15px; + border-radius: 8px; + text-align: center; + flex: 1 1 calc(25% - 20px); + box-sizing: border-box; +} + +.food p { + font-size: 20px; + margin-bottom: 10px; +} + +.food button { + background-color: var(--main-color); + color: white; + border: none; + padding: 10px; + font-size: 16px; + border-radius: 5px; + cursor: pointer; + width: 100%; + transition: background-color 0.3s; +} + +.food button:hover { + background-color: #972615; +} + +#display { + flex-grow: 1; + overflow-y: auto; + background-color: var(--background-color); + color: white; + padding: 10px; + font-family: monospace; + white-space: pre-wrap; + box-sizing: border-box; + height: 0; + max-height: calc(100vh - 200px); + overflow-y: scroll; +} + +.log-message { + padding: 5px; + border-radius: 5px; + animation: fadeOut 5s forwards; + overflow-y: hidden; + justify-content: center; + text-align: center; + align-items: center; +} + +.log-message.info { + color: var(--own-white); + font-size: 20px; +} + +.log-message.error { + color: #f44336; +} + +.log-message.warn { + color: #ffc107; +} + +@keyframes fadeOut { + 0% { + opacity: 1; + } + + 80% { + opacity: 1; + } + + 100% { + opacity: 0; + } +} + +#errorscript { + color: red; + font-size: 30px; + font-weight: bold; + text-align: center; + display: flex; + justify-content: center; + align-items: center; + width: 100%; + height: 100%; + background-color: rgba(255, 255, 255, 0.8); + box-sizing: border-box; + border-radius: 15px; + padding: 20px; +} + +footer img { + size: 15px; +} + +footer { + flex-shrink: 0; + background-color: var(--main-color); + color: white; + text-align: center; + padding: 20px; + display: flex; + justify-content: center; + align-items: center; + gap: 20px; +} + +footer p { + font-size: 20px; +}
\ No newline at end of file |
