Homework

Headlines
Numbers… (and their representation)

N°INSEE

Implanter en C++ et/ou Java et/ou Python et/ou JavaScript/TypeScript dans une classe N_INSEE un système de saisie contrôlée d'un N°INSEE (ou N°SS) selon la formule suivante : clef = 97 - (N°INSEE % 97). On rappelle qu'un N°INSEE est défini sur 13 chiffres (e.g., 1630125388055, clef = 29) et que sa clef est saisie simultanément pour contrôle.

En C++, il est nécessaire de vérifier qu'un N°INSEE tient sur le format long et dans le cas contraire le remplacer par le format long long, e.g., long long n_insee_de_Franck_Barbier = 1630125388055LL; (ne pas oublier le suffixe LL derrière la constante). Si l’on passe par des chaînes de caractères (i.e., std::string), il faut utiliser la fonction C de conversion std::atoll (#include <cstdlib>) pour convertir des chaînes de caractères en variables de type long long.

Contrôler qu'un N°INSEE saisi est « bien formé » (i.e., 13 chiffres exactement, 1er chiffre égal à 1 ou 2, etc.) en définissant et utilisant une expression régulière (ici… ou … pour se faire la main en JavaScript/TypeScript).

En JavaScript/TypeScript, pour signifier le résultat à l'utilisateur, utiliser la librairie SweetAlert2. A ce titre, faire apparaître un message différencié selon l'issue du calcul de clef (i.e., OK ou Non OK). Organiser le code en deux fichiers source différents, l'un (N_INSEE.js) faisant le calcul et l'autre Main.jsl'interaction homme-machine. Pour le premier fichier, utiliser export et le second utiliser import.

Avec Angular, partir de l'implémentation TypeScript précédente pour obtenir le visuel qui suit.

Faire de même avec React en partant de l'implémentation JavaScript.

Application(s)
Predefined versus user-defined types

Before yesterday, yesterday…

En s'inspirant d'un programme C++ déterminant en fonction du temps machine si une date donnée est « Avant hier », « Hier »…, implanter en Java et/ou Python et/ou JavaScript/TypeScript un programme équivalent.

Pour Java, il y a lieu de mettre en œuvre l'API Date-Time qui a complètement été revue en Java 8 (ici).

// Before_yesterday_.h
#ifndef _Before_yesterday_H
#define _Before_yesterday_H

#include <string>

class Before_yesterday_ {
public:
    static const std::string Avant_hier;
    static const std::string Hier;
    static const std::string Aujourd_hui;
    static const std::string Demain;
    static const std::string Apres_demain;
    static const std::string Je_n_en_sais_rien;

    Before_yesterday_(int, int, int, std::string&);
};

#endif

// Main.cpp
#include <cassert>
#include <ctime>

#include <iostream>
#include <string>

#include "Before_yesterday_.h"

const std::string Before_yesterday_::Avant_hier = "Avant hier";
const std::string Before_yesterday_::Hier = "Hier";
const std::string Before_yesterday_::Aujourd_hui = "Aujourd'hui";
const std::string Before_yesterday_::Demain = "Demain";
const std::string Before_yesterday_::Apres_demain = "Après demain";
const std::string Before_yesterday_::Je_n_en_sais_rien = "Je n'en sais rien";

Before_yesterday_::Before_yesterday_(int jour, int mois, int annee, std::string& resultat) {
    assert(jour > 0 && mois > 0 && annee > 0);
    assert(jour <= 31 && mois <= 12);

    std::time_t maintenant = std::time(&maintenant);
    //    std::cout << std::asctime(std::localtime(&maintenant)) << std::endl;

    std::tm *maintenant_comme_structure_de_donnes = std::gmtime(&maintenant);
    // 'auto' permet de déterminer automatiquement le type de 'jour_systeme' en fonction du type (ici 'int') de la donnée affectée : 
    auto jour_systeme = maintenant_comme_structure_de_donnes->tm_mday;
    auto mois_systeme = maintenant_comme_structure_de_donnes->tm_mon + 1; // Attention : 'tm_mon' retourne le mois système moins '1' !
    auto annee_systeme = maintenant_comme_structure_de_donnes->tm_year + 1900; // Attention : 'tm_year' retourne l'année système moins '1900' !

    resultat = Je_n_en_sais_rien;
    if (annee == annee_systeme) {
        if (mois == mois_systeme) {
            if (jour == jour_systeme - 2) resultat = Avant_hier;
            if (jour == jour_systeme - 1) resultat = Hier;
            if (jour == jour_systeme) resultat = Aujourd_hui;
            if (jour == jour_systeme + 1) resultat = Demain;
            if (jour == jour_systeme + 2) resultat = Apres_demain;
        }
    }
}

