ajout des tp de Cpp

master
Antoine PEREDERII 2 years ago
parent abe5cf3824
commit 1095c82a37

Binary file not shown.

@ -6,25 +6,25 @@ using namespace std;
namespace appli {
Ingredient::Ingredient(const string &aliment, const Quantite &quantite)
: aliment{aliment}, quantite{quantite}
{}
string Ingredient::getAliment() const {
return aliment;
}
Quantite Ingredient::getQuantite() const {
return quantite;
}
ostream &operator<<(ostream &os, const Ingredient &i) {
os << i.getQuantite() << " " << i.getAliment() << endl;
return os;
}
bool operator==(const Ingredient &i1, const Ingredient &i2) {
return(i1.getAliment() == i2.getAliment());
}
Ingredient::Ingredient(const string &aliment, const Quantite &quantite)
: aliment{aliment}, quantite{quantite}
{}
string Ingredient::getAliment() const {
return aliment;
}
Quantite Ingredient::getQuantite() const {
return quantite;
}
ostream &operator<<(ostream &os, const Ingredient &i) {
os << i.getQuantite() << " " << i.getAliment() << endl;
return os;
}
bool operator==(const Ingredient &i1, const Ingredient &i2) {
return(i1.getAliment() == i2.getAliment());
}
}

@ -8,16 +8,21 @@
namespace appli {
class Ingredient {
std::string aliment;
Quantite quantite;
public:
Ingredient(const std::string &aliment, const Quantite &quantite);
std::string getAliment() const;
Quantite getQuantite() const;
};
std::ostream &operator<<(std::ostream &os, const Ingredient &i);
bool operator==(const Ingredient &i1, const Ingredient &i2);
}
namespace std {

@ -0,0 +1,29 @@
#include "livreRecettes.hpp"
using namespace std;
namespace appli {
// map<Recette, unordered_set<Ingredient>> LivreRecettes::rechercherRecette(const string &nomRecette) {
// for(auto it = )
// }
map<string, Quantite> LivreRecettes::faireListeCourses(list<Recette> l) {
}
void LivreRecettes::ajouter(const Recette &r, list<Ingredient> l) {
l.push_back(r)
ajouter dans le livre la rec
}
void LivreRecettes::afficherNomRecette() {
}
void LivreRecettes::afficher() {
}
}

@ -0,0 +1,29 @@
#ifndef LIVRERECETTES_HPP
#define LIVRERECETTES_HPP
#include "recette.hpp"
#include "ingredient.hpp"
#include <map>
#include <unordered_set>
#include <list>
namespace appli {
class LivreRecettes {
std::list<Ingredient *> livre;
public:
std::map<Recette, std::unordered_set<Ingredient>> rechercherRecette(const std::string &nomRecette);
std::map<std::string, Quantite> faireListeCourses(std::list<Recette> l);
void ajouter(const Recette &r, std::list<Ingredient> l);
void afficherNomRecette();
void afficher();
};
}
#endif // LIVRERECETTES_HPP

@ -1,11 +1,11 @@
#include<iostream>
// #include<map>
#include<map>
#include<unordered_set>
#include"unite.hpp"
#include"quantite.hpp"
#include"ingredient.hpp"
#include"recette.hpp"
// #include"recetteAffichage.hpp"
#include"recetteAffichage.hpp"
using namespace std;
@ -35,19 +35,19 @@ void testQuantite(){
cout << "1.5L => " << appli::Quantite{1.5, appli::Unite::L} << endl;
// Partie 3:
// cout << "15L => " << appli::Quantite{15, appli::Unite::L}.normaliser() << endl;
// cout << "1.5L => " << appli::Quantite{15, appli::Unite::DL}.normaliser() << endl;
// cout << "0.15L => " << appli::Quantite{15, appli::Unite::CL}.normaliser() << endl;
// cout << "0.015L => " << appli::Quantite{15, appli::Unite::ML}.normaliser() << endl;
// cout << "15L => " << appli::Quantite{15, appli::Unite::L}.normaliser() << endl;
// cout << "0.8kg => " << appli::Quantite{0.8, appli::Unite::KG}.normaliser() << endl;
// cout << "0.5kg => " << appli::Quantite{500, appli::Unite::G}.normaliser() << endl;
// cout << "2 => " << appli::Quantite{2, appli::Unite::UNITE}.normaliser() << endl;
// cout << "1.5kg => " << appli::Quantite{1, appli::Unite::KG}+appli::Quantite{500, appli::Unite::G} << endl;
// cout << "0.75L => " << appli::Quantite{5, appli::Unite::DL}+appli::Quantite{250, appli::Unite::ML} << endl;
// cout << "Détection d'erreur ?" << endl;
// cout << appli::Quantite{5, appli::Unite::DL}+appli::Quantite{250, appli::Unite::G} << endl;
cout << "15L => " << appli::Quantite{15, appli::Unite::L}.normaliser() << endl;
cout << "1.5L => " << appli::Quantite{15, appli::Unite::DL}.normaliser() << endl;
cout << "0.15L => " << appli::Quantite{15, appli::Unite::CL}.normaliser() << endl;
cout << "0.015L => " << appli::Quantite{15, appli::Unite::ML}.normaliser() << endl;
cout << "15L => " << appli::Quantite{15, appli::Unite::L}.normaliser() << endl;
cout << "0.8kg => " << appli::Quantite{0.8, appli::Unite::KG}.normaliser() << endl;
cout << "0.5kg => " << appli::Quantite{500, appli::Unite::G}.normaliser() << endl;
cout << "2 => " << appli::Quantite{2, appli::Unite::UNITE}.normaliser() << endl;
cout << "1.5kg => " << appli::Quantite{1, appli::Unite::KG}+appli::Quantite{500, appli::Unite::G} << endl;
cout << "0.75L => " << appli::Quantite{5, appli::Unite::DL}+appli::Quantite{250, appli::Unite::ML} << endl;
cout << "Détection d'erreur ?" << endl;
cout << appli::Quantite{5, appli::Unite::DL}+appli::Quantite{250, appli::Unite::G} << endl;
}
@ -76,41 +76,41 @@ void testRecette(){
appli::Recette r{"Soupe de poireaux", "Faire cuire les légumes puis mixer."};
// unordered_set<appli::Ingredient> ing;
// ing.insert(appli::Ingredient{"poireaux", appli::Quantite{2, appli::Unite::UNITE}});
// ing.insert(appli::Ingredient{"pommes de terre", appli::Quantite{300, appli::Unite::G}});
// ing.insert(appli::Ingredient{"eau", appli::Quantite{50, appli::Unite::CL}});
unordered_set<appli::Ingredient> ing;
ing.insert(appli::Ingredient{"poireaux", appli::Quantite{2, appli::Unite::UNITE}});
ing.insert(appli::Ingredient{"pommes de terre", appli::Quantite{300, appli::Unite::G}});
ing.insert(appli::Ingredient{"eau", appli::Quantite{50, appli::Unite::CL}});
// cout << "Résultat attendu" << endl << "=>" << endl << "résultat" << endl << endl;
// cout << "Soupe de poireaux\n\t300g pommes de terre\n\t50cL eau\n\t2 poireaux" << endl << "=>" << endl;
// afficherNomEtIngredients(r, ing);
cout << "Résultat attendu" << endl << "=>" << endl << "résultat" << endl << endl;
cout << "Soupe de poireaux\n\t300g pommes de terre\n\t50cL eau\n\t2 poireaux" << endl << "=>" << endl;
afficherNomEtIngredients(r, ing);
// cout << endl;
// cout << "Soupe de poireaux\n\t300g pommes de terre\n\t50cL eau\n\t2 poireaux\ndescription :\nFaire cuire les légumes puis mixer." << endl << "=>" << endl;
// afficherTout(r, ing);
cout << endl;
cout << "Soupe de poireaux\n\t300g pommes de terre\n\t50cL eau\n\t2 poireaux\ndescription :\nFaire cuire les légumes puis mixer." << endl << "=>" << endl;
afficherTout(r, ing);
// appli::Recette r2{"Crêpes", "Faire fondre le beurre. Mélanger la farine, le sel et le sucre. Y ajouter les oeufs puis le lait et enfin le beurre fondu. Faire cuire à la poêle quelques minutes de chaque côté."};
// unordered_set<appli::Ingredient> ing2;
// ing2.insert(appli::Ingredient{"farine", appli::Quantite{250, appli::Unite::G}});
// ing2.insert(appli::Ingredient{"lait", appli::Quantite{0.5, appli::Unite::L}});
// ing2.insert(appli::Ingredient{"sucre", appli::Quantite{30, appli::Unite::G}});
// ing2.insert(appli::Ingredient{"oeufs", appli::Quantite{4, appli::Unite::UNITE}});
// ing2.insert(appli::Ingredient{"sel", appli::Quantite{3, appli::Unite::G}});
// ing2.insert(appli::Ingredient{"beurre", appli::Quantite{50, appli::Unite::G}});
// map<appli::Recette, unordered_set<appli::Ingredient>> recettes;
// recettes.insert(pair{r,ing});
// recettes.insert(pair{r2,ing2});
appli::Recette r2{"Crêpes", "Faire fondre le beurre. Mélanger la farine, le sel et le sucre. Y ajouter les oeufs puis le lait et enfin le beurre fondu. Faire cuire à la poêle quelques minutes de chaque côté."};
unordered_set<appli::Ingredient> ing2;
ing2.insert(appli::Ingredient{"farine", appli::Quantite{250, appli::Unite::G}});
ing2.insert(appli::Ingredient{"lait", appli::Quantite{0.5, appli::Unite::L}});
ing2.insert(appli::Ingredient{"sucre", appli::Quantite{30, appli::Unite::G}});
ing2.insert(appli::Ingredient{"oeufs", appli::Quantite{4, appli::Unite::UNITE}});
ing2.insert(appli::Ingredient{"sel", appli::Quantite{3, appli::Unite::G}});
ing2.insert(appli::Ingredient{"beurre", appli::Quantite{50, appli::Unite::G}});
map<appli::Recette, unordered_set<appli::Ingredient>> recettes;
recettes.insert(pair{r,ing});
recettes.insert(pair{r2,ing2});
// cout << endl;
// cout << "Crêpes\n\t50g beurre\n\t3g sel\n\t4 oeufs\n\t30g sucre\n\t0.5L lait\n\t250g farine\ndescription :\nFaire fondre le beurre. Mélanger la farine, le sel et le sucre. Y ajouter les oeufs puis le lait et enfin le beurre fondu. Faire cuire à la poêle quelques minutes de chaque côté.\nSoupe de poireaux\n\t300g pommes de terre\n\t50cL eau\n\t2 poireaux\ndescription :\nFaire cuire les légumes puis mixer." << endl << "=>" << endl;
// afficherTout(recettes);
cout << endl;
cout << "Crêpes\n\t50g beurre\n\t3g sel\n\t4 oeufs\n\t30g sucre\n\t0.5L lait\n\t250g farine\ndescription :\nFaire fondre le beurre. Mélanger la farine, le sel et le sucre. Y ajouter les oeufs puis le lait et enfin le beurre fondu. Faire cuire à la poêle quelques minutes de chaque côté.\nSoupe de poireaux\n\t300g pommes de terre\n\t50cL eau\n\t2 poireaux\ndescription :\nFaire cuire les légumes puis mixer." << endl << "=>" << endl;
afficherTout(recettes);
// cout << endl;
// cout << "Crêpes\nSoupe de poireaux" << endl << "=>" << endl;
// afficherNoms(recettes);
cout << endl;
cout << "Crêpes\nSoupe de poireaux" << endl << "=>" << endl;
afficherNoms(recettes);
}

@ -5,21 +5,62 @@ using namespace std;
namespace appli {
Quantite::Quantite(double nombre, const Unite &unite)
: nombre{nombre}, unite{unite}
{}
double Quantite::getNombre() const {
return nombre;
}
Unite Quantite::getUnite() const {
return unite;
}
ostream &operator<<(ostream &os, const Quantite &q) {
os << q.getNombre() << q.getUnite();
return os;
}
Quantite::Quantite(double nombre, const Unite &unite)
: nombre{nombre}, unite{unite}
{}
double Quantite::getNombre() const {
return nombre;
}
Unite Quantite::getUnite() const {
return unite;
}
Quantite Quantite::normaliser() const {
switch(unite) {
case Unite::KG :
return *this;
break;
case Unite::G :
return Quantite{nombre / 1000,Unite::KG};
break;
case Unite::L :
return *this;
break;
case Unite::DL :
return Quantite{nombre / 10, Unite::L};
break;
case Unite::CL :
return Quantite{nombre / 100, Unite::L};
break;
case Unite::ML :
return Quantite{nombre / 1000, Unite::L};
break;
case Unite::UNITE :
return Quantite{nombre / 1, Unite::UNITE};
break;
};
return *this;
}
ostream &operator<<(ostream &os, const Quantite &q) {
os << q.getNombre() << q.getUnite();
return os;
}
Quantite operator+(const Quantite &q1, const Quantite &q2) {
if(q1.getUnite() == q2.getUnite()) return Quantite(q1.getNombre() + q2.getNombre(), q1.getUnite());
else {
Quantite q1bis = q1.normaliser();
Quantite q2bis = q2.normaliser();
if(q1bis.getUnite() == q2bis.getUnite())
return Quantite{q1bis.getNombre() + q2bis.getNombre(), q1bis.getUnite()};
else {
cout << "Impossible d'ajouter des unités non compatibles" << endl;
return q1;
}
}
}
}

@ -8,17 +8,23 @@
namespace appli {
class Quantite {
double nombre;
Unite unite;
public:
Quantite(double nombre=1, const Unite &unite=Unite::UNITE);
Quantite normaliser() const;
double getNombre() const;
Unite getUnite() const;
Quantite normalier();
};
std::ostream &operator<<(std::ostream &os, const Quantite &q);
// double operator+(const double &n1, const )
Quantite operator+(const Quantite &q1, const Quantite &q2);
}

@ -4,21 +4,25 @@ using namespace std;
namespace appli {
Recette::Recette(const string &nom, const string &description)
: nom{nom}, description{description}
{}
Recette::Recette(const string &nom, const string &description)
: nom{nom}, description{description}
{}
string Recette::getNom() const {
return nom;
}
string Recette::getNom() const {
return nom;
}
string Recette::getDescription() const {
return description;
}
string Recette::getDescription() const {
return description;
}
ostream &operator<<(ostream &os, const Recette &r) {
os << r.getNom() << " " << r.getDescription();
return os;
}
bool operator<(const Recette &r1, const Recette &r2) {
if(r1.getNom() < r2.getNom())
return true;
if(r1.getNom() > r2.getNom())
return false;
return r1.getDescription() < r2.getDescription();
}
}

@ -8,15 +8,20 @@
namespace appli {
class Recette {
std::string nom;
std::string description;
public:
Recette(const std::string &nom, const std::string &description);
std::string getNom() const;
std::string getDescription() const;
};
// "operateur prends deux qqt, si q1 == q2 en unité alors on peut construire un nouvelle quantite avec l'unité de q1 ou q2
// on regarde ce que retourne q1 et q2 normalisé pas d'ajout de kg et litre et donc mettre un message d'erreur en cerr et on return q1"
bool operator<(const Recette &r1, const Recette &r2);
}

@ -0,0 +1,35 @@
#include "recetteAffichage.hpp"
using namespace std;
using namespace appli;
void afficherNomEtIngredients(const Recette &r, const unordered_set<Ingredient> &ingred) {
cout << r.getNom() << endl;
for(auto it = ingred.cbegin(); it != ingred.cend(); ++it) {
cout << "\t" << *it;
}
// for(Ingredient i : ingred) { //! OU CETTE FAÇON
// cout << i << endl;
// }
}
void afficherTout(const Recette &r, const unordered_set<Ingredient> &ingredient) {
cout << r.getNom() << endl;
for(auto it = ingredient.cbegin(); it != ingredient.cend(); ++it) {
cout << "\t" << *it;
}
cout << "description :\n" << r.getDescription() << endl;
}
void afficherTout(const map<Recette, unordered_set<Ingredient>> &recettes) {
for(auto it = recettes.cbegin(); it != recettes.cend(); ++it) {
afficherTout(it->first, it->second);
}
}
void afficherNoms(const map<Recette, unordered_set<Ingredient>> &recettes) {
for(map<Recette, unordered_set<Ingredient>>::const_iterator it = recettes.cbegin(); it != recettes.cend(); ++it){
cout << it->first.getNom() << endl;
}
}

@ -0,0 +1,15 @@
#ifndef RECETTEAFFICHAGE_HPP
#define RECETTEAFFICHAGE_HPP
#include "recette.hpp"
#include "ingredient.hpp"
#include <unordered_set>
#include <map>
void afficherNomEtIngredients(const appli::Recette &r, const std::unordered_set<appli::Ingredient> &ingred);
void afficherTout(const appli::Recette &r, const std::unordered_set<appli::Ingredient> &ingredients);
void afficherTout(const std::map<appli::Recette, std::unordered_set<appli::Ingredient>> &recettes);
void afficherNoms(const std::map<appli::Recette, std::unordered_set<appli::Ingredient>> &recettes);
#endif // RECETTEAFFICHAGE_HPP

@ -2,6 +2,7 @@
using namespace std;
namespace appli {
ostream &operator<<(ostream &os, const Unite &u) {
switch(u) {
case Unite::KG : os << "kg";

@ -4,9 +4,11 @@
#include <iostream>
namespace appli {
enum class Unite{KG, G, L, DL, CL, ML, UNITE};
std::ostream &operator<<(std::ostream &os, const Unite &u);
}
#endif // UNITE_HPP

@ -1,26 +0,0 @@
#CC : le compilateur à utiliser
CC=g++
#CFLAGS : les options de compilation
CFLAGS= -std=c++17 -Wall
# les fichiers sources : tous les fichiers présents dans src/
SRC=$(wildcard src/*.cpp)
# les fichiers objets (.o)
OBJ=$(patsubst src/%.cpp,obj/%.o,$(SRC))
#edition des liens : génération de l'exécutable à partir des .o
bin/exe: $(OBJ)
$(CC) $(OBJ) -o $@
# génération des .o à partir des .cpp et .hpp crrespondants :
obj/%.o: src/%.cpp
$(CC) $(CFLAGS) -c $< -o $@
#nettoyage : destruction des .o et de l'exécutable
clean:
rm obj/*.o bin/exe

@ -1,17 +0,0 @@
#include "aurevoir.hpp"
#include <ostream>
using namespace std;
Aurevoir::Aurevoir()
:
{}
ostream &operator<<(ostream &os, const Aurevoir &a) {
return os;
}

@ -1,17 +0,0 @@
#ifndef AUREVOIR_HPP
#define AUREVOIR_HPP
#include <ostream>
class Aurevoir {
public:
Aurevoir();
friend std::ostream &operator<<(ostream &os, const Aurevoir &a);
~Aurevoir()=default;
};
#endif // AUREVOIR_HPP

@ -1,17 +0,0 @@
#include "bonjour.hpp"
#include <ostream>
using namespace std;
Bonjour::Bonjour()
:
{}
ostream &operator<<(ostream &os, const Bonjour &b) {
return os;
}

@ -1,17 +0,0 @@
#ifndef BONJOUR_HPP
#define BONJOUR_HPP
#include <ostream>
class Bonjour {
public:
Bonjour();
friend std::ostream &operator<<(ostream &os, const Bonjour &b);
~Bonjour()=default;
};
#endif // BONJOUR_HPP

@ -1,7 +0,0 @@
int main() {
return 0;
}

@ -1,122 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="AutoImportSettings">
<option name="autoReloadType" value="SELECTIVE" />
</component>
<component name="CMakeRunConfigurationManager" shouldGenerate="true" shouldDeleteObsolete="true">
<generated>
<config projectName="tp4" targetName="tp" />
<config projectName="tp4" targetName="all" />
</generated>
</component>
<component name="CMakeSettings">
<configurations>
<configuration PROFILE_NAME="Debug" ENABLED="true" CONFIG_NAME="Debug" />
</configurations>
</component>
<component name="ChangeListManager">
<list default="true" id="5166c46f-7695-4267-b320-10c19351e428" name="Changes" comment="" />
<option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" />
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
<option name="LAST_RESOLUTION" value="IGNORE" />
</component>
<component name="ClangdSettings">
<option name="formatViaClangd" value="false" />
</component>
<component name="ExternalProjectsData">
<projectState path="$PROJECT_DIR$">
<ProjectState />
</projectState>
</component>
<component name="MacroExpansionManager">
<option name="directoryName" value="i1r2peki" />
</component>
<component name="MakefileLocalSettings">
<option name="availableProjects">
<map>
<entry>
<key>
<ExternalProjectPojo>
<option name="name" value="tp4" />
<option name="path" value="$PROJECT_DIR$" />
</ExternalProjectPojo>
</key>
<value>
<list>
<ExternalProjectPojo>
<option name="name" value="tp4" />
<option name="path" value="$PROJECT_DIR$" />
</ExternalProjectPojo>
</list>
</value>
</entry>
</map>
</option>
<option name="projectSyncType">
<map>
<entry key="$PROJECT_DIR$" value="RE_IMPORT" />
</map>
</option>
</component>
<component name="MarkdownSettingsMigration">
<option name="stateVersion" value="1" />
</component>
<component name="ProjectApplicationVersion">
<option name="ide" value="CLion" />
<option name="majorVersion" value="2021" />
<option name="minorVersion" value="3.3" />
</component>
<component name="ProjectId" id="25QGgkT8LgL96Tg1ndpZCQ5vyhU" />
<component name="ProjectViewState">
<option name="hideEmptyMiddlePackages" value="true" />
<option name="showLibraryContents" value="true" />
</component>
<component name="PropertiesComponent">
<property name="RunOnceActivity.OpenProjectViewOnStart" value="true" />
<property name="RunOnceActivity.ShowReadmeOnStart" value="true" />
<property name="RunOnceActivity.cidr.known.project.marker" value="true" />
<property name="WebServerToolWindowFactoryState" value="false" />
<property name="cf.first.check.clang-format" value="false" />
<property name="cidr.known.project.marker" value="true" />
<property name="last_opened_file_path" value="$PROJECT_DIR$" />
<property name="node.js.detected.package.eslint" value="true" />
<property name="node.js.detected.package.tslint" value="true" />
<property name="node.js.selected.package.eslint" value="(autodetect)" />
<property name="node.js.selected.package.tslint" value="(autodetect)" />
<property name="nodejs_package_manager_path" value="npm" />
</component>
<component name="RunManager" selected="Makefile Application.all">
<configuration name="all" type="CLionNativeAppRunConfigurationType" REDIRECT_INPUT="false" ELEVATE="false" USE_EXTERNAL_CONSOLE="false" PASS_PARENT_ENVS_2="true" PROJECT_NAME="tp4" TARGET_NAME="all" CONFIG_NAME="all" version="1" RUN_PATH="$PROJECT_DIR$/tp">
<method v="2">
<option name="CLION.COMPOUND.BUILD" enabled="true" />
</method>
</configuration>
<configuration name="tp" type="CLionNativeAppRunConfigurationType" REDIRECT_INPUT="false" ELEVATE="false" USE_EXTERNAL_CONSOLE="false" PASS_PARENT_ENVS_2="true" PROJECT_NAME="tp4" TARGET_NAME="tp" CONFIG_NAME="tp" version="1">
<method v="2">
<option name="CLION.COMPOUND.BUILD" enabled="true" />
</method>
</configuration>
<list>
<item itemvalue="Makefile Application.all" />
<item itemvalue="Makefile Application.tp" />
</list>
</component>
<component name="SpellCheckerSettings" RuntimeDictionaries="0" Folders="0" CustomDictionaries="0" DefaultDictionary="application-level" UseSingleDictionary="true" transferred="true" />
<component name="TaskManager">
<task active="true" id="Default" summary="Default task">
<changelist id="5166c46f-7695-4267-b320-10c19351e428" name="Changes" comment="" />
<created>1645452010045</created>
<option name="number" value="Default" />
<option name="presentableId" value="Default" />
<updated>1645452010045</updated>
<workItem from="1645452011288" duration="2111000" />
<workItem from="1645481264154" duration="1379000" />
<workItem from="1645526791307" duration="1000" />
</task>
<servers />
</component>
<component name="TypeScriptGeneratedFilesManager">
<option name="version" value="3" />
</component>
</project>

Binary file not shown.

Binary file not shown.

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

Binary file not shown.

@ -0,0 +1 @@
Subproject commit 7889c358580048048f8f092d3fe5d893b1102c42

Binary file not shown.
Loading…
Cancel
Save