summaryrefslogtreecommitdiff
path: root/graphs/js/foodTruck
diff options
context:
space:
mode:
authorMartial Simon <msimon_fr@hotmail.com>2025-09-15 01:08:27 +0200
committerMartial Simon <msimon_fr@hotmail.com>2025-09-15 01:08:27 +0200
commitc9b6b9a5ca082fe7c1b6f58d7713f785a9eb6a5c (patch)
tree3e4f42f93c7ae89a364e4d51fff6e5cec4e55fa9 /graphs/js/foodTruck
add: graphs et rushs
Diffstat (limited to 'graphs/js/foodTruck')
-rw-r--r--graphs/js/foodTruck/data.js70
-rw-r--r--graphs/js/foodTruck/dirtyFoodTruck.js172
-rw-r--r--graphs/js/foodTruck/foodTruck.js124
-rw-r--r--graphs/js/foodTruck/index.html40
-rw-r--r--graphs/js/foodTruck/sleep.js11
-rw-r--r--graphs/js/foodTruck/static/failedOnload.js9
-rw-r--r--graphs/js/foodTruck/static/index.js78
-rw-r--r--graphs/js/foodTruck/static/style.css200
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