int main(int argc, char** argv) {
    std::string resultat;
    Before_yesterday_ Before_yesterday_(9, 5, 2019, resultat);
    std::cout << resultat << std::endl;

    return 0;
}
Application(s)

Leap year

Implanter en C++ et/ou Java et/ou Python et/ou JavaScript/TypeScript dans une classe Annee_bissextile, deux fonctions booléennes établissant si, oui ou non, une année est bissextile (leap year en anglais). La première fonction prend en paramètre l'année sous forme entière alors que la seconde la prend sous forme d'un type gérant les dates.

Pour C++, ce type est time_t (#include <ctime>).

Pour Java, ce type peut être java.util.Calendar ou mieux, on utilise l'API Date-Time complètement relookée en Java 8 (ici).

Les deux exemples qui suivent donnent une méthode de récupération de l'année du temps machine en C++ et Java.

std::time_t now = std::time(&now); // '#include <ctime>'
// Display for control:
std::cout << std::asctime(std::localtime(&now)) << std::endl; // '#include <iostream>'
std::tm *now_as_data_structure = std::gmtime(&now);
int year = now_as_data_structure->tm_year; // Caution: 'tm_year' returns the current year minus '1900'!
java.util.Calendar now = java.util.Calendar.getInstance();
int year = now.get(java.util.Calendar.YEAR);
Application(s)

Lotto!

Implanter en C++ et/ou Java et/ou Python et/ou JavaScript/TypeScript dans une classe Tirage_loto un calcul permettant de remplir automatiquement une grille de loto simple avec 48 valeurs différentes à choisir entre 1 et 49 inclus. On a en fait 8 jeux consistant à choisir à chaque fois 6 chiffres mais on n'utilise pas les mêmes chiffres entre chaque jeu.

Pour gérer des suites de nombres aléatoires, on utilise opportunément :

Application(s)

Color

Implanter en C++ et/ou Java et/ou Python et/ou JavaScript/TypeScript une classe RGB_color sur le modèle Java qui suit. Une couleur RGB est représentée sur 32 bits : 8 bits les plus à gauche pour l'opacité puis 8 bits pour la nuance de rouge, etc.

public class RGB_color { // RGB: 8 left-most bits: alpha, then next 8 bits: red, green, blue...
    public enum Red_shade { // Look at red color named shades in CSS and HTML on the Web...
        crimson, darkred, tomato // Etc.
    };
    public RGB_color(String css_html_hexadecimal) { // Use a regular expression to check 'css_html_hexadecimal' format,
        // e.g., "#FFFF0000" for "fully opaque red"...
        // Construct '_representation' from 'css_html_hexadecimal'...
    }
    private java.util.BitSet _representation = new java.util.BitSet(Byte.SIZE * 4);
    public float alpha() {
        // '0.F' if totally transparent, '1.F' if totally opaque, between '0.F' and '1.F' otherwise
        return ...;
    }
    public boolean is_color(Red_shade red_shade) {
        // 'true' if 'red_shade' is color implemented as bit set in '_representation'
        return ...;
    }
    public String css_html_hexadecimal() {
        String css_html_hexadecimal;
        // Construct 'css_html_hexadecimal' from '_representation', for example, "fully opaque red":
        return "#FFFF0000";
    }
}

Account

Implanter en C++ et/ou Java et/ou Python et/ou JavaScript/TypeScript une classe Account sur la base du type abstrait de données Account.
TYPES FUNCTIONS AXIOMS PRE-CONDITIONS

Temperature

Implanter en C++ et/ou Java et/ou Python et/ou JavaScript/TypeScript le concept de température sachant qu'une température ne peut pas descendre en dessous du zéro absolu. Cette propriété peut être formalisée via une fonction accessor constante sur le type abstrait de données Temperature comme suit : La fonction Min est basée sur l'axiome suivant : Par ailleurs, il existe trois unités de mesure des températures qui sont les °C, les °F et les °K. Ces trois unités sont matérialisées par les trois fonctions accessor suivantes : Les deux axiomes suivants s'appliquent : Prévoir des fonctions d'incrémentation et de décrémentation avec un pas « fin » (10-3 ou moins) matérialisé par une variable d'instance _step.

Pour Java, créer une classe Temperature_UI (utiliser JavaFX*) contrôlant la température de façon à ne pas descendre en dessous de 40°Fahrenheit et ne pas monter au-dessus de 90°Fahrenheit (afficher ces valeurs de manière fixe dans l'interface homme-machine). Pour changer la valeur de la température, prévoir un slider. Pour visualiser la valeur courante de la température, prévoir au plus simple une zone de texte. Prévoir aussi une checkbox pour établir dans quelle unité de mesure s'exprime cette température (exprimer avec °C ou °F uniquement).

*L'outil JavaFX Scene Builder peut être intégré dans à NetBeans pour dessiner l'interface homme-machine.

Pour JavaScript/TypeScript, appliquer les mêmes règles que pour Java et créer l'interface homme-machine dans une page Web avec HTML et CSS.

Application(s)
Array, dictionary…

Face detection

Ce travail concerne les tableaux JavaScript (type Array : doc. ici…) qui jouent un rôle extrêmement important. Un logiciel de détection de caractéristiques (la face en bleu, la bouche en vert et les yeux en rouge) donne des résultats pléthoriques nécessitant un post-processing.

Le post-processing consiste à appliquer des heuristiques simples comme par exemple le fait que « les yeux se trouvent au-dessus de la bouche » ou encore « la bouche et les yeux sont totalement inclus dans la face » (voir toutefois Macron pour qui cette heuristique est inadaptée). Dans le logiciel de détection, this._eyes est une promesse JavaScript  qui par la fonction then permet d'accéder à un tableau eyes ; eyes.length est alors le nombre d'yeux trouvés. Au-delà, eyes[0].x et eyes[0].y représentent le coin supérieur gauche du rectangle bornant le premier œil alors que eyes[0].width et eyes[0].height donnent la largeur et hauteur du rectangle. L'idée du travail à réaliser est d'utiliser les primitives sur les tableaux de manière à améliorer la qualité de détection.

L'exemple d'application d'heuristique qui suit est : « on ne garde que la bouche la plus basse ».

this._mouth.then(function (mouth) {
    if (mouth !== null && mouth.length > 1)
        mouth.sort(function (mouth1, mouth2) {
            return mouth2.y - mouth1.y;
        }).splice(1, mouth.length - 1);
});
Application(s)

Horner

Implanter en C++ et/ou Java et/ou Python et/ou JavaScript/TypeScript la méthode de Horner qui est un mécanisme efficace d'évaluation d'un polynôme en un point x. Elle se base sur la factorisation de x qui est multiplié au résultat de l'itération antérieure. Utiliser la librairie SweetAlert2 en JavaScript/TypeScript pour saisir le polynôme.

La difficulté réside dans le choix de la structure de données pour stocker le polynôme (idéalement un dictionnaire) sachant qu'il est utile que le polynôme soit rangé dans l'ordre croissant des puissances de x. On peut opportunément en JavaScript/TypeScript utiliser la fonction sort sur les tableaux pour obtenir cet ordre après la saisie avec SweetAlert2.

En l'occurrence, le programme Horner_method.js ci-après utilise la variable polynomial comme un tableau d'objets, i.e., polynomial.push({degree: …, coeff: …});. Réviser ce programme en utilisant un dictionnaire JavaScript/TypeScript Map.

Application(s)

Lips

Le but du travail est de manipuler les tableaux en JavaScript (type Array : doc. ici). L'application 3D qui suit montre une géométrie de lèvres « brute ». Une géométrie est fondée sur un tableau de sommets (vertices en anglais) et un tableau de faces. Si g est une géométrie alors g.vertices et g.faces sont deux tableaux de type Array. Une face est composée de trois sommets exactement. Si f est une face alors f.a, f.b et f.c sont des index dans le tableau de sommets. A titre d'illustration, g.vertices[f.a] est un des trois sommets de la face f.

Before processing

L'application 3D qui suit montre la géométrie de lèvres reconstruite. En fait, les tableaux vertices et faces ont été ré-organisés (re-triés spécialement) de manière à isoler cinq zones distinctes. A titre d'illustration, en jouant sur le paramètre Color, on colorie en blanc la zone la plus extérieure des lèvres.

After processing

En résumé, à partir de l'application 3D basée sur la géométrie de lèvres « brute », il faut aboutir à la géométrie de lèvres reconstruite.

Application(s)
Genericity

Palindrome

Soit un programme C++ permettant de détecter si une phrase est un palindrome c'est-à-dire la possibilité de la lire de la droite vers la gauche en ignorant les caractères non alphabétiques.
On doit en particulier s'intéresser à la notion de n-uplet (tuple en anglais) incarnée par la classe générique template<class T1,class T2> struct pair (2-uplet uniquement) et plus généralement la classe générique template<class... Types> class tuple en C++.

Traduire ce programme en Java et/ou Python et/ou JavaScript/TypeScript en gérant les accents français ainsi que le « ç » voire d'autres caractères « problématiques ».

En JavaScript/TypeScript, utiliser la balise HTML input en conjonction avec les événements input (un caractère saisi) et change (tous les caractères saisis). Tenter de détecter au plus tôt avec l'événement input, le milieu du palindrome où s'effectue le basculement : « élu par cet<basculement>te crapule ».

<input placeholder="Enter palindrome here..." name="palindrome"/>
window.document.querySelector('input').addEventListener('input', () => {
    …
});

C++

// Palindrome.h
#ifndef  _Palindrome
#define  _Palindrome

#include <string>
#include <utility> // 'std::pair'

class Palindrome : public std::string {
private:
    // 'constexpr' works with 'static' only...
    // 'constexpr' avoids allocation in compilation unit, i.e., '.cpp' file
    // 'constexpr' allows immediate initialization:
    constexpr static /* const */ std::pair<char, char> _Intervals[] = { std::pair<char, char>('a', 'z'), std::pair<char, char>('A', 'Z') };
public: // Something less than '3' -> compilation "error: excess elements in struct initializer"
    constexpr static /* const */ std::array<char, 3> Special_characters{ ' ', '\n', '\t' };
public:
    Palindrome(const std::string&);
    virtual bool isPalindrome() const;
    const char* toString() const;
};

#endif

// Palindrome.cpp
#include <cctype> // 'std::tolower'
#include <iterator> // C++17: 'std::size'
#include <string> // 'std::string'
#include <utility> // 'std::pair'

#include "Palindrome.h"

Palindrome::Palindrome(const std::string& string) {
    for (char c : string) { // For each character in the source string
        for (int j = 0; j < std::size(_Intervalles); ++j) { // C++17
            if (c >= _Intervals[j].first && c <= _Intervals[j].second) { // The character belongs to the authorized intervals
                this->push_back(c); // Character is valid and thus added to the palindrome
                break; // Quit the 'for' loop on 'j'
            }
        }
    }
}

bool Palindrome::isPalindrome() const {
    for (int i = 0; i < this->length() / 2; ++i) { // For each character in the palindrome (up to half of the palindrome's length)
        // 'std::tolower': 'A' -> 'a'
        if (std::tolower(this->operator[](i)) != std::tolower(this->operator[](this->length() - 1 - i)))
            return false;
    }
    return true;
}

const char* Palindrome::toString() const {
    return this->data(); // Content of a string as 'const char*' for compatibility with the C programming language...
}

// Main.cpp
#include <iostream>

#include "Palindrome.h"

int main(int argc, char** argv) {
    Palindrome p1("Elu par cette crapule"); // French
    Palindrome p2("Esope reste ici et se repose"); // French
    Palindrome p3("Was it a car or a cat I saw?"); // English
    Palindrome p4("This is not a palindrome"); // English

    std::cout << p1.toString() << ": " << (p1.isPalindrome() ? "true" : "false") << '\n'; // 'true'
    std::cout << p2.toString() << ": " << (p2.isPalindrome() ? "true" : "false") << '\n'; // 'true'
    std::cout << p3.toString() << ": " << (p3.isPalindrome() ? "true" : "false") << '\n'; // 'true'
    std::cout << p4.toString() << ": " << (p4.isPalindrome() ? "true" : "false") << '\n'; // 'false'

    return 0;
}
Application(s)
Inheritance and polymorphism

Currency

Un programmeur C++ a écrit une classe Currency ainsi qu'un programme simple manipulant cette classe. La hiérarchie d'héritage proposée s'appuie sur l'héritage multiple entre classes de C++. Revoir en Java et/ou Python et/ou JavaScript/TypeScript cette classe C++ Currency ainsi que ses descendantes.

Construire en suivant les classes Dirham_marocain et Dollar. Dans une autre branche de la hiérarchie, construire la classe Bitcoin comme sous-classe d'une classe Crypto_currency.

// '.h' file:
class Currency;
class Obsolete_currency {
public:
    static const Currency& Default_substitute;
    const Currency& substitute() const;
    bool still_active_() const;
    virtual std::tm substitution_date() const = 0;
};
class Currency {
public:
    const std::string _common_symbol; // $ <- exemple du dollar américain
    const int _iso_code; // 840 <- exemple du dollar américain
    const std::string _iso_symbol; // USD <- exemple du dollar américain
protected:
    Currency(std::string, int, std::string);
public:
    double rate(const Currency& currency) const;
    virtual double to_dollar_rate() const = 0;
    double convert_to_dollar(const double amount) const;
    virtual double to_euro_rate() const = 0;
    double convert_to_euro(const double amount) const;
};
class Euro : public Currency {
public:
    Euro();
    double to_dollar_rate() const;
    double to_euro_rate() const;
};
class Lats : public Currency, public Obsolete_currency { /** Monnaie de la Lettonie remplacée par l'Euro le 1er janvier 2014 **/
private:
    static const std::tm _Substitution_date;
public:
    Lats();
    double to_dollar_rate() const;
    double to_euro_rate() const;
    std::tm substitution_date() const;
};

// '.cpp' file:
const Currency& Obsolete_currency::Default_substitute = Euro();
const Currency& Obsolete_currency::substitute() const {
    return Default_substitute;
}
bool Obsolete_currency::still_active_() const {
    return false;
}
Currency::Currency(std::string common_symbol, int iso_code, std::string iso_symbol) :
_common_symbol(common_symbol),
_iso_code(iso_code),
_iso_symbol(iso_symbol) {}
double Currency::rate(const Currency& currency) const {
    return 1. / currency.to_euro_rate();
}
double Currency::convert_to_dollar(const double amount) const {
    return amount * to_dollar_rate();
}
double Currency::convert_to_euro(const double amount) const {
    return amount * to_euro_rate();
}
Euro::Euro() : Currency("€", 978, "EUR") {}
double Euro::to_dollar_rate() const {
    return 1.1; // Taux pris le 17 sept. 2019
}
double Euro::to_euro_rate() const {
    return 1.;
}
const std::tm Lats::_Substitution_date = tm{.tm_mday = 1, .tm_mon = 0, .tm_year = 114};
Lats::Lats() : Currency("Ls", 428, "LVL") {}
double Lats::to_dollar_rate() const {
    const Currency& substitute = this->substitute();
    return rate(substitute) * substitute.to_dollar_rate();
}
double Lats::to_euro_rate() const {
    return 1. / 0.702804; // Jan. 1, 2014 exchange rate
}
std::tm Lats::substitution_date() const {
    return _Substitution_date;
}
int main() {
    Lats lats;
    std::cout << lats.convert_to_euro(100) << '\n';
    std::cout << lats.convert_to_dollar(100) << '\n';
}
Application(s)

Telecom

Alcatel, ex. grand équipementier télécom français a développé en C++ une classe permettant de manipuler des vecteurs de bits de taille a priori infinie. L'idée est de pouvoir agir sur chaque bit dans le flux, faire des opérations logiques, réserver des portions du flux en leur donnant des significations particulières comme par exemple des checksum lors de transmissions télécom. Tout cela est basé sur un encombrement mémoire minimal et une vitesse d'exécution des opérations sur le flux la meilleure possible vu la nature « système » des traitements envisagés. Les applications reposant sur ce genre de concept informatique sont nombreuses et variées comme la codification et la transmission de messages, la compression, la gestion de flux multimédia, etc.

Dans le code C++ figure l'exemple d'une classe Message pour la transmission de messages de 16 bits au sein d'une infrastructure sous-marine de réseaux à fibre optique. Cet équipementier s'est demandé l'intérêt d'aller plus en avant dans l'extension et donc la maintenance de cette classe Message. En effet, tant C++ (std::bitset) que Java (java.util.BitSet) proposent des composants logiciels capables de « motoriser » la classe Message.

Revoir en C++ et/ou Java et/ou Python et/ou JavaScript/TypeScript la classe C++ Message.

public class Bit {
    private final boolean _implementation;

    public Bit(char c) {
        _implementation = c == '0' ? false : true;
    }
    // Other constructors and methods here...
}

public class Message /* extends ? */ {
    ...
    public Bit start_bit() { return new Bit('0'); } // Bit 1: set to 0
    public java.util.BitSet address() { ... } // Bits 2->11
    public Bit direction() { ... } // Bit 12
    public java.util.BitSet command_code() { ... } // Bits 13->15
    public Bit parity() { ... } // Bit 16
}
Application(s)

Central Intelligence Agency

Un programme Java faisant hériter une classe Confidential_note d'une classe Note montre l'impossibilité de redéfinir des méthodes déclarées private en Java. Il en résulte qu'une méthode déclarée private en Java est implicitement final, i.e., non rédéfinissable du point de vue de l'héritage.

Traduire ce programme en C++ et/ou Python et/ou JavaScript/TypeScript en vérifiant si ces langages autorisent de poser de telles contraintes sur l'héritage ?

public class Note { // Fichier 'Note.java'

    private final static char _Caractere_de_fin = '\n';
    private final static String _Entete_par_defaut = "Pour information : ";
    private final static int _Nombre_d_espaces_par_defaut = 1;
    private final String[] _source;
    protected String _texte;

    public Note(String[] source, String entete) {
        _source = source;
        initialization(entete);
    }

    protected void initialization(String entete) {
        if (entete != null) {
            _texte = entete;
        } else {
            _texte = _Entete_par_defaut;
        }
    }

    public String construire() {
        for (String s : _source) {
            _texte += s;
            for (int i = 0; i < _Nombre_d_espaces_par_defaut; i++) {
                _texte += ' ';
            }
        }
        _texte += _Caractere_de_fin;
        return _texte;
    }
}
…
public class Confidential_note extends Note { // Fichier 'Confidential_note.java'

    private final static String _Entete_par_defaut = "Pour information (confidentiel) : ";

    public Confidential_note(String[] source, String entete) {
        super(source, entete);
    }

    protected void initialization(String entete) {
        // On est obligé de redéfinir la fonction 'initialization' car '_Entete_par_defaut' est différent...
        if (entete != null) {
            super.initialization(entete);
        } else {
            _texte = _Entete_par_defaut;
        }
    }
}
Application(s)

Légumes

Un légume est la partie comestible d’une plante potagère. Parfois, on en consomme les fruits, d’autres fois, les feuilles, mais on peut aussi en consommer les tiges, les graines ou les racines… Selon la partie de la plante qui est consommée, on distingue plusieurs catégories de légumes :

Sur la base de cette classification des légumes, donnez le code sous forme de graphe d’héritage en C++ et/ou Java et/ou JavaScript et/ou Python à partir de la classe suivante :

class Legume {
public:
    virtual Legume* graine() const = 0; // Retourne un clone du légume en question, i.e., un clone de 'this'...
};
abstract public class Legume {
    abstract public Legume graine(); // Retourne un clone du légume en question, i.e., un clone de 'this'...
}
class Legume {
    // On simule avec 'return undefined;' le fait que 'graine' est une méthode abstraite, i.e.,
    // on aurait utilisé le mot-clef 'abstract' en Java mais il n'existe pas en JavaScript :
    graine() { return undefined; } // Retourne un clone du légume en question, i.e., un clone de 'this'...
}

C++ : donnez ensuite un exemple de polymorphisme basé sur les références C++ et découlant du graphe d’héritage construit.

C++ : on fait l'hypothèse qu'il existe une classe abstraite pré-existante Fruit ; que devient le graphe d'héritage ?

Java : remplacer après la classe Legume par une interface et donnez le lien entre l'interface Legume et le type « légumes-feuilles ».

Remarque générale : il est inutile d’implanter tous les légumes cités avant ; une classe suffit (Celeri, Laitue, Poireau…) pour illustrer chacune des sous-branches de la classification.

Application(s)
Complexity

Quick sort

Implanter en C++ et/ou Java et/ou Python et/ou JavaScript/TypeScript le tri lent et le tri rapide (quick sort en anglais)

En C++, faire des mesures de temps calcul grâce aux types time_t et tm (#include <ctime>) de la bibliothèque standard ou timeb (#include <sys/timeb.h>) de la bibliothèque « système » (localisation avec more < /usr/include/sys/timeb.h sous UNIX).

Faire de même en Java sans mesure de temps calcul puis, dans un second temps, réutiliser la classe Java java.util.Collections et ses méthodes sort.

Faire de même en Python sans mesure de temps calcul puis, dans un second temps, réutiliser la classe Python list et sa fonction sort.

Faire de même en JavaScript/TypeScript sans mesure de temps calcul puis, dans un second temps, réutiliser la classe JavaScript Array et sa fonction sort.

Pour remplir les tableaux à trier en gagnant du temps, on peut opportunément utiliser :

Application(s)

Fibonacci

Implanter en C++ et/ou Java et/ou Python et/ou JavaScript/TypeScript la suite de Fibonacci sur la base de trois méthodes de calcul : méthode récursive, méthode itérative ou formule de Binet.

Faire des mesures de temps calcul (cf. Quick sort) et expliquer les performances inhérentes aux trois méthodes lorsque les nombres en entrée deviennent « grands ».

Application(s)

Euclid

Implanter en C++ et/ou Java et/ou Python et/ou JavaScript/TypeScript l'algorithme d'Euclide.

Introduire une variable « artificielle » mesurant le coût du calcul récursif (i.e., incrémenter le coût de 1 à chaque appel récursif). Vérifier empiriquement que ce coût est proche de log(b) si on calcule euclid(a,b).

Application(s)
Security

RSA algorithm

L'algorithme RSA est un algorithme de cryptage basé sur des mathématiques (fichier PDF ici…). Faire une implémentation en Java de cet algorithme en tirant parti de la classe java.math.BigInteger qui offre en standard les calculs mathématiques exposés dans le fichier PDF.
Application(s)
Web

Currency++

L'étude de cas Currency utilise « en dur » dans le code les taux de conversion à l'Euro et/ou au Dollar. Etendre cette étude de cas en allant chercher ces taux de conversion de façon actualisée sur un site Web idoine, par exemple, Open Exchange Rates.

En JavaScript/TypeScript, utiliser l'API fetch (ici…) pour interroger un site Web. Prévoir une interface homme-machine HTML-CSS permettant de faire les conversions avec, notamment, le Dirham marocain et le Bitcoin.

En Java, interroger un site Web et traiter des données JSON est expliqué ici. Utiliser l'API native de Java ou, par exemple, la bibliothèque OkHttp. Prévoir une interface homme-machine permettant de faire les conversions en choisissant l'une ou l'autre des modalités suivantes :

  1. Utiliser JavaFX,
  2. Ou communiquer les données Java à JavaScript/TypeScript grâce à la technologie WebSockets (des archétypes de collaboration sont expliqués et disponibles ici…). Prévoir une interface homme-machine HTML-CSS permettant de faire les conversions avec, notamment, le Dirham marocain et le Bitcoin.
Application(s)

Image processing

Le but du travail est de s'intéresser aux objets JavaScript de type HTMLCanvasElement (spec. ici). On peut aisément créer dynamiquement un canvas.

let canvas = window.document.createElement('canvas');
canvas.id = "My canvas";
canvas.width = 1200;
canvas.height = 800;
canvas.style.zIndex = 10;
canvas.style.position = "absolute";
canvas.style.border = "1px solid";
window.document.body.appendChild(canvas);

Un canvas offre des fonctions de dessin et/ou il est rempli via une image. Dans le second cas, il est alors intéressant de pouvoir faire des traitements d'image (illustration ici) via l'accès aux pixels du canvas. Toutefois, ces traitements peuvent être couteux en temps machine d'où la nécessité de travailler directement avec des background buffers qui sont formatés spécialement pour des accélérations GPU (illustration ici).

Voici un exemple de traitement d'image de manière à reconstruire cette image dans un monde 3D.

En s'aidant de la bibliothèque logicielle dat.GUI, le travail consiste à construire une page Web dans laquelle on charge une image puis on opère des changements comme ceux proposés ici. On rappelle qu'il faut manipuler les pixels avec les background buffers.

Application(s)

Drag & Drop

Le but du travail est de s'intéresser aux événements JavaScript clavier, souris ainsi qu'aux événements Drag & Drop. Considérant l'application JavaScript en fonctionnement ci-dessous, on souhaite faire évoluer son fonctionnement comme suit :

  1. On veut pouvoir à tout moment annuler le compte à rebours en cours avec la souris puis on saisit une donnée définissant une nouvelle valeur de compte à rebours ; on redémarre le compte à rebours.
  2. Avec la souris toujours, on veut pouvoir effectuer une pause du compte à rebours en cours ; on le reprend à la demande.
  3. On veut pouvoir à tout moment changer l'image (la texture en fait) de l'objet 3D injecté via un Drag & Drop. Attention, le Drag & Drop est ici un glisser-lâcher d'un fichier image provenant du système d'exploitation. Par défaut, un browser affiche cette image. Ce comportement par défaut doit donc être redéfini.

Mise à jour de la texture :

new THREE.TextureLoader().load(/* URL du fichier récupéré via 'FileReader' */, function(texture) {
    let bus = this._scene.getObjectByName(this._image_URL);
    bus.material.map = texture;
    bus.material.needsUpdate = true;
}.bind(this));
Application(s)

Statecharts

L'application My device est une application JavaFX pour la partie interface homme-machine. Le cœur de l'application est un automate de type Statecharts de Harel. L'exécution de cet automate est basé sur la bibliothèque Java PauWare. L'équivalent de PauWare en JavaScript est SCION-CORE. L'application My device, bien qu'elle puisse s'exécuter dans un browser, pose des contraintes de sécurité qu'il est de plus en plus difficile de satisfaire en regard de l'évolution des browser du marché (Firefox, Chrome, Safari, etc.).

Le travail consiste ainsi à concevoir l'interface homme-machine en HTML, CSS et JavaScript/TypeScript ainsi que réécrire le cœur de l'application avec le « moteur d'exécution » SCION-CORE sous les considérations suivantes :

Le programme Node.js de Web scraping qui suit récupère sommairement des images via le moteur de recherche Google dédié : images.google.com. Toutefois, l'« aspiration » de données sur le Web est souvent considérée comme une forme de vol d'où une sécurisation à tout-va, exemple : société DataDome. Le groupe Carrefour par exemple protège ses données via la technologie de cette société. Typiquement la requête https://www.carrefour.fr/s?q=3560070478781, bien qu'elle puisse s'exécuter via un browser (Firefox, Chrome, Safari, etc.), est plus difficile à exécuter par un « bot » qui souhaite aspirer photos, prix… voire qualités nutritionnelles, composition (produits alimentaires uniquement)… associés à un produit connu par son code barre ou GTIN (Global Trade Item Number).

En opposition à ce mouvement de sécurisation à tout-va, notre ami El Pueblo souhaite disposer d'une application capable, sur la base d'une liste de produits bien déterminés, lui dire si Carrefour Lescar, Leclerc Pau Université, Géant Casino Lons… lui garantit le prix le plus bas pour sa liste. Si une telle application aujourd'hui existe (?), elle masque peut-être le fait que les données qu'elle utilise sont payées ; en d'autres termes, des groupes comme Carrefour cherchent à (aussi) devenir des entreprises « digitales ».

Le travail consiste ainsi à adapter le programme Node.js qui suit pour tenter d'aspirer les photos des produits Carrefour. Méthode :

/* Node.js program */

const fs = require('fs'); // 'npm i @types/node' let us access to 'require', etc.

// 'puppeteer.js' library: https://developers.google.com/web/tools/puppeteer/
const puppeteer = require('puppeteer'); // 'npm install --save puppeteer' or 'sudo npm install --save puppeteer'
// Recent download problems require this: 'sudo npm install puppeteer --unsafe-perm=true --allow-root'

// 'request.js' library: https://www.npmjs.com/package/request
const request = require('request'); // 'npm install --save request' or 'sudo npm install --save request'

// Check whether 'puppeteer.js' and 'request.js' have been properly installed: 'npm list -depth=0'

class Google_Images {

    private static readonly _Database: string = './Database/';
    private static readonly _Path: string = '/search?tbm=isch&q=';
    private static readonly _URL: string = 'https://www.google.com';

    static async Take_picture() { // Returned type is inferred from 'async', i.e., 'Promise'
        const browser = await puppeteer.launch({headless: true}); // Launch 'Chrome' *WITHOUT* visual environment
        // Following call *DOES NOT* occur (because of prior 'await') until prior one terminates:
        const page = await browser.newPage();
        await page.goto(Google_Images._URL + Google_Images._Path + (typeof process.argv[2] === 'string' ? process.argv[2] : '')); // By default, 'page.goto(...)' waits for the page load event
        const photo_file_name: String = (typeof process.argv[2] === 'string' ? process.argv[2] : 'undefined') + '.png';

        let body: String = await page.evaluate(() => document.body.innerHTML);
        const start_index: number = body.search("https://encrypted-tbn0.gstatic.com");
        if (start_index !== -1) {
            let image_URL: String = body.substring(start_index);
            image_URL = image_URL.substring(0, image_URL.search("\""));
            request(image_URL).pipe(fs.createWriteStream(Google_Images._Database + photo_file_name));
        }
        else
            await page.screenshot({path: Google_Images._Database + photo_file_name}); // Default picture...
        await browser.close();
        return photo_file_name;
    }
}

Google_Images.Take_picture().then((photo_file_name) => {
    console.log('Photo file name: ' + photo_file_name);
});
Application(s)

Crisis management

L'application Java BCMS est un système de gestion de crise impliquant policiers et pompiers qui de façon coopérative procèdent à une intervention sur le lieu d'une crise « en cours ». Le processus de gestion de crise consiste à décider de l'envoi de voitures et de camions dont policiers et pompiers suivent l'envoi et l'arrivée jusqu'à ce que la crise soit terminée. En l'état, l'application n'a pas d'interface homme-machine. Plus précisément, un programme Java main teste l'enchaînement de deux crises pour vérifier grossièrement que l'application globalement fonctionne.

Le travail consiste à fabriquer une interface homme-machine en JavaFX ou en HTML, CSS et JavaScript/TypeScript. Dans le second cas, il faut utiliser la technologie WebSockets pour pousser les données à afficher de Java au browser ; les consignes arrivent alors elles en sens inverse (des exemples de programmes WebSockets sont expliqués et disponibles ici…). Cette interface homme-machine doit permettre de se connecter en tant que policier (Police Station Coordinator) ou en tant que pompier (Fire Station Coordinator). Une fois connecté en tant que policier, seules les fonctionnalités associées au rôle de policier dans l'application sont disponibles et donc activables via l'interface homme-machine (idem pour la « connexion pompier »). Par exemple, l'instruction Java bCMS.state_fire_truck_number(2); du programme de test actuel ne doit être accessible qu'à la « connexion pompier ».

Artificial Intelligence (AI)

xxx.

yyy.

Application(s)

Computer Integrated Manufacturing (CIM)

Une application Node.js (cahier des charges ici… et implémentation …) écrite en TypeScript et basée sur les “frameworks” Express et @Hapi/Joi est un embryon d'architecture micro-services permettant de créer des « articles » de type « produit fini », « matière première », « pièce » et « sous-ensemble ». Au service Web de création d'article (POST), s'ajoutent deux services Web de lecture, d'un article sur sa « référence » et de tous les articles (GET).

Le travail consiste à ajouter un service Web de mise à jour d'un article sur la base de sa « référence » (PUT) et un service Web de suppression d'un article sur la base de cette même « référence » (DELETE).

Application(s